简介    

    将彩色图像转化成为灰度图像的过程成为图像的灰度化处理。彩色图像中的每个像素的颜色有R、G、B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*255)的颜色的变化范围。而灰度图像是R、G、B三个分量相同的一种特殊的彩色图像,其一个像素点的变化范围为255种,所以在数字图像处理种一般先将各种格式的图像转变成灰度图像以使后续的图像的计算量变得少一些。灰度图像的描述与彩色图像一样仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征。

首先上转换代码:

int main(int argc, char** argv)
{
    Mat src = imread("G:\\opencv-4.1.1\\faceDete\\faceDete\\aaa.jpg", IMREAD_COLOR);
    Mat grey(src.rows, src.cols, CV_8UC1, Scalar(0));
    //每行循环处理
    for (int y = 0; y < src.rows; y++) {
        uchar* cp = src.ptr<uchar>(y);//获取第y行像素的首地址
        uchar* gp = grey.ptr<uchar>(y);//获取第y行像素的首地址
        for (int x = 0; x < src.cols; x++) {//列
            *gp = (15 * cp[0] + 75 * cp[1] + 38 * cp[2]) >> 7;
            cp += 3;
            gp++;
        }
    }
 
    imshow("src", src);
    imshow("grey", grey);
    waitKey(0);
    return 0;
}

 以上代码是在OPENCV中,RGB图像转换为灰度图像的实现方式。

原理

RGB彩色图像中,一种彩色由R(红色),G(绿色),B(蓝色)三原色按比例混合而成。图像基本单元是一个像素,一个像素需要3块表示,分别代表R,G,B,如果8位表示一个颜色,就由0-255区分不同亮度的某种原色。

一张9像素的8位RGB图像,在计算机内存中的分布大概示意如下:

java opencv灰度化 opencv将图像变换为灰度图_java opencv灰度化

实际中数都是二进制形式的。

灰度图像是用不同饱和度的黑色来表示每个图像点,比如用8位 0-255数字表示“灰色”程度,每个像素点只需要一个灰度值,8位即可,这样一个3X3的灰度图,只需要9个byte就能保存。

RGB值和灰度的转换,实际上是人眼对于彩色的感觉到亮度感觉的转换,这是一个心理学问题,有一个公式:

Grey = 0.299*R + 0.587*G + 0.114*B

根据这个公式,依次读取每个像素点的R,G,B值,进行计算灰度值(转换为整型数),将灰度值赋值给新图像的相应位置,所有像素点遍历一遍后完成转换。一张500X500的图像转换为同样大小的灰度图需要进行25万次上述公式的计算。进行优化是很有必要的,这个简单的算法是O(n)复杂度的,应该是不能优化了(或者用并行进行优化,本文不涉及),但是Grey = 0.299*R + 0.587*G + 0.114*B有更加高效的等价形式。可以通过将浮点数运算转化为整数运算,整数运算转换为位操作进行优化
Grey = 0.299*R + 0.587*G + 0.114*B

可以转换为:

Grey = (299*R + 587*G + 114*B + 500) /1000

整数运算会截断小数部分,加上500是为了四舍五入(找两个例子便可理解),减少精度损失。

这里的除法/ 即使是整数除法计算也是很耗时,转换为移位操作可以优化,那么怎么转换为位操作?左右移位对应于乘除2的幂,为了把除法转为右移操作,做如下处理:

Grey = 0.299*R + 0.587*G + 0.114*B
    Grey = (299*R+ 587*G + 114*B)÷ 1000
    Grey = (1024*299*R+ 1024*587*G + 1024*114*B)÷(1024*1000)
    Grey = (306176*R+601088*G + 116736*B)÷(1024*1000)
    Grey = (306.176*R+601.088*G + 116.736*B)÷(1024)
    Grey = (306*R+601*G + 116*B)÷(1024)//截断误差
    Grey = (306*R+601*G + 116*B) >> 10;

误差最大是多少?
  (0.176*255+0.088*255 + 0.736*255) ÷1024 = 255÷1024=0.249,可能会导致1个灰度值的波动。

 2-10位精度的公式如下:

Grey = (R*1 + G*2 + B*1) >> 2
Grey= (R*2 + G*5 + B*1) >> 3
Grey= (R*4 + G*10 + B*2) >> 4
Grey = (R*9 + G*19 + B*4) >> 5
Grey = (R*19 + G*37 + B*8) >> 6
Grey= (R*38 + G*75 + B*15) >> 7
Grey= (R*76 + G*150 + B*30) >> 8
Grey = (R*153 + G*300 + B*59) >> 9
Grey = (R*306 + G*601 + B*117) >> 10
Grey = (R*612 + G*1202 + B*234) >> 11
Grey = (R*1224 + G*2405 + B*467) >> 12
Grey= (R*2449 + G*4809 + B*934) >> 13
Grey= (R*4898 + G*9618 + B*1868) >> 14
Grey = (R*9797 + G*19235 + B*3736) >> 15
Grey = (R*19595 + G*38469 + B*7472) >> 16
Grey = (R*39190 + G*76939 + B*14943) >> 17
Grey = (R*78381 + G*153878 + B*29885) >> 18
Grey =(R*156762 + G*307757 + B*59769) >> 19
Grey= (R*313524 + G*615514 + B*119538) >> 20