cpp rgb 到 yuv422 的转换

编程入门 行业动态 更新时间:2024-10-21 09:24:01
本文介绍了cpp rgb 到 yuv422 的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试将 RGB/RGBA 格式(可以更改)的图像(最初来自 QImage)转换为 YUV422 格式.我最初的意图是使用 OpenCV cvtColor 来完成这项工作但是不支持RGB/RGBA到422格式的转换.

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.

所以我的问题是对于 RGB->YUV422 转换我有哪些好的选择?如果他们在 GPU 而不是 CPU 上执行转换会更好.

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.

提前致谢

推荐答案

我使用 OpenCL 解决了我的问题,如下:教程:简单开始使用 OpenCL 和 C++

I solved my problem using OpenCL, following this: Tutorial: Simple start with OpenCL and C++

我将转换从 Format_ARGB32_Premultiplied 更改为 YUV422,但它可以轻松更改为任何格式.

I changed the conversion to be Format_ARGB32_Premultiplied to YUV422 but it can be easily changed to any format.

openclwrapper.h:

class OpenClWrapper { public: OpenClWrapper(size_t width, size_t height); ~OpenClWrapper(); void RGB2YUV422(unsigned int * yuvImg, unsigned char * rgbImg); private: std::vector<cl::Platform> m_all_platforms; std::vector<cl::Device> m_all_devices; cl::Platform m_default_platform; cl::Device m_default_device; cl::Context m_context; cl::Program::Sources m_sources; cl::Program m_program; cl::CommandQueue m_queue; cl::Buffer m_buffer_yuv; cl::Buffer m_buffer_rgb; std::string m_kernel_code; size_t m_width; size_t m_height; };

openclwrapper.cpp:

#include "openclwrapper.h" #include <iostream> #include <sstream> OpenClWrapper::OpenClWrapper(size_t width, size_t height) : m_height(height), m_width(width) { //get all platforms (drivers) cl::Platform::get(&m_all_platforms); if(m_all_platforms.size()==0){ std::cout<<" No platforms found. Check OpenCL installation!\n"; exit(1); } m_default_platform=m_all_platforms[0]; //get default device of the default platform m_default_platform.getDevices(CL_DEVICE_TYPE_ALL, &m_all_devices); if(m_all_devices.size()==0){ std::cout<<" No devices found. Check OpenCL installation!\n"; exit(1); } m_default_device=m_all_devices[0]; m_context = *(new cl::Context({m_default_device})); std::ostringstream oss; oss << " void kernel RGB2YUV422(global const unsigned char rgbImg[" << m_height << "][" << m_width << "*4], global unsigned int yuvImg[" << m_height << "][" << m_width << "/2]){ \n" " int x_idx = get_global_id(0); \n" " int y_idx = get_global_id(1)*8; \n" " int alpha1 = rgbImg[x_idx][y_idx+3]; \n" " int alpha2 = rgbImg[x_idx][y_idx+7]; \n" " unsigned char R1 = rgbImg[x_idx][y_idx+2] * (255 / alpha1); \n" " unsigned char G1 = rgbImg[x_idx][y_idx+1] * (255 / alpha1); \n" " unsigned char B1 = rgbImg[x_idx][y_idx] * (255 / alpha1); \n" " unsigned char R2 = rgbImg[x_idx][y_idx+6] * (255 / alpha2); \n" " unsigned char G2 = rgbImg[x_idx][y_idx+5] * (255 / alpha2); \n" " unsigned char B2 = rgbImg[x_idx][y_idx+4] * (255 / alpha2); \n" " unsigned char Y1 = (unsigned char)(0.299000*R1 + 0.587000*G1 + 0.114000*B1); \n" " unsigned char Y2 = (unsigned char)(0.299000*R2 + 0.587000*G2 + 0.114000*B2); \n" " unsigned char U = (unsigned char)(-0.168736*R1-0.331264*G1+0.500000*B1+128);//(0.492*(B1-Y1)); \n" " unsigned char V = (unsigned char)(0.500000*R1-0.418688*G1-0.081312*B1+128);//(0.877*(R1-Y1)); \n" " yuvImg[get_global_id(0)][get_global_id(1)] = (unsigned int)(Y2 << 24 | V << 16 | Y1 << 8 | U); \n" " } "; m_kernel_code = oss.str(); m_sources.push_back({m_kernel_code.c_str(),m_kernel_code.length()}); m_program = *(new cl::Program(m_context,m_sources)); if(m_program.build({m_default_device})!=CL_SUCCESS){ std::cout<<" Error building: "<<m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_default_device)<<"\n"; exit(1); } // create buffers on the device m_buffer_yuv = *(new cl::Buffer(m_context,CL_MEM_READ_WRITE,sizeof(unsigned int)*(m_width*m_height/2))); //each cell is int so it is 4 times the mem nedded, but each pixel is represented by 16 bits m_buffer_rgb = *(new cl::Buffer(m_context,CL_MEM_READ_WRITE,sizeof(unsigned char)*(m_width*m_height*4))); // each pixel is represented by 4 bytes (alpha, RGB) } OpenClWrapper::~OpenClWrapper(){ free(&m_buffer_rgb); free(&m_buffer_yuv); } void OpenClWrapper::RGB2YUV422(unsigned int * yuvImg, unsigned char * rgbImg){ cl::CommandQueue queue(m_context,m_default_device); //write rgb image to the OpenCl buffer queue.enqueueWriteBuffer(m_buffer_rgb,CL_TRUE,0,sizeof(unsigned char)*(m_width*m_height*4),rgbImg); //run the kernel cl::Kernel kernel_yuv2rgb=cl::Kernel(m_program,"RGB2YUV422"); kernel_yuv2rgb.setArg(0,m_buffer_rgb); kernel_yuv2rgb.setArg(1,m_buffer_yuv); queue.enqueueNDRangeKernel(kernel_yuv2rgb,cl::NullRange,cl::NDRange(m_height,(m_width/2)),cl::NullRange); //range is divided by 2 because we have width is represented in integers instead of 16bit (as needed in yuv422). queue.finish(); //read result yuv Image from the device to yuv Image pointer queue.enqueueReadBuffer(m_buffer_yuv,CL_TRUE,0,sizeof(unsigned int)*(m_width*m_height/2),yuvImg); }

更多推荐

cpp rgb 到 yuv422 的转换

本文发布于:2023-11-30 20:44:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1651420.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:cpp   rgb

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!