Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get threshold value from histogram?

I'm writing an Android app in OpenCV to detect blobs. One task is to threshold the image to differentiate the foreground objects from the background (see image).

It works fine as long as the image is known and I can manually pass a threshold value to threshold()--in this particular image say, 200. But assuming that the image is not known with the only knowledge that there would be a dark solid background and lighter foreground objects how can I dynamically figure out the threshold value?

I've come across the histogram where I can compute the intensity distribution of the grayscale image. But I couldn't find a method to analyze the histogram and choose the value where the objects of interest (lighter) lies. That is; I want to differ the obviously dark background spikes from the lighter foreground spikes--in this case above 200, but in another case could be say, 100 if the objects are grayish.

enter image description here

like image 612
Tru Avatar asked Jun 29 '12 17:06

Tru


2 Answers

If all your images are like this, or can be brought to this style, i think cv2.THRESHOLD_OTSU, ie otsu's tresholding algorithm is a good shot.

Below is a sample using Python in command terminal :

>>> import cv2
>>> import numpy as np
>>> img2 = cv2.imread('D:\Abid_Rahman_K\work_space\sofeggs.jpg',0)

>>> ret,thresh = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

>>> ret
122.0

ret is the threshold value which is automatically calculated. We just pass '0' as threshold value for this.

I got 124 in GIMP ( which is comparable to result we got). And it also removes the noise. See result below:

enter image description here

like image 111
Abid Rahman K Avatar answered Oct 11 '22 07:10

Abid Rahman K


If you say that the background is dark (black) and the foreground is lighter, then I recommend to use the YUV color space (or any other YXX like YCrCb, etc.), because the first component of such color spaces is luminance (or lightning).

light channel

So after the Y channel is extracted (via the extractChennel function) we need to analyse the histogram of this channel (image):

histogram

See the first (left) hump? It represents dark areas (the background in your situation) on your image. So our aim now is to find a segment (on abscissa, it's red part in the image) that contains this hump. Obviously the left point of this segment is zero. The right point is the first point where:

  • the (local) maximum of histogram is from the left of the point
  • the value of histogram is less than some small epsilon (you can set it to 10)

I drew a green vertical line to show the location of the right point of the segment in this histogram.

And that's it! This right point of the segment is the needed threshold. Here's the result (epsilon is 10 and the calculated threshold is 50):

result

I think that it's not a problem for you to delete the noise in the image above.

like image 33
ArtemStorozhuk Avatar answered Oct 11 '22 08:10

ArtemStorozhuk