PhotoShop算法实现--图像灰度化处理(六)
http://blog.csdn.net/kezunhai
在日常的工程应用中,经常需要将彩色图像转换为灰度图像。在一般情况下,彩色图像每个像素用3个字节表示,每个字节分别对应着R、G、B分量的亮度值,转换后的黑白图像用一个像素来表示灰度值,它的值在0到255间,数值越大该点越亮,反之,越暗。图像灰度化算法包括最大值化、平均值法和加权平均值法。
1)最大值法
这种方法的原理是取RGB三个分量的最大值作为灰度化图像的值,即:R=G=B=Max(R,G,B)。使用最大值法会使处理后的图像的灰度偏亮。
2)平均值法
这种方法的原理是取RGB三个分量的平均值作为灰度化图像的值,即:R=G=B=(R+G+B)/3。使用平均值法处理后的图像显得较为柔和。
3)加权平均值法
加权平均值法的原理是给R、G、B三个分量赋予不同的权值,并取RGB三个分量加权的平均值作为灰度图像的均值,即:R=G=B=WrR+WgG+WbB,取不同的权重就可以得到不同的灰度图像。由于人眼对绿色敏感度最高、红色次之,对蓝色敏感度最低,因此通常Wg>Wr>Wb,生成的图像也更符合人眼的视觉感受。根据统计分析,通常当Wr=30%, Wg=59%, Wb=11%时得到的图像最为合理。
算法实现:
enum GRAYMETHOD { WEIGHTAVERAGE, MAXIMUM, AVERAGE };
void PhotoShop::Gray(Mat& img, Mat &gImg, GRAYMETHOD method)
{ if ( gImg.empty()) gImg.create(img.rows, img.cols, img.type()); gImg = cv::Scalar::all(0); int i, j; Size size = img.size(); int chns = img.channels(); if (img.isContinuous() && gImg.isContinuous()) { size.width *= size.height; size.height = 1; } for ( i= 0; i<size.height; ++i) { const unsigned char* src = (const unsigned char*)(img.data+ img.step*i); unsigned char* dst = (unsigned char*)gImg.data+gImg.step*i; for ( j=0; j<size.width; ++j) { uchar val; switch(method) { case WEIGHTAVERAGE: val =saturate_cast<uchar>(03.*src[j*chns] + 0.59*src[j*chns+1]+0.11*src[j*chns+2]+0.5); dst[j*chns] = dst[j*chns+1] = dst[j*chns+2] = val; break; case MAXIMUM: val = (val = src[j*chns]>src[j*chns+1] ? src[j*chns]:src[j*chns+1])> src[j*chns+2]?val:src[j*chns+2]; dst[j*chns] = dst[j*chns+1] = dst[j*chns+2] = val; break; case AVERAGE: val = (src[j*chns] + src[j*chns+1] + src[j*chns+2])/3; dst[j*chns] = dst[j*chns+1] = dst[j*chns+2] = val; break; default: val = (src[j*chns] + src[j*chns+1] + src[j*chns+2])/3; dst[j*chns] = dst[j*chns+1] = dst[j*chns+2] = val; break; } } } }以上介绍的方法在视觉看来一切都很正常,但是对于图像分析来说,以上方法的灰度化方法丢失了大量的信息,尤其是对比度的丢失,现有大量关于对比度保留的灰度化方法。要了解有关对比度保留的灰度化方法可以参考: 对比度保留之彩色图像去色算法。