openCV: adaptive threshold / OTSU threshold issues

Hello wonderful beauties!

I’m starting to get along with OpenCV in Touchdesigner and practicing with some basic operations.

While contour detection, some masking or edge detection work good at the moment, I am encountering some issues when trying working with thresholds.

Specifically binary / to zero / truncation thresholds did not show any problems while writing down the script and importing the code in script TOP, however I did have some issues with trying to work with adaptive/Otsu thresholds.

The error reported in my code is always the same:

'cv2.error: OpenCV(4.8.0) D:\devel\opencv\modules\imgproc\src\thresh.cpp:1555: error: (-2:Unspecified error) in function ‘double __cdecl cv::threshold(const class cv::_InputArray &,const class cv::_OutputArray &,double,double,int)’

THRESH_OTSU mode:
‘src_type == CV_8UC1 || src_type == CV_16UC1’
where
‘src_type’ is 24 (CV_8UC4)’

the related code I am using which gives me back this error is:

import cv2
import numpy as np

def onCook(scriptOp):
	
	#input image
	image = op('flip1').numpyArray()

	gray =  cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	gray =  (image*255).astype(np.uint8)
	blurred = cv2.GaussianBlur(gray, (7, 7), 0)
	
	# apply Otsu's automatic thresholding
	(T, threshInv) = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
	
	scriptOp.copyNumpyArray(threshInv)

Do you have any ideas on why the error is displayed and eventually if there could be any solutions for that?

Beside practicing, I’d like in the future to have more control on preparing the image for further segmentation or for specific object detection based on shape/contour, color/background subtraction.

thank you for any advice you want to share with me!

Hi @Karim_khalou,

not fully sure, but could it be that it’s still 4 channels (rgba) when you are passing in blurred but it actually is expecting a single channel source? Expecting 8UC1 but getting 8UC4?

cheers
Markus

Thank you for your reply @snaut really appreciated it!

when excluding from the code the line referring to thresholds and returning ‘blurred’ as output i can actually see the blurred image with no errors

i also printed the ‘blurred’ and its return keeps repeating the following in textport dat

[[[0 0 0 0]
[0 0 0 0]
[0 0 0 0]

[0 0 0 0]
[0 0 0 0]
[0 0 0 0]]

a few times.
therefore i believe the pixel format for the blurred image is actually an 8UC4 (if i am not wrong but not totally sure).

not sure neither, on how i can convert the pixel format to UC1 in order to feed the image successfully for thresholding according to Otsu/adaptive requirements.

Let me know if anything springs to your mind that can brings light to this dark corner.

Hi @Karim_khalou,

I missed one part in your script:

	gray =  cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	gray =  (image*255).astype(np.uint8)

while in the first line you are converting to a single channel array, the second line uses the original image again to create a uint8. While this works for the gaussian blur, the threshold only allows for single channel inputs…

so changing the script slightly, it works as expected:

import cv2
import numpy as np

def onCook(scriptOp):
	
	# input image from first input
	image = scriptOp.inputs[0].numpyArray()

	# convert to 8bit image
	image = (image*255).astype(np.uint8)

	# convert to grayscale and apply blur
	gray =  cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	blurred = cv2.GaussianBlur(gray, (7, 7), 0)
	
	# apply Otsu's automatic thresholding
	(T, threshInv) = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)

	# reassemble the image, using the thresh result as the alpha channel
	image = cv2.merge([image[:,:,0], image[:,:,1], image[:,:,2], threshInv])
	
	scriptOp.copyNumpyArray(image)

hope this helps
Markus