【图像算法】彩色图像分割专题一:颜色空间3(部分源码)
SkySeraph May 5th 2011 HQU
Email:zgzhaobo@gmail.com 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; } }
空间转换函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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: zgzhaobo@gmail.com QQ:452728574
From: http://www.cnblogs.com/skyseraph/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的劳动成果