Ask Your Question

Conversion from BGR to YUV for Nvidia encoder SDK

asked 2019-02-26 10:02:02 -0600

Hi, I am a beginner at OpenCV so, I request you to explain in a very simple way. Here is my code using which I am trying to convert BGR to YUV 444 packed format and writing to a file.

cv::cuda::GpuMat yuvFrame(height, width, CV_8UC3)

cv::cuda::cvtColor(bgrFrame, yuvFrame, cv::COLOR_BGR2YUV);;

fwrite(, 1, width * height * 3, fileWriter);

In COLOR_BGR2YUV, the YUV format is packed YUV 444. I want an output format which is compatible with Nvidia Encoder SDK. When I try to use the YV12 - COLOR_BGR2YUV_YV12 or IYUV - COLOR_BGR2YUV_IYUV, the cvtColor function is giving me some memory exception error (do I need to initialize that GpuMat in a different way? Any code snippet would be helpful).

I could not find conversions from BGR to any of ARGB, ABGR, YUV420, NV12, YUV444 Planar - which are also supported by Nvidia SDK.

edit retag flag offensive close merge delete


Are you sure that conversion is supported by the CUDA modules? I ask because I had a quick look and could not find an implementation or a test of this functionality.

cudawarped gravatar imagecudawarped ( 2019-02-27 04:50:05 -0600 )edit

The conversion from BGR to YUV is supported by cuda. (YUV 444 packed). But I was not able to convert BGR to YV12 or IYUV.

rohith81 gravatar imagerohith81 ( 2019-02-27 07:33:30 -0600 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2019-02-27 09:31:44 -0600

updated 2019-02-27 09:51:15 -0600

Apologies, I see that you are new to OpenCV. Unfortunately not all of the data types and functions supported by OpenCv natively on the CPU are supported by CUDA on the GPU.

I suspect that the functions you require, BGR2YUV_IYUV and BGR2YUV_YV12, whose enums evaluate to conversion code 127 and 131 respectively are not supported in the CUDA implementation.

If you inspect the source, the maximum conversion code is 127 < BGR2YUV_IYUV. Additionally you will notice that in both conversion to //YUV 4:2:0 formats family and //YUV 4:2:2 formats family there are 0's in the mapping from OpenCV colour conversion code to the CUDA implementation.

Both of these things imply to me that there are no corresponding CUDA implementations to or from YUV 4:2:[0|2].

I may be wrong but I ran a quick test from Python and was able to convert successfully COLOR_RGB2YUV_IYUV on the CPU and COLOR_RGB2YUV with CUDA but I got an unsupported error when trying COLOR_RGB2YUV_IYUV in CUDA.

import numpy as np
import cv2 as cv
rgb = np.random.randint(255, size=(1024,1024,3),dtype=np.uint8)
yuv_iyuv = cv.cvtColor(rgb,cv.COLOR_RGB2YUV_IYUV)
# no errors here
cu_rgb = cv.cuda_GpuMat()
cu_yuv = cv.cuda.cvtColor(cu_rgb,cv.COLOR_RGB2YUV)
# still no errors
cu_yuv_IYUV = cv.cuda.cvtColor(cu_rgb,cv.COLOR_RGB2YUV_IYUV)
# error: OpenCV(4.0.0) J:\opencv_contrib\modules\cudaimgproc\src\color.cpp:2103: error: (-206:Bad flag (parameter or structure field)) Unknown/unsupported color conversion code in function 'cv::cuda::cvtColor'

I hope this helps.

I am not sure why you received a memory error instead, which version of OpenCv are you using?

edit flag offensive delete link more


I am using OpenCV 4.0.0. After seeing your comment yesterday, I checked the conversion from bgr to yuv on COLOR_BGR2YUV. I noticed that the process is not using gpu at all. So I assumed that the cuda version is not implemented yet.

rohith81 gravatar imagerohith81 ( 2019-02-28 01:09:45 -0600 )edit

Hi, just to confirm are you saying that your call to cv::cuda::cvtColor(bgrFrame, yuvFrame, cv::COLOR_BGR2YUV); is not using the GPU? If so are you getting any error codes? COLOR_BGR2YUV is implemented in CUDA, COLOR_RGB2YUV_IYUV is not.

cudawarped gravatar imagecudawarped ( 2019-02-28 04:30:06 -0600 )edit

I am not sure about that. I found that, for BGR2YUV, my program works fine but the task manager shows that it is not using any GPU. For the other conversions, My program crashes and gives me a memory exception

rohith81 gravatar imagerohith81 ( 2019-02-28 05:22:28 -0600 )edit

Do other CUDA functions show GPU usage, how are you checking this, for me on Windows 10 it is under GPU 1, and I have to change the drop down to Compute_0. The device usage is very small, it may be more noticeable if you dramatically increase the size of the image. You should definitely see the usage increase if you loop the operation many times, that is from my previous example issue something similar to the following

for i in range(1,1000):
    cu_yuv = cv.cuda.cvtColor(cu_rgb,cv.COLOR_RGB2YUV)
cudawarped gravatar imagecudawarped ( 2019-02-28 06:40:14 -0600 )edit

I will check it again with a large image. However that is not useful for me right now. I have implemented the conversion in cuda myself (NV12->BGR and back) so I will let you know about the GPU implementation when I am free.

rohith81 gravatar imagerohith81 ( 2019-02-28 06:53:53 -0600 )edit

Question Tools

1 follower


Asked: 2019-02-26 10:02:02 -0600

Seen: 3,745 times

Last updated: Feb 27 '19