zoukankan      html  css  js  c++  java
  • 【图像算法】彩色图像分割专题一:颜色空间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/

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

  • 相关阅读:
    【总结】——Repeater控件详细应用
    【SelfIntroduction in Optional Course】
    【软考之后的思考】
    打印菱形图案printDiamond
    【这是来自Word 2010 的Test】
    【30岁前挣够500万】
    【总结 CKEditor 和 CKFinder 的配置和使用】
    linux压缩(解压缩)命令详解 [转]
    关于吞吐量和并发度 [转]
    Linux的五个查找命令 [转]
  • 原文地址:https://www.cnblogs.com/skyseraph/p/2038317.html
Copyright © 2011-2022 走看看