我正在为自动化领域的高等研究做一项研究。我已经完成了显微镜的自动化部分,但我在MATLAB中需要帮助。我想分段的例子如下:
我需要从此图像中提取暗紫色像素,并仅在图中显示。它几乎就像基于颜色的分割,但我只想从整个图像中获取深紫色像素。
在这种情况下我该怎么做?
答案 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
执行。接下来,我们生成一个新图,并将每个组件放在三列的单行中。第一列表示色调,下一列表示饱和度,最后一列表示值。这是我们看到的数字:
对于第一个数字,看起来主色是紫色,无论是浅色调还是暗色调,所以色调不会对我们有所帮助。如果你看一下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);
我们也会显示结果。这就是我们得到的:
正如你所看到的,这项工作非常出色,但我们在最终结果中没有留下我们不想要的红色箭头的残余。为了进行一些清理,我们可以使用形态学 - 特别是小窗口的开放滤波器,这样我们就不会影响我们想要的像素。我们可以使用imopen
为我们执行开仓操作。形态开口可移除图像周围出现的孤立像素。您使用所谓的structuring element来查看图像的本地邻域。对于基础知识,任何与结构化元素中包含的形状一样小的像素区域都将被删除。因为我们想要保留其他对象的形状,我们可以尝试使用5 x 5磁盘结构元素来清理这些像素:
figure;
se = strel('disk', 2, 0);
final = imopen(result, se);
imshow(final);
这就是我们得到的:
还不错!我们需要修补一些漏洞,所以让我们用imfill
填补这些漏洞:
figure;
final_noholes = imfill(final, 'holes');
imshow(final_noholes);
这就是我们得到的:
OK!所以我们有面具。我们需要做的最后一件事是呈现图像,以便您只显示原始图像中的深紫色,而不显示任何其他颜色。使用bsxfun
:
figure;
out = bsxfun(@times, im, uint8(final_noholes));
imshow(out);
上述操作采用遮罩,并通过此遮罩将图像中的每个像素相乘。我想指出的一件小事是我们在上一步中找到的掩码需要强制转换为uint8
,因为bsxfun
需要乘法(或者你执行的任何操作)需要相同类型。我们在3D中复制这个蒙版,以便您屏蔽掉不需要的RGB像素,并且只保留您要查找的像素。
这是我们最终得到的:
正如你所看到的,它并不完美,但它足以让你开始。那些阈值是重要的,但是通过一些非常简单的阈值处理,我提取了大部分紫色像素。
为了方便您,我在上面编写的代码可以轻松复制并粘贴到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