1

I have a grayscale image,

the dominant colors in the background are shades of white and light gray, I have tried using otsu binarization but it gave no good results, so I decided according to the histogram below to write manually:

img_gray[img_gray > 130] = 255

so all white/gray shades have been converted to white. it worked impressively well, I was wondering is there an efficient way getting this threshold without re-inventing the wheel, I know I can apply: np.bincount(img_gray.ravel()) and try to find the beginning of the ramp before the peak.

enter image description here

Is there any function in openCV which offers something similar to this?

Thank you all!

Community
  • 1
  • 1
JammingThebBits
  • 732
  • 11
  • 31

2 Answers2

2

try using mean and standard deviation. But this will only work as long as you have a single peak

mean,std = cv2.meanStdDev(img_gray) 
low_thresh = mean - (std*2)

or use std*1 if you want a tighter threshold

Ta946
  • 1,342
  • 12
  • 19
  • Thank you for the reply, I know in advance by the nature of the images I will always have two peaks, one small and the other is big. is there another approach? – JammingThebBits May 26 '21 at 11:30
  • 1
    you can probably filter out the small peak then run mean & std, but just thinking about it now, mean & std might not give you the exact location where the peak starts, rather it would give you 68–95–99.7% for 1std, 2std & 3std respectively. I think you'll have a better response asking at the signal processing stackoverflow https://dsp.stackexchange.com/ – Ta946 May 26 '21 at 16:41
1

If you know your images will always have two peaks, maybe you can use the quantiles to filter out the lower peak before calculating your threshold value:

filtered_image = np.where(img_gray > np.quantile(img_gray, 0.2), img_gray, 0)
threshold, thresh_image = cv2.threshold(filtered_image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)

First, filter the lower end of the image using a quantile threshold that works for your images. I used 0.2 in this example. Fine tune the value that removes your first peak. Then, use the OTSU threshold option in your filtered image and get the threshold value close to what you are looking for.

Carlos Melus
  • 1,472
  • 2
  • 7
  • 12