【图像算法】彩色图像分割专题一:颜色空间3(部分源码)
SkySeraph May 5th 2011 HQU
Email:[email protected] QQ:452728574
Latest Modified Date:May 5th 2011 HQU
原理:http://www.cnblogs.com/skyseraph/archive/2011/05/03/2035643.html
结果:http://www.cnblogs.com/skyseraph/archive/2011/05/05/2038308.html
核心源码
空间转换响应
////////////////////////////////////////////////////////////////////////// // 空间转换 ////////////////////////////////////////////////////////////////////////// void CColorSegDlg::OnProcess() { // UpdateData(TRUE); //验证 if (TheImage==NULL) { MessageBox("Please Load Image!"); return; } if (m_ColorSpace==-1) { MessageBox("Please choose a Space!"); return; } if( ToDisplayCtr2 ) cvReleaseImage( &ToDisplayCtr2 ); //cvZero ToDisplayCtr2 = cvCloneImage(TheImage); //ToDisplayCtr2 "初始化" ColorSpaceCov(ToDisplayCtr1,ToDisplayCtr2); // 备份 if(ToDisplayCtr2BK) cvReleaseImage(&ToDisplayCtr2BK); ToDisplayCtr2BK = cvCloneImage(ToDisplayCtr2); } void CColorSegDlg::ColorSpaceCov(IplImage *sr, IplImage *dst) // ColorSpace Convertion { IplImage *temp1=cvCreateImage(cvGetSize(sr),IPL_DEPTH_8U,1); IplImage *temp2=cvCreateImage(cvGetSize(sr),IPL_DEPTH_8U,1); IplImage *temp3=cvCreateImage(cvGetSize(sr),IPL_DEPTH_8U,1); // 按钮选择 if(m_ColorSpace==0) //HSV-OpenCV { cvCvtColor(sr,dst,CV_BGR2HSV); } if(m_ColorSpace==1) //Lab-OpenCV { cvCvtColor(sr,dst,CV_BGR2Lab); } if (m_ColorSpace==2) //XYZ-OpenCV { cvCvtColor(sr,dst,CV_BGR2XYZ); } if(m_ColorSpace==3) //YCrCb-OpenCV { cvCvtColor(sr,dst,CV_BGR2YCrCb); } if(m_ColorSpace==4) //Luv-OpenCV { cvCvtColor(sr,dst,CV_BGR2Luv); } if(m_ColorSpace==5) //HSI_Me -My { RGBtoHSI(sr,dst); } if(m_ColorSpace==6) //HLS-OpenCV { cvCvtColor(sr,dst,CV_BGR2HLS); } if(m_ColorSpace==7) //RGB-OpenCV { dst = sr; } if(m_ColorSpace==8) //Test-My { RGBtoABC(sr,dst); } DrawPicToHDC(dst,IDC_ImgShowCtrl2); // 各分量/通道 for (int i=0;i<dst->height;i++) { for (int j=0;j<dst->width;j++) { // 采用C++外壳的方式来获取像素元素 if(m_ColorSpace==0) //HSV { HsvImage imgA(dst); ((uchar *)(temp1->imageData+i*temp1->widthStep))[j]=imgA[i][j].h; ((uchar *)(temp2->imageData+i*temp2->widthStep))[j]=imgA[i][j].s; ((uchar *)(temp3->imageData+i*temp3->widthStep))[j]=imgA[i][j].v; } if(m_ColorSpace==1) //Lab { LabImage imgB(dst); ((uchar *)(temp1->imageData+i*temp1->widthStep))[j]=imgB[i][j].l; ((uchar *)(temp2->imageData+i*temp2->widthStep))[j]=imgB[i][j].a; ((uchar *)(temp3->imageData+i*temp3->widthStep))[j]=imgB[i][j].b; } if(m_ColorSpace==2) //XYZ { XyzImage imgC(dst); ((uchar *)(temp1->imageData+i*temp1->widthStep))[j]=imgC[i][j].x; ((uchar *)(temp2->imageData+i*temp2->widthStep))[j]=imgC[i][j].y; ((uchar *)(temp3->imageData+i*temp3->widthStep))[j]=imgC[i][j].z; } // 采用指针访问的方式来获取像素元素 if(m_ColorSpace==3||m_ColorSpace==4 ||m_ColorSpace==6 ||m_ColorSpace==7) //YCrCb/Luv { ((uchar *)(temp1->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+0]; ((uchar *)(temp2->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+1]; ((uchar *)(temp3->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+2]; } if(m_ColorSpace==5 || m_ColorSpace==8) //HSI_Me { ((uchar *)(temp1->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+0]; ((uchar *)(temp2->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+1]; ((uchar *)(temp3->imageData+i*temp1->widthStep))[j]= ((uchar *)(dst->imageData+i*dst->widthStep))[j*dst->nChannels+2]; } } } // ToDisplayCtr3 = cvCloneImage(temp1); ToDisplayCtr4 = cvCloneImage(temp2); ToDisplayCtr5 = cvCloneImage(temp3); cvSaveImage("A.jpg", ToDisplayCtr3); cvSaveImage("B.jpg", ToDisplayCtr4); cvSaveImage("C.jpg", ToDisplayCtr5); // DrawPicToHDC(ToDisplayCtr3,IDC_ImgShowCtrl3); DrawPicToHDC(ToDisplayCtr4,IDC_ImgShowCtrl4); DrawPicToHDC(ToDisplayCtr5,IDC_ImgShowCtrl5); // 备份 if(ToDisplayCtr3BK) cvReleaseImage(&ToDisplayCtr3BK); ToDisplayCtr3BK = cvCloneImage(ToDisplayCtr3); if(ToDisplayCtr4BK) cvReleaseImage(&ToDisplayCtr4BK); ToDisplayCtr4BK = cvCloneImage(ToDisplayCtr4); if(ToDisplayCtr5BK) cvReleaseImage(&ToDisplayCtr5BK); ToDisplayCtr5BK = cvCloneImage(ToDisplayCtr5); // 释放资源 cvReleaseImage(&temp1); cvReleaseImage(&temp2); cvReleaseImage(&temp3); return; }
响应模块函数
void CColorSegDlg::RGBtoHSI(IplImage *src, IplImage *dst) // RGBimg to HSIimg { IplImage* a = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); IplImage* b = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); IplImage* c = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); MyColorSpace pColorSpace; // 源图像信息 int width = src->width; int height = src->height; int channel = src->nChannels; // 色彩空间转化 int i,j; double R,G,B; double X,Y,Z; for(j=0;j<height;j++) for(i=0;i<width;i++) { B = ((uchar*)(src->imageData + j*src->widthStep))[i*channel]; G = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+1]; R = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+2]; // RGB to *** pColorSpace.MyRGB2HSI(R,G,B,X,Y,Z); //HSI //pColorSpace.RGB2HSV(R,G,B,X,Y,Z,TRUE);//HSV //pColorSpace.RGB2YUV(R,G,B,X,Y,Z);//YUV //pColorSpace.RGB2YCbCr(R,G,B,X,Y,Z);//YCbCr // ***图像 ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels] = (uchar)X; ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels+1] = (uchar)Y; ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels+2] = (uchar)Z; // ***通道图像 ((uchar *)(a->imageData + j*a->widthStep))[i*a->nChannels] = (uchar)X; ((uchar *)(b->imageData + j*b->widthStep))[i*b->nChannels] = (uchar)Y; ((uchar *)(c->imageData + j*c->widthStep))[i*c->nChannels] = (uchar)Z; } } void CColorSegDlg::RGBtoABC(IplImage *src, IplImage *dst) { IplImage* a = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); IplImage* b = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); IplImage* c = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); MyColorSpace pColorSpace; // 源图像信息 int width = src->width; int height = src->height; int channel = src->nChannels; // 色彩空间转化 int i,j; double R,G,B; double X,Y,Z; for(j=0;j<height;j++) for(i=0;i<width;i++) { B = ((uchar*)(src->imageData + j*src->widthStep))[i*channel]; G = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+1]; R = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+2]; // RGB to *** //pColorSpace.MyRGB2YUV(R,G,B,X,Y,Z); //HSV pColorSpace.MyRGB2HSV(R,G,B,X,Y,Z,1); // ***图像 ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels] = (uchar)X; ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels+1] = (uchar)Y; ((uchar *)(dst->imageData + j*dst->widthStep))[i*dst->nChannels+2] = (uchar)Z; // ***通道图像 ((uchar *)(a->imageData + j*a->widthStep))[i*a->nChannels] = (uchar)X; ((uchar *)(b->imageData + j*b->widthStep))[i*b->nChannels] = (uchar)Y; ((uchar *)(c->imageData + j*c->widthStep))[i*c->nChannels] = (uchar)Z; } } void CColorSegDlg::HSItoRGB(IplImage *hsi) // HSIimg to RGBimg { MyColorSpace pColorSpace; int width = hsi->width; int height = hsi->height; for(int row=0; row<height; row++) for(int col=0; col<width; col++) { int step = row*hsi->widthStep; uchar H = ((uchar *)(hsi->imageData+step))[col*hsi->nChannels]; uchar S = ((uchar *)(hsi->imageData+step))[col*hsi->nChannels+1]; uchar I = ((uchar *)(hsi->imageData+step))[col*hsi->nChannels+2]; int R,G,B; pColorSpace.HSI2RGB(H, S, I, R, G, B); ((uchar *)(hsi->imageData+step))[col*hsi->nChannels] = (uchar)B; ((uchar *)(hsi->imageData+step))[col*hsi->nChannels+1] = (uchar)G; ((uchar *)(hsi->imageData+step))[col*hsi->nChannels+2] = (uchar)R; } }
空间转换函数
1 // =============================================== //
2 // RGB -- HSV
3 // =============================================== //
4 /* ************************************************
5 * way:
6 1. First compute the base H,S and V
7 H - Hue if Color1 is Max H = ( Color2 - Color3 ) / ( Max - Min )
8 S - Saturation S = Max - Min / Max;
9 V - Value V = max of either R,G or B
10 2. Normalize the values
11 General H,S,V has ranges:
12 0 <= Hue <= 360
13 0 <= Sat <= 100
14 0 <= Val <= 255
15 3. H - Hue is set based on the dominant color. It has three different basic ranges based on what that color is.
16 if Red H *= 60
17 if Green H += 2; H *= 60
18 if Blue H += 4; H *= 60
19 4. In essence this forces the recognizable 0-360 value seen in hue
20 5. S - May be S *= 100 , I like in some cases to keep it from 0 to 1
21 6. V - is V *= 255
22 * NORM: used to decide whether to output traditional HSV values where
23 0 <= S <= 100 and 0 <= V <= 255. //TRUE
24 Else we keep the values at a norm where //FASLE
25 0 <= S <= 1 and 0 <= V <= 1.
26 * Note:
27 R, G and B are assumed to be between 0 and 255
28 Floats can be used in place of doubles. It depends on whether you want precision or speed
29 * From: http://ilab.usc.edu/wiki/index.php/HSV_And_H2SV_Color_Space
30 * zhaobo
31 ************************************************* */
32 void MyColorSpace::MyRGB2HSV( const double R, const double G, const double B,
33 double & H, double & S, double & V,
34 const bool NORM)
35 {
36 if ((B > G) && (B > R)) // Blue is Max
37 {
38 // set V
39 V = B;
40 if (V != 0 )
41 {
42 double min;
43 if (R > G)
44 min = G;
45 else
46 min = R;
47 // compute S by delta
48 const double delta = V - min;
49 if (delta != 0 )
50 {
51 S = (delta / V);
52 H = 4 + (R - G) / delta;
53 }
54 else
55 {
56 S = 0 ;
57 H = 4 + (R - G);
58 }
59 // H
60 H *= 60 ;
61 if (H < 0 )
62 H += 360 ;
63 if ( ! NORM) // FALSE 归一化
64 V = (V / 255 );
65 else
66 S *= ( 100 );
67 }
68 else
69 {
70 S = 0 ;
71 H = 0 ;
72 }
73 }
74 else if (G > R)
75 {
76 V = G;
77 if (V != 0 )
78 {
79 double min;
80 if (R > B)
81 min = B;
82 else
83 min = R;
84 const double delta = V - min;
85 if (delta != 0 )
86 {
87 S = (delta / V);
88 H = 2 + (B - R) / delta;
89 }
90 else
91 {
92 S = 0 ;
93 H = 2 + (B - R);
94 }
95 H *= 60 ;
96 if (H < 0 )
97 H += 360 ;
98 if ( ! NORM)
99 V = (V / 255 );
100 else
101 S *= ( 100 );
102 }
103 else
104 {
105 S = 0 ;
106 H = 0 ;
107 }
108 }
109 else
110 {
111 V = R;
112 if (V != 0 )
113 {
114 double min;
115 if (G > B)
116 min = B;
117 else
118 min = G;
119 const double delta = V - min;
120 if (delta != 0 )
121 {
122 S = (delta / V);
123 H = (G - B) / delta;
124 }
125 else
126 {
127 S = 0 ;
128 H = (G - B);
129 }
130 H *= 60 ;
131 if (H < 0 )
132 H += 360 ;
133 if ( ! NORM)
134 V = (V / 255 );
135 else
136 S *= ( 100 );
137 }
138 else
139 {
140 S = 0 ;
141 H = 0 ;
142 }
143 }
144 }
145
146 // =============================================== //
147 // RGB -- HSI
148 // =============================================== //
149 // ------------------------------------------------/
150 void MyColorSpace::MyRGB2HSI( double R, double G, double B, double & H, double & S, double & I)
151 {
152 // find out the min, mid, and max of R, G, B
153 double min, mid, max;
154 MyMath pMath;
155 min = pMath.ReturnMaxMidMinInThree(R,G,B, 1 );
156 mid = pMath.ReturnMaxMidMinInThree(R,G,B, 2 );
157 max = pMath.ReturnMaxMidMinInThree(R,G,B, 3 );
158
159 // 归一化(亮度数值最大为1)
160 double r,g,b;
161 r = ( double )R / ( double )(R + G + B);
162 g = ( double )G / ( double )(R + G + B);
163 b = ( double )B / ( double )(R + G + B);
164 /*
165 r = (double)R/255;
166 g = (double)G/255;
167 b = (double)B/255;
168 */
169
170 // 求H/S/I(几何推导法)
171 // I: 0~100% 扩充到255
172 I = (( double )(R + G + B) / 3 / 255 ) * 255 ;
173
174 // S:0~100% 扩充到100
175 S = ( 1 - 3 * min / ( double )(R + G + B)) * 100 ;
176
177 // H:0~360 转换为弧度
178 double h;
179 if (B <= G)
180 h = acos( 0.5 * (r - g + r - b) / sqrt((r - g) * (r - g) + (r - b) * (g - b) + DELT) );
181 else
182 h = 2 * PI - acos( 0.5 * (r - g + r - b) / sqrt((r - g) * (r - g) + (r - b) * (g - b) + DELT) );
183 H = h * 180 / PI;
184 }
185 。。。
Author: SKySeraph
Email/GTalk: [email protected] QQ:452728574
From: http://www.cnblogs.com/skyseraph/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的劳动成果