1. BGR变32:cvConvertScale

2.BGR32-》HSV32:cvCvtColor

3.分HSV32为H32,S32,V32:cvSplit

4.压缩H32,S32,V32为H8,S8,V8范围0~255:cvConvertScale

5.合并H8,S8,V8为HSV8:cvMerge

6.保存HSV8:cvSaveImage

7.读取HSV8:cvLoadImage

8.分离HSV8为H8,S8,V8:cvSplit

9.扩展H8,S8,V8为H32,S32,V32,第4步逆过程:cvSplit

10.合并H32,S32,V32为HSV32:cvMerge

11.HSV32-》BGP32:cvCvtColor

12.BGP32变BGP8

总结:

BGR转换为HSV用32位,保存压缩到8位,显示用BGR8位

说明:

1.要1,2步骤因为8位的char型取值范围只能到255,而H的取值为360,所以正常情况下没有1,2步骤直接用cvCvtColor转换的话H的取值压缩到0~180,

这样转换之后H取值0~360,S取值0~1,V取值0~255

2.因为32位float型的图像不能用cvSaveImage保存,所以要转换为8位char型图像,分别转换H,S,V,范围为0~255,然后合成并且保存

3.要正常显示必须BGR8位

程序:

wKioL1PsfhzjzQ_2AATswBbnDig375.jpg

说明:

图像从左到右分别为原图,BGR32位图,HSV32位图,压缩为8位保存前的HSV图,加载的图(和原图有点差别,不懂为什么),还原的32位HSV图,BGR32位图,还原的原图

代码:

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <iostream>
int BGR2HSV(int argc,char** argv)
{
IplImage* BGRImage=cvLoadImage("e:\\picture\\4.jpg");
cvNamedWindow("BGP");
cvShowImage("BGP",BGRImage);
//步骤1:BGR变32
IplImage* BGR32Float=cvCreateImage(cvGetSize(BGRImage),32,3);
IplImage* HSV32Float=cvCreateImage(cvGetSize(BGRImage),32,3);
IplImage* H32Float=cvCreateImage(cvGetSize(BGRImage),32,1);
IplImage* S32Float=cvCreateImage(cvGetSize(BGRImage),32,1);
IplImage* V32Float=cvCreateImage(cvGetSize(BGRImage),32,1);
cvConvertScale(BGRImage,BGR32Float,1.0,0);
cvNamedWindow("BGR32Float");
cvShowImage("BGR32Float",BGR32Float);
//步骤2:BGR32-》HSV32
cvCvtColor(BGR32Float,HSV32Float,CV_BGR2HSV);
cvNamedWindow("HSV32Float");
cvShowImage("HSV32Float",HSV32Float);
//步骤3:分HSV32为H32,S32,V32
cvSplit(HSV32Float,H32Float,S32Float,V32Float,NULL);
//显示H大于300的值
for(int y=0;y<H32Float->height;y++)
{
for(int x=0;x<H32Float->width;x++)
{
float value=cvGetReal2D(H32Float,y,x);
if(value>300)
std::cout<<value<<" ";
}
}
//步骤4:压缩H32,S32,V32为H8,S8,V8范围0~255
IplImage* HSV8Char=cvCreateImage(cvGetSize(BGRImage),8,3);
IplImage* H8Char=cvCreateImage(cvGetSize(BGRImage),8,1);
IplImage* S8Char=cvCreateImage(cvGetSize(BGRImage),8,1);
IplImage* V8Char=cvCreateImage(cvGetSize(BGRImage),8,1);
cvConvertScale(H32Float,H8Char,(1.0/360)*255,0);
cvConvertScale(S32Float,S8Char,255,0);
cvConvertScale(V32Float,V8Char,1,0);
//步骤5:合并H8,S8,V8为HSV8
cvMerge(H8Char,S8Char,V8Char,NULL,HSV8Char);
cvNamedWindow("HSV8Char");
cvShowImage("HSV8Char",HSV8Char);
//步骤6:保存HSV8
cvSaveImage("c:\\4HSV.jpg",HSV8Char);
//步骤7:读取HSV8
IplImage* HSVSrc=cvLoadImage("c:\\4HSV.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
cvNamedWindow("4HSV");
cvShowImage("4HSV",HSVSrc);
IplImage* HSrc8=cvCreateImage(cvGetSize(HSVSrc),8,1);
IplImage* ***c8=cvCreateImage(cvGetSize(HSrc8),8,1);
IplImage* VSrc8=cvCreateImage(cvGetSize(HSrc8),8,1);
IplImage* HSVSrc32Float=cvCreateImage(cvGetSize(HSrc8),32,3);
IplImage* HSVDst32=cvCreateImage(cvGetSize(HSrc8),32,3);
IplImage* HDst32=cvCreateImage(cvGetSize(HSrc8),32,1);
IplImage* SDst32=cvCreateImage(cvGetSize(HSrc8),32,1);
IplImage* VDst32=cvCreateImage(cvGetSize(HSrc8),32,1);
IplImage* BGRDst32=cvCreateImage(cvGetSize(HSrc8),32,3);
IplImage* BGRDst8=cvCreateImage(cvGetSize(HSrc8),8,3);
cvZero(HSrc8);
cvZero(***c8);
cvZero(VSrc8);
cvZero(HSVSrc32Float);
cvZero(HSVDst32);
cvZero(HDst32);
cvZero(SDst32);
cvZero(VDst32);
cvZero(BGRDst32);
cvZero(BGRDst8);
//步骤8:分离HSV8为H8,S8,V8
cvSplit(HSVSrc,HSrc8,***c8,VSrc8,NULL);
//步骤9:扩展H8,S8,V8为H32,S32,V32,第4步逆过程
cvConvertScale(HSrc8,HDst32,(1.0/255)*360,0);
cvConvertScale(***c8,SDst32,1.0/255,0);
cvConvertScale(VSrc8,VDst32,1,0);
//步骤10:合并H32,S32,V32为HSV32
cvMerge(HDst32,SDst32,VDst32,NULL,HSVDst32);
cvNamedWindow("HSVDst32");
cvShowImage("HSVDst32",HSVDst32);
//步骤11:HSV32-》BGP32
cvCvtColor(HSVDst32,BGRDst32,CV_HSV2BGR);
cvNamedWindow("BGRDst32");
cvShowImage("BGRDst32",BGRDst32);
//步骤12:BGP32变BGP8
cvConvertScale(BGRDst32,BGRDst8,1,0);
cvNamedWindow("BGRDst8");
cvShowImage("BGRDst8",BGRDst8);
cvWaitKey(0);
cvDestroyWindow("BGP");
cvReleaseImage(&BGRImage);
cvDestroyWindow("HSV8Char");
cvReleaseImage(&HSV8Char);
cvDestroyWindow("BGRDst32");
cvReleaseImage(&BGRDst32);
//cvDestroyWindow("4HSV");
//cvReleaseImage(&HSVSrc);
//cvDestroyWindow("BGR32Float");
//cvReleaseImage(&BGR32Float);
cvWaitKey(0);
return 0;
}