C++ 在OpenCV中将YUV转换为BGR或RGB
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7954416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting YUV into BGR or RGB in OpenCV
提问by Seb
I have a TV capture card that has a feed coming in as a YUV format. I've seen other posts here similar to this question and attempted to try every possible method stated, but neither of them provided a clear image. At the moment the best results were with the OpenCV cvCvtColor(scr, dst, CV_YUV2BGR)
function call.
我有一个电视采集卡,它有一个 YUV 格式的提要。我在这里看到过类似这个问题的其他帖子,并尝试尝试所有可能的方法,但它们都没有提供清晰的图像。目前最好的结果是使用 OpenCVcvCvtColor(scr, dst, CV_YUV2BGR)
函数调用。
I am currently unaware of the YUV format and to be honest confuses me a little bit as it looks like it stores 4 channels, but is only 3? I have included an image from the capture card to hope that someone can understand what is possibly going on that I could use to fill in the blanks.
我目前不知道 YUV 格式,老实说让我有点困惑,因为它看起来存储 4 个频道,但只有 3 个?我已经包含了捕获卡中的图像,希望有人能够理解可能发生的事情,我可以用它来填补空白。
The feed is coming in through a DeckLink Intensity Pro card and being accessed in a C++ application in using OpenCV in a Windows 7 environment.
该提要通过 DeckLink Intensity Pro 卡进入,并在 Windows 7 环境中使用 OpenCV 的 C++ 应用程序中访问。
Update
更新
I have looked at a wikipedia article regarding this information and attempted to use the formula in my application. Below is the code block with the output received from it. Any advice is greatly appreciated.
我查看了有关此信息的维基百科文章,并尝试在我的应用程序中使用该公式。下面是带有从它接收到的输出的代码块。任何意见是极大的赞赏。
BYTE* pData;
videoFrame->GetBytes((void**)&pData);
m_nFrames++;
printf("Num Frames executed: %d\n", m_nFrames);
for(int i = 0; i < 1280 * 720 * 3; i=i+3)
{
m_RGB->imageData[i] = pData[i] + pData[i+2]*((1 - 0.299)/0.615);
m_RGB->imageData[i+1] = pData[i] - pData[i+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[i+2]*((0.299*(1 - 0.299))/(0.615*0.587));
m_RGB->imageData[i+2] = pData[i] + pData[i+1]*((1 - 0.114)/0.436);
}
采纳答案by Mark Ransom
It looks to me like you're decoding a YUV422 stream as YUV444. Try this modification to the code you provided:
在我看来,您正在将 YUV422 流解码为 YUV444。尝试对您提供的代码进行此修改:
for(int i = 0, j=0; i < 1280 * 720 * 3; i+=6, j+=4)
{
m_RGB->imageData[i] = pData[j] + pData[j+3]*((1 - 0.299)/0.615);
m_RGB->imageData[i+1] = pData[j] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587));
m_RGB->imageData[i+2] = pData[j] + pData[j+1]*((1 - 0.114)/0.436);
m_RGB->imageData[i+3] = pData[j+2] + pData[j+3]*((1 - 0.299)/0.615);
m_RGB->imageData[i+4] = pData[j+2] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587));
m_RGB->imageData[i+5] = pData[j+2] + pData[j+1]*((1 - 0.114)/0.436);
}
I'm not sure you've got your constants correct, but at worst your colors will be off - the image should be recognizable.
我不确定你的常数是否正确,但最坏的情况是你的颜色会消失 - 图像应该是可识别的。
回答by kyencn
In newer version of OPENCV
there is a built in function can be used to do YUV
to RGB
conversion
在较新版本中OPENCV
有一个内置函数可用于YUV
进行RGB
转换
cvtColor(src,dst,CV_YUV2BGR_YUY2);
cvtColor(src,dst,CV_YUV2BGR_YUY2);
specify the YUV
format after the underscore, like this CV_YUYV2BGR_xxxx
指定YUV
下划线后的格式,像这样CV_YUYV2BGR_xxxx
回答by Martin Beckett
The BlackMagic Intensity software return YUVY' format in bmdFormat8BitYUV, so 2 sources pixels are compressed into 4bytes - I don't think openCV's cvtColor can handle this.
BlackMagic Intensity 软件以 bmdFormat8BitYUV 返回 YUVY' 格式,因此 2 个源像素被压缩为 4 个字节 - 我认为 openCV 的 cvtColor 无法处理这个问题。
You can either do it yourself, or just call the Intensity software ConvertFrame() function
您可以自己做,也可以调用 Intensity 软件 ConvertFrame() 函数
edit: Y U V is normally stored as
编辑:YUV 通常存储为
There is a Y (brightness) for each pixel but only a U and V (colour) for every alternate pixel in the row.
每个像素都有一个 Y(亮度),但行中的每个交替像素只有一个 U 和 V(颜色)。
So if data is an unsigned char pointing to the start of the memory as shown above.
所以如果数据是一个无符号字符,指向内存的开始,如上所示。
pixel 1, Y = data[0] U = data[+1] V = data[+3]
pixel 2, Y = data[+2] U = data[+1] V = data[+3]
像素 1,Y = 数据[0] U = 数据[+1] V = 数据[+3]
像素 2,Y = 数据[+2] U = 数据[+1] V = 数据[+3]
Then use the YUV->RGB coefficients you used in your sample code.
然后使用您在示例代码中使用的 YUV->RGB 系数。
回答by cggos
I use the following C++ code using OpenCV to convert yuv data (YUV_NV21) to rgb image (BGR in OpenCV)
我使用以下 C++ 代码使用 OpenCV将 yuv 数据(YUV_NV21)转换为 rgb 图像(OpenCV 中的 BGR)
int main()
{
const int width = 1280;
const int height = 800;
std::ifstream file_in;
file_in.open("../image_yuv_nv21_1280_800_01.raw", std::ios::binary);
std::filebuf *p_filebuf = file_in.rdbuf();
size_t size = p_filebuf->pubseekoff(0, std::ios::end, std::ios::in);
p_filebuf->pubseekpos(0, std::ios::in);
char *buf_src = new char[size];
p_filebuf->sgetn(buf_src, size);
cv::Mat mat_src = cv::Mat(height*1.5, width, CV_8UC1, buf_src);
cv::Mat mat_dst = cv::Mat(height, width, CV_8UC3);
cv::cvtColor(mat_src, mat_dst, cv::COLOR_YUV2BGR_NV21);
cv::imwrite("yuv.png", mat_dst);
file_in.close();
delete []buf_src;
return 0;
}
and the converted result is like the image yuv.png.
转换后的结果就像图像yuv.png。
you can find the testing raw imagefrom hereand the whole projectfrom my Github Project
回答by Temak
Maybe someone is confused by color models YCbCr and YUV. Opencv does not handle YCbCr. Instead it has YCrCb, and it implemented the same way as YUVin opencv.
也许有人对颜色模型 YCbCr 和 YUV 感到困惑。Opencv 不处理YCbCr。相反,它有YCrCb,它的实现方式与opencv 中的YUV 相同。
From the opencv sources https://github.com/Itseez/opencv/blob/2.4/modules/imgproc/src/color.cpp#L3830:
从 opencv 源https://github.com/Itseez/opencv/blob/2.4/modules/imgproc/src/color.cpp#L3830:
case CV_BGR2YCrCb: case CV_RGB2YCrCb:
case CV_BGR2YUV: case CV_RGB2YUV:
// ...
// 1 if it is BGR, 0 if it is RGB
bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;
//... converting to YUV with the only difference that brings
// order of Blue and Red channels (variable bidx)
But there is one more thing to say.
There is currently a bugin conversion CV_BGR2YUVand CV_RGB2YUVin OpenCV branch 2.4.* .
但还有一件事要说。
目前在 OpenCV 分支 2.4.*中转换CV_BGR2YUV和CV_RGB2YUV存在错误。
At present, this formula is used in implementation:
目前在实现中使用这个公式:
Y = 0.299B + 0.587G + 0.114R
U = 0.492(R-Y)
V = 0.877(B-Y)
What it should be (according to wikipedia):
它应该是什么(根据维基百科):
Y = 0.299R + 0.587G + 0.114B
U = 0.492(B-Y)
V = 0.877(R-Y)
The channels Red and Blue are misplaced in the implemented formula.
红色和蓝色通道在实施的公式中错位。
Possible workaround to convert BGR->YUV while the bug is not fixed :
在错误未修复时转换 BGR->YUV 的可能解决方法:
cv::Mat source = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
cv::Mat yuvSource;
cvtColor(source, yuvSource, cv::COLOR_BGR2RGB); // rearranges B and R in the appropriate order
cvtColor(yuvSource, yuvSource, cv::COLOR_BGR2YUV);
// yuvSource will contain here correct image in YUV color space
回答by Sam
It may be the wrong path, but many people (I mean, engineers) do mix YUV with YCbCr.
这可能是错误的路径,但很多人(我的意思是工程师)确实将 YUV 与 YCbCr 混合使用。
Try to
尝试
cvCvtColor(src, dsc, CV_YCbCr2RGB)
or CV_YCrCb2RGB or maybe a more exotic type.
或 CV_YCrCb2RGB 或者更奇特的类型。