您的位置:首页 > 编程语言

RGB彩色图像与灰度图像转换 opencv实现 代码及分析

2012-09-25 15:42 1156 查看
#include <iostream>
#include <string>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace std;

int main(int argc, char** argv)
{
IplImage* src = cvLoadImage("lena.jpg");
if(!src){
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}

//创建2个窗体,分别显示源图像和处理后的灰度图
cvNamedWindow("RGB");
cvNamedWindow("GRAY");

//显示源图像
cvShowImage("RGB",src);

//创建一个源图像一样的IplImage指针
IplImage* dst = cvCreateImage(cvGetSize(src),src->depth,1);

//核心函数:色彩空间转换,转换类型为CV_BGR2GRAY
cvCvtColor(src,dst,CV_BGR2GRAY);

//显示灰度图
cvShowImage("GRAY",dst);

//释放资源
cvReleaseImage(&dst);

//Wait for the user to hit a key, then clean up the windows
cvWaitKey(0);

cvDestroyWindow("RGB");
cvDestroyWindow("GRAY");

while(1)
{
if(cvWaitKey(100)==27)
break;
}

cvReleaseImage(&src);
exit(0);

}
//运行环境:opencv2.3 / vs2010 / win7 64位

运行结果:



CvtColor函数的分析:

色彩空间转换

void cvCvtColor( const CvArr* src, CvArr* dst, int code );

src输入的 8-bit , 16-bit 或 32-bit 单倍精度浮点数影像.dst输出的 8-bit , 16-bit 或 32-bit 单倍精度浮点数影像.code色彩空间转换,通过定义 CV_<src_color_space>2<dst_color_space> 常数 (见下面).函数 cvCvtColor 将输入图像从一个色彩空间转换为另外一个色彩空间。函数忽略 IplImage 头中定义的 colorModel 和 channelSeq 域,所以输入图像的色彩空间应该正确指定 (包括通道的顺序,对RGB空间而言,BGR 意味着布局为 B0 G0 R0 B1 G1 R1 ... 层叠的 24-位格式,而 RGB 意味着布局为 R0 G0 B0 R1 G1 B1 ... 层叠的24-位格式. 函数做如下变换:

RGB 空间内部的变换,如增加/删除 alpha 通道,反相通道顺序,到16位 RGB彩色或者15位RGB彩色的正逆转换(Rx5:Gx6:Rx5),以及到灰度图像的正逆转换,使用:

RGB[A]->Gray: Y=0.212671*R + 0.715160*G + 0.072169*B + 0*A
Gray->RGB[A]: R=Y G=Y B=Y A=0

所有可能的图像色彩空间的相互变换公式列举如下:

RGB<=>XYZ (CV_BGR2XYZ, CV_RGB2XYZ, CV_XYZ2BGR, CV_XYZ2RGB):

|X|   |0.412411  0.357585  0.180454| |R|
|Y| = |0.212649  0.715169  0.072182|*|G|
|Z|   |0.019332  0.119195  0.950390| |B|

|R|   | 3.240479  -1.53715  -0.498535| |X|
|G| = |-0.969256   1.875991  0.041556|*|Y|
|B|   | 0.055648  -0.204043  1.057311| |Z|

RGB<=>YCrCb (CV_BGR2YCrCb, CV_RGB2YCrCb, CV_YCrCb2BGR, CV_YCrCb2RGB)

Y=0.299*R + 0.587*G + 0.114*B
Cr=(R-Y)*0.713 + 128
Cb=(B-Y)*0.564 + 128

R=Y + 1.403*(Cr - 128)
G=Y - 0.344*(Cr - 128) - 0.714*(Cb - 128)
B=Y + 1.773*(Cb - 128)

RGB=>HSV (CV_BGR2HSV,CV_RGB2HSV)

V=max(R,G,B)
S=(V-min(R,G,B))*255/V   if V!=0, 0 otherwise

(G - B)*60/S,  if V=R
H= 180+(B - R)*60/S,  if V=G
240+(R - G)*60/S,  if V=B

if H<0 then H=H+360

使用上面从 0° 到 360° 变化的公式计算色调(hue)值,确保它们被 2 除后能适用于8位。

RGB=>Lab (CV_BGR2Lab, CV_RGB2Lab)

|X|   |0.433910  0.376220  0.189860| |R/255|
|Y| = |0.212649  0.715169  0.072182|*|G/255|
|Z|   |0.017756  0.109478  0.872915| |B/255|

L = 116*Y1/3      for Y>0.008856
L = 903.3*Y      for Y<=0.008856

a = 500*(f(X)-f(Y))
b = 200*(f(Y)-f(Z))
where f(t)=t1/3              for t>0.008856
f(t)=7.787*t+16/116   for t<=0.008856

上面的公式可以参考 http://www.cica.indiana.edu/cica/faq/color_spaces/color.spaces.html

RGB=>HLS (CV_BGR2HLS, CV_RGB2HLS)

HSL 表示 hue(色相)、saturation(饱和度)、lightness(亮度)。有的地方也称为HSI,其中I表示intensity(强度)

转换公式见http://zh.wikipedia.org/wiki/HSL_%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4


Bayer=>RGB (CV_BayerBG2BGR, CV_BayerGB2BGR, CV_BayerRG2BGR, CV_BayerGR2BGR, CV_BayerBG2RGB, CV_BayerRG2BGR, CV_BayerGB2RGB, CV_BayerGR2BGR, CV_BayerRG2RGB, CV_BayerBG2BGR, CV_BayerGR2RGB, CV_BayerGB2BGR)

Bayer 模式被广泛应用于 CCD 和 CMOS 摄像头. 它允许从一个单独平面中得到彩色图像,该平面中的 R/G/B 象素点被安排如下:

RGRGR
GBGBG
RGRGR
GBGBG
RGRGR
GBGBG
对像素输出的RGB份量由该像素的1、2或者4邻域中具有相同颜色的点插值得到。以上的模式可以通过向左或者向上平移一个像素点来作一些修改。转换常量CV_BayerC1C22{RGB|RGB}中的两个字母C1和C2表示特定的模式类型:颜色份量分别来自于第二行,第二和第三列。比如说,上述的模式具有很流行的"BG"类型。

参考链接:

1.http://www.opencv.org.cn/index.php/Cv%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86#CvtColor

2.http://www.cnblogs.com/davy2495/archive/2012/02/11/2346806.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息