关于用L * a * b *进行颜色分割的几个问题

时间:2014-02-10 03:35:27

标签: matlab image-processing image-segmentation

我试图通过颜色分割识别下图中内锥上方红/黄色的开始。

Inner light blue and outer dark blue cone and a red/yellow region above the inner cone

为此,我实施了lab color segmentation

clear all
close all
%Plot image
flame = imread('flamePic.JPG');
flame = imrotate(flame,270);
figure(1), imshow(flame), title('Flame');


%Find color of small region
load regioncoordinates;

nColors = 6;
sample_regions = false([size(flame,1) size(flame,2) nColors]);

for count = 1:nColors
  sample_regions(:,:,count) = roipoly(flame,region_coordinates(:,1,count),...
                                      region_coordinates(:,2,count));
end

%imshow(sample_regions(:,:,2)),title('sample region for red');

%Convert your fabric RGB image into an L*a*b* image using makecform and applycform.
cform = makecform('srgb2lab');
lab_fabric = applycform(flame,cform);

%Calculate the mean 'a*' and 'b*' value for each area that you extracted with roipoly. These values serve as your color markers in 'a*b*' space.
a = lab_fabric(:,:,2);
b = lab_fabric(:,:,3);
color_markers = repmat(0, [nColors, 2]);

for count = 1:nColors
  color_markers(count,1) = mean2(a(sample_regions(:,:,count)));
  color_markers(count,2) = mean2(b(sample_regions(:,:,count)));
end

%For example, the average color of the red sample region in 'a*b*' space is
disp(sprintf('[%0.3f,%0.3f]',color_markers(2,1),color_markers(2,2)));

%Create an array that contains your color labels, i.e., 0 = background, 1 = red, 2 = green, 3 = purple, 4 = magenta, and 5 = yellow.
color_labels = 0:nColors-1;

%Initialize matrices to be used in the nearest neighbor classification.
a = double(a);
b = double(b);
distance = repmat(0,[size(a), nColors]);

%Perform classification
for count = 1:nColors
  distance(:,:,count) = ( (a - color_markers(count,1)).^2 + ...
                      (b - color_markers(count,2)).^2 ).^0.5;
end

[value, label] = min(distance,[],3);
label = color_labels(label);
clear value distance;

%Step 4: Display Results of Nearest Neighbor Classification
%The label matrix contains a color label for each pixel in the fabric image. Use the label matrix to separate objects in the original fabric image by color.

rgb_label = repmat(label,[1 1 3]);
segmented_images = repmat(uint8(0),[size(flame), nColors]);

for count = 1:nColors
  color = flame;
  color(rgb_label ~= color_labels(count)) = 0;
  segmented_images(:,:,:,count) = color;
end

%Demonstrate red objects
figure(2),
imshow(segmented_images(:,:,:,1)), title('Color1');
figure(3),
imshow(segmented_images(:,:,:,2)), title('Color2');
figure(4),
imshow(segmented_images(:,:,:,3)), title('Color3');
figure(5),
imshow(segmented_images(:,:,:,4)), title('Color4');
figure(6),
imshow(segmented_images(:,:,:,5)), title('Color5');
figure(7),
imshow(segmented_images(:,:,:,6)), title('Color6');

在上面的图像上运行此算法给出了以下内容:

enter image description here enter image description here

我不确定是什么颜色被分开,但是有大量的红色尚未被识别出来。另外,我无法区分内部,更白的锥体和外部的深蓝色锥体。我认为这与我如何使用roipoly对颜色和感兴趣区域进行采样有关,但我不确定如何改进它。您对如何改进此特定应用程序的细分有任何提示吗?

2 个答案:

答案 0 :(得分:0)

边界并不完美,希望你可以从这里开始......

I=imread('http://i.stack.imgur.com/j86kO.jpg');
I=I(1:2200,800:1600,:);
cform = makecform('srgb2lab');
lab_fabric = applycform(I,cform);
IL=lab_fabric(:,:,1);
Ia=lab_fabric(:,:,2);
Ib=lab_fabric(:,:,3);
I1=I(:,:,1);

mask1=(IL>=100);
mask1=imdilate(mask1,strel('disk',10));

mask2=(I1>0);

mask3=((IL+Ib)<200 & (IL+Ib)>140);
mask3=imopen(mask3,strel('disk',12));

I_blue(:,:,1)=I(:,:,1).*uint8(mask1);
I_blue(:,:,2)=I(:,:,2).*uint8(mask1);
I_blue(:,:,3)=I(:,:,3).*uint8(mask1);
subplot(1,3,1),imshow(I_blue)

I_red(:,:,1)=I(:,:,1).*uint8(mask3);
I_red(:,:,2)=I(:,:,2).*uint8(mask3);
I_red(:,:,3)=I(:,:,3).*uint8(mask3);
subplot(1,3,2),imshow(I_red)

I_dark(:,:,1)=I(:,:,1).*uint8(mask2&~mask3&~mask1);
I_dark(:,:,2)=I(:,:,2).*uint8(mask2&~mask3&~mask1);
I_dark(:,:,3)=I(:,:,3).*uint8(mask2&~mask3&~mask1);
subplot(1,3,3),imshow(I_dark)

enter image description here

答案 1 :(得分:0)

解决方案II

我刚刚注意到您在问题中提供的链接。我不得不说,该示例中的聚类方法更适合“纯”颜色分布。您的图像包含不同颜色之间非常模糊的边界,因此分割在很大程度上取决于您如何标记区域坐标。

删除load regioncoordinates;,更改nColors = 4;,然后在代码开头添加以下坐标:

region_coordinates(:,1,1)=[1113 1180 1180 1230 1113];
region_coordinates(:,2,1)=[1156 1156 1440 1440 1156];
region_coordinates(:,1,2)=[1180 1180 1213 1213 1180];
region_coordinates(:,2,2)=[1620 1680 1675 1600 1620];
region_coordinates(:,1,3)=[1080 1080 1120 1120 1080];
region_coordinates(:,2,3)=[1290 2000 1280 1990 1290];
region_coordinates(:,1,4)=[1495 1496 1496 1499 1495];
region_coordinates(:,2,4)=[1280 1280 1285 1285 1280];

保持代码中的所有其他内容不变,仅显示从figure(1)figure(5),分段结果将为:

enter image description here

除了红色区域外,它基本上看起来不错。为了提高准确性,您可以提供该部分的更多“训练样本”。您可以在运行代码之前尝试roipoly(flame)。将显示一个交互式图形工具,您可以在图像中绘制多边形,您可以粗略地绘制所需的红色区域的形状,然后将坐标保存为region_coordinates之一。您可能需要注意的一件事是,您需要为所有其他颜色的多边形设置边数size(region_coordinates,1)