Sarin Suriyakoon
Sarin Suriyakoon

Reputation: 440

Opencv Otsu Thresholding error after use numpy?

In my ex-post I optimize the python iteration loop into numpy way.

Then I face next problem to convert it to binary image like this

def convertRed(rawimg):
    blue = rawimg[:,:,0]
    green = rawimg[:,:,1]
    red = rawimg[:,:,2]
    exg = 1.5*red-green-blue
    processedimg = np.where(exg > 50, exg, 2)
    ret2,th2 = cv2.threshold(processedimg,0,255,cv2.THRESH_OTSU) //error line

    return processedimg

The error is here

error: (-215) src.type() == CV_8UC1 in function cv::threshold

How to solve this problem?

Upvotes: 0

Views: 3470

Answers (2)

Yasin Yousif
Yasin Yousif

Reputation: 967

it is an error of "Data Type" ,

as Eliezer said, when you multiply by 1.5 , the exg matrix convert to float64, which didn't work for cv2.threshold which require uint8 data type ,

so , one of the solutions could be adding:

def convertRed(rawimg):
    b = rawimg[:,:,0]
    g = rawimg[:,:,1]
    r = rawimg[:,:,2]
    exg = 1.5*r-g-b;
    processedimg = np.where(exg > 50, exg, 2)
    processedimg = np.uint8(np.abs(processedimg));#abs to fix negative values,

    ret2,th2 = cv2.threshold(processedimg,0,255,cv2.THRESH_OTSU) #error line

return processedimg

I used np.uint8() after np.abs() to avoid wrong result,(nigative to white ) in the converstion to uint8 data type.

Although , your very array processedimg is positive, because of the np.where statement applied before , but this practice is usually safer.

why it converts to float64? because in python , when multiply any integer value with "float comma" it get converted to float ,

Like :

type(1.5*int(7))==float # true

another point is the usage of numpy functions instead of Opencv's, which is usually faster .

Upvotes: 1

Eliezer Bernart
Eliezer Bernart

Reputation: 2426

The cv2.threshold function only accepts uint8 values, this means that you can only apply Otsu's algorithm if the pixel values in your image are between 0 and 255.

As you can see, when you multiply your values by 1.5 your image starts to present floating point values, making your image not suited for cv2.threshold, hence your error message src.type() == CV_8UC1.

You can modify the following parts of your code:

processedimg = np.where(exg > 50, exg, 2)
processedimg = cv2.convertScaleAbs(processedimg)
ret2,th2 = cv2.threshold(processedimg,0,255,cv2.THRESH_OTSU) //error line

What we are doing here is using the OpenCV function cv2.convertScaleAbs, you can see in the OpenCV Documentation:

cv2. convertScaleAbs

Scales, calculates absolute values, and converts the result to 8-bit.

Python: cv2.convertScaleAbs(src[, dst[, alpha[, beta]]]) → dst

Upvotes: 5

Related Questions