您的位置:首页 > 运维架构

OpenCV之RGB与HSV颜色空间的转换

2014-10-18 20:10 330 查看
关于HSV颜色空间,还有一些参考性的博客,如http://blog.sina.com.cn/s/blog_6a22365901012nxl.html

HSV的介绍请参见维基百科:http://en.wikipedia.org/wiki/HSL_and_HSV,与其类似的颜色空间还有HSL(或称HLS)和HSI。本文有两则代码,代码一,自实现了RGB颜色空间与HSV颜色空间之间的转换,并与OpenCV中的cvCvtColor进行了比较;代码二,实现了一个HSV颜色盘。

代码一:

[cpp] view
plaincopy





//====================================================================

// 作者 : quarryman

// 邮箱 : quarrying{at}qq.com

// 主页 : http://blog.csdn.net/quarryman

// 日期 : 2013年12月22日

// 描述 : RGB颜色空间与HSV颜色空间之间的转换

//====================================================================

#include <cv.h>

#include <highgui.h>

#define max(a,b) (((a)>(b))?(a):(b))

#define min(a,b) (((a)<(b))?(a):(b))



IplImage* kcvRGB2HSV(IplImage* img)

{

int w=img->width;

int h=img->height;

IplImage* dst=cvCreateImage(cvSize(w,h),8,3);

for(int j=0;j<w;++j)

{

for(int i=0;i<h;++i)

{

int b=CV_IMAGE_ELEM(img,uchar,i,j*3+0);

int g=CV_IMAGE_ELEM(img,uchar,i,j*3+1);

int r=CV_IMAGE_ELEM(img,uchar,i,j*3+2);

int maxval=max(b,max(g,r));

int minval=min(b,min(g,r));

int v=maxval;

double diff=maxval-minval;

int s=diff*255/(v+DBL_EPSILON);



double h=0;

diff=60/(diff+DBL_EPSILON);

if(v==r)

{

h=(g-b)*diff;

}

else if(v==g)

{

h=(b-r)*diff+120.f;

}

else

{

h=(r-g)*diff+240.f;

}

if( h<0)

{

h+=360.f;

}

CV_IMAGE_ELEM(dst,uchar,i,j*3+0)=h/2;

CV_IMAGE_ELEM(dst,uchar,i,j*3+1)=s;

CV_IMAGE_ELEM(dst,uchar,i,j*3+2)=v;

}

}

return dst;

}



IplImage* kcvHSV2RGB(IplImage* img)

{

int w=img->width;

int h=img->height;

IplImage* dst=cvCreateImage(cvSize(w,h),8,3);

for(int j=0;j<w;++j)

{

for(int i=0;i<h;++i)

{

int h=CV_IMAGE_ELEM(img,uchar,i,j*3+0);

int s=CV_IMAGE_ELEM(img,uchar,i,j*3+1);

int v=CV_IMAGE_ELEM(img,uchar,i,j*3+2);

int c=(double)v*s/255;

double hh=(double)h*2/60;

double x=c*(1-abs(fmod(hh,2)-1));

int r,g,b;

if(0<=hh&&hh<1)

{

r=c;g=x;b=0;

}

else if(1<=hh&hh<2)

{

r=x;g=c;b=0;

}

else if(2<=hh&&hh<3)

{

r=0;g=c;b=x;

}

else if(3<=hh&&hh<4)

{

r=0;g=x;b=c;

}

else if(4<=hh&&hh<5)

{

r=x;g=0;b=c;

}

else

{

r=c;g=0;b=x;

}

int m=v-c;

CV_IMAGE_ELEM(dst,uchar,i,j*3+0)=b+m;

CV_IMAGE_ELEM(dst,uchar,i,j*3+1)=g+m;

CV_IMAGE_ELEM(dst,uchar,i,j*3+2)=r+m;

}

}

return dst;

}



int main( int argc, char** argv )

{

IplImage* img=cvLoadImage("lena.jpg",1);

IplImage* hsv=kcvRGB2HSV(img);

IplImage* hsv2=cvCreateImage(cvGetSize(img),8,3);

cvCvtColor(img,hsv2,CV_BGR2HSV);

// 注意不能是下面的语句

// cvCvtColor(img,hsv2,CV_RGB2HSV);

IplImage* dst=kcvHSV2RGB(hsv);

IplImage* dst2=cvCreateImage(cvGetSize(img),8,3);

cvCvtColor(hsv2,dst2,CV_HSV2BGR);

// 注意不能是下面的语句

// cvCvtColor(hsv2,dst2,CV_HSV2RGB);



cvNamedWindow("img");

cvNamedWindow("hsv");

cvNamedWindow("hsv2");

cvNamedWindow("dst");

cvNamedWindow("dst2");

cvShowImage("img",img);

cvShowImage("hsv",hsv);

cvShowImage("hsv2",hsv2);

cvShowImage("dst",dst);

cvShowImage("dst2",dst2);

cvWaitKey(0);

cvDestroyAllWindows();

cvReleaseImage(&img);

cvReleaseImage(&hsv);

cvReleaseImage(&hsv2);

cvReleaseImage(&dst);

cvReleaseImage(&dst2);

return 0;

}

代码二:

[cpp] view
plaincopy





//====================================================================

// 作者 : quarryman

// 邮箱 : quarrying{at}qq.com

// 主页 : http://blog.csdn.net/quarryman

// 日期 : 2013年12月22日

// 描述 : HSV颜色盘

//====================================================================

#include <cv.h>

#include <highgui.h>

#define max(a,b) (((a)>(b))?(a):(b))

#define min(a,b) (((a)<(b))?(a):(b))



double module(CvPoint pt)

{

return sqrt((double)pt.x*pt.x+pt.y*pt.y);

}



double distance(CvPoint pt1,CvPoint pt2)

{

int dx=pt1.x-pt2.x;

int dy=pt1.y-pt2.y;

return sqrt((double)dx*dx+dy*dy);

}



double cross(CvPoint pt1,CvPoint pt2)

{

return pt1.x*pt2.x+pt1.y*pt2.y;

}



double angle(CvPoint pt1,CvPoint pt2)

{

return acos(cross(pt1,pt2)/(module(pt1)*module(pt2)+DBL_EPSILON));

}



// p和c其中一个是圆心

int inCircle(CvPoint p, CvPoint c, int r)

{

int dx=p.x-c.x;

int dy=p.y-c.y;

return dx*dx+dy*dy<=r*r?1:0;

}



IplImage* createPlate(int radius)

{

IplImage* img=cvCreateImage(cvSize(radius<<1,radius<<1),8,3);

cvSet(img,cvScalar(0,0,255));

int w=img->width;

int h=img->height;

int cx=w>>1;

int cy=h>>1;

CvPoint pt1=cvPoint(cx,0);



for(int j=0;j<w;++j)

{

for(int i=0;i<h;++i)

{

CvPoint pt2=cvPoint(j-cx,i-cy);

if(inCircle(cvPoint(0,0),pt2,radius))

{

int theta=angle(pt1,pt2)*180/3.1415926;

if(i>cx)

{

theta=-theta+360;

}

CV_IMAGE_ELEM(img,uchar,i,j*3+0)=theta/2;

CV_IMAGE_ELEM(img,uchar,i,j*3+1)=module(pt2)/cx*255;

CV_IMAGE_ELEM(img,uchar,i,j*3+2)=255;

}

}

}

IplImage* dst=cvCreateImage(cvGetSize(img),8,3);

cvCvtColor(img,dst,CV_HSV2BGR);

cvReleaseImage(&img);

return dst;

}



int main( int argc, char** argv )

{

IplImage* img=createPlate(300);

cvNamedWindow("img");

cvShowImage("img",img);

cvWaitKey(0);

cvDestroyAllWindows();

cvReleaseImage(&img);

return 0;

}

效果图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: