不幸的是,您别无选择,只能检测瞳孔所在的位置并用您想要的颜色填充这些像素。简单的阈值处理是行不通的,因为睫毛的强度分布与瞳孔大致相同。
我们能做的就是做一些后期处理after您对图像设置阈值。然而,我建议需要 MATLAB 中的图像处理工具箱。如果您没有这个,那么不幸的是我的解决方案将不起作用。
假设您确实可以访问此内容,我可以建议使用regionprops http://www.mathworks.com/help/images/ref/regionprops.html检测图像中的独特形状。这是假设您正确地对图像进行阈值设置。我要专门看看'Area'
and 'PixelList'
属性。一旦我们对图像进行阈值处理,我们应该预期主要有两个聚集像素区域:睫毛和瞳孔。睫毛的面积可能最大,而瞳孔的面积第二大。因此,让我们看一下Area
属性并确定图像中面积第二大的对象。一旦我们找到这个对象,我们就会将该区域所在的这些像素设置为您想要的任何颜色。但是,我们必须进行一些后期处理,以确保整个瞳孔被填充。您会看到瞳孔中间有一个白点,很可能是由于相机的闪光灯造成的。我们本质上需要确保整个检测到的瞳孔是一个闭合轮廓,然后填充该形状。一旦我们填充了这个形状,我们只需使用这些像素并将它们设置为您希望在输出图像中出现的任何颜色。
现在,第一步是正确设置图像阈值。首先,我直接从 StackOverflow 读取图像。但是,该图像是 RGB 图像,我想要等效的灰度图像。我们可以用rgb2gray http://www.mathworks.com/help/matlab/ref/rgb2gray.html为我们实现这一目标。完成后,我使用强度阈值 35,然后运行regionprops
像这样:
im = imread('https://i.stack.imgur.com/d3hy5.jpg');
im = rgb2gray(im);
s = regionprops(im < 35, 'Area', 'PixelList');
s
将包含信息结构,其中每个元素告诉您属于图像中检测到的每个唯一对象的区域和像素。我们来看看该地区:
areas = [s.Area].'
areas =
1
2
1
2
5
3
1
19
3
1
2
2
1
23
1224
1
2
41
12
2
1
2
1
5
2
33
480
3
6
1
2
1
1
2
1
您可以看到,在我们阈值之后产生了很多虚假的孤立像素,这是有道理的。您还会看到,我们有几个补丁的面积比大多数补丁的面积要大得多。有一个斑块的面积为 1433,而另一个斑块的面积为 480。1433 的区域很可能是属于睫毛的像素,因为它们或多或少具有与瞳孔相同的强度分布。瞳孔将失去的可能是第二高的区域。因此,让我们看一下具有以下内容的补丁:第二高面积。要找出这是哪里,请使用find http://www.mathworks.com/help/matlab/ref/find.html:
ind = find(areas == 480);
现在我们知道它位于哪里s
,让我们把这个拿出来PixelList
属性。这将为您提供属于该对象的像素列表:
pix = s(ind).PixelList;
第一列表示属于对象的每个像素的列位置,而第二列表示行位置。接下来我要做的是获取这些像素并创建一个mask仅包含这些检测到的像素。我将使用这个蒙版来索引原始图像并将这些像素设置为您想要的任何颜色。像这样:
mask = logical(full(sparse(pix(:,2), pix(:,1), 1, size(im,1), size(im,2))));
代码使用sparse http://www.mathworks.com/help/matlab/ref/sparse.html创建一个稀疏矩阵,其中每个值都是 0except对于那些定义在中的像素位置pix
。这是一种仅在指定位置创建 1 矩阵的更简单方法,否则创建 0 矩阵。因为这是sparse
,我需要将其更改为full http://www.mathworks.com/help/matlab/ref/full.html我们可以使用的数字矩阵,最后我们需要使用logical
以确保正确的面罩。
如果我们使用这个掩码来展示imshow
,这就是我们得到的:
您可以看到,由于原始图像中瞳孔的白点而存在间隙,这是有道理的。您还会注意到瞳孔的轮廓并未完全闭合。因此,我将通过以下方式执行形态学关闭imclose http://www.mathworks.com/help/images/ref/imclose.html通过选择磁盘结构元素来弥补差距。一旦我们缩小了差距,我们就可以使用imfill http://www.mathworks.com/help/images/ref/imfill.html并选择'holes'
标志来填补这些漏洞。
现在我们有了一个完全填充的蒙版,我们最终可以用它来索引原始图像并设置颜色。像这样:
mask = imclose(mask, strel('disk', 4, 4));
mask = imfill(mask, 'holes');
这是面具现在的样子:
凉爽的!现在您需要做的最后一件事就是用您想要的任何颜色为这些像素着色。为此,您需要制作图像的 RGB 版本。因此,只需创建红色、绿色和蓝色通道来复制图像的灰度内容,并使用蒙版中定义的像素为每个通道设置适当的颜色。
red = im;
red(mask) = 255;
green = im;
green(mask) = 0;
blue = im;
blue(mask) = 0;
out = cat(3, red, green, blue);
imshow(out);
请记住,对于灰度图像,RGB 等效值具有相同的所有红色、绿色和蓝色值。一旦我们设置了瞳孔的颜色,使用以下命令将所有这些堆叠在一起作为 3D 矩阵cat http://www.mathworks.com/help/matlab/ref/cat.html最后我们展示了图像。我还将瞳孔的颜色设置为红色。您可以通过更改常量分配将 RGB 值更改为您想要的任何值(255, 0, 0)
成为您想要的颜色。
这就是我们得到的:
为了您复制和粘贴的乐趣,这是从开始到结束的完整代码:
im = imread('https://i.stack.imgur.com/d3hy5.jpg');
im = rgb2gray(im);
s = regionprops(im < 35, 'Area', 'PixelList');
areas = [s.Area].';
ind = find(areas == 480);
pix = s(ind).PixelList;
mask = logical(full(sparse(pix(:,2), pix(:,1), 1, size(im,1), size(im,2))));
mask = imclose(mask, strel('disk', 4, 4));
mask = imfill(mask, 'holes');
red = im;
red(mask) = 255;
green = im;
green(mask) = 0;
blue = im;
blue(mask) = 0;
out = cat(3, red, green, blue);
imshow(out);