Opencv中HIS和RGB图像互转代码,添加一个类名为:HSI_RGB_TRAN,以下分别为.h .cpp文件
HSI_RGB_TRAN.h
#include <cv.h>
#include <math.h>
#include <highgui.h>
#include <vector>
using namespace std;
typedef struct HSI_Data
{
int H;
int S;
int I;
}HSI_Data;
typedef struct HSI_Data_Uchar
{
uchar H;
uchar S;
uchar I;
}HSI_Data_Uchar;
class HSI_RGB_TRAN
{
public:
HSI_RGB_TRAN(void);
~HSI_RGB_TRAN(void);
IplImage*HSI_RGB_TRAN::HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I);
void HSI_RGB_TRAN::RGB2HSImage(IplImage*img,CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I);
IplImage*HSI_RGB_TRAN:: catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I);
};
HSI_RGB_TRAN.cpp
#include "stdafx.h"
#include "HSI_RGB_TRAN.h"
HSI_RGB_TRAN::HSI_RGB_TRAN(void)
{
}
HSI_RGB_TRAN::~HSI_RGB_TRAN(void)
{
}
IplImage*HSI_RGB_TRAN::HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
{
IplImage * RGB_Image = cvCreateImage(cvGetSize(HSI_H), IPL_DEPTH_8U, 3 );
int iB, iG, iR;
for(int i = 0; i < RGB_Image->height; i++)
{
for(int j = 0; j < RGB_Image->width; j++)
{
// 该点的色度H
double dH = cvmGet( HSI_H, i, j );
// 该点的色饱和度S
double dS = cvmGet( HSI_S, i, j );
// 该点的亮度
double dI = cvmGet( HSI_I, i, j );
double dTempB, dTempG, dTempR;
// RG扇区
if(dH < 120 && dH >= 0)
{
// 将H转为弧度表示
dH = dH * 3.1415926 / 180;
dTempB = dI * (1 - dS);
dTempR = dI * ( 1 + (dS * cos(dH))/cos(3.1415926/3 - dH) );
dTempG = (3 * dI - (dTempR + dTempB));
}
// GB扇区
else if(dH < 240 && dH >= 120)
{
dH -= 120;
// 将H转为弧度表示
dH = dH * 3.1415926 / 180;
dTempR = dI * (1 - dS);
dTempG = dI * (1 + dS * cos(dH)/cos(3.1415926/3 - dH));
dTempB = (3 * dI - (dTempR + dTempG));
}
// BR扇区
else
{
dH -= 240;
// 将H转为弧度表示
dH = dH * 3.1415926 / 180;
dTempG = dI * (1 - dS);
dTempB = dI * (1 + (dS * cos(dH))/cos(3.1415926/3 - dH));
dTempR = (3* dI - (dTempG + dTempB));
}
iB = dTempB * 255;
iG = dTempG * 255;
iR = dTempR * 255;
cvSet2D( RGB_Image, i, j, cvScalar( iB, iG, iR ) );
}
}
return RGB_Image;
}
void HSI_RGB_TRAN::RGB2HSImage(IplImage*img,CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
{
// 原始图像数据指针, HSI矩阵数据指针
uchar* data;
// rgb分量
byte img_r, img_g, img_b;
byte min_rgb; // rgb分量中的最小值
// HSI分量
double fHue, fSaturation, fIntensity;
for(int i = 0; i < img->width; i++)
{
for(int j = 0; j < img->height; j++)
{
data = cvPtr2D(img, j, i, 0);
img_b = *data;
data++;
img_g = *data;
data++;
img_r = *data;
// Intensity分量[0, 1]
fIntensity = (float)((img_b + img_g + img_r)/3)/255;
// 得到RGB分量中的最小值
float fTemp = img_r < img_g ? img_r : img_g;
min_rgb = fTemp < img_b ? fTemp : img_b;
// Saturation分量[0, 1]
fSaturation = 1 - (float)(3 * min_rgb)/(img_r + img_g + img_b);
// 计算theta角
float numerator = (img_r - img_g + img_r - img_b ) / 2;
float denominator = sqrt(
pow(double (img_r - img_g), 2 ) +double( (img_r - img_b)*(img_g - img_b)) );
// 计算Hue分量
if(denominator != 0)
{
float theta = acos( numerator/denominator) * 180/3.14;
if(img_b <= img_g)
{
fHue = theta ;
}
else
{
fHue = 360 - theta;
}
}
else
{
fHue = 0;
}
// 赋值
cvmSet( HSI_H, i, j, fHue );
cvmSet( HSI_S, i, j, fSaturation);
cvmSet( HSI_I, i, j, fIntensity );
}
}
}
// 将HSI颜色空间的三个分量组合起来,便于显示
IplImage*HSI_RGB_TRAN:: catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
{
IplImage* HSI_Image = cvCreateImage( cvGetSize( HSI_H ), IPL_DEPTH_8U, 3 );
for(int i = 0; i < HSI_Image->height; i++)
{
for(int j = 0; j < HSI_Image->width; j++)
{
double d = cvmGet( HSI_H, i, j );
int b = (int)(d * 255/360);
d = cvmGet( HSI_S, i, j );
int g = (int)( d * 255 );
d = cvmGet( HSI_I, i, j );
int r = (int)( d * 255 );
cvSet2D( HSI_Image, i, j, cvScalar( r, g, b ) );
}
}
return HSI_Image;
}
///////调用
CvMat* HSI_H=NULL,*HSI_S=NULL,*HSI_I=NULL;
HSI_H = cvCreateMat( AOImage->width, AOImage->height, CV_32FC1 );
HSI_S = cvCreateMat( AOImage->width, AOImage->height, CV_32FC1 );
HSI_I = cvCreateMat(AOImage->width, AOImage->height, CV_32FC1 );
hsi_rgb.RGB2HSImage(AOImage,HSI_H,HSI_S,HSI_I);