Thread Subject: Matlab and Otsu Thresholding query

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 11:19:05

Message: 1 of 27

Hello everyone.

I have a problem regarding thresholding of an image. I'm using Otsu's thresholding method by the command level = graythresh(I) where a threshold is determined according to the image.
Now my problem is that when I have a white backround with a black ruler for example the object is detected perfectly while the background is recognised as background. However when I remove the ruler such that the image detected should be white (i.e. i.e. thresholding is supposed to detect no objects) , lots of gray areas are detected as part of my image:/
How can I eliminate these gray areas??

Thanks
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 11:42:40

Message: 2 of 27

Kenneth :
That's not true. That method forces a threshold to be chosen. In
cases like these, you don't use an automatic threshold, you use a
fixed threshold. You need to do this in conjunction with intensity
correction. This will solve your problem.
-ImageAnalyst

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 11:57:20

Message: 3 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <cce067d5-87e1-4435-9ec8-f8a114c7c816@21g2000yqj.googlegroups.com>...
> Kenneth :
> That's not true. That method forces a threshold to be chosen. In
> cases like these, you don't use an automatic threshold, you use a
> fixed threshold. You need to do this in conjunction with intensity
> correction. This will solve your problem.
> -ImageAnalyst
Hi thanks for your reply.

But how can I use a fixed threshold if my objects have different colours?

Thanks

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 12:40:09

Message: 4 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <cce067d5-87e1-4435-9ec8-f8a114c7c816@21g2000yqj.googlegroups.com>...
> Kenneth :
> That's not true. That method forces a threshold to be chosen. In
> cases like these, you don't use an automatic threshold, you use a
> fixed threshold. You need to do this in conjunction with intensity
> correction. This will solve your problem.
> -ImageAnalyst

What I mean is that I will have one object at a time in my image ...but the objects have different colours and not necessarily all black..that's why I was using an automatic threshold!!! Initally I used a fixed threshold for example 0.5 but it was not always suitable for differnt coloured objects :( With automatic threshold it was great till unfortunately I met this problem! Is there a solution to this?
Regards
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 13:01:47

Message: 5 of 27

Well then you might have to do more complicated things than
thresholding, such as color classification. See my simple demo here:
http://www.mathworks.com/matlabcentral/fileexchange/26420-simplecolordetection
Actually this color detection demo is so simple that it just uses
thresholding, but on all three color planes and then combines them.
So it's basically chopping out a rectangular gamut out of the 3D RGB
color space. There are more sophisticated color classification method
that can be done if necessary. But you can do this type of thing to
detect your background color and then everything not background will
be foreground (your objects).

If you are able to choose your background color then you might be able
to get your object mask just by looking at a particular color plane,
or by subtracting or dividing your test image by a reference (blank)
background image that has nothing in it except the background (no
objects present).

There are even more methods but we can't get into all possbilities of
methods. It would be best if you posted some images (such as to
http:://drop.io which is the easiest) that illustrate the thresholding
difficulties you are having.

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 13:29:04

Message: 6 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <c8eeb205-2cbb-4f95-a108-feeb4c668a14@l26g2000yqd.googlegroups.com>...
> Well then you might have to do more complicated things than
> thresholding, such as color classification. See my simple demo here:
> http://www.mathworks.com/matlabcentral/fileexchange/26420-simplecolordetection
> Actually this color detection demo is so simple that it just uses
> thresholding, but on all three color planes and then combines them.
> So it's basically chopping out a rectangular gamut out of the 3D RGB
> color space. There are more sophisticated color classification method
> that can be done if necessary. But you can do this type of thing to
> detect your background color and then everything not background will
> be foreground (your objects).
>
> If you are able to choose your background color then you might be able
> to get your object mask just by looking at a particular color plane,
> or by subtracting or dividing your test image by a reference (blank)
> background image that has nothing in it except the background (no
> objects present).
>
> There are even more methods but we can't get into all possbilities of
> methods. It would be best if you posted some images (such as to
> http:://drop.io which is the easiest) that illustrate the thresholding
> difficulties you are having.
Hi thanks for your reply
This link shows my problems http://drop.io/objectthreshold
With objects thresholding is perfect. Without objects (but exactly the same background) thresholding is sick :/ as you can see. Complications are what I really need to eliminate unfortunately :/
Thanks

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 13:40:13

Message: 7 of 27

Well the shadows are going to cause you a problem because it won't
know if you want to consider shadows an object or not. They're simply
a different color than the background, just like everything else in
the photo.

But your problem is that you're thresholding before background
correction. You want to threshold AFTER you get the background
corrected image.

First of all, convert the images to floating point. Then either
subtract or divide your test image by your background image. It's at
THIS point that you threshold. Actually you'll have two thresholds,
for subtraction, everything less than some negative tolerance or
greater than a positive tolerance will be foreground (bitand()those
two thresholded images together), or
for division, everything less than (1.0 - some tolerance) or greater
than (1 + some tolerance) will be foreground (bitand() those two
thresholded images together).

Then call label, and call regionprops. You might want to do a little
clean up either before of after thresholding, such as small object
removal (use bwareaopen) or hole filling (imfill), or boundary
smoothing (imclose), etc.

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 13:58:04

Message: 8 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <02124bab-d7f0-4848-ba04-7f17b82d0ea0@f11g2000yqm.googlegroups.com>...
> Well the shadows are going to cause you a problem because it won't
> know if you want to consider shadows an object or not. They're simply
> a different color than the background, just like everything else in
> the photo.
>
> But your problem is that you're thresholding before background
> correction. You want to threshold AFTER you get the background
> corrected image.
>
> First of all, convert the images to floating point. Then either
> subtract or divide your test image by your background image. It's at
> THIS point that you threshold. Actually you'll have two thresholds,
> for subtraction, everything less than some negative tolerance or
> greater than a positive tolerance will be foreground (bitand()those
> two thresholded images together), or
> for division, everything less than (1.0 - some tolerance) or greater
> than (1 + some tolerance) will be foreground (bitand() those two
> thresholded images together).
>
> Then call label, and call regionprops. You might want to do a little
> clean up either before of after thresholding, such as small object
> removal (use bwareaopen) or hole filling (imfill), or boundary
> smoothing (imclose), etc.

That sounds great. However I'm not up to standard to certain things you said such as what I have to do before thresholding :) Labelling, regionprops, small object removal hole filling and boundary smoothing are all done. Can you please show me a simple code (few lines) of how to achive floating point conversion, subtraction/division and dealing of the two thresholds before finally thresholding automatically.
Thanks again
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 14:05:28

Message: 9 of 27

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.

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 14:57:04

Message: 10 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <4e2e9862-9014-476e-95b7-db349024b01e@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.

I understood the concept. You are great. I tried it out but I'm having a minor problem. Maybe a small error in my code. This is my 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));

binaryImageRed = redPlane_test - redPlane_background;
binaryImageGreen = greenPlane_test - greenPlane_background;
binaryImageBlue = bluePlane_test - bluePlane_background;
binaryImage = binaryImageRed & binaryImageGreen & binaryImageBlue

imshow(binaryImage)

In this case since my test image is background (to check if it becomes white) it's becoming totally black:/ It's surely a small bug in my code grrr!! Pls help

Thanks
Kenneth

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 15:07:05

Message: 11 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <4e2e9862-9014-476e-95b7-db349024b01e@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

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 16:06:13

Message: 12 of 27

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');

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 17:20:21

Message: 13 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <aba0c951-40a2-4f05-b3e8-b2da7585044e@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 !!

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 17:27:27

Message: 14 of 27

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;

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 17:54:03

Message: 15 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <e898f069-d53a-4348-a178-77e37c88c21e@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

  

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 18:45:07

Message: 16 of 27

"Kenneth Galea" <k.galea@hotmail.com> wrote in message <hkhlvr$s4q$1@fred.mathworks.com>...
> ImageAnalyst <imageanalyst@mailinator.com> wrote in message <e898f069-d53a-4348-a178-77e37c88c21e@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

I'm asking just because I didn't include the other part of your demo code after it and it still worked:
i.e. I didn't include the following:
                redThresholdLow = uint8(redThresholdLow * 255);
greenThresholdHigh = uint8(greenThresholdHigh * 255);
blueThresholdHigh = uint8(blueThresholdHigh * 255);

Since when adding the latter part of code to the other part where graythresh was used it didn't work... strange !!
>thanks
Kenneth
>

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 19:17:27

Message: 17 of 27

graythresh() computes the Otsu threshold automatically from the
image. Unfortunately, it returns a value in the range of 0-1. I
didn't want this - I wanted the actual gray level so that's why I
multipliled it by 255.

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 19:48:04

Message: 18 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <25d4fe97-a899-4902-ac8d-62caebb220fa@m16g2000yqc.googlegroups.com>...
> graythresh() computes the Otsu threshold automatically from the
> image. Unfortunately, it returns a value in the range of 0-1. I
> didn't want this - I wanted the actual gray level so that's why I
> multipliled it by 255.

Yes ok I understand that.... But why do you use graythresh for low red threshold but graythresh for high blue and green thresholds ?? ...as shown:

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

Thanks
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 5 Feb, 2010 19:59:08

Message: 19 of 27

Because I wanted to select objects that had high red values but low
green and low blue values. Objects that have high red and low green
and blue signal will appear as red in the image. Make sense?

As a counter example if I wanted greenish things, I'd take reds in the
range 0-redThresh, greens in range greenThresh-255, and blues in the
range 0-blueThresh.

If I wanted blue things I'd take pixels having higher blue values and
lower red and green values.
Does that make more sense now?

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 21:08:04

Message: 20 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <43b5892c-04fa-4b61-b1cc-328deeb03719@t1g2000vbq.googlegroups.com>...
> Because I wanted to select objects that had high red values but low
> green and low blue values. Objects that have high red and low green
> and blue signal will appear as red in the image. Make sense?
>
> As a counter example if I wanted greenish things, I'd take reds in the
> range 0-redThresh, greens in range greenThresh-255, and blues in the
> range 0-blueThresh.
>
> If I wanted blue things I'd take pixels having higher blue values and
> lower red and green values.
> Does that make more sense now?

Yes thanks a lot. Now I my problem is that when I subtract a white image from another white image some "salt and pepper nosie is seen". I used medfilt2 but its still not enough. After I used bwareaopen which didn't make any diffenerce even if I consider an area of 50 pixels...don't know why its not working!! Is there another method for this noise removal??

Thanks
Kenneth

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 5 Feb, 2010 23:40:24

Message: 21 of 27

"Kenneth Galea" <k.galea@hotmail.com> wrote in message <hki1bk$ee5$1@fred.mathworks.com>...
> ImageAnalyst <imageanalyst@mailinator.com> wrote in message <43b5892c-04fa-4b61-b1cc-328deeb03719@t1g2000vbq.googlegroups.com>...
> > Because I wanted to select objects that had high red values but low
> > green and low blue values. Objects that have high red and low green
> > and blue signal will appear as red in the image. Make sense?
> >
> > As a counter example if I wanted greenish things, I'd take reds in the
> > range 0-redThresh, greens in range greenThresh-255, and blues in the
> > range 0-blueThresh.
> >
> > If I wanted blue things I'd take pixels having higher blue values and
> > lower red and green values.
> > Does that make more sense now?
>
> Yes thanks a lot. Now I my problem is that when I subtract a white image from another white image some "salt and pepper nosie is seen". I used medfilt2 but its still not enough. After I used bwareaopen which didn't make any diffenerce even if I consider an area of 50 pixels...don't know why its not working!! Is there another method for this noise removal??
>
> Thanks
> Kenneth

Hi sorry to send you again.
 I am having a bit of the same problem again with subtraction. I tried the background division as an alternative method and when I divided the test by background, the images are not even recognisable at that point. So I decided to keep with subtraction method. In this case I'm ensuring that illumination is always the same and from the same position (i'm not moving the camera) and when I compare a test image (containing an object) with the background image its perfect.....however when I compare a white image with another white image taken exactly from the same place with the same amount of light but taken a few seconds later there is a noticable difference since the result is quite a noisy image which sometimes can't be removed by filtering. Why am I still obtaining this difference....it's really frustrating !!!?? Maybe if i'll buy a camera with flash incorporated would it be better?....
since I'm really clueless at this stage:(

Thanks
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 6 Feb, 2010 00:45:24

Message: 22 of 27

Kenneth    
You need to remove noise from your reference (background) image.
Otherwise the noise essentially doubles up because you have noise from
both images and they'll add in quadrature more or less. Imagine that
you had an exposure that was hours long - you wouldn't have any video
noise would you? This is what you want to achieve because this would
represent the "true" illumination pattern. So how can you get that?
Well you could average together a bunch of images to beat down the
noise. Or you could try to run some noise reduction filters on the
image, such as simple averaging or median filters, or more
sophisticated methods like bilateral filters, sigma filters, etc. to
the even more sophisticated methods like "non-local means," BM3D
(http://www.cs.tut.fi/~foi/GCF-BM3D/), UINTA (http://www.cs.utah.edu/
~suyash/pubs/uinta/), K-LLD (http://users.soe.ucsc.edu/~milanfar/
talks/), or many others.

Of course more light is better but you have to have controlled light,
which light from a flash IS NOT. If you do that, heck even if you
don't, you might want to put a standard in your image, such as a gray
scale step wedge running along one edge of your image. Then you can
check that and apply the appropriate intensity correction to your test
image to bring it back to the standard.

Once you've removed the noise from your background, you'll have only
the noise in your image to worry about. You can use the same kind of
techniques there. It really depends on what analysis you want to do
as far as how much effort you need to put into a noise reduction
method. If the simplest works for you, then great. Otherwise try
better ones. Why don't you post your "good, improved" intensity-
corrected images and I'll see what I can do with them this weekend?

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 6 Feb, 2010 00:53:14

Message: 23 of 27

Here's a big list of noise reduction methods, including some with
MATLAB implementations:

http://www.stanford.edu/~slansel/tutorial/software.htm

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 6 Feb, 2010 01:33:02

Message: 24 of 27

Hi
I wanted to post my final code first so that you can easily understand what I did:

background = imread('C:\Users\Kenneth\Desktop\background.jpg');
subplot(3,3, 1);
imshow(background);
set(gcf, 'Position', get(0, 'ScreenSize')); % Maximize figure.
title('Background Image');

testImage = imread('C:\Users\Kenneth\Desktop\test3.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');


redThreshold = graythresh(subtractedImageRed)
greenThreshold = graythresh(subtractedImageGreen)
blueThreshold = graythresh(subtractedImageBlue)

        redThreshold = uint8(redThreshold * 255);
greenThreshold = uint8(greenThreshold * 255);
blueThreshold = uint8(blueThreshold * 255);
    
binaryImageRed1 = (subtractedImageRed < -redThreshold) ;
subplot(3,3, 4);
imshow(binaryImageRed1, []) ;
title('Dark things');
binaryImageRed2 =(subtractedImageRed > redThreshold);
subplot(3,3, 5);
imshow(binaryImageRed2, []);
title('Bright things');

binaryImageRed = (subtractedImageRed < -redThreshold) |(subtractedImageRed > redThreshold);
binaryImageGreen = (subtractedImageGreen < -greenThreshold) | (subtractedImageGreen > greenThreshold);
binaryImageBlue = (subtractedImageBlue < -blueThreshold) | (subtractedImageBlue > blueThreshold);


binaryImage = binaryImageRed & binaryImageGreen & binaryImageBlue ;
binaryImage = ~binaryImage;
subplot(3,3, 6);
imshow(binaryImage)
title('Both Dark and Bright things');

figure
imshow(binaryImage)
binaryImage = im2bw(binaryImage)

filtered_binaryImage = medfilt2(binaryImage);
figure
imshow(filtered_binaryImage)

Link: http://drop.io/thresholdbackground
This link shows what I was trying to work on (N.B. these two images are 2 different background images taken exactly one after each other - everything the same though as I said when subtracting noise is observed as can be seen in the third image "result"). In my opinion, with objects thresholding was better when graythresh was used on a gray image instead of considering red,green and blue. However in the case when there are no objects using the latter method gave better results ...which still need to be improved as you can see in the link.

Regards
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 6 Feb, 2010 03:44:28

Message: 25 of 27

Kenneth
I'm not exactly sure how to respond. With objects in the image and a
blank background you can use a threshold on monochrome images, or use
color classification on color images. With color images, simple color
classification can sometimes be done with thresholding the three color
bands, which will essentially select out a rectangular chunk out of
the 3D rgb color space. You pick a threshold such that it will select
the objects and not select the background. If you can do this with an
auto threshold, such as the Otsu method used by graythresh, then
fine. However a simple auto method (like gray thresh) will force a
threshold to be picked that divides the image into foreground and
background. If you're looking at a picture that has no foreground
because it's all background then it will basically split the
background into two classes (light background and dark background),
which is not what you want. That's why I said to use a fixed
threshold. It will always pick out the proper things regardless of
how large or small the foreground objects are. With an autothreshold
method, the threshold that is picked depends on the area fraction of
the objects in the foreground. If they are of substantial size with
respect to the background it may pick a good threshold value but if
the foreground is too small or nonexistent then it will try to pick a
threshold based on just the background which will of course be
unacceptable.

In your latest case you had no foreground and so the subtraction is
essentially all just noise. Then the autothreshold picked some gray
level right in the midst of that noise and so it picks out the
strongest noise as foreground objects. Obviously you don't want
that. If you're going to have images that range anywhere from big
objects to small objects to no objects, then you're going to have to
have a threshold selection method that will give you the correct
threshold. I've had cases like this and I can tell you that I use a
fixed threshold. You pick a threshold and if there's something above
it, it's an objects. If there's nothing above it there's o objects.
It works for any and all object sizes, from an object that is 100% of
the pixels all the way down to 0% of the pixels. It ALWAYS works,
unlike an autothreshold method which only works well if the foreground
and background can be split into two histogram humps (unless of course
the auto method is smart enough to revert to a fixed threshold when it
recognized that the test image histogram is essentially no different
than the background histogram, but then we're back to the fixed
threshold again.)

So if you want to be completely general I'd stick with a fixed
threshold. But if you're always going to have objects that take up a
substantial portion of the image (like your scissors and pen image)
AND you're going to correct for shading in the background
illumination, then an auto threshold can work. But like I said, it
won't work for the "no objects" case.

Subject: Matlab and Otsu Thresholding query

From: Kenneth Galea

Date: 6 Feb, 2010 08:30:14

Message: 26 of 27

ImageAnalyst <imageanalyst@mailinator.com> wrote in message <5087fb31-67df-4dc6-aee9-2c37024794dd@a13g2000vbf.googlegroups.com>...
> Kenneth
> I'm not exactly sure how to respond. With objects in the image and a
> blank background you can use a threshold on monochrome images, or use
> color classification on color images. With color images, simple color
> classification can sometimes be done with thresholding the three color
> bands, which will essentially select out a rectangular chunk out of
> the 3D rgb color space. You pick a threshold such that it will select
> the objects and not select the background. If you can do this with an
> auto threshold, such as the Otsu method used by graythresh, then
> fine. However a simple auto method (like gray thresh) will force a
> threshold to be picked that divides the image into foreground and
> background. If you're looking at a picture that has no foreground
> because it's all background then it will basically split the
> background into two classes (light background and dark background),
> which is not what you want. That's why I said to use a fixed
> threshold. It will always pick out the proper things regardless of
> how large or small the foreground objects are. With an autothreshold
> method, the threshold that is picked depends on the area fraction of
> the objects in the foreground. If they are of substantial size with
> respect to the background it may pick a good threshold value but if
> the foreground is too small or nonexistent then it will try to pick a
> threshold based on just the background which will of course be
> unacceptable.
>
> In your latest case you had no foreground and so the subtraction is
> essentially all just noise. Then the autothreshold picked some gray
> level right in the midst of that noise and so it picks out the
> strongest noise as foreground objects. Obviously you don't want
> that. If you're going to have images that range anywhere from big
> objects to small objects to no objects, then you're going to have to
> have a threshold selection method that will give you the correct
> threshold. I've had cases like this and I can tell you that I use a
> fixed threshold. You pick a threshold and if there's something above
> it, it's an objects. If there's nothing above it there's o objects.
> It works for any and all object sizes, from an object that is 100% of
> the pixels all the way down to 0% of the pixels. It ALWAYS works,
> unlike an autothreshold method which only works well if the foreground
> and background can be split into two histogram humps (unless of course
> the auto method is smart enough to revert to a fixed threshold when it
> recognized that the test image histogram is essentially no different
> than the background histogram, but then we're back to the fixed
> threshold again.)
>
> So if you want to be completely general I'd stick with a fixed
> threshold. But if you're always going to have objects that take up a
> substantial portion of the image (like your scissors and pen image)
> AND you're going to correct for shading in the background
> illumination, then an auto threshold can work. But like I said, it
> won't work for the "no objects" case.

Hi.
Thanks for your reply. Today I'll decide where to put the camera (in terms of height). My final aim since I haven't told you yet is to move a robotic arm towards any object and then grab them according to the image using what is called a "blind grasp" since no feedback will be given about positions but I just give a position to the arm and it must go exactly to the object (if calibrations are made right). So if I decide to use a fixed threshold let's say 0.9 (since that is what I used if I remember well), my white background will not be detected as object in NO CASE thats right?? But on the other hand, with this fixed threshold, I will be limited to having only dark coloured objects which contrast well from the background.....So from what you said and if what I'm saying above is correct, I think I'll prefer to use a FIXED THRESHOLD with only dark coloured objects to ENSURE that
background is ALWAYS ELIMINATED!! Please correct me if I'm wrong

Thanks
Kenneth

Regards
Kenneth

Subject: Matlab and Otsu Thresholding query

From: ImageAnalyst

Date: 6 Feb, 2010 15:06:45

Message: 27 of 27

Kenneth:
If you have a camera on the end of the arm and moving around to
different parts of your scene (work environment), then the
illumination will not be constant. The lighting will be different,
there will be shadows from parts and equipment, etc. One problem with
your other image was that your objects had intensities that were
darker, brighter, and the same as the background making it difficult
to segment out what you want with simple thresholding. If you can
make all your parts darker and make your background always lighter (or
vice versa) then of course that would be best. But in the real world
there are some things you can control and somethings that are given
and beyond your control. for example in a parts picking operation you
are probably stuck with the parts but may have some control over their
illumination, their placement/orientation on a background, the color
of light used, etc. You may have control over the background, for
example the parts are always placed on a flat conveyor belt, or you
may not have control, for example the parts are to be picked from a
big bin full of parts all touching and randomly oriented. I don't
know your situation but if you're going to be designing a robust
industrial parts robot then you probably can't simply specify that all
your parts are dark, but maybe you can make sure that they're placed
on a really white background. Then you should just use a fixed
threshold. If not, for example it must be on some kind of gray
webbing and the parts are both brighter and darker than the background
then I suggest you look into edge segmentation where you do an edge
detection and then fill in the objects and use that as the mask. You
might have to twiddle with the edge filter parameters to try to get
boundaries as closed and connected as possible.
-ImageAnalyst

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
image processing Kenneth Galea 5 Feb, 2010 06:24:06
thresholding Kenneth Galea 5 Feb, 2010 06:24:06
rssFeed for this Thread
 

MATLAB Central Terms of Use

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Terms prior to use.

Contact us at files@mathworks.com