From: Kenneth Galea on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <4e2e9862-9014-476e-95b7-db349024b01e(a)h2g2000yqj.googlegroups.com>...
> Look at the color detection demo - it has right in there some code to
> threshold a range. You'd do something like
>
> tolerance = 2; % Gray levels.
> binaryImageRed = (subtractedImageRed < tolerance) &
> (subtractedImageRed > tolerance);
> same for green and red, then and them together
> binaryImage = binaryImage Red & binaryImageGreen & binaryImageBlue;
>
> labeledImage = bwconncomp(binaryImage);
> measurements = regionprops(labeledImage);
>
> Or, for divided images,
> tolerance = 0.2; % Gray levels.
> binaryImageRed = (dividedImageRed < (1.0 - tolerance)) &
> (dividedImageRed > (1+tolerance));
> etc.
>
> You'll have to subtract or divide every color channel one at a time.
> redPlane = double(rgbImage(:, :, 1));
> greenPlane = double(rgbImage(:, :, 2));
> bluePlane = double(rgbImage(:, :, 3));
> do this for both your test image, and your background image, so that
> you have two red images, two green images, and two blue images. Then
> subtract or divide them.

Actually previously I left something out. This is my actual code:
background = imread('C:\Users\Kenneth\Desktop\test3.jpg');
test = imread('C:\Users\Kenneth\Desktop\test3.jpg');
redPlane_test = double(test(:, :, 1));
greenPlane_test = double(test(:, :, 2));
bluePlane_test = double(test(:, :, 3));

redPlane_background = double(background(:, :, 1));
greenPlane_background = double(background(:, :, 2));
bluePlane_background = double(background(:, :, 3));

subtractedImageRed = redPlane_test - redPlane_background;
subtractedImageGreen = greenPlane_test - greenPlane_background;
subtractedImageBlue = bluePlane_test - bluePlane_background;

tolerance = 2;
binaryImageRed = (subtractedImageRed < tolerance) & (subtractedImageRed > tolerance);
binaryImageGreen = (subtractedImageGreen < tolerance) & (subtractedImageGreen > tolerance);
binaryImageBlue = (subtractedImageBlue < tolerance) & (subtractedImageBlue > tolerance);

binaryImage = binaryImageRed & binaryImageGreen & binaryImageBlue

imshow(binaryImage)

But I'm still obtaining a black image instead of white:/

Thanks
Kenneth
From: ImageAnalyst on
Kenneth:
The problem is that you don't have good control over your exposure and
didn't do the background correction like I suggested. The background
in these two photos is way different. I also had an error in my code
(I hadn't tested it) - you need -tolerance and | instead of &. I
fixed that and got a little futher but it's still not good. You'll
probably get better luck if you do background division instead of
subtraction. I didn't code that up for you. I figure you can do
that, but here's some slightly improved subtraction code (that still
is not optimal). Seriously, try the background division. Background
subtraction won't work if the backgrounds are different brightnesses.
But not only do you have differences in background overall intensity,
but you also have differences in the PATTERN of the illumination, and
this is really what's killing you.


clc;
clear all;
close all;
workspace;

background = imread('C:\Documents and Settings\Kenneth\My Documents
\Temporary stuff\test3.jpg');
subplot(3,3, 1);
imshow(background);
set(gcf, 'Position', get(0, 'ScreenSize')); % Maximize figure.
title('Background Image');

testImage = imread('C:\Documents and Settings\Kenneth\My Documents
\Temporary stuff\test.jpg');
subplot(3,3, 2);
imshow(testImage);
title('Test Image');

redPlane_test = double(testImage(:, :, 1));
greenPlane_test = double(testImage(:, :, 2));
bluePlane_test = double(testImage(:, :, 3));

redPlane_background = double(background(:, :, 1));
greenPlane_background = double(background(:, :, 2));
bluePlane_background = double(background(:, :, 3));


subtractedImageRed = redPlane_test - redPlane_background;
subtractedImageGreen = greenPlane_test - greenPlane_background;
subtractedImageBlue = bluePlane_test - bluePlane_background;
subplot(3,3, 3);
imshow(subtractedImageRed, [])
title('Subtracted Red');


tolerance = 20;
binaryImageRed1 = (subtractedImageRed < -tolerance) ;
subplot(3,3, 4);
imshow(binaryImageRed1, []) ;
title('Dark things');
binaryImageRed2 =(subtractedImageRed > tolerance);
subplot(3,3, 5);
imshow(binaryImageRed2, []);
title('Bright things');

binaryImageRed = (subtractedImageRed < -tolerance) |
(subtractedImageRed > tolerance);
binaryImageGreen = (subtractedImageGreen < -tolerance) |
(subtractedImageGreen > tolerance);
binaryImageBlue = (subtractedImageBlue < -tolerance) |
(subtractedImageBlue > tolerance);


binaryImage = binaryImageRed & binaryImageGreen & binaryImageBlue ;
subplot(3,3, 6);
imshow(binaryImage)
title('Both Dark and Bright things');
From: Kenneth Galea on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <aba0c951-40a2-4f05-b3e8-b2da7585044e(a)v5g2000vbb.googlegroups.com>...
> Kenneth:
> The problem is that you don't have good control over your exposure and
> didn't do the background correction like I suggested. The background
> in these two photos is way different. I also had an error in my code
> (I hadn't tested it) - you need -tolerance and | instead of &. I
> fixed that and got a little futher but it's still not good. You'll
> probably get better luck if you do background division instead of
> subtraction. I didn't code that up for you. I figure you can do
> that, but here's some slightly improved subtraction code (that still
> is not optimal). Seriously, try the background division. Background
> subtraction won't work if the backgrounds are different brightnesses.
> But not only do you have differences in background overall intensity,
> but you also have differences in the PATTERN of the illumination, and
> this is really what's killing you.
>
>
> clc;
> clear all;
> close all;
> workspace;
>
> background = imread('C:\Documents and Settings\Kenneth\My Documents
> \Temporary stuff\test3.jpg');
> subplot(3,3, 1);
> imshow(background);
> set(gcf, 'Position', get(0, 'ScreenSize')); % Maximize figure.
> title('Background Image');
>
> testImage = imread('C:\Documents and Settings\Kenneth\My Documents
> \Temporary stuff\test.jpg');
> subplot(3,3, 2);
> imshow(testImage);
> title('Test Image');
>
> redPlane_test = double(testImage(:, :, 1));
> greenPlane_test = double(testImage(:, :, 2));
> bluePlane_test = double(testImage(:, :, 3));
>
> redPlane_background = double(background(:, :, 1));
> greenPlane_background = double(background(:, :, 2));
> bluePlane_background = double(background(:, :, 3));
>
>
> subtractedImageRed = redPlane_test - redPlane_background;
> subtractedImageGreen = greenPlane_test - greenPlane_background;
> subtractedImageBlue = bluePlane_test - bluePlane_background;
> subplot(3,3, 3);
> imshow(subtractedImageRed, [])
> title('Subtracted Red');
>
>
> tolerance = 20;
> binaryImageRed1 = (subtractedImageRed < -tolerance) ;
> subplot(3,3, 4);
> imshow(binaryImageRed1, []) ;
> title('Dark things');
> binaryImageRed2 =(subtractedImageRed > tolerance);
> subplot(3,3, 5);
> imshow(binaryImageRed2, []);
> title('Bright things');
>
> binaryImageRed = (subtractedImageRed < -tolerance) |
> (subtractedImageRed > tolerance);
> binaryImageGreen = (subtractedImageGreen < -tolerance) |
> (subtractedImageGreen > tolerance);
> binaryImageBlue = (subtractedImageBlue < -tolerance) |
> (subtractedImageBlue > tolerance);
>
>
> binaryImage = binaryImageRed & binaryImageGreen & binaryImageBlue ;
> subplot(3,3, 6);
> imshow(binaryImage)
> title('Both Dark and Bright things');

Hi
Is it better to use thresholding like you did in your demo??

i.e. something like the following?

binaryImageRed= (subtractedImageRed >= redThresholdLow) | (subtractedImageRed <= -redThresholdHigh);
binaryImageGreen = (subtractedImageGreen >= greenThresholdLow) | (subtractedImageGreen <= -greenThresholdHigh);
blinaryImageBlue = (subtractedImageBlue >= -blueThresholdLow) | (subtractedImageBlue <= -blueThresholdHigh);

Also if I ensure that illumination is the same in both images (i.e. when having objects and no objects) the problem is still persisting with subtraction. Hopefully with division I might get it right !!
From: ImageAnalyst on
Kenneth:
You could do it that way, bit if you do then you'd be thresholding for
the background. That's fine, but then you have to invert it to get
the mask for the objects. But that's easy, just do
binaryImage = ~binaryImage;

From: Kenneth Galea on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <e898f069-d53a-4348-a178-77e37c88c21e(a)z26g2000yqm.googlegroups.com>...
> Kenneth:
> You could do it that way, bit if you do then you'd be thresholding for
> the background. That's fine, but then you have to invert it to get
> the mask for the objects. But that's easy, just do
> binaryImage = ~binaryImage;

Hi. Finally I got it right using subtraction and ensuring that illumination is the same!! Yes I used equals instead of binaryImage = ~binaryImage. Does it make a difference?
i.e. for example:
binaryImageRed = (subtractedImageRed <= -redThresholdHigh) |(subtractedImageRed >= redThresholdLow);
Both of them gave the same result except the inversion of colour (i.e. objects are black and background is white when not using =~) . Thanks a lot for your help since without your help I surely wouldn't have managed :) Just one last thing. I can't understand the meanings behind these values in your demo code (which I had to use and I really need to understand) :

redThresholdLow = graythresh(subtractedImageRed);
redThresholdHigh = 255;
greenThresholdLow = 0;
greenThresholdHigh = graythresh(subtractedImageGreen);
blueThresholdLow = 0;
blueThresholdHigh = graythresh(subtractedImageGreen);

Thanks again
Kenneth