查找图像中的深紫色像素

时间:2015-02-02 17:36:30

标签: matlab image-processing pixel

我正在为自动化领域的高等研究做一项研究。我已经完成了显微镜的自动化部分,但我在MATLAB中需要帮助。我想分段的例子如下:

我需要从此图像中提取暗紫色像素,并仅在图中显示。它几乎就像基于颜色的分割,但我只想从整个图像中获取深紫色像素。

在这种情况下我该怎么做?

2 个答案:

答案 0 :(得分:4)

这里有一些让你入门的东西。让我们以色彩分割为主题,您只想提取深紫色的像素。在我们开始之前,我想指出HSV colour space。 HSV色彩空间非常适合以对人类最直观的方式表示色彩。我们倾向于通过其主色来描述颜色,然后是诸如颜色如何褪色或多么纯净以及颜色的亮度或暗度等属性。主色是由色调表示的,外观是如何褪色或色彩的纯度由饱和度表示,色彩的强度由值表示,因此 H ue- S aturation- V alue或HSV色彩空间。

我们可以变换RGB图像,使其成为rgb2hsv的HSV。这将返回一个3D矩阵,其色调,饱和度和值作为3D矩阵中的2D切片,非常类似于RGB图像,其中每个切片代表红色,绿色和蓝色通道。一旦我们将图像转换为HSV,让我们看看每个组件的样子:

im = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
hsv = rgb2hsv(im2double(im));
figure;
for idx = 1 : 3
    subplot(1,3,idx);
    imshow(hsv(:,:,idx));
end

第一行代码从URL读取图像。我将使用Hoki推荐给你的那个,因为它是最简单的一个。对于自我遏制,这就是原始图像的样子:

一旦我们这样做,我们将图像转换为HSV颜色空间。将图像转换为double精度非常重要,并将每个组件规范化为[0,1],并由im2double执行。接下来,我们生成一个新图,并将每个组件放在三列的单行中。第一列表示色调,下一列表示饱和度,最后一列表示值。这是我们看到的数字:

enter image description here

对于第一个数字,看起来主色是紫色,无论是浅色调还是暗色调,所以色调不会对我们有所帮助。如果你看一下HSV色轮:

http://www.hobbitsandhobos.com/wp-content/uploads/2011/06/colorWheel.png

将滚轮标准化,使其落在[0,1]而不是0到360度之间。由于颜色空间的性质,色调实际上表示为度数,但MATLAB将其归一化为[0,1]。您可以看到紫色落在[0.6,0.8]的色调范围内,这与我向您展示的第一个显示图像色调的图形相对应。如果检查图像周围的像素,它们会在此范围之间波动。因此,色调在这里不会对我们有所帮助。

饱和度和价值成分肯定会对我们有所帮助。如果看一看,深紫色像素的饱和度高于背景的其余部分,这是有道理的,因为深紫色比背景的其余部分具有更纯的紫色版本。对于该值,您可以看到深紫色的亮度比背景暗。

我们可以使用这两点来分析图像中的紫色。最简单的做法是对饱和度值和值平面进行阈值处理,以便保留在某个范围内的任何值,而在您之外的值则丢弃。因此,您可以这样做:

sThresh = hsv(:,:,2) > 0.6 & hsv(:,:,2) < 0.9;
vThresh = hsv(:,:,3) > 0.4 & hsv(:,:,3) < 0.65;

我使用impixelinfo并将鼠标悬停在饱和度和值组件上,以检查深紫色区域的值。看起来那些深紫色的像素的饱和度值介于0.6和0.9之间,而值组件的值介于0.4和0.65之间。上面的代码将创建两个二进制掩码,其中true表示像素满足我们的标准,而false表示它没有。因为我想将两者结合在一起并且不遗余力,所以让我们将这些面具合理地用于最终结果:

figure;
result = sThresh | vThresh;
imshow(result);

我们也会显示结果。这就是我们得到的:

enter image description here

正如你所看到的,这项工作非常出色,但我们在最终结果中没有留下我们不想要的红色箭头的残余。为了进行一些清理,我们可以使用形态学 - 特别是小窗口的开放滤波器,这样我们就不会影响我们想要的像素。我们可以使用imopen为我们执行开仓操作。形态开口可移除图像周围出现的孤立像素。您使用所谓的structuring element来查看图像的本地邻域。对于基础知识,任何与结构化元素中包含的形状一样小的像素区域都将被删除。因为我们想要保留其他对象的形状,我们可以尝试使用5 x 5磁盘结构元素来清理这些像素:

figure;
se = strel('disk', 2, 0);
final = imopen(result, se);
imshow(final);

这就是我们得到的:

enter image description here

还不错!我们需要修补一些漏洞,所以让我们用imfill填补这些漏洞:

figure;
final_noholes = imfill(final, 'holes');
imshow(final_noholes);

这就是我们得到的:

enter image description here

OK!所以我们有面具。我们需要做的最后一件事是呈现图像,以便您只显示原始图像中的深紫色,而不显示任何其他颜色。使用bsxfun

可以轻松实现这一目标
figure;
out = bsxfun(@times, im, uint8(final_noholes));
imshow(out);

上述操作采用遮罩,并通过此遮罩将图像中的每个像素相乘。我想指出的一件小事是我们在上一步中找到的掩码需要强制转换为uint8,因为bsxfun需要乘法(或者你执行的任何操作)需要相同类型。我们在3D中复制这个蒙版,以便您屏蔽掉不需要的RGB像素,并且只保留您要查找的像素。

这是我们最终得到的:

enter image description here

正如你所看到的,它并不完美,但它足以让你开始。那些阈值是重要的,但是通过一些非常简单的阈值处理,我提取了大部分紫色像素。


为了方便您,我在上面编写的代码可以轻松复制并粘贴到MATLAB中供您运行:

clear all; close all; clc;
im = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
hsv = rgb2hsv(im2double(im));
figure;
for idx = 1 : 3
    subplot(1,3,idx);
    imshow(hsv(:,:,idx));
end

sThresh = hsv(:,:,2) > 0.6 & hsv(:,:,2) < 0.9;
vThresh = hsv(:,:,3) > 0.4 & hsv(:,:,3) < 0.65;

figure;
result = sThresh | vThresh;
imshow(result);

figure;
se = strel('disk', 2, 0);
final = imopen(result, se);
imshow(final);

figure;
final_noholes = imfill(final, 'holes');
imshow(final_noholes);

figure;
out = bsxfun(@times, im, uint8(final_noholes));
imshow(out);

祝你好运!

答案 1 :(得分:-1)

尝试一下:

function main
    clc,clear

    A = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
    subplot(1,2,1)
    imshow(A)

    RGB = [230 210 200];      % color you want
    e = 40;                   % color shift

    B = pix_in(A,RGB,e);
    B = B + 255.*uint8(~B);   % choosing white background
    subplot(1,2,2)
    imshow(B)
end

function B = pix_in(A,RGB,e)
    % select specific pixels in image
    % A - color image (3D matrix uint8)
    % RGB - [R G B] - color to select
    % e - color shift/deviation

    A = double(A);              % for same class operations (RGB - double)
    [m, n, ~] = size(A);
    RGB = reshape(RGB,1,1,3);
    RGB = repmat(RGB,m,n,1);    % creating 3D matrix
    b = abs(A-RGB) < e;         % logical 3D
    b = sum(b,3) == 3;          % if [R,G,B] of a pixel in range
    B = A.*repmat(b,1,1,3);     % selecting pixels those in range
    B = uint8(B);
end