How to filter an RGB image and transform into an BW one.

I have been trying to do that:
http://prntscr.com/umv66 -> http://goo.gl/Bgmv2 (You can ignore the red lines, I just added them to illustrate the final objective)
So, what I've done in the first case was: I transformed rgb -> hsv and picked up the s channel (a.k.a saturation). Then I used Otsu (called graythresh in matlab) to binarize and transform into a black and white picture. Everything worked perfectly.
Now, in the second case this doesn't work so well:
Base img( http://goo.gl/OtK4G) -> S Channel( http://goo.gl/oo8h6>) ->Otsu( http://goo.gl/cnfxU)
As you can see, the Otsu filter becomes useless in this case. Is there any workaround or other way I should be taking? Thanks in advance!

2 Comments

Is there a particular reason you choose saturation rather than hue?
Yes, hue didn't work, I didn't add an another image to avoid making the post too convoluted with links.
Thanks for the answer!

Sign in to comment.

 Accepted Answer

I think you need to try some noise removal first. You can try a median filter first because it's easy. If that doesn't work, try a bilateral filter or a mean shift filter. After that you should be able to threshold it reasonably well in the Saturation channel. If you look at the image's 3D color gamut you'll see that it is like a slab but it's not radial along a constant hue - it's tilted in the Hue-Saturation plane, so to do the best job of segmentation you'll need to do principal components analysis and find the axis and then threshold in the PC2 or PC3 component. You could do the PCA in either RGB color space or HSV colorspace. However, if you look at it in LAB color space, it's pretty much has a constant "b" value with varying "a" value. So use makecform to convert to lab colorspace and threshold the "a" channel, after noise reduction of course. That would be my recommendation after inspecting the gamut with this.

6 Comments

Thanks! I would like to say that used a few of your scripts already throughout my Matlab life and to thank you for doing them!
That being said, I'm going to research and try everything you recommended. ps: I had already tried a median filter, without success though.
Please take a look at my maze solving application: http://www.mathworks.com/matlabcentral/fileexchange/27175-mazesolution
For your image, try this:
% Demo to threshold maze image based on CIE LAB
clc;
clear
workspace;
format compact
fontSize = 24;
% Read in a standard MATLAB color demo image.
folder = 'C:\Users\Shizuka\Documents\Temporary';
baseFileName = 'fPJ76KR.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% Display the original color image.
subplot(2, 4, 1);
imshow(rgbImage);
title('Original Color Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Convert to LAB color space.
cform = makecform('srgb2lab');
lab = applycform(rgbImage, cform);
lImage = lab(:, :, 1);
aImage = lab(:, :, 2);
bImage = lab(:, :, 3);
% Display them
subplot(2, 4, 2);
imshow(lImage);
title('L Image', 'FontSize', fontSize);
subplot(2, 4, 3);
imshow(aImage);
title('A Image', 'FontSize', fontSize);
subplot(2, 4, 4);
imshow(bImage);
title('B Image', 'FontSize', fontSize);
% Let's compute and display the histogram of the a image.
[pixelCount grayLevels] = imhist(aImage);
subplot(2, 4, 5);
bar(pixelCount);
grid on;
title('Histogram of A image', 'FontSize', fontSize);
xlim([120 170]); % Scale x axis manually.
% Call ImageAnalyst's interactive threshold app.
% [lowThreshold highThreshold lastThresholdedBand] = threshold(140, 255, aImage);
thresholdValue = 255 * graythresh(aImage);
% Binarize the image
binaryImage = aImage > thresholdValue;
% Get rid of small things
binaryImage = bwareaopen(binaryImage, 50);
subplot(2, 4, 6);
imshow(binaryImage);
title('Binarized Bright A Image', 'FontSize', fontSize);
% Show the inverse:
subplot(2, 4, 7);
imshow(~binaryImage);
title('Binarized Dark A Image', 'FontSize', fontSize);
Hoooly moly, I didn't expect the bilateral filter to work, but it did, and PERFECTLY! Thanks a lot! Let me show you the results with everything that you told me and I could figure out: Base image(<http://prntscr.com/umlvu>) --applying bilat filter--> (<http://prntscr.com/uoetd)>.
Now, with the noiseless image, I had a few options that you listed, let me post the results of them: Option 1) rgb2hsv
noiseless = imread('E:\Mazealgorithm\bflt_img2.jpg','jpg');
hsv = rgb2hsv(noiseless);
h = hsv(:, :, 1);
s = hsv(:, :, 2);
v = hsv(:, :, 3);
level = graythresh(h);
BW = im2bw(h,level);
imshow(BW)
imwrite(BW, 'Otsu2.jpg','jpg');
Which produced: http://prntscr.com/uofgg
Option 2)LAB conversion:
colorTransform = makecform('srgb2lab');
lab = applycform(rgbImage, colorTransform);
A_Image = lab(:, :, 2);
imshow(A_Image, []);
level = graythresh(A_Image);
BW = im2bw(A_Image,level);
InvertBW = imcomplement(BW); %%For some reason the image ends up inverted, so I just invert again to get the desired result.
imshow(InvertBW);
imwrite(InvertBW,'whathever.jpg')
Which produced: http://prntscr.com/uofrj
Now, both of those solved my initial problem, even though I preferred the LAB conversion (I mean, it's more 'clean' than the RGB, but I both are equally useful). That being said,
1)I didn't understand what you said about inspecting the gamut.
2)Did you have another solution in mind too? I ask because I want to learn, and I generally like your scripts.
3)Lastly, the bilateral filter is wonderful, but it takes around 10 seconds or so (again, it really is wonderful and there's no real problem about said delay, but I was just wondering, is there any other filter that could solve my problem more efficiently? I tried median and mean shift without success.
MATLAB does not have a gamut inspection tool like ImageJ does. So download imageJ and install it, and download the Color Inspector 3D jar file and put it in the imageJ plugins folder. Then read in an image and run the color plugin on it and you'll get an interactive 3D gamut like this: http://snag.gy/4wkwj.jpg By trying different color spaces and moving the gamut around to see different viewpoints, I determined that the best segmentation would happen in LAB color space.
Try my code. It produces just as good a segmentation as yours and faster, because I didn't do any noise filtering at all because I discovered that all the noise was in the L channel and there was virtually no noise at all in the A and B channel. Just look at the images and you'll see.
Ohh, I apologize, I didn't refresh before my message, and thus didn't see your beautiful solution! It works way better and faster than mine! Thanks a lot :D I have to study it a little more, but I already tested it and it's perfect.
regarding your maze solving script that you linked I was already using it! Ever since I discovered it a few days ago. I told you I love your scripts :P
Thanks a lot again, really, you solved a problem that I had almoost lost all hope!
I do have another question (that one regards the usage of your maze solving script), but I'm going to ask that in another post, because I believe this would be off topic here.
i just want to combine the above features and then have to use PCA for dimension reduction..if anyone know the idea can u please tell

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!