原文摘自:http://blog.csdn.net/quarryman/article/details/17474861
HSV的介绍请参见维基百科:http://en.wikipedia.org/wiki/HSL_and_HSV,与其类似的颜色空间还有HSL(或称HLS)和HSI。本文有两则代码,代码一,自实现了RGB颜色空间与HSV颜色空间之间的转换,并与OpenCV中的cvCvtColor进行了比较;代码二,实现了一个HSV颜色盘。
代码一:
-(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 max1 = (g>r)?g:r;
int maxval = (b>max1)?b:max1;
int min1 = (g<r)?g:r;
int minval = (b<min1)?b:min1;
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;
}
代码二:
- //====================================================================
- // 作者 : 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;
- }
效果图如下: