MATLAB rgb2ycbcr与opencv的转换的区别

说明:原文转自:https://www.yuanmacha.com/19077745197.html:
根据原文作者的讲解,验证了下,在matlab下,转换后的Y 分量亮度的确在【16,235】之间,而不是0-255。

在我成功地在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)")

两个的结果是不一样的
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’s”数字视频简介中的等式执行的(第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;
并且还提到:

如果输入是uint8,则YCBCR是uint8其中Y在上述范围内[16 235],并且Cb和Cr是范围[16 240]。

另一方面,在OCV (实现)中,使用以下关系执行:
另一方面,在OCV (实现)中,使用以下关系执行:

在此输入图像描述

注意它是如何说“ Y,Cr和Cb覆盖整个数值范围。 ”。
在这里插入图片描述

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

OCV_Y = 0.299imgrgb(:,:,1) + 0.587imgrgb(:,:,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
根据维基百科关于YCbCr的文章,似乎OCV实现了“ JPEG转换 ”变体,而MATLAB实现了ITU-R BT.601的“标准清晰度电视”变体。

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





  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值