首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用OpenCV和Matlab实现RGB到YCbCr的不同颜色转换

用OpenCV和Matlab实现RGB到YCbCr的不同颜色转换
EN

Stack Overflow用户
提问于 2019-02-10 10:38:07
回答 1查看 2.8K关注 0票数 2

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

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

这是我为MATLAB和C++编写的代码( OpenCV 4.0.1)。

Matlab:

代码语言:javascript
运行
复制
% 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++:

代码语言:javascript
运行
复制
// 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是以下宏:

代码语言:javascript
运行
复制
#define PRINT_MAT(mat, msg) std::cout<< std::endl <<msg <<":" <<std::endl <<mat <<std::endl;

打印出RGB通道,对于Matlab和OpenCV,我获得相同的值(对于前8x8块),而对于Y、Cb和Cr,则得到不同的值。例如,对于Luma组件:

Matlab:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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

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

EN

回答 1

Stack Overflow用户

发布于 2019-02-10 13:50:24

事实证明两者都是“正确的”。而OpenCV为Y采用了整个范围,而MATLAB则为16,235。这个推理可以在另一个问题/回答中看到。

您可以在MATLAB 文档中阅读

图像在YCbCr颜色空间中,返回为m-by n-by-3数组.

  • 如果输入为双输入或单输入,则Y在16/255、235/255范围内,Cb和Cr在16/255、240/255范围内。
  • 如果输入是,则Y在16,235范围内,Cb和Cr在16,240范围内。
  • 如果输入为uint16,则Y在4112、60395范围内,Cb和Cr在4112、61680范围内。

在OpenCV 文档

  • Y= 0.299R + 0.587G + 0.114B
  • Cr = (R - Y)⋅0.713 +δ
  • Cb = (B )⋅0.564+ \delta

..。

Y,Cr和Cb覆盖整个值范围

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54615539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档