图像灰度化方法总结及其VC实现
http://blog.csdn.net/likezhaobin/article/details/6915754
最近一段时间作者开始进行运动目标识别定位系统设计,本文以及后续的几篇文章都是从一个图像处理初学者的角度来总结目标检测定位过程中所应用到的各种常见的算法,尤其是解决算法实现过程中由于粗心大意或者C编程基本功不扎实所引起的各种问题。本文主要对彩色图片灰度化的方法及其实现过程进行总结,最终给出实现的C代码。
在进行视频流目标识别与跟踪时,通常第一个步骤就是对采集到的彩色图像进行灰度化,这是因为黑白照片数据量小,相比彩照更易实现实时算法,另一方面黑白照片是由未处理的光线所形成的照片,因此从图像处理学角度来看,这种未经特殊滤光处理的图片所涵盖的信息更有价值。
目前,在图像处理过程中,最常用的彩色图片格式有RGB,HSV、YUV以及HLS三种。以下分别对这三种格式的彩色图像进行灰度化实现。
1、RGB空间图像
定义于RGB空间的彩色图,其每个像素点的色彩由R、G、B三个分量共同决定。每个分量在内存所占的位数共同决定了图像深度,即每个像素点所占的字节数。以常见的24深度彩色RGB图来说,其三个分量各占1个字节,这样每个分量可以取值为0~255,这样一个像素点可以有1600多万(255*255*255)的颜色的变化范围。对这样一幅彩色图来说,其对应的灰度图则是只有8位的图像深度(可认为它是RGB三个分量相等),这也说明了灰度图图像处理所需的计算量确实要少。不过需要注意的是,虽然丢失了一些颜色等级,但是从整幅图像的整体和局部的色彩以及亮度等级分布特征来看,灰度图描述与彩色图的描述是一致的。
对于RGB图像进行灰度化,通俗点说就是对图像的RGB三个分量进行加权平均得到最终的灰度值。最常见的加权方法如下:
1)Gray=B;Gray=G;Gray=R
2)Gray=max(B+G+R)
3)Gray=(B+G+R)/3
4)Gray= 0.072169B+ 0.715160G+ 0.212671R
5)Gray= 0.11B+ 0.59G+ 0.3R
这三种方法中,第一种为分量法,即用RGB三个分量的某一个分量作为该点的灰度值;第二种方法为最大值法,将彩色图像中的三分量亮度的最大值作为灰度图的灰度值。第三种方法将彩色图像中的三分量亮度求平均得到一个灰度图;后两种都是属于加权平均法,其中第四种是OpenCV开放库所采用的灰度权值,第五种为从人体生理学角度所提出的一种权值(人眼对绿色的敏感最高,对蓝色敏感最低)。
2、其他颜色空间的灰度化
关于HSV以及HLS颜色空间的彩色图灰度化,可以参考网页《HSL和HSV色彩空间》,该网页中所述方法可将几种不同颜色表达方式进行转换,将其转换到RGB空间,然后再采用上述公式进行灰度化。
关于YUV空间的彩色图像,其Y的分量的物理意义本身就是像素点的亮度,由该值反映亮度等级,因此可根据RGB和YUV颜色空间的变化关系建立亮度Y与R、G、B三个颜色分量的对应:Y=0.3R+0.59G+0.11B,以这个亮度值表达图像的灰度值。
3、代码实现
本文旨在对整个实现原理及思路进行总结,因此以下基于OpenCv的基本函数实现这几种变化过程,至于位图以及其他形式的图像,在获取了图像原始数据后,处理方法都一样,仅需注意指针的位置操作即可。具体代码如下:
- IplImage *ColorImage; //定义相应的图像指针
- IplImage *GrayImage1; //从1~5代表5中不同权值的结果
- IplImage *GrayImage2;
- IplImage *GrayImage3;
- IplImage *GrayImage4;
- IplImage *GrayImage5;
- IplImage *GrayImage6;
- IplImage *GrayImage7;
- ColorImage = cvLoadImage( "49138.jpg", -1 ); //读取图片
- if (ColorImage == NULL)
- return;
- GrayImage1 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage2 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage3 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage4 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage5 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage6 = cvCreateImage(cvGetSize(ColorImage),8,1);
- GrayImage7 = cvCreateImage(cvGetSize(ColorImage),8,1);
- CvMat* pGrayMat1 = NULL; //定义与图像关联的数据指针
- CvMat* pGrayMat2 = NULL;
- CvMat* pGrayMat3 = NULL;
- CvMat* pGrayMat4 = NULL;
- CvMat* pGrayMat5 = NULL;
- CvMat* pGrayMat6 = NULL;
- CvMat* pGrayMat7 = NULL;
- pGrayMat1 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat2 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat3 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat4 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat5 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat6 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- pGrayMat7 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
- BYTE data1; //中间过程变量
- BYTE data2;
- BYTE data3;
- BYTE data4;
- BYTE data5;
- BYTE data6;
- BYTE data7;
- for(int j=0; j<ColorImage->height; j++)
- {
- for(int i=0; i<ColorImage->width; i++)
- {
- data1 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3]; //B分量
- data2 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 1]; //G分量
- data3 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 2]; //R分量
- data4 = max(data1, max(data2, data3)); //最大值
- data5 = (BYTE)((data1 + data2 + data3)/3);
- data6 = (BYTE)(0.072169*data1 + 0.715160*data2 + 0.212671*data3);
- data7 = (BYTE)(0.11*data1 + 0.59*data2 + 0.30*data3);
- cvmSet(pGrayMat1, j, i, data1);
- cvmSet(pGrayMat2, j, i, data2);
- cvmSet(pGrayMat3, j, i, data3);
- cvmSet(pGrayMat4, j, i, data4);
- cvmSet(pGrayMat5, j, i, data5);
- cvmSet(pGrayMat6, j, i, data6);
- cvmSet(pGrayMat7, j, i, data6);
- }
- }
- cvConvert(pGrayMat1, GrayImage1);
- cvConvert(pGrayMat2, GrayImage2);
- cvConvert(pGrayMat3, GrayImage3);
- cvConvert(pGrayMat4, GrayImage4);
- cvConvert(pGrayMat5, GrayImage5);
- cvConvert(pGrayMat6, GrayImage6);
- cvConvert(pGrayMat7, GrayImage7);
- cvNamedWindow( "ColorImage",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage1",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage2",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage3",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage4",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage5",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage6",CV_WINDOW_AUTOSIZE);
- cvNamedWindow( "GrayImage7",CV_WINDOW_AUTOSIZE);
- cvShowImage("ColorImage", ColorImage);
- cvShowImage("GrayImage1", GrayImage1);
- cvShowImage("GrayImage2", GrayImage2);
- cvShowImage("GrayImage3", GrayImage3);
- cvShowImage("GrayImage4", GrayImage4);
- cvShowImage("GrayImage5", GrayImage5);
- cvShowImage("GrayImage6", GrayImage6);
- cvShowImage("GrayImage7", GrayImage7);
- cvWaitKey(0);
- cvDestroyWindow("ColorImage");
- cvDestroyWindow("GrayImage1");
- cvDestroyWindow("GrayImage2");
- cvDestroyWindow("GrayImage3");
- cvDestroyWindow("GrayImage4");
- cvDestroyWindow("GrayImage5");
- cvDestroyWindow("GrayImage6");
- cvDestroyWindow("GrayImage7");
- cvReleaseImage(&ColorImage);
- cvReleaseImage(&GrayImage1);
- cvReleaseImage(&GrayImage2);
- cvReleaseImage(&GrayImage3);
- cvReleaseImage(&GrayImage4);
- cvReleaseImage(&GrayImage5);
- cvReleaseImage(&GrayImage6);
- cvReleaseImage(&GrayImage7);
- cvReleaseMat(&pGrayMat1);
- cvReleaseMat(&pGrayMat2);
- cvReleaseMat(&pGrayMat3);
- cvReleaseMat(&pGrayMat4);
- cvReleaseMat(&pGrayMat5);
- cvReleaseMat(&pGrayMat6);
- cvReleaseMat(&pGrayMat7);
各种不同方法实现灰度化的效果图对比如下;

图1 待处理的原始图像—脱离低级趣味的猫

图2 分量灰度化—B分量

图3 分量灰度化—G分量

图4 分量灰度化—R分量

图5 最大值灰度化

图6 均值灰度化

图7 OpenCV权值系数灰度化

图8 网络常用权值灰度化
4、思考
上文的代码实现中,以最后一种方法为例,用到了如下代码:
Gray= (0.11* Blue + 0.59* Green + 0.30* Red);
实际计算机处理时,这种方法已经很快了,但实际上还存在可以优化的余地。以上代码所采用的是浮点运算。而在图像处理中,速度就是生命,实时性往往是很重要的指标,这就要求我们在实现算法时必须考虑到代码的效率问题。所以有一个原则:在图像处理中,能不用浮点运算,就最好不要用!
因此,上述代码可以等效的优化为:
Gray = (30 * Red + 59 *Green + 11 * Blue) / 100;
这样一改,可以有效避免浮点运算,因此可以提高代码的效率
对这行代码还可以继续改进为如下:
Gray= HiByte(77 * Red + 151 * Green + 28 * Blue);
其中77,151,28分别除以256,即为上文的三个系数。
同样的,还可以实现为:
Gray= (77 * Red + 151 * Green + 28 * Blue) shr 8;
这种方法实现了移位运算,避免了除法,效率上又有所提高。
关于具体的代码效率问题,可以参考博文《由图像的灰度化看基本图像处理》。
图像灰度化方法总结及其VC实现的更多相关文章
- 【转】图像灰度化方法总结及其VC实现
转载自: http://blog.csdn.net/likezhaobin/article/details/6915754 最近一段时间作者开始进行运动目标识别定位系统设计,本文以及后续的几篇文章都 ...
- java实现图像灰度化
/*在研究Java实现将一张图片转成字符画的时候,发现将图像转化字符串是根据照片的灰度采用不同的字符画出来,形成一个灰度表.于是就研究了下关于灰度值这个东西,于是跳了一个大坑...因为鄙人用的ubun ...
- Java图像灰度化的实现过程解析
概要 本文主要介绍了灰度化的几种方法,以及如何使用Java实现灰度化.同时分析了网上一种常见却并不妥当的Java灰度化实现,以及证明了opencv的灰度化是使用“加权灰度化”法 24位彩色图与8位灰度 ...
- c#图像灰度化、灰度反转、二值化
图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*25 ...
- 深入学习OpenCV中图像灰度化原理,图像相似度的算法
最近一段时间学习并做的都是对图像进行处理,其实自己也是新手,各种尝试,所以我这个门外汉想总结一下自己学习的东西,图像处理的流程.但是动起笔来想总结,一下却不知道自己要写什么,那就把自己做过的相似图片搜 ...
- python 图像处理中二值化方法归纳总结
python图像处理二值化方法 1. opencv 简单阈值 cv2.threshold 2. opencv 自适应阈值 cv2.adaptiveThreshold 3. Otsu's 二值化 例子: ...
- java+opencv实现图像灰度化
灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度,范围一般从0到255,白色为255,黑色为0.所谓灰度值是指色彩的浓淡程度,灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰 ...
- PhpStorm2017版激活方法、汉化方法以及界面配置
PhpStorm激活和汉化文件下载网址:http://pan.baidu.com/s/1nuHF1St(提取密码:62cg) PHPMailer的介绍 PhpStorm是一个轻量级且便捷的PHP ID ...
- 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)(转)
转自: https://zhuanlan.zhihu.com/p/22252270 ycszen 另可参考: https://blog.csdn.net/llx1990rl/article/de ...
随机推荐
- AnyProxy对搜狐汽车app抓包
关于AnyProxy 详细文档链接 http://anyproxy.io/cn/ anyproxy流程图 简要描述 当http请求经过代理服务器时,具体处理过程是: 收集请求所有请求参数,包括meth ...
- Python解包参数列表及 Lambda 表达式
解包参数列表 当参数已经在python列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况.例如,内置的 range() 函数需要单独的 start 和 stop 参数.如果它们不能 ...
- Linux文件归档和解压缩
1.tar tar命令相当于归档,不做压缩,解压同样也是把归档文件释放出来(归档通俗上可以理解为把文件分类,把一些文件放到一个包中归类,方便用户管理) 解包:tar -zxvf file.tar #解 ...
- scikit-learn使用PCA降维小结
本文在主成分分析(PCA)原理总结和用scikit-learn学习主成分分析(PCA)的内容基础上做了一些笔记和补充,强调了我认为重要的部分,其中一些细节不再赘述. Jupiter notebook版 ...
- 微信小程序-----自定义验证码实现
这一段时间做小程序项目,使用的是mpvue的框架,需要自己实现验证码输入,模拟input的光标,上一个框输入后后一个框自动获取焦点,删除时从后往前依次删除.下图是整体效果: <template& ...
- 【技术向】rainmeter的设计与发现
我们在大学期间所学的那点代码知识还远远不够,于是我就自己寻找到了一款简单易懂的软件,来丰富我的代码知识. 这款软件叫rainmeter,中文叫做雨滴,是一款可以修改桌面的软件.它可以将桌面上更改出硬盘 ...
- lintcode-451-两两交换链表中的节点
451-两两交换链表中的节点 给一个链表,两两交换其中的节点,然后返回交换后的链表. 样例 给出 1->2->3->4, 你应该返回的链表是 2->1->4->3. ...
- MySQL 基于xtrabackup备份—热备工具
xtrabackup(仅对InnoDB存储引擎支持热备) percona公司开发 改进的MySQL分支:percona-server 存储引擎改进:InnoDB —> XtraDB 使用本地的R ...
- 转 Maven常用仓库地址以及手动添加jar包到仓库
转自:http://blog.csdn.net/kqygww/article/details/12837783 共有的仓库 http://repository.sonatype.org/content ...
- crontab & php实现多进程思路
<?php $startTime = time(); while(1) { if (time() - $startTime > 600) { exit; } // ... Do SomeT ...