I'm trying to convert an image (originally from QImage) in a RGB/RGBA format (can be changed) to a YUV422 format. My initial intention was to use OpenCV cvtColor to do the work but it does not enable the conversion of RGB/RGBA to 422 format.
I searched for alternatives and even considered to write my own conversion according to this but it would not work fast enough.
I searched for another library to use and found this post but it is relay old and not so relevant.
So my question is what good options do I have for RGB->YUV422 conversions? It would be better if they perform conversions on the GPU instead of the CPU.
Thanks in advance
A simple implementation for OpenCV:
void rgb_to_yuv422_uyvy(const cv::Mat& rgb, cv::Mat& yuv) {
assert(rgb.size() == yuv.size() &&
rgb.depth() == CV_8U &&
rgb.channels() == 3 &&
yuv.depth() == CV_8U &&
yuv.channels() == 2);
for (int ih = 0; ih < rgb.rows; ih++) {
const uint8_t* rgbRowPtr = rgb.ptr<uint8_t>(ih);
uint8_t* yuvRowPtr = yuv.ptr<uint8_t>(ih);
for (int iw = 0; iw < rgb.cols; iw = iw + 2) {
const int rgbColIdxBytes = iw * rgb.elemSize();
const int yuvColIdxBytes = iw * yuv.elemSize();
const uint8_t R1 = rgbRowPtr[rgbColIdxBytes + 0];
const uint8_t G1 = rgbRowPtr[rgbColIdxBytes + 1];
const uint8_t B1 = rgbRowPtr[rgbColIdxBytes + 2];
const uint8_t R2 = rgbRowPtr[rgbColIdxBytes + 3];
const uint8_t G2 = rgbRowPtr[rgbColIdxBytes + 4];
const uint8_t B2 = rgbRowPtr[rgbColIdxBytes + 5];
const int Y = (0.257f * R1) + (0.504f * G1) + (0.098f * B1) + 16.0f ;
const int U = -(0.148f * R1) - (0.291f * G1) + (0.439f * B1) + 128.0f;
const int V = (0.439f * R1) - (0.368f * G1) - (0.071f * B1) + 128.0f;
const int Y2 = (0.257f * R2) + (0.504f * G2) + (0.098f * B2) + 16.0f ;
yuvRowPtr[yuvColIdxBytes + 0] = cv::saturate_cast<uint8_t>(U );
yuvRowPtr[yuvColIdxBytes + 1] = cv::saturate_cast<uint8_t>(Y );
yuvRowPtr[yuvColIdxBytes + 2] = cv::saturate_cast<uint8_t>(V );
yuvRowPtr[yuvColIdxBytes + 3] = cv::saturate_cast<uint8_t>(Y2);
}
}
}
Note this assumes (and checks) RGB as well as YUV422 UYVY flavor. I found this to be quite fast, but obviously it's embarrassingly parallel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With