gpt4 book ai didi

c++ - 使用 OpenCV 和 Matlab 从 RGB 到 YCbCr 的不同颜色转换

转载 作者:搜寻专家 更新时间:2023-10-31 00:51:36 25 4
gpt4 key购买 nike

在 MATLAB 中成功实现后,我正在尝试使用 openCV 复制 jpeg 算法。我注意到 MATLAB 和 OpenCV 对于从 RGB 到 YCbCr 的色彩空间转换给出了不同的结果。

查看OpenCV的文档,似乎唯一使用的函数是cv::cvtColor,但是打印Y、Cb和Cr的第一个8x8子矩阵,它们是不一样的。

这是我的 MATLAB 和 C++(使用 OpenCV 4.0.1)代码。

Matlab:

% Read rgb image
imgrgb = imread('lena512color.bmp');

% Convert to ycbcr
imgycbcr = rgb2ycbcr(imgrgb);

% Extract the 3 components
luma = imgycbcr (:,:,1);
cb = imgycbcr (:,:,2);
cr = imgycbcr (:,:,3);

C++:

// Load img
cv::Mat bgrImg = imread( "lena512color.bmp", cv::IMREAD_COLOR );
assert( bgrImg.data && "No image data");

// Declare an empty Mat for dst image
cv::Mat ycrcbImg;

// Convert to ycrcb
cv::cvtColor(bgrImg, ycrcbImg, cv::COLOR_BGR2YCrCb);

// Split bgr into 3 channels
cv::Mat bgrChan[3];
cv::split(bgrImg, bgrChan);

// Split ycrcb into 3 channels
cv::Mat ycrcbChan[3];
cv::split(ycrcbImg, ycrcbChan);

// Print first block for each channel
PRINT_MAT(ycrcbChan[0](cv::Rect(0, 0, 8, 8)), "LUMA (first 8x8 block)")
PRINT_MAT(ycrcbChan[1](cv::Rect(0, 0, 8, 8)), "Cr (first 8x8 block)")
PRINT_MAT(ycrcbChan[2](cv::Rect(0, 0, 8, 8)), "Cb (first 8x8 block)")

PRINT_MAT(bgrChan[0](cv::Rect(0, 0, 8, 8)), "Blue (first 8x8 block)")
PRINT_MAT(bgrChan[1](cv::Rect(0, 0, 8, 8)), "Green (first 8x8 block)")
PRINT_MAT(bgrChan[2](cv::Rect(0, 0, 8, 8)), "Red (first 8x8 block)")

其中 PRINT_MAT 是以下宏:

#define PRINT_MAT(mat, msg) std::cout<< std::endl <<msg <<":" <<std::endl <<mat <<std::endl;

打印出 RGB channel 后,我为 Matlab 和 OpenCV 获得了相同的值(对于第一个 8x8 block ),而对于 Y、Cb 和 Cr,我获得了不同的值。例如,对于 Luma 组件:

Matlab:

155 155 155 154 155 150 156 154
155 155 155 154 155 150 156 154
155 155 155 154 155 150 156 154
155 155 155 154 155 150 156 154
155 155 155 154 155 150 156 154
157 157 151 149 154 153 152 153
154 154 156 152 154 155 153 150
152 152 149 150 152 152 150 151

OpenCV:

162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
162 162 162 161 162 157 163 161
164 164 158 155 161 159 159 160
160 160 163 158 160 162 159 156
159 159 155 157 158 159 156 157

什么是正确的转换?为什么结果不同?

最佳答案

通过查看 MATLAB 的 rgb2ycbcr 的源代码,转换是根据取自“Poynton 的“数字视频简介”(第 176 页,方程 9.6)":

origT = [ ...
65.481 128.553 24.966;...
-37.797 -74.203 112 ;...
112 -93.786 -18.214];
origOffset = [16; 128; 128];
ycbcr = origT * rgb + origOffset;

还提到:

If the input is uint8, then YCBCR is uint8 where Y is in the range [16 235], and Cb and Cr are in the range [16 240].

In OCV ( implementation ) 另一方面,这是使用以下关系执行的:

enter image description here

请注意“Y、Cr 和 Cb 覆盖整个值范围”。

如果我们在 MATLAB 中使用相同的方程式,我们会得到更接近 OCV 的结果(也许我使用的是不同的源图像)。例如,对于 Y:

OCV_Y = 0.299*imgrgb(:,:,1) + 0.587*imgrgb(:,:,2) + 0.114*imgrgb(:,:,3);

给出第一个 8x8:

   162   162   162   162   163   157   163   161
162 162 162 162 163 157 163 161
162 162 162 162 163 157 163 161
162 162 162 162 163 157 163 161
162 162 162 162 163 157 163 161
164 164 158 155 162 159 159 160
161 161 163 158 160 161 158 155
159 159 156 156 159 158 157 157

根据wikipedia article on YCbCr ,似乎 OCV 实现了“JPEG Conversion”变体,而 MATLAB 实现了 ITU-R BT.601 的“标准清晰度电视”变体。

总结:我会说这两个定义都是正确,但如果您特别关心 JPEG 的正确实现,我会说 OCV 的方式更好。无论如何,在 MATLAB 中实现任何其他变体都非常容易。

关于c++ - 使用 OpenCV 和 Matlab 从 RGB 到 YCbCr 的不同颜色转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54615539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com