【图像算法】彩色图像分割专题一:颜色空间3(部分源码)

【图像算法】彩色图像分割专题一:颜色空间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;
        }
}

  空间转换函数

 

View Code
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/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的劳动成果


作者:skyseraph
出处:http://www.cnblogs.com/skyseraph/
更多精彩请直接访问SkySeraph个人站点:http://skyseraph.com//
Email/GTalk: zgzhaobo@gmail.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2011-05-05 22:16  SkySeraph  阅读(10145)  评论(3编辑  收藏  举报