Overload resolution failed: cv2.cuda.cvtColor with stream doesn't like GpuMat

Hello all

I am trying to optimize a bigger project for GPU but got stuck with uploading GpuMat into cv2.cuda.cvtColor in Python. I am quite a newbie, so I apologise in advance.

Here is the code:

import cv2 as cv
import time

input_video_filename = “filename.mp4”

cap = cv.VideoCapture(input_video_filename)

gpu_frame = cv.cuda.GpuMat()
stream = cv.cuda.Stream()

start_time = time.time()

frame_count = 0

while cap.isOpened():

cap.set(cv.CAP_PROP_POS_FRAMES, frame_count)

ret, frame_cpu = cap.read()

if not ret or frame_cpu is None:
    break

print(f'Frame_cpu shape: {frame_cpu.shape}')
print(f'ret status:{ret}')

gpu_frame.upload(frame_cpu, stream)

# Debugging statement to check the type of gpu_frame
print(f"Type of gpu_frame: {type(gpu_frame)}\n\n")

# Ensure gpu_frame is a cv.cuda.GpuMat
if not isinstance(gpu_frame, cv.cuda.GpuMat):
    raise TypeError("gpu_frame is not a cv.cuda.GpuMat")

gpu_gray = cv.cuda.cvtColor(gpu_frame, cv.COLOR_BGR2GRAY, stream)

frame_gray_cpu = gpu_gray.download(stream)

stream.waitForCompletion()

frame_count += 1

end_time = time.time()

print(f"Processing time for stream: {end_time - start_time:.3f} seconds")

And here is the output:

Frame_cpu shape: (1080, 1920, 3)
ret status:True
Type of gpu_frame: <class ‘cv2.cuda.GpuMat’>

Traceback (most recent call last):

gpu_gray = cv.cuda.cvtColor(gpu_frame, cv.COLOR_BGR2GRAY, stream)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

cv2.error: OpenCV(4.10.0) :-1: error: (-5:Bad argument) in function ‘cvtColor’

Overload resolution failed:

  • src is not a numpy array, neither a scalar
  • Expected Ptrcv::cuda::GpuMat for argument ‘dst’
  • Expected Ptrcv::UMat for argument ‘src’

All in all, I have no idea why cv2.cuda.cvtColor doesn’t like the frame I use. I tried to check the parameters of the first argument so they fit those that are provided in the documentation for cvtColor, but gpu_frame.depth() returns 0, and I am having trouble interpreting that.

I am quite in the woods. Please send helpz.

Thanks!

Best thing to do before calling a function is to check out the help for that function. e.g.

help(cv2.cuda.cvtColor)
Help on built-in function cvtColor:

cvtColor(…)
cvtColor(src, code[, dst[, dcn[, stream]]]) → dst
. @brief Converts an image from one color space to another.
.
. @param src Source image with CV_8U , CV_16U , or CV_32F depth and 1, 3, or 4 channels.
. @param dst Destination image.
. @param code Color space conversion code. For details, see cvtColor .
. @param dcn Number of channels in the destination image. If the parameter is 0, the number of the
. channels is derived automatically from src and the code .
. @param stream Stream for the asynchronous version.
.
. 3-channel color spaces (like HSV, XYZ, and so on) can be stored in a 4-channel image for better
. performance.
.
. @sa cvtColor

Looking at the help the cvtColor function is assuming that the third argument you are providing is dst

cvtColor(src, code[, dst[, dcn[, stream]]]) -> dst

which is why you are getting an error as the python bindings try to resolve all the arguments you’ve provided against different valid possibilities without finding a match.

If you want to pass the stream as the third argument then you have to pass it as a named argument. i.e.

gpu_gray = cv.cuda.cvtColor(gpu_frame, cv.COLOR_BGR2GRAY, stream=stream)
1 Like

Yup, that was it. Thank you!