【问题标题】:OpenCV understanding GreyscaleOpenCV 理解灰度
【发布时间】:2023-03-10 18:21:01
【问题描述】:

我对 OpenCV 如何进行颜色到灰度转换感到困惑。如果我向它发送一个仅由纯红色、纯绿色和纯蓝色组成的图像(例如 {255,0,0}),我希望它将其转换为值 255/3 = 85 的一致灰度,但这不是这样的。

我试过了:

IplImage* src;
src=cvLoadImage("image.bmp", 0)
val = cvGetReal2D( src, y, x );

这会产生令人困惑的输出,将纯红色转换为 147,将纯绿色转换为 200,将纯蓝色转换为 95(我想我在那里得到了命令)。灰色会按照您的预期进行转换(例如 {127,127,127} --> 127)。

然后我遇到了 cvCVTColor 函数,这似乎使用人眼反应来加权转换(灰色 = 0.299*Red + 0.587*Green + 0.114*Blue):

IplImage *im_rgb  = cvLoadImage("image.bmp");
IplImage *im_gray = cvCreateImage(cvGetSize(im_rgb),IPL_DEPTH_8U,1);
cvCvtColor(im_rgb,im_gray,CV_RGB2GRAY);
val = cvGetReal2D( im_gray, y, x ); 

我已通过拆分渠道成功转换:

IplImage* red_channel = cvCreateImage(cvSize(src->width, src->height), 8, 1);
IplImage* green_channel = cvCreateImage(cvSize(src->width, src->height), 8, 1);
IplImage* blue_channel = cvCreateImage(cvSize(src->width, src->height), 8, 1);
cvSplit( src, blue_channel , green_channel, red_channel , NULL);
val = ( cvGetReal2D( red_channel, y, x ) + cvGetReal2D( green_channel, y, x ) + cvGetReal2D( blue_channel, y, x ) ) / 3;

但我想从中了解 OpenCV 在使用 cvLoadImage 时如何转换为灰度和/或是否有一个函数可以在没有人眼响应的情况下进行转换(即 Gray = (Red+Green+Blue) /3)?

【问题讨论】:

    标签: opencv image-processing colors computer-vision


    【解决方案1】:

    我认为没有单一功能,但您可以拆分通道,将每个通道与其系数相乘,然后将所有通道相加在一张图像中。

    c++ 语法是:

    int main()
    {
      cv::Mat color = cv::imread("lena.jpg");
      cv::Mat red(color.rows, color.cols, CV_8UC1);
      cv::Mat green(color.rows, color.cols, CV_8UC1);
      cv::Mat blue(color.rows, color.cols, CV_8UC1);
    
      std::vector<cv::Mat> output;
      output.push_back(blue);
      output.push_back(green);
      output.push_back(red);
    
      cv::split(color,output);
    
      float r = 0.0f;
      float g = 0.2f;
      float b = 1.0f - (r + g);
      cv::Mat graySelf = r*red + g*green + b*blue;
      // could be computed with two calls of cv function addWeighted() in the same way!
    
    
      cv::Mat grayCV;
      cv::cvtColor(color,grayCV, CV_RGB2GRAY);
    
      cv::namedWindow("cv"); cv::imshow("cv", grayCV);
      cv::namedWindow("self"); cv::imshow("self", graySelf);
      cv::namedWindow("color"); cv::imshow("color", color);
    
      cv::imwrite("cv.png", grayCV);
      cv::imwrite("self.png", graySelf);
      cv::waitKey(-1);
    
    
      return 0;
    }
    

    提供图片:

    颜色:

    openCV:

    自我:

    在 cvtColor 中,opencv 2.4.4 c++ 内部在 imgproc/src/color.cpp 中使用了这个函数 sn-p 我猜:

    int scn = srccn;
    float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
    for(int i = 0; i < n; i++, src += scn)
        dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
    

    【讨论】:

    • 谢谢 Micka,一个非常全面的答案,有有用的例子。
    【解决方案2】:

    彩色到灰度的转换公式不是(R+G+B)/3

    找出正确的,为什么在Wikipedia上会这样

    【讨论】:

    • 我知道,在许多应用程序中,您希望使用人眼响应来衡量转换,但在我的应用程序中,我希望它对蓝色和绿色或红色一样敏感。跨度>
    • 然后编写自己的转换。 OpenCV 遵循标准。不需要它来实现没有实际意义的转换。但我真的怀疑你的项目需要 R、G、B 平均值。
    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 2018-11-18
    • 1970-01-01
    相关资源
    最近更新 更多