【发布时间】:2014-12-19 23:00:25
【问题描述】:
我正在尝试更改以下图像的瞳孔:
这不是特征提取或眼睛检测任务。我想“手动”改变瞳孔的颜色。
我试图做的是定位瞳孔颜色值并将它们更改为红色或紫色,例如:
I2是加载的图片:
I3=(I2<100);
figure(5)
imagesc(I3)
colormap purple
我已经在论坛中搜索过,但没有看到任何合适的解决方案
有什么建议吗?
【问题讨论】:
我正在尝试更改以下图像的瞳孔:
这不是特征提取或眼睛检测任务。我想“手动”改变瞳孔的颜色。
我试图做的是定位瞳孔颜色值并将它们更改为红色或紫色,例如:
I2是加载的图片:
I3=(I2<100);
figure(5)
imagesc(I3)
colormap purple
我已经在论坛中搜索过,但没有看到任何合适的解决方案
有什么建议吗?
【问题讨论】:
不幸的是,您别无选择,只能检测瞳孔的位置并用您想要的颜色填充这些像素。简单的阈值化是行不通的,因为睫毛的强度分布与瞳孔大致相同。
我们可以做的是在您对图像设置阈值之后进行一些后期处理。但是,我的建议将需要 MATLAB 中的图像处理工具箱。如果你没有这个,那么很遗憾我的解决方案将不起作用。
假设您确实可以访问它,我可以建议使用regionprops 来检测图像中的独特形状。这是假设您正确地对图像进行阈值处理。我将专门查看'Area' 和'PixelList' 属性。一旦我们对图像进行阈值处理,我们应该主要期待两个聚集像素区域:睫毛和瞳孔。睫毛的面积可能最大,而瞳孔的面积第二大。因此,让我们看一下Area 属性并确定图像中具有第二大面积的对象。一旦我们找到这个对象,我们将把这个区域所在的这些像素设置为你想要的任何颜色。但是,我们将不得不进行一些后期处理以确保整个瞳孔都被填满。您会看到瞳孔中间有一个白点,这很可能是由于相机的闪光灯造成的。我们基本上需要确保整个检测到的瞳孔是一个闭合轮廓,然后填充形状。填充此形状后,我们只需使用这些像素并将它们设置为您希望输出图像中的任何颜色。
现在,第一步是正确地对图像进行阈值处理。首先,我直接从 StackOverflow 读取图像。但是,此图像是 RGB 图像,我想要等效的灰度图像。我们可以使用rgb2gray 为我们完成这项工作。完成后,我使用强度阈值 35,然后像这样运行regionprops:
im = imread('http://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:
ind = find(areas == 480);
现在我们知道它在s 中的位置,让我们把它拉出来并取出PixelList 属性。这会为您提供属于该对象的像素列表:
pix = s(ind).PixelList;
第一列表示属于对象的每个像素的列位置,第二列表示行位置。接下来我要做的是获取这些像素并创建一个仅包含这些检测到的像素的掩码。我将使用此蒙版索引原始图像并将这些像素设置为您想要的任何颜色。因此:
mask = logical(full(sparse(pix(:,2), pix(:,1), 1, size(im,1), size(im,2))));
代码使用sparse 创建一个稀疏矩阵,其中每个值都为0 除了,对于那些在pix 中定义的像素位置。这是仅在指定位置创建 1 矩阵,否则创建 0 矩阵的更简单方法。因为这是sparse,所以我需要将其更改为我们可以使用的full 数字矩阵,最后我们需要使用logical 进行转换以确保正确的掩码。
如果我们使用imshow 显示这个掩码,我们会得到:
可以看到,原图中由于瞳孔的白点存在间隙,是有道理的。您还会注意到瞳孔的轮廓并未完全闭合。因此,我将通过选择磁盘结构元素来通过imclose 执行形态闭合来闭合间隙。一旦我们缩小了差距,我们就可以使用imfill 并选择'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 等效值具有相同的所有红色、绿色和蓝色值。一旦我们设置了瞳孔的颜色,使用cat 将所有这些堆叠在一起作为一个 3D 矩阵,我们最终显示图像。我还将瞳孔的颜色设置为红色。您可以通过将常量分配 (255, 0, 0) 更改为您想要的颜色来将 RGB 值更改为您想要的任何颜色。
这是我们得到的:
为了您的复制和粘贴乐趣,这是从头到尾的完整代码:
im = imread('http://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);
【讨论】:
createMask??
这是手动选择瞳孔的解决方案。基本上,您选择要填充瞳孔的颜色,然后手动跟踪感兴趣的区域并填充该区域。在示例中,我选择了一个大得离谱的区域,但您明白这一点:)
代码如下:
clear
clc
close all
A = imread('pupil.jpg');
imshow(A)
%// Create dialog box to choose color to fill.
ListColors = {'red' 'green' 'blue' 'magenta' 'white' 'yellow' 'cyan' 'random'};
[Selection,ok] = listdlg('ListString',ListColors,'PromptString','Choose color','SelectionMode','single');
%//Freehand tool
hHand = imfreehand(gca,'Closed',true);
%// createMask is a method from imfreehand. Image processing toolbox required.
mask = createMask(hHand);
%// Create color mask. You can create your own mask with any 3-element vector.
switch ListColors{Selection}
case 'red'
colormask = 255*[1, 0, 0];
case 'green'
colormask = 255*[0, 1, 0];
case 'blue'
colormask = 255*[0, 0, 1];
case 'white'
colormask = 255*[1, 1, 1];
case 'yellow'
colormask = 255*[1, 1, 0];
case 'magenta'
colormask = 255*[1, 0, 1];
case 'cyan'
colormask = 255*[0, 1, 1];
case 'random'
colormask = 255*[rand(1), rand(1), rand(1)];
end
% Extract the individual channels.
redChannel = A(:, :, 1);
greenChannel = A(:, :, 2);
blueChannel = A(:, :, 3);
%// Apply mask to the ROI
redChannel(mask) = colormask(1);
greenChannel(mask) = colormask(2);
blueChannel(mask) = colormask(3);
%// Generate 3 channels final image
A = cat(3, redChannel, greenChannel, blueChannel);
imshow(A)
一些屏幕截图显示输出:
1) 选择颜色(这里随机)
2) 追踪区域
3) 输出:
这很有趣哈哈希望有帮助!
【讨论】: