1、YUV422转RGB
#include <opencv2/opencv.hpp>
#define TUNE(r) ( r < 0 ? 0 : (r > 255 ? 255 : r) )
void YUVptr2RGBmat(unsigned char* pYUV, int width, int height, cv::Mat& RGBmat)
{
RGBmat.create(cv::Size(width, height), CV_8UC3);
unsigned char* pRGB = RGBmat.data;
unsigned char y, u, v, y1;
int r, g, b;
int size = width * height;
unsigned int i = 0;
unsigned int loop = size >> 1;
while (loop-- > 0)
{
y = *pYUV; pYUV++;
u = *pYUV; pYUV++;
y1 = *pYUV; pYUV++;
v = *pYUV; pYUV++;
r = 1.164 * (y - 16) + 1.596 * (v - 128);
g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.392 * (u - 128);
b = 1.164 * (y - 16) + 2.017 * (u - 128);
*pRGB = TUNE(r); pRGB++;
*pRGB = TUNE(g); pRGB++;
*pRGB = TUNE(b); pRGB++;
r = 1.164 * (y1 - 16) + 1.596 * (v - 128);
g = 1.164 * (y1 - 16) - 0.813 * (v - 128) - 0.392 * (u - 128);
b = 1.164 * (y1 - 16) + 2.017 * (u - 128);
*pRGB = TUNE(r); pRGB++;
*pRGB = TUNE(g); pRGB++;
*pRGB = TUNE(b); pRGB++;
}
}
int main()
{
// YUV文件的路径
std::string yuvFilePath = "E:\\嵌入式\\YUV422data\\01_1920x1080.yuv";
// 打开YUV文件
std::ifstream yuvFile(yuvFilePath, std::ios::binary);
if (!yuvFile.is_open())
{
std::cerr << "Failed to open YUV file!" << std::endl;
return -1;
}
int width = 1920;
int height = 1080;
int frameSize = width * height * 2;
cv::Mat yuvImage(height, width * 2, CV_8UC1); // w*h*2
yuvFile.read(reinterpret_cast<char*>(yuvImage.data), frameSize);
yuvFile.close();
unsigned char* pYUV = yuvImage.data;
cv::Mat rgbImage;
YUVptr2RGBmat(pYUV, width, height, rgbImage);
return 0;
}
2、YV12转RGB
#include <opencv2/opencv.hpp>
bool YV12ToBGR24_Native(unsigned char* pYUV, int width, int height, cv::Mat& RGBmat)
{
RGBmat.create(cv::Size(width, height), CV_8UC3);
unsigned char* pBGR24 = RGBmat.data;
if (width < 1 || height < 1 || pYUV == NULL || pBGR24 == NULL)
return false;
const long len = width * height;
unsigned char* yData = pYUV;
unsigned char* vData = &yData[len];
unsigned char* uData = &vData[len >> 2];
int bgr[3];
int yIdx, uIdx, vIdx, idx;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
yIdx = i * width + j;
vIdx = (i / 2) * (width / 2) + (j / 2);
uIdx = vIdx;
bgr[0] = (int)(yData[yIdx] + 1.732446 * (uData[vIdx] - 128)); // b分量
bgr[1] = (int)(yData[yIdx] - 0.698001 * (uData[uIdx] - 128) - 0.703125 * (vData[vIdx] - 128)); // g分量
bgr[2] = (int)(yData[yIdx] + 1.370705 * (vData[uIdx] - 128)); // r分量
for (int k = 0; k < 3; k++)
{
idx = (i * width + j) * 3 + k;
if (bgr[k] >= 0 && bgr[k] <= 255)
pBGR24[idx] = bgr[k];
else
pBGR24[idx] = (bgr[k] < 0) ? 0 : 255;
}
}
}
return true;
}
int main()
{
// YV12-->RGB
if (1)
{
// YUV文件的路径
std::string yuvFilePath = "E:\\嵌入式\\YV12Data\\03_1080.yuv";
// 打开YUV文件
std::ifstream yuvFile(yuvFilePath, std::ios::binary);
if (!yuvFile.is_open())
{
std::cerr << "Failed to open YUV file!" << std::endl;
return -1;
}
int width = 1920;
int height = 1080;
int frameSize = width * height * 1.5;
cv::Mat yuvImage(height * 1.5, width, CV_8UC1); // w*h*2
yuvFile.read(reinterpret_cast<char*>(yuvImage.data), frameSize);
yuvFile.close();
unsigned char* pYUV = yuvImage.data;
// cv::Mat rgbImage(height, width, CV_8UC3); // w*h*3
// unsigned char* pRGB = rgbImage.data;
cv::Mat rgbImage;
YV12ToBGR24_Native(pYUV, width, height, rgbImage);
cv::cvtColor(rgbImage, rgbImage, cv::COLOR_RGB2BGR);
cv::imwrite("E:\\嵌入式\\YV12Data\\03_1080_2.jpg", rgbImage);
cv::namedWindow("BGRImage", cv::WINDOW_NORMAL);
cv::resizeWindow("BGRImage", rgbImage.cols * 0.4, rgbImage.rows * 0.4);
cv::imshow("BGRImage", rgbImage);
cv::waitKey(0);
return 0;
}
}