• 【图像处理】图像灰度化


    写在前面的话

    老式黑白电视只有一个通道的图像数据,通过灰度值在黑白电视上显示灰度图像,即图像的亮度,是Y通道数据。

    后来出现了彩色电视,为了兼容老式黑白电视,使用YCrCb(YUV)方式传输图像。

    如下分析一下彩色图像转成灰度图的方法和原理。

    彩色图和灰度图说明

    彩色图像可以有4个通道,的BGR-[A](Blue Green Red Alpha)蓝,绿,红和透明4个通道。

    也可以是BGR(Blue Green Red)蓝,绿,红3个通道三通道。

    BGR的数据存储格式如下所示:

     灰度图是单通道图像,数据存储格式如下所示:

    转化分析

    在opencv中可以使用API将彩色图像转成灰度图。

    将彩色图像转成灰度图的方式有如下两种方式

    方式一:

    RGB  YCrCb JPEG (or YCC)

    Y = 0.299R+0.587G+0.114B

    Cr = (RY)0.713+delta

    Cb = (BY)0.564+delta

    方式二:

    RGB ↔ CIE

     Y = 0.212671R+0.715160G+0.072169B

    opencv默认将RGB图像转成Gray的方式是

    RGB  GRAY

    RGB[A] to Gray: Y = 0.299R+0.587G+0.114B

    效果如下:

    使用opencv的API进行灰度化处理代码

        void toGray(cv::Mat& inImage, cv::Mat& outGrayImage) {
            cv::cvtColor(inImage, outGrayImage, cv::COLOR_RGB2GRAY);
    
            cv::imshow("raw-image", inImage);
            cv::imshow("gray-image", outGrayImage);
        }

    遍历图像矩阵,使用CIE方式将BGR转Gray的公式计算如下:

        void toGrayImpl(cv::Mat &inImage, cv::Mat &outGrayImage) {
            outGrayImage = cv::Mat::zeros(inImage.rows, inImage.cols, CV_8UC1);
            for (int i = 0; i < inImage.rows; ++i) {
                unsigned char *ptSrcRow = inImage.ptr<uchar>(i);
                unsigned char *ptDstRow = outGrayImage.ptr<uchar>(i);
                for (int j = 0; j < inImage.cols; ++j) {
                    int pos = j * inImage.channels();
                    // Y = B * 0.072169f + G * 0.715160f + R * 0.212671f;
                    ptDstRow[j] = cv::saturate_cast<uchar>(0.212671f * (float) ptSrcRow[pos + 2] +
                                                           0.71516f * (float) ptSrcRow[pos + 1] +
                                                           0.072169f * (float) ptSrcRow[pos]);
                }
            }
    
            cv::imshow("raw-image", inImage);
            cv::imshow("gray-image", outGrayImage);
        }

     通过YCrCb方式转成灰度图:

        void toGrayImplByYCrCb(cv::Mat &inImage, cv::Mat &outGrayImage) {
            outGrayImage = cv::Mat::zeros(inImage.rows, inImage.cols, CV_8UC1);
            for (int i = 0; i < inImage.rows; ++i) {
                for (int j = 0; j < inImage.cols; ++j) {
                    // BGR -> Gray
                    // Y = B * 0.114 + G * 0.587 + R * 0.299;
                    outGrayImage.at<uchar>(i, j) = 0.299 * (float) inImage.at<cv::Vec3b>(i, j)[2]
                                                   + 0.587 * (float) inImage.at<cv::Vec3b>(i, j)[1]
                                                   + 0.114 * (float) inImage.at<cv::Vec3b>(i, j)[0];
                }
            }
    
            cv::imshow("raw-image", inImage);
            cv::imshow("gray-image-YCrCb", outGrayImage);
        }

    另外一种方式,直接使用opencv的API将BGR图像转成YCrCb格式,提取Y通道的数据imageList[0]

        void toGrayByYCrCbSplit(cv::Mat &inImage, cv::Mat &outGrayImage) {
            cv::cvtColor(inImage, outGrayImage, cv::COLOR_BGR2YCrCb);
            std::vector<cv::Mat> imageList;
            cv::split(outGrayImage, imageList);
    
            cv::imshow("raw-image", inImage);
            cv::imshow("gray-image-Y", imageList[0]);
            cv::imshow("gray-image-Cr", imageList[1]);
            cv::imshow("gray-image-Cb", imageList[2]);
        }

    将彩色图转成YCrCb,如下是Y通道的灰度图,Cr是R通道和Y的差值,Cb是B通道和Y的差值。

      

    参考文档:

    https://docs.opencv.org/3.3.1/de/d25/imgproc_color_conversions.html#color_convert_rgb_gray

  • 相关阅读:
    简述Mesos API–files
    docker-compose常用命令
    Linux命令行--使用linux环境变量(转)
    docker:从 tomcat 容器连接到 mysql 容器
    开发环境、生产环境、测试环境的基本理解和区别(转)
    Linux命令行–更多bash shell命令(转)
    docker启动Mysql(转)
    Linux命令行–基本的bash shell命令
    浅谈 man 命令的日常使用
    Linux命令行–走进shell
  • 原文地址:https://www.cnblogs.com/voipman/p/15238651.html
Copyright © 2020-2023  润新知