首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BGR -> YCbCr转换不能正常工作

BGR -> YCbCr转换不能正常工作
EN

Stack Overflow用户
提问于 2019-06-23 23:05:19
回答 2查看 315关注 0票数 0

我正在尝试手动将图像从RBG (OpenCV中的BGR)转换到YCbCr颜色空间。

我的图像是png彩色图像,宽800,高600,3通道,16位深。

下面是我尝试解决这个问题的方法。

代码语言:javascript
复制
cv::Mat convertToYCbCr(cv::Mat image) {                                         
    // converts an RGB image to YCbCr                                           
    // cv::Mat: B-G-R                                                           
    std::cout << "Converting image to YCbCr color space." << std::endl;         
    int i, j;                                                                   
    for (i = 0; i <= image.cols; i++) {                                         
        for (j = 0; j <= image.rows; j++) {                                     

            // R, G, B values                                                   
            auto R = image.at<cv::Vec3d>(j, i)[2];                              
            auto G = image.at<cv::Vec3d>(j, i)[1];                              
            auto B = image.at<cv::Vec3d>(j, i)[0];                              

            // Y'                                                               
            auto Y = image.at<cv::Vec3d>(j,i)[0] = 0.299 * R + 0.587 * G + 0.114 * B + 16;

            // Cb                                                               
            auto Cb = image.at<cv::Vec3d>(j,i)[1] = 128 + (-0.169 * R -0.331 * G + 0.5 * B);

            // Cr                                                               
            auto Cr = image.at<cv::Vec3d>(j,i)[2] = 128 + (0.5 * R -0.419 * G -0.081 * B);
            std::cout << "At conversion: Y = " << Y << ", Cb = " << Cb << ", "  
                << Cr << std::endl;                                             
        }                                                                       
    }                                                                           
    std::cout << "Converting finished." << std::endl;                           
    return image;                                                               
}

我收到的图片如下所示:

我期望的是这样(使用OpenCV方法):

竖线可能暗示了什么?我的循环是不是错了?我可以用YCbCr值“替换”RGB值并期望图像看起来像示例吗?typeid()为两个图像返回相同的值N2cv3MatE

EN

回答 2

Stack Overflow用户

发布于 2019-06-23 23:55:16

您应该使用cv::cvtColor

代码语言:javascript
复制
cvtColor(src, target_image, cv::COLOR_RGB2YCrCb);

然后只需翻转第二个和第三个频道。

尽管你可能会得到这个错误,因为你没有将结果值转换成整数。

票数 1
EN

Stack Overflow用户

发布于 2019-06-24 04:30:11

观察到不正确结果的主要原因是用于访问映像的数据类型不正确。访问16位无符号像素的正确类型是cv::Vec3w (而不是cv::Vec3d)。

下一个问题是用于转换的系数是为模拟信号( YPbPr )设计的。对于数字图像,我们必须使用为数字图像设计的系数( YCbCr )。您可以在ITU-R BT.601 conversion一节中找到有关Wikipedia article on YCbCr的更多详细信息。

文章中缺少的一条信息是,如果图像是16位无符号深度或32位浮点深度,系数将如何变化?这个问题的答案是,我们必须根据图像的位深度来缩放系数。

对于16位无符号深度的图像,需要进行如下缩放操作:

代码语言:javascript
复制
auto Y = (R * 65.481f * scale) + (G * 128.553f * scale) + (B * 24.966f * scale) + (16.0f * offset);
auto Cb = (R * -37.797f * scale) + (G * -74.203f * scale) + (B * 112.0f * scale) + (128.0f * offset);
auto Cr = (R * 112.0f * scale) + (G * -93.786f * scale) + (B * -18.214f * scale) + (128.0f * offset);

其中scale等于257.0/65535.0offset等于257.0

这种转换技术是从rgb2ycbcr函数的MATLAB源代码中采用的,该源代码参考了下面描述缩放的书籍:

C.A.Poynton,"A Technical Introduction to Digital Video",John Wiley & Sons,Inc.,1996,第9章,第175页

现在已经完成了转换,我们面临的第三个问题是图像的可视化,类似于OpenCV。当我们使用OpenCV执行颜色转换时,输出图像以YCrCb的顺序存储,而不是通常的YCbCr。因此,为了获得与我们的自定义转换逻辑相同的图像,我们必须以相关的顺序存储值。

示例转换代码可能如下所示:

代码语言:javascript
复制
if(image.type() == CV_16UC3)
{
    const float scale = 257.0f / 65535.0f;
    const float offset = 257.0f;
    for (int i = 0; i < image.cols; i++)
    {
        for (int j = 0; j < image.rows; j++)
        {
            auto R = image.at<cv::Vec3w>(j, i)[2];
            auto G = image.at<cv::Vec3w>(j, i)[1];
            auto B = image.at<cv::Vec3w>(j, i)[0];

            auto Y = (R * 65.481f * scale) + (G * 128.553f * scale) + (B * 24.966f * scale) + (16.0f * offset);
            auto Cb = (R * -37.797f * scale) + (G * -74.203f * scale) + (B * 112.0f * scale) + (128.0f * offset);
            auto Cr = (R * 112.0f * scale) + (G * -93.786f * scale) + (B * -18.214f * scale) + (128.0f * offset);

            image.at<cv::Vec3w>(j, i)[0] = (unsigned short)Y;
            image.at<cv::Vec3w>(j, i)[1] = (unsigned short)Cr;
            image.at<cv::Vec3w>(j, i)[2] = (unsigned short)Cb;
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56725115

复制
相关文章

相似问题

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