Loren在Matlab的艺术上

将想法转化为MATLAB

我的胡子在一周内成长多久了?

冒险的心灵弯曲的故事。一种温和令人争论的纱线。
今天的客人博客是罗茨·霍尔特,他在马萨诸塞州纳尼克的Mathworks工作。
Rob目前担任MathWorks的生物科学经理。他是生物、生物技术和制药应用的协调员和合作者。此前,罗伯曾在柯尼卡美能达(Konica Minolta)的公司Invicro担任5年的高级科学家,在那里他设计、实施并传播用于药物发现和开发的图像分析算法。罗布在达特茅斯学院获得博士学位,在那里他专注于通过多模式医学图像合成的分子癌症成像。关注Robÿs的更多滑稽动作 他的推特 他的linkedin
我上周末修剪了我的胡子。虽然我的思想由于缺乏附近的计算设备而徘徊,但我认为“我的胡子头发的快速成长?”这是我无法思考的想法之一。所以我开始计划了。
我想,我可以让它长一个月,然后用尺子测量,但那样的话,我可能不得不从刮得干干净净变成一丝不挂,牺牲了我所保留的专业素养。
然后灵感了。修剪胡子,让它生长一个星期,然后再修剪到相同的长度。如果我们有一幅修剪过的毛发的图片,以及图片中已知大小的东西,我们可以提取一些长度信息。辉煌!

阅读并显示图像

%加载图像
imname =.“mySink.jpg”;
我= imread (imname);
数字;
imshow (im);
标题(原始图像的);
注意,视场中有一枚硬币。我把它扔进水槽的原因是一枚硬币的直径被定义为19.05毫米。这作为一个已知的参考来确定以后的像素大小。这也是我能负担得起的。

使用PENNY获得像素大小

这个函数 imfindcircles. 可用于在视场中寻找圆形物体。注意,我粗略估计了一下半径范围,因为硬币的颜色比背景颜色深,所以我们将物体的极性设置为黑色。
裁掉关于便士的图像
pennyImage = im(1400:1800、1000:1500:);
%过滤一点折叠图像
PennyImagefilt = Medfilt3(PennyImage,[15 15 1]);
%使用imfindcircles函数查找硬币
拉伸= [100 300];
[中心,半径]= imfindcircles(pennyImageFilt,radrange,...
'objectpolarity'“黑暗”);
%可视化找到的所有圆圈
数字;
imshow (pennyImage)
viscircles(中心、半径、'Edgecolor'“b”);
标题(“有圆圈注释的便士细节”);
%从硬币的半径计算像素大小
%使用毫米直径/像素直径
pSize = 19.05 /(半径(1)* 2);%像素大小,单位为毫米
fprintf(“像素大小为%d微米\n”而圆(pSize * 1000))
像素尺寸为62微米

段的头发

现在我们有像素尺寸,我们可以分割头发并试图找到它们的长度。为了保持更简单的事情,让我们播出一个只有头发的部分。
justHair = im(500:1800、1500:3000:);
数字;
次要情节(121)
imshow(justhair);
标题(“只是头发”);
次要情节(122)
imshow(justhair(150:500,900:1350,:));
标题(“头发细节”);
现在我们需要从背景中分割头发。由于头发是黑暗的,背景是白色的,这相当简单。这也可以在灰度图像上完成,因为颜色并不将任何信息添加到此任务。
grayHair = rgb2gray (justHair);
数字;
次要情节(121)
imshow (grayHair);
标题(“我的白发”);
次要情节(122)
imshow(Grayhair(150:500,900:1350))
标题(“灰色头发”细节');
希望这是我在未来几年里唯一的一根白头发。
现在我们可以使用经典的OTSU阈值,它根据强度自动将图像分为两种类别。这可以使用命令完成 曲折 ,它决定了根据强度将这两个级别区分开来的阈值 imbinarize ,它使用这个阈值来制作二值图像。
thresh = twaythresh(灰色);
发舵=〜Imbinarize(灰毛,阈值);
数字;
次要情节(121)
imshow (hairSeg);
标题('头发细分');
次要情节(122)
imshow(发型(150:500,900:1350));
标题(“头发细分细节”
在这种情况下, imbinarize 使光明的部分"真实",所以 逻辑上是把头发翻转过来吗 发桥 ,分割的头发,将被 真正的

尽量保持头发不结块

现在我们有所有的毛发。其中一些是丛生的,但大多数看起来都是独立的。对于第一次通过估计,让我们去除较大的簇,以及较小的簇,留下大多是独特的毛发。
去除任何被剪掉的毛发
发舵= inclecleborder(bairseg);
%删除任何太小的簇
hairSeg = bwareaopen (hairSeg 30);
%删除过大的群集
hairSeg = hairSeg & ~ bwareaopen(hairSeg,300);
数字;
次要情节(121)
imshow (hairSeg)
标题(“检查头发长度”);
次要情节(122)
imshow (hairSeg (150:500,900:1350))
标题('毛发的细节为长度检查');

估计所有头发的长度

我们现在有一段最好的头发供我们检查。要估计它们的长度,我们首先要做的是将它们的头发骨架化(使每根头发的宽度最多为一个像素),然后计算每根骨架化的头发中的像素。这是使用属性“面积”完成的,但由于每根头发是一个像素宽,面积大致等于头发的长度。
削去头发
hairSkel = bwskel (hairSeg);
显示骨骼%
数字;
次要情节(121)
imshow (hairSkel);
标题('头发骨架化');
次要情节(122)
imshow (hairSkel (150:500,900:1350));
标题(“毛发骨架化的细节”);
%计算所有毛发的长度
统计= regionprops (hairSkel,“区域”);
%从Struc中获得区域
stats.Area hairLengthInPixels =猫(1);
%转变为现实世界长度
Hairlength = hairlengthinpixels * psize;

计算平均头发长度

现在我们有了所有头发长度的列表。因此,我们可以可视化直方图以及计算平均长度。
数字;
直方图(发型);
包含(的头发长度(毫米));
ylabel (毛发的数量);
meanhairlength =平均(发型);
fprintf(平均头发长度:%.1fmm\n,意思是尺寸;
平均头发长度:2.2mm

总结和讨论

这就是它!我的胡子每周会长2.2毫米,或者说每天会长0.31毫米。这非常接近 吉列估计每天0.27毫米
当然,这个模型并不完美。通过将曲线拟合到每条头发,长度计算可以更准确。如果我们找到了分离更多较大的毛发的方法,分割可能更准确。但是为了大多数实际目的,这将是一个很好的估计。
这种工作流程也可应用于其他图像处理方案。例如,在生命科学研究中测量毛虫或蠕虫的长度,或为工业制造质量控制测量碎片长度。
你最近在做什么奇怪的项目吗?你知道你可以用MATLAB来解决这类问题吗?你觉得我胡子的高分辨率照片不合适吗?请在评论中分享你的想法和意见 在这里
版权所有:The MathWorks, Inc.
|

评论

要留下评论,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。