简体   繁体   English

更改眼睛图像中特定区域的颜色[Matlab]

[英]Change color of a specific region in eye image [Matlab]

I am trying to change the pupil of the following image: 我正在尝试更改以下图像的瞳孔:
在此处输入图片说明
This is not a feature extraction or eye detection task. 这不是功能提取或眼睛检测任务。 I want to "manually" change the color of the pupil. 我想“手动”更改瞳孔的颜色。

What I tried to do is to locate the pupil color values and change them to red or purple for example: 我试图做的是找到瞳孔颜色值并将其更改为红色或紫色,例如:

I2 is the loaded image: I2是加载的图像:

I3=(I2<100);
figure(5)
imagesc(I3) 
colormap purple


I already searched in the forum and I didn't see any proper solutions 我已经在论坛中搜索了,但没有找到合适的解决方案
Any suggestions? 有什么建议么?

Unfortunately, you don't have a choice but to detect where the pupil is located and fill those pixels in with your desired colour. 不幸的是,您别无选择,只能检测瞳孔所在的位置,并用所需的颜色填充这些像素。 Simply thresholding will not work because the eyelashes have roughly the same intensity distribution as the pupil. 由于睫毛的强度分布与瞳孔大致相同,因此简单地阈值化将不起作用。

What we can do is do some post-processing after you threshold the image. 我们可以做的是对图像进行阈值处理进行一些后处理。 However, what I am suggesting will require the Image Processing Toolbox in MATLAB. 但是,我的建议是需要MATLAB中的图像处理工具箱。 If you don't have this, then unfortunately my solution won't work. 如果您没有此功能,那么很遗憾,我的解决方案将无法正常工作。

Assuming that you do have access to this, what I can suggest is use regionprops to detect unique shapes in your image. 假设您确实可以使用此功能,我建议您使用regionprops检测图像中的独特形状。 This is assuming that you threshold the image properly. 这是假设您正确设置了图像阈值。 I'm going to specifically look at the 'Area' and 'PixelList' attributes. 我将专门研究'Area''PixelList'属性。 Once we threshold the image, we should expect predominantly two areas of clustered pixels: The eyelashes and the pupil. 一旦我们对图像进行阈值处理,我们应该主要预期两个区域的聚集像素:睫毛和瞳孔。 The eyelashes will probably have the largest amount of area while the pupil the second largest. 睫毛的面积可能最大,而瞳孔的面积第二大。 As such, let's take a look at the Area attribute and determine the object in your image that has the second largest area. 这样,让我们​​看一下Area属性,并确定图像中面积第二大的对象。 Once we find this object, we will set these pixels where this area is located to whatever colour you wish. 找到该对象后,我们会将这些区域所在的像素设置为所需的任何颜色。 However, we're going to have to do a bit of post-processing to ensure that the entire pupil gets filled in. You see that there is a white spot in the middle of the pupil most likely due to the flash of the camera. 但是,我们将必须进行一些后期处理,以确保将整个瞳孔都填满。您会看到,瞳孔中间有一个白点,这很可能是由于相机的闪光灯引起的。 We would essentially need to ensure that the entire detected pupil is a closed contour, then fill in the shape. 我们本质上需要确保整个检测到的瞳孔是闭合轮廓,然后填充形状。 Once we fill in this shape, we simply use these pixels and set them to whatever colour you wish in the output image. 填充此形状后,我们只需使用这些像素并将其设置为输出图像中所需的任何颜色即可。


Now, the first step is to threshold the image properly. 现在,第一步是适当地对图像进行阈值处理。 First, I read in the image directly from StackOverflow. 首先,我直接从StackOverflow中读取图像。 However, this image is a RGB image, and I want the grayscale equivalent. 但是,此图像是RGB图像,我想要等效的灰度。 We can use rgb2gray to accomplish that for us. 我们可以使用rgb2gray为我们完成此任务。 Once that's done, I used a threshold of intensity 35, then ran through regionprops like so: 完成后,我使用强度阈值35,然后像这样通过regionprops运行:

im = imread('http://i.stack.imgur.com/d3hy5.jpg');
im = rgb2gray(im);
s = regionprops(im < 35, 'Area', 'PixelList');

s will contain a structure of information, where each element tells you the area and the pixels that belong to each unique object that was detected in your image. s将包含的信息的结构,其中每个元素告诉你的面积,属于在图像中检测到每一个独特的对象像素。 Let's take a look at the area: 让我们看一下该区域:

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

You can see that there are a lot of spurious isolated pixels that result after we threshold, which makes sense. 您可以看到,在我们设定阈值之后,会产生很多虚假的孤立像素,这是有道理的。 You will also see that we have a couple of patches that have a significantly larger area than the majority of the patches. 您还将看到我们有几个补丁,它们的面积比大多数补丁大得多。 There is one patch that has an area of 1433, while another 480. The area with 1433 is most likely the pixels that belong to the eyelashes, as they more or less share the same intensity distribution as that of your pupil. 有一个斑块的面积为1433,而另一个斑块的面积为480。面积为1433的像素很可能属于睫毛,因为它们或多或少共享与瞳孔相同的强度分布。 The pupil will lost likely be the second highest area. 学生可能会失去第二高的区域。 As such, let's take a look at the patch that has the second highest area . 这样,让我们​​看一下具有第二高面积的补丁。 To figure out where this is, use find : 要找出这是哪里,请使用find

ind = find(areas == 480);

Now that we know where this is located in s , let's pull this out and get out the PixelList attribute. 现在我们知道它在s ,让我们将其拉出并获得PixelList属性。 This gives you a list of pixels that belong to the object: 这为您提供了属于该对象的像素列表:

pix = s(ind).PixelList;

The first column denotes the column position of each pixel belonging to the object while the second column denotes the row position. 第一列表示属于对象的每个像素的列位置,而第二列表示行位置。 What I'm going to do next is take these pixels and create a mask that only contains these detected pixels. 我接下来要做的是获取这些像素,并创建仅包含这些检测到的像素的蒙版 I will use this mask to index into the original image and set those pixels to whatever colour you want. 我将使用此蒙版将原始图像编入索引,并将这些像素设置为所需的任何颜色。 As such: 因此:

mask = logical(full(sparse(pix(:,2), pix(:,1), 1, size(im,1), size(im,2))));

The code uses sparse to create a sparse matrix where every value is 0 except for those pixel locations defined in pix . 该代码使用sparse来创建稀疏矩阵,其中 pix定义的那些像素位置 ,每个值均为0。 This is an easier way of creating matrix of 1s only at specified locations and 0 otherwise. 这是一种仅在指定位置创建1的矩阵,否则创​​建0的矩阵的简便方法。 Because this is sparse , I need to change this to a full numeric matrix that we can use, and we finally need to cast using logical to ensure a proper mask. 因为这是sparse ,所以我需要将其更改为可以使用的full数值矩阵,最后我们需要使用logical以确保适当的掩码。

If we show this mask using imshow , this is what we get: 如果我们使用imshow显示此蒙imshow ,则会得到以下结果:

在此处输入图片说明

You can see that there is a gap due to the white spot of the pupil in the original image, which makes sense. 您会看到,由于原始图像中瞳孔的白点而存在间隙,这是有道理的。 You will also notice that the contour of the pupil isn't entirely closed. 您还将注意到,瞳孔的轮廓并未完全闭合。 As such, I'm going to perform morphological closing by imclose by choosing a disk structuring element to close the gaps. 因此,我要进行形态学闭imclose通过选择一个磁盘结构元素以填补缺口。 Once we close the gaps, we can use imfill and choose the 'holes' flag to fill in these holes. 缩小差距后,我们可以使用imfill并选择'holes'标志来填充这些孔。

We now have a fully filled in mask that we can finally use to index into the original image and set our colours. 现在,我们有了一个完全填充的遮罩,我们可以将其最终用于索引原始图像并设置颜色。 As such: 因此:

mask = imclose(mask, strel('disk', 4, 4));
mask = imfill(mask, 'holes');

Here's what the mask looks like now: 这是面具现在的样子:

在此处输入图片说明

Cool! 凉! Now the last thing you need to do is colour in those pixels with whatever colour you wish. 现在,您需要做的最后一件事就是为这些像素中的颜色加上所需的颜色。 To do this, you'll need to make a RGB version of your image. 为此,您需要制作图像的RGB版本。 As such, simply create red, green and blue channels that replicate the grayscale content of your image and set each channel with the appropriate colour using the pixels defined in the mask. 这样,只需创建红色,绿色和蓝色通道即可复制图像的灰度内容,并使用蒙版中定义的像素为每个通道设置适当的颜色。

red = im;
red(mask) = 255;
green = im;
green(mask) = 0;
blue = im;
blue(mask) = 0;
out = cat(3, red, green, blue);
imshow(out);

Remember that for grayscale images, the RGB equivalent has all of the red, green and blue values the same. 请记住,对于灰度图像,相当于RGB的所有红色,绿色和蓝色值都相同。 Once we set the colour for the pupil, stack all of these together as a 3D matrix using cat and we finally show the image. 设置好瞳孔的颜色后,使用cat所有这些颜色堆叠为3D矩阵,最后显示图像。 I've also set the colour of the pupil to red. 我还将瞳孔的颜色设置为红色。 You can change the RGB value to whatever you desire by changing the constant assignment (255, 0, 0) to be your desired colour. 通过将常量分配(255, 0, 0)更改为所需的颜色(255, 0, 0)可以将RGB值更改为所需的值。

This is what we get: 这是我们得到的:

在此处输入图片说明


For your copying and pasting pleasure, this is the full code from start to finish: 为了您的复制和粘贴乐趣,这是从头到尾的完整代码:

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);

Here is a solution for manual selection of the pupil. 这是手动选择瞳孔的解决方案。 Basically you select a color with which to want to fill the pupil, then trace a region of interest by hand and the region gets filled. 基本上,您要选择一种颜色来填充瞳孔,然后手动跟踪感兴趣的区域并填充该区域。 In the example I selected a ridiculously large region but you see the point :) 在示例中,我选择了一个非常大的区域,但是您看到了要点:)

Here is the code: 这是代码:

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)

A few screenshots to show you the output: 一些屏幕截图向您显示输出:

1) Select the color (here random) 1)选择颜色(这里是随机的)

在此处输入图片说明

2) Trace the region 2)追踪区域

在此处输入图片说明

3) Output: 3)输出:

在此处输入图片说明

That was fun haha hope that helps! 那很有趣,哈哈希望能有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM