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的基本函数实现这几种变化过程,至于位图以及其他形式的图像,在获取了图像原始数据后,处理方法都一样,仅需注意指针的位置操作即可。具体代码如下:

  1. IplImage    *ColorImage;                        //定义相应的图像指针
  2. IplImage    *GrayImage1;                        //从1~5代表5中不同权值的结果
  3. IplImage    *GrayImage2;
  4. IplImage    *GrayImage3;
  5. IplImage    *GrayImage4;
  6. IplImage    *GrayImage5;
  7. IplImage    *GrayImage6;
  8. IplImage    *GrayImage7;
  9. ColorImage = cvLoadImage( "49138.jpg", -1 );    //读取图片
  10. if (ColorImage == NULL)
  11. return;
  12. GrayImage1 = cvCreateImage(cvGetSize(ColorImage),8,1);
  13. GrayImage2 = cvCreateImage(cvGetSize(ColorImage),8,1);
  14. GrayImage3 = cvCreateImage(cvGetSize(ColorImage),8,1);
  15. GrayImage4 = cvCreateImage(cvGetSize(ColorImage),8,1);
  16. GrayImage5 = cvCreateImage(cvGetSize(ColorImage),8,1);
  17. GrayImage6 = cvCreateImage(cvGetSize(ColorImage),8,1);
  18. GrayImage7 = cvCreateImage(cvGetSize(ColorImage),8,1);
  19. CvMat* pGrayMat1 = NULL;         //定义与图像关联的数据指针
  20. CvMat* pGrayMat2 = NULL;
  21. CvMat* pGrayMat3 = NULL;
  22. CvMat* pGrayMat4 = NULL;
  23. CvMat* pGrayMat5 = NULL;
  24. CvMat* pGrayMat6 = NULL;
  25. CvMat* pGrayMat7 = NULL;
  26. pGrayMat1 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  27. pGrayMat2 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  28. pGrayMat3 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  29. pGrayMat4 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  30. pGrayMat5 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  31. pGrayMat6 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  32. pGrayMat7 = cvCreateMat(ColorImage->height, ColorImage->width, CV_32FC1);
  33. BYTE data1;       //中间过程变量
  34. BYTE data2;
  35. BYTE data3;
  36. BYTE data4;
  37. BYTE data5;
  38. BYTE data6;
  39. BYTE data7;
  40. for(int j=0; j<ColorImage->height; j++)
  41. {
  42. for(int i=0; i<ColorImage->width; i++)
  43. {
  44. data1 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3];     //B分量
  45. data2 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 1]; //G分量
  46. data3 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 2]; //R分量
  47. data4 = max(data1, max(data2, data3));    //最大值
  48. data5 = (BYTE)((data1 + data2 + data3)/3);
  49. data6 = (BYTE)(0.072169*data1 + 0.715160*data2 + 0.212671*data3);
  50. data7 = (BYTE)(0.11*data1 + 0.59*data2 + 0.30*data3);
  51. cvmSet(pGrayMat1, j, i, data1);
  52. cvmSet(pGrayMat2, j, i, data2);
  53. cvmSet(pGrayMat3, j, i, data3);
  54. cvmSet(pGrayMat4, j, i, data4);
  55. cvmSet(pGrayMat5, j, i, data5);
  56. cvmSet(pGrayMat6, j, i, data6);
  57. cvmSet(pGrayMat7, j, i, data6);
  58. }
  59. }
  60. cvConvert(pGrayMat1, GrayImage1);
  61. cvConvert(pGrayMat2, GrayImage2);
  62. cvConvert(pGrayMat3, GrayImage3);
  63. cvConvert(pGrayMat4, GrayImage4);
  64. cvConvert(pGrayMat5, GrayImage5);
  65. cvConvert(pGrayMat6, GrayImage6);
  66. cvConvert(pGrayMat7, GrayImage7);
  67. cvNamedWindow( "ColorImage",CV_WINDOW_AUTOSIZE);
  68. cvNamedWindow( "GrayImage1",CV_WINDOW_AUTOSIZE);
  69. cvNamedWindow( "GrayImage2",CV_WINDOW_AUTOSIZE);
  70. cvNamedWindow( "GrayImage3",CV_WINDOW_AUTOSIZE);
  71. cvNamedWindow( "GrayImage4",CV_WINDOW_AUTOSIZE);
  72. cvNamedWindow( "GrayImage5",CV_WINDOW_AUTOSIZE);
  73. cvNamedWindow( "GrayImage6",CV_WINDOW_AUTOSIZE);
  74. cvNamedWindow( "GrayImage7",CV_WINDOW_AUTOSIZE);
  75. cvShowImage("ColorImage", ColorImage);
  76. cvShowImage("GrayImage1", GrayImage1);
  77. cvShowImage("GrayImage2", GrayImage2);
  78. cvShowImage("GrayImage3", GrayImage3);
  79. cvShowImage("GrayImage4", GrayImage4);
  80. cvShowImage("GrayImage5", GrayImage5);
  81. cvShowImage("GrayImage6", GrayImage6);
  82. cvShowImage("GrayImage7", GrayImage7);
  83. cvWaitKey(0);
  84. cvDestroyWindow("ColorImage");
  85. cvDestroyWindow("GrayImage1");
  86. cvDestroyWindow("GrayImage2");
  87. cvDestroyWindow("GrayImage3");
  88. cvDestroyWindow("GrayImage4");
  89. cvDestroyWindow("GrayImage5");
  90. cvDestroyWindow("GrayImage6");
  91. cvDestroyWindow("GrayImage7");
  92. cvReleaseImage(&ColorImage);
  93. cvReleaseImage(&GrayImage1);
  94. cvReleaseImage(&GrayImage2);
  95. cvReleaseImage(&GrayImage3);
  96. cvReleaseImage(&GrayImage4);
  97. cvReleaseImage(&GrayImage5);
  98. cvReleaseImage(&GrayImage6);
  99. cvReleaseImage(&GrayImage7);
  100. cvReleaseMat(&pGrayMat1);
  101. cvReleaseMat(&pGrayMat2);
  102. cvReleaseMat(&pGrayMat3);
  103. cvReleaseMat(&pGrayMat4);
  104. cvReleaseMat(&pGrayMat5);
  105. cvReleaseMat(&pGrayMat6);
  106. 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实现的更多相关文章

  1. 【转】图像灰度化方法总结及其VC实现

    转载自:  http://blog.csdn.net/likezhaobin/article/details/6915754 最近一段时间作者开始进行运动目标识别定位系统设计,本文以及后续的几篇文章都 ...

  2. java实现图像灰度化

    /*在研究Java实现将一张图片转成字符画的时候,发现将图像转化字符串是根据照片的灰度采用不同的字符画出来,形成一个灰度表.于是就研究了下关于灰度值这个东西,于是跳了一个大坑...因为鄙人用的ubun ...

  3. Java图像灰度化的实现过程解析

    概要 本文主要介绍了灰度化的几种方法,以及如何使用Java实现灰度化.同时分析了网上一种常见却并不妥当的Java灰度化实现,以及证明了opencv的灰度化是使用“加权灰度化”法 24位彩色图与8位灰度 ...

  4. c#图像灰度化、灰度反转、二值化

    图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*25 ...

  5. 深入学习OpenCV中图像灰度化原理,图像相似度的算法

    最近一段时间学习并做的都是对图像进行处理,其实自己也是新手,各种尝试,所以我这个门外汉想总结一下自己学习的东西,图像处理的流程.但是动起笔来想总结,一下却不知道自己要写什么,那就把自己做过的相似图片搜 ...

  6. python 图像处理中二值化方法归纳总结

    python图像处理二值化方法 1. opencv 简单阈值 cv2.threshold 2. opencv 自适应阈值 cv2.adaptiveThreshold 3. Otsu's 二值化 例子: ...

  7. java+opencv实现图像灰度化

    灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度,范围一般从0到255,白色为255,黑色为0.所谓灰度值是指色彩的浓淡程度,灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰 ...

  8. PhpStorm2017版激活方法、汉化方法以及界面配置

    PhpStorm激活和汉化文件下载网址:http://pan.baidu.com/s/1nuHF1St(提取密码:62cg) PHPMailer的介绍 PhpStorm是一个轻量级且便捷的PHP ID ...

  9. 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)(转)

    转自: https://zhuanlan.zhihu.com/p/22252270    ycszen 另可参考: https://blog.csdn.net/llx1990rl/article/de ...

随机推荐

  1. 虚拟货币——比特币行情价格分析

    最近挖以太币的朋友们在关注以太坊行情时,一定会发现以太币的价格对比之前上涨了不少.肯定有部分朋友想了解这次上涨的原因,我们特地为此查询了一番.因为比特币相当于虚拟货币中的黄金,它的价格波动会波及到其他 ...

  2. mac安装pkg 一直“正在验证” 卡着

    今天换了新mac, 但是之前wireshark(抓包工具) 不能用了 ,要安装Xquartz. 下载之后一直卡着, 网上找了半天没有解决方法. 最后我重启一下就好了... 重启一下. 2. 15款ma ...

  3. ES6的新特性(8)——数组的扩展

    数组的扩展 扩展运算符 含义 扩展运算符(spread)是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. console.log(...[1, 2, 3]) / ...

  4. 详讲H5、WebApp项目中常见的坑以及注意事项

    首先我们中会有一些常用的meta标签,如下: <!--防止手机中网页放大和缩小--> <meta name="viewport" content="wi ...

  5. tomcat配置服务

    1.在server中右键添加tomcat 2.双击tomcat打开配置窗口添加jvm参数 -Doapath="C:\exeye-workspace\exEyeWeb\oadoc"  ...

  6. yum源中默认好像是没有mysql的。为了解决这个问题,我们要先下载mysql的repo源。

    CentOS7的yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql的repo源. 1. 下载mysql的repo源 $ wget http://repo.mysql.com ...

  7. 把a文件删除b文件中的相同的行

    grep -vxFf b.txt a.txt > newa.txt 更好的方法是 comm - - b.txt a.txt > newa.txt 来自Tool in unix to sub ...

  8. Java compiler level does not match the version of the installed Java project facet. map解决方法

    右键项目"Properties",在弹出的"Properties"窗口左侧,单击"Project Facets",打开"Proje ...

  9. jmeter 配置元件之计数器Counter

    用jmeter生成数据 我用过几种以下几种方法 1.CSV Data Set Config  参数化 2.${_Random} ${_Random}是jmeter函数助手里面自带的一个函数,作用是返回 ...

  10. ie浏览器升级的正确姿势

    一.版本说明 1.当前IE浏览器分为一下几个版本:IE 6,IE 7,IE 8,IE 9,IE 10,IE 11 2.windows最高支持IE版本win xp:IE 8win 7 :IE 11win ...