Threshold value question using otsu method

I am doing Plant leaf disease detection & classification project. In that i am using otsu method to calculate threshold value for all leaves. But thershold value for some type of leaves could not detect the diseased part correctly..so i am using some constant threshold value(0.17,0.6). Can anyone please give some other method to find threshold value other than otsu method that is suitable for all type of leaves..

 Accepted Answer

See my attached code. I use an image with black background and even black spots inside it. I correctly identify the diseased areas and give the area fraction of them relative to the entire leaf area (diseased + healthy areas).
If this solves your question, please mark as Accepted.

24 Comments

Okay..sure. I will try this code and thank u so much.
It really works..but i want to know one thing.. what about the values 0.5 & 0.15 is it a threshold values,if so how did u select those particular two values to point out the healthy parts????
I looked at the histogram. 0.15 is in the valley between the two humps.
okay. Thank you. And one more doubt sum(~background(:)) and sum(diseasedImage(:)) i can't understand the work of these two statements..what it actually do??? and for some type of leaves the diseased part will be white(background and healthy part will be black) and for some type of leaves the diseased part will be black(background and healthy part will be white).For both these situations area fraction of diseased part will be correctly calculated???
It simply counts the number of white pixels in the image. Just try it and see if it works on all your images. If it doesn't, then you'll have to make the algorithm more sophisticated to handle those cases.
why this kind of result occurs???i mean why that code marks the diseased part with black color for some kind of leaves??
My code assumes that the healthy pixels are green and non-green pixels are diseased. If you have an image where that is not the case, then please attach it, and state what green pixels are labeled as healthy but are actually diseased.
Packiya
Packiya on 5 Jan 2015
Edited: Packiya on 5 Jan 2015
Everything is good.Thank you so much. Do you have any idea about texture features of an image.. In my project finally i need to classify the diseases..Diseases are classified based on the values of texture features called Contrast, Correlation, Homogeneity, Energy.. I have calculated all these values using graycoprops() method.. But these values does not show any big difference for different types of diseases. So you have any idea about these please share that with me.
There are many texture algorithms listed here http://www.visionbib.com/bibliography/contentstwod.html#2-D%20Feature%20Analysis,%20Extraction%20and%20Representations,%20Shape,%20Skeletons,%20Texture, but it sounds like you already have a paper that says what textures are good for plant diseases so I'm surprised that it doesn't work for your images.
Actually I don't have clear idea about this..In the existing paper they were using "minimum distance criterion" classifier. In that, they mentioned "the feature values are compared with the feature library.." If so, all the training image values should be stored in a database??? And the values are varied based on the amount of disease. If i store the values of 10 leaves with the disease amount of some 50,60,70..and if the testing image disease amount some 30 means how can i compare the value of a testing image with the database??
For a blackspot disease on rose leaves, it shows the contrast value 0.2456 and for the rust disease also it shows 0.2489. Then how can i classify the diseases..I am totally confused. So please give me some idea
Do you have any idea????
No, I don't. There are many, many measurements that could be made, and you have to compare a weighted average of them (or some algorithm) to compare to feature vectors of whatever they're trying to match (like reference images in a database).
I worked out your file "SimpleColorDetectionByHue.m". In that meanHSV will be calculated for each blobs. can i try this for my project? if so the area of diseased part will be varied? how can i find the meanHSV for the whole leaf?
Yes, you can. Just use the healthy and diseased masks to get the mean HSV value of the image in the mask area
meanHealthyH = mean(h(healthyMask));
meanHealthyS = mean(s(healthyMask));
meanHealthyV = mean(v(healthyMask));
meanDiseasedH = mean(h(diseasedMask));
meanDiseasedS = mean(s(diseasedMask));
meanDiseasedV = mean(v(diseasedMask));
Thank you. And one more help. I need a image data set for diseased leaves. Where from i can download it?
Whoever is sponsoring your project should be able to provide those. If someone is paying you to do this project then they must have a need for whatever software you deliver, so they must have diseased leaves. Obtain them from that person or organization.
Packiya
Packiya on 23 Jan 2015
Edited: Packiya on 23 Jan 2015
Thank you. Feature values like contrast, energy are not fully work to my project. So i am segmenting the images based on color using "SimpleColorDetectionByHue.m". In that, image is segmented into blobs based on the feature(diseased parts). And each blop have varying size. For Example one blob contains 2789 Pixels and it shows mean value for H,S,V as 0.12,0.31,0.45. And another blob contains only 161 pixels. so it shows some bigger value like 0.63,0.71,0.56. But i want some same values with only little bit difference between blobs in one leaf. For that i need to process some constant number of pixels from all the blobs. How can i do this?
Why do you say "i need to process some constant number of pixels from all the blobs."? I don't think that is necessary.
By the way, the method I used in my demo above - segmentation by thresholding in HSV color space - is the same one I use in my "SimpleColorDetectionByHue.m" tutorial.
But based on the number of pixels of blobs, the mean value will varied? what i have to do now?
What? Why???? No it won't. Why do you think the mean of a region depends on how many pixels are in that region?
Packiya
Packiya on 30 Jan 2015
Edited: Packiya on 30 Jan 2015
sorry..That's my mistake. Now i understood it fully. It really helps to me. Thank you very much for kindly guiding me.
Forgive me for interrupting your discussion...
i'm bit confused when you choose 0.15 and 0.5 as healthy image...
"I looked at the histogram. 0.15 is in the valley between the two humps." this is from your previous answer..
can you explain more what if the graph only have one humps if 0 until 0.3.. what value i one to pick as healty image?
For your image (which you forgot to attach), it seems like the hue is not a feature that will have discriminating power. You should probably choose another feature, like maybe saturation or value or texture.

Sign in to comment.

More Answers (4)

Show us an image! Without an image, it's very difficult if not impossible to guess at what you need.
Have you tried the multilevel otsu threshold? I.e. the Image Processing function imquantize?

7 Comments

Bacterial1.jpg-- for this image otsu method correctly detects the disease.. blackrot14.jpg-- for this image it shows the whole image as diseased one.
Only use otsu to identify the object, i.e. the whole leaf. Use other methods to detect the rot.
I don't know who thought of photographing a green leaf on a green background, but it's a bad idea. Photograph them on a black background.
Actually i want to display the diseased part as either white(background and healthy part of leaf becomes black) or black(background and healthy part of leaf becomes white)..If i set the background as black means,then the both the diseased part and the background becomes white..In this case, the background also considered as a diseased part..so in order to avoid this, i set the background color as green..
Packiya
Packiya on 30 Dec 2014
Edited: Packiya on 30 Dec 2014
In the "black_background" both diseased part & the background part becomes white..so i could't say that the white part is a diseased part..but if i set the background as green i can point out the white part as a diseased part("green_background")..and i used that resultant image for further processing..in the next step i am splitting that resultant image into equal sized blocks.And then i counted the no. of blocks having either value 1(white)(background & healthy part-black) or value 0(black)(background & healthy part - white) in order to level the disease. so only i set the background as green.
No, that's not true. Or it's only true if you don't do it the way you're supposed to do it. With your way, you can't find the area of the leaf so you can't get area fractions.
First of all you segment for black. But you only want black if it's connected to the background, not if, say, there is a hole in the leaf due to disease, so you call imclearborder() and subtract that from the first binary image to get only the black connected to the border. Now mask your image and convert to hsv color space. Then define some hue sector that is "green" and sum the pixels in this sector - that's your green area. The rest of the pixels that aren't green and aren't part of the background are "disease". See my color segmentation routines, probably the HSV one would be best, in my File Exchange. Let me know if you need further help.
A clarification - the function to use for multilevel Otsu is multithresh . It outputs the threshold level(s). If required, the image can then be quantized using those thresholds using imquantize.

Sign in to comment.

I almost never use Otsu. It's usually no good. It's good mostly in cases with high contrast images with widely separated bimodal histograms, like where there is a uniform object on a uniform background and they have very different intensities. In real world situations, Otsu is often/usually not the best choice.
Actually using a fixed threshold like you're doing is a very good but under-used and under-appreciated method. People always want to use automatic thresholding but simple-minded autothresholding methods like Otsu have the drawback in that they always have to find a threshold somewhere in the histogram. Let's say you're looking at some image and the disease or stuff you want to find can be anywhere from 0% area fraction all the way up to 100% area fraction. Let's say you have a hump centered at 100 for good/normal/non-diseased pixels, and as the pixel goes "bad" the pixels get darker, which means their histogram shifts darker. Let's say one that was 100% bad would give you a hump at 50 gray levels. But what if you had a 100% bad image and Otsu would try to split that histogram and might give you something around 48 or 55 or whatever. It would give you the wrong area fraction because it was forced to find a threshold in a histogram hump that was essentially all the same - all bad. It would be much better to just say that anything below, say, 75 is bad and above 75 is good. That way you can get accurate area fractions all the way from 0% to 100%. If you have good control over your lighting and exposure so that similar images produce similar gray levels, then using a fixed threshold is a fine idea.
But in general, you need to decide upon a thresholding scheme based on the complete range of images that you expect to encounter. You haven't shown us even a single image, much less the entire span of images you expect the algorithm to be able to handle. Usually people asking for image processing advice attach an image to we don't have to work "blind."

1 Comment

I agree that fixed thresholds are useful, especially for x-rays where the pixel values are a direct measure of energy passing through.
However, Otsu is appealing too for images where there is an object in the foreground and a background. It can do a good job dealing with changes in lighting etc.

Sign in to comment.

I haven't read the entire thread above. I'm sure there's a lot of good information there. I take it you are trying to threshold the 'diseased' portion of the leaf. So, essentially you want an image with disease pixels vs non-disease pixels.
I tried using the colorThresholder App with a couple of the images you've attached.
Here's how it looks:
im = imread('http://www.mathworks.com/matlabcentral/answers/uploaded_files/23137/Bacterial1.jpg');
% Open the colorThresholder
colorThresholder(im)
The hue channel in the HSV color space seems to separate the disease pretty well, so select HSV. Once the image opens in the HSV color space, move the hue slider appropriately to threshold the image.
Now export the code and use this on the other images.
Hope this helps!
thanks and it is very helpful for my project, but I had some problem, which is if the image of the leaf is healthy, through the code above, I had got the healthy region and diseases region. may I know is there any code that able to choose the image of leaf whether it is healthy or not. thanks

1 Comment

No, that is the part that you need to do yourself, or hire someone to do. But once they've all been analyzed, and you have a boolean variable "isDiseased", then you can find the index of diseased ones, something like this
for k = 1 : length(isDiseased)
if ~isDiseased
continue; % Skip healthy ones.
end
thisFileName = allFileNames{k};
imshow(thisFileName);
drawnow;
end

Sign in to comment.

Categories

Find more on Agriculture 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!