我正在尝试更改以下图像的瞳孔:
这不是特征提取或眼睛检测任务。我想“手动”改变瞳孔的颜色。
我尝试做的是找到瞳孔颜色值并将其更改为红色或紫色,例如:
I2
是加载的图片:
I3=(I2<100);
figure(5)
imagesc(I3)
colormap purple
我已经在论坛中搜索过,但我没有看到任何正确的解决方案
有什么建议吗?
答案 0 :(得分:3)
不幸的是,您无法选择,只能检测瞳孔的位置,并用您想要的颜色填充这些像素。简单的阈值处理是行不通的,因为睫毛的强度分布与瞳孔大致相同。
我们可以做的是在对图像进行阈值处理后对进行一些后期处理。但是,我建议的将需要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
创建一个稀疏矩阵,其中pix
中定义的那些像素位置的每个值都为0 ,但除外。这是仅在指定位置创建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);
答案 1 :(得分:2)
这是手动选择瞳孔的解决方案。基本上,您选择要填充瞳孔的颜色,然后手动追踪感兴趣的区域并填充区域。在这个例子中,我选择了一个可笑的大区域,但你看到了这一点:)
以下是代码:
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)输出:
这很有趣哈哈希望有所帮助!