0

I read an image, and converted it to gray-scale using this function:

def rgb2gray(img):
    if len(img.shape)==3 & img.shape[-1] == 3:  # img is RGB
        return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    return img

now, I try to convert my image to binary using this:

def apply_threshold(img):
    if len(np.unique(img))==2: #img is already binary
        return img
    gray_img=rgb2gray(img)
    _,binary_img=cv2.threshold(gray_img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
return binary_img

but I get this annoying error:

cv2.error: OpenCV(3.4.1) C:\projects\opencv-python\opencv\modules\imgproc\src\thresh.cpp:1406: error: (-215) src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function cv::threshold

I can't understand why since gray_img is for sure gray-scale! I looked at this question, and the top answer by salvador daly proposed that the input picture is not gray-scale, but I checked it multiple times and it for sure is.

Any help will be appreciated!

Binyamin Even
  • 3,318
  • 1
  • 18
  • 45
  • I ran your code with RGB image read in uint8 format. It is working fine without error. – Dinesh Oct 10 '18 at 20:48
  • 1
    Note that the image also has to be `uint8`. You said the image is binary---but what is the `dtype`? You need to cast it: `img = np.uint8(img)` or `img = img.astype(np.uint8)`. Note the error here says nothing about the number of channels, but of the `type` of the image. Also off-topic but in your `rgb2gray` function, you should be using `and`, not `&`. It doesn't matter here, but in general, if you're comparing booleans, use the keywords `and`/`or`. – alkasm Oct 10 '18 at 23:59
  • @AlexanderReynolds thanks! it solved the problem! – Binyamin Even Oct 11 '18 at 11:42

1 Answers1

0

You can try this approach for getting the threshold version/binary image of color image.

""" Read the original image in color form"""
image = cv2.imread(r'image.png') 

""" Convert the image to gray scale"""
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

""" reducing the Noise """
blur = cv2.GaussianBlur(gray, (3,3), 0)

""" Applying Otsu thresholding """
_, thres = cv2.threshold(blur, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)

or if you want adaptive threshold of image, you can try this as well

thres = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY_INV,15,2)

for more details on thresholding you can check this site https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

also you can check whether the image is of color or gray scale version by checking the shape of the channels of image.

  • The color image has 3 channels or 3-D matrix ( Red, Green and Blue) so the dimension of the image matrix will be W x H x C (width x height x channel ) for e.g 300 x 300 x 3
  • The grayscale or binary image has only one channel (gray scale) or it is only 2-D matrix. for e.g 300 x 300.
Vaibhav K
  • 2,762
  • 3
  • 21
  • 22