图像灰度化方法总结及其VC实现

来源:互联网 发布:个人可以注册域名吗 编辑:程序博客网 时间:2024/06/05 11:46
   最近一段时间作者开始进行运动目标识别定位系统设计,本文以及后续的几篇文章都是从一个图像处理初学者的角度来总结目标检测定位过程中所应用到的各种常见的算法,尤其是解决算法实现过程中由于粗心大意或者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,以这个亮度值表达图像的灰度值

HSLHSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法。这两种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观。

HSL即色相、饱和度、亮度(英语:Hue, Saturation, Lightness),又称HLS

HSV即色相、饱和度、明度(英语:Hue, Saturation, Value),又称HSB,其中B即英语:Brightness

  • 色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。
  • 饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
  • 明度(V),亮度(L),取0-100%。

从RGB到HSL或HSV的转换[编辑]

设 (r, g, b)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设max等价于r,gb中的最大者。设min等于这些值中的最小者。要找到在HSL空间中的 (h,s, l)值,这里的h ∈ [0, 360)度是角度的色相角,而s,l ∈ [0,1]是饱和度和亮度,计算为:

h =\begin{cases}0^\circ & \mbox{if } max = min \\60^\circ \times \frac{g - b}{max - min} + 0^\circ,   & \mbox{if } max = r \mbox{ and } g \ge b \\60^\circ \times \frac{g - b}{max - min} + 360^\circ,   & \mbox{if } max = r \mbox{ and } g < b \\60^\circ \times \frac{b - r}{max - min} + 120^\circ, & \mbox{if } max = g \\60^\circ \times \frac{r - g}{max - min} + 240^\circ, & \mbox{if } max = b\end{cases}
l = \begin{matrix} \frac{1}{2} \end{matrix} (max + min)
s =\begin{cases}0 & \mbox{if } l = 0 \mbox{ or } max = min \\\frac{max-min}{max+min} = \frac{max-min}{2l}, & \mbox{if } 0 < l \leq \frac{1}{2} \\\frac{max-min}{2-(max+min)} = \frac{max-min}{2-2l}, & \mbox{if } l > \frac{1}{2}\end{cases}

h的值通常规范化到位于0到360°之间。而h = 0用于max = min的(就是灰色)时候而不是留下h未定义。

HSL和HSV有同样的色相定义,但是其他分量不同。HSV颜色的sv的值定义如下:

s =\begin{cases}0, & \mbox{if } max = 0 \\\frac{max - min}{max} = 1 - \frac{min}{max}, & \mbox{otherwise}\end{cases}
v = max \,

从HSL到RGB的转换[编辑]

给定HSL空间中的 (h, s, l)值定义的一个颜色,带有h在指示色相角度的值域[0, 360)中,分别表示饱和度和亮度的sl在值域[0, 1]中,相应在RGB空间中的 (r,g, b)三原色,带有分别对应于红色、绿色和蓝色的r, gb也在值域[0, 1]中,它们可计算为:

首先,如果s = 0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r, gb都等于l。注意h的值在这种情况下是未定义的。

s ≠ 0的时候,可以使用下列过程:[1]

q=\begin{cases}l \times (1+s), & \mbox{if } l < \frac{1}{2} \\l+s-(l \times s), & \mbox{if } l \ge \frac{1}{2}\end{cases}
p = 2 \times l - q \,
h_k = {h \over 360} \, h进行单位换算成[0,1)转内)
t_R = h_k+\frac{1}{3} \,
t_G = h_k \,
t_B = h_k-\frac{1}{3} \,
\mbox{if } t_C < 0 \rightarrow t_C = t_C + 1.0 \quad \mbox{for each}\,C \in \{R,G,B\}
\mbox{if } t_C > 1 \rightarrow t_C = t_C - 1.0 \quad \mbox{for each}\,C \in \{R,G,B\}

对于每个颜色向量Color = (ColorR,ColorG, ColorB) = (r,g, b),

{Color}_C =\begin{cases}p+ \left((q-p) \times 6 \times t_C\right), & \mbox{if } t_C < \frac{1}{6}  \\q, & \mbox{if } \frac{1}{6} \le t_C < \frac{1}{2}  \\p+\left((q-p) \times 6 \times (\frac{2}{3} - t_C) \right), & \mbox{if } \frac{1}{2} \le t_C < \frac{2}{3} \\p, & \mbox{otherwise }\end{cases}
\mbox{for each}\,C \in \{R,G,B\}

从HSV到RGB的转换[编辑]

类似的,给定在HSV中 (h, s, v)值定义的一个颜色,带有如上的h,和分别表示饱和度和明度的sv变化于0到1之间,在RGB空间中对应的 (r,g, b)三原色可以计算为(R,G,B变化于0到1之间):

h_i \equiv \left\lfloor \frac{h}{60} \right\rfloor \pmod{6}
f = \frac{h}{60} - h_i
p = v \times (1 - s) \,
q = v \times (1 - f \times s) \,
t = v \times (1 - (1 - f) \times s) \,

对于每个颜色向量 (r, g, b),

(r, g, b) =\begin{cases}(v, t, p), & \mbox{if } h_i = 0  \\(q, v, p), & \mbox{if } h_i = 1  \\(p, v, t), & \mbox{if } h_i = 2  \\(p, q, v), & \mbox{if } h_i = 3  \\(t, p, v), & \mbox{if } h_i = 4  \\(v, p, q), & \mbox{if } h_i = 5  \\\end{cases}

3、代码实现

     本文旨在对整个实现原理及思路进行总结,因此以下基于OpenCv的基本函数实现这几种变化过程,至于位图以及其他形式的图像,在获取了图像原始数据后,处理方法都一样,仅需注意指针的位置操作即可。具体代码如下:

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

     这种方法实现了移位运算,避免了除法,效率上又有所提高。

     关于具体的代码效率问题,可以参考博文《由图像的灰度化看基本图像处理》。

文章出处:http://blog.csdn.net/likezhaobin/article/details/6915754

0 0