问题
I am trying to identify the onset of red/yellow color above the inner cone in the following image with color segmentation.
To do this, I implemented 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');
Running this algorithm on the above image gives me the following:
I am not exactly sure what color is being separated, but there is plenty of red that has not been identified. In addition, I am unable to distinguish between the inner, whiter cone, and the outer, dark blue cone. I think it has to do with how I sample the colors and the regions of interest with roipoly
but I am not sure how I can improve it. Do you have any tips on how I can improve the segmentation for this specific application?
回答1:
The boundary is not perfectly, hopefully you can start from here...
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)
回答2:
Solution II
I just noticed the link you provided in your question. I have to say that the clustering method in that example is better suit for 'pure' color distributions. Your image includes pretty much ambiguous boundaries between different colors, so the segmentation heavily depends on how you label the region coordinates.
Remove load regioncoordinates;
, change nColors = 4;
, then added the coordinates below at the beginning of your code:
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];
Keep everything else in your code unchanged, only display from figure(1)
to figure(5)
, the segmentation result will be:
It basically looks good except the red region. To improve the accuracy, you may provide more 'training samples' of that part. You can try roipoly(flame)
before you run your code. An interactive figure tool will be shown for your to draw a polygon in the image, you can roughly draw the shape of red region you want, then save the coordinates as one of the region_coordinates
. One thing you may pay attention to is, you need to make the edge number of all the polygons for other colors size(region_coordinates,1)
来源:https://stackoverflow.com/questions/21668687/a-few-questions-about-color-segmentation-with-lab