How to get threshold value from histogram?

前端 未结 3 1416
無奈伤痛
無奈伤痛 2021-02-01 09:08

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 wo

相关标签:
3条回答
  • 2021-02-01 09:34

    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.

    0 讨论(0)
  • 2021-02-01 09:49

    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

    0 讨论(0)
  • 2021-02-01 09:53

    The following is a C++ implementation of Abid's answer that works with OpenCV 3.x:

    // Convert the source image to a 1 channel grayscale:
    Mat gray;
    cvtColor(src, gray, CV_BGR2GRAY);
    // Apply the threshold function with the CV_THRESH_OTSU setting as well
    // You can skip having it return the value, but I include it for showing the
    // results from OTSU
    double thresholdValue = threshold(gray, gray, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU);
    // Present the threshold value
    printf("Threshold value: %f\n", thresholdValue);
    

    Running this against the original image, I get the following:

    OpenCV calculated a threshold value of 122 for it, close to the value Abid found in his answer.

    Just to verify, I altered the original image as seen here:

    And produced the following, with a new threshold value of 178:

    0 讨论(0)
提交回复
热议问题