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

opencv调节图像色相、饱和度、明度(H\S\V)

2015-11-10 11:04 423 查看
一、环境

1、Qt5.5.1;

2、opencv3.0;

3、visual studio 2013.

二、核心代码

1、图像处理部分

//调节图像的色相、饱和度、明度
bool CvImageAdjust::AddHSV(const QImage& inImg, QImage& outImg, double dH, double dS, double dV)
{
bool  bResult = false;
QImage imgSrc = inImg.copy();
IplImage *lImage = CImageConvert::ConvertToIplImage(imgSrc);
cvCvtColor(lImage, lImage, CV_BGR2HSV);
int i;
uchar lut[256][3];
CvMat* lut_mat;
lut_mat = cvCreateMatHeader(1, 256, CV_8UC3);
cvSetData(lut_mat, lut, 0);
for (i = 0; i < 256; i++)
{
int h = (i + dH);
if (h > 180)
{
h -= 180;
}
else if (h < 0)
{
h += 180;
}

int s = (i + dS);
if (s < 0)
s = 0;
if (s > 255)
s = 255;

int v = (i + dV);
if (v < 0)
v = 0;
if (v > 255)
v = 255;

lut[i][0] = (uchar)h;
lut[i][1] = (uchar)s;
lut[i][2] = (uchar)v;
}
cvLUT(lImage, lImage, lut_mat);
cvCvtColor(lImage, lImage, CV_HSV2BGR);

QImage imgRult = CImageConvert::ConvertToQImage(lImage);
CImageConvert::AddAlpha(inImg, imgRult);
outImg = imgRult;

cvReleaseImage(&lImage);
bResult = true;
return bResult;
}
//自动调节图片色彩到目标值,取出H\S\V值
bool CvImageAdjust::AutoAdjustHsv(QImage& imgGoal, QImage& img_ave, double& dH, double& dS, double& dV)
{
if (imgGoal.width() <= 0
|| imgGoal.height() <= 0
|| img_ave.width() <= 0
|| img_ave.height() <= 0)
{
return false;
}

//创建AVG_S
QImage avgImage(QSize(1, 1), QImage::Format_ARGB32);
QRgb rgb = imgGoal.pixel(82 / 512.0 * imgGoal.width(), 162 / 512.0 * imgGoal.height());
avgImage.setPixel(0, 0, rgb);
//计算参考H,S,L值
int H_src, S_src, L_src;
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_src, S_src, L_src);

//循环查找适当的HSV增量
int nH, nS, nV;
nH = nS = nV = 0;

for (int i = 0; i < 200; ++i)
{
int H_cur, S_cur, L_cur;
QImage imgtemp;
AddHSV(img_ave,imgtemp, nH, nS, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
//
int ic;
if (L_src > L_cur)
{
ic = 1;
}
else
{
ic = -1;
}

int errLast = abs(L_cur - L_src);
for (; nV <= 255 && nV >= -255; nV += ic)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH, nS, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
int errCur = abs(L_cur - L_src);
if (errCur > errLast)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH, nS, nV -= ic);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
errCur = abs(L_cur - L_src);

break;
}
errLast = errCur;
}

//
if (H_src > H_cur)
{
ic = 1;
}
else
{
ic = -1;
}

errLast = abs(H_cur - H_src);
for (; nH <= 180 && nH >= -180; nH += ic)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH, nS, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
int errCur = abs(H_cur - H_src);
if (errCur > errLast)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH -= ic, nS, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
errCur = abs(H_cur - H_src);

break;
}
errLast = errCur;
}

//
if (S_src > S_cur)
{
ic = 1;
}
else
{
ic = -1;
}

errLast = abs(S_cur - S_src);
for (; nS <= 255 && nS >= -255; nS += ic)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH, nS, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur
4000
, S_cur, L_cur);
int errCur = abs(S_cur - S_src);
if (errCur > errLast)
{
QImage imgtemp;
AddHSV(img_ave, imgtemp, nH, nS -= ic, nV);
QRgb rgb = imgtemp.pixel(0, 0);
CImageConvert::RGB2HSL_INT(qRed(rgb), qGreen(rgb), qBlue(rgb), H_cur, S_cur, L_cur);
errCur = abs(S_cur - S_src);

break;
}
errLast = errCur;
}

if (abs(H_cur - H_src) <= 3 && abs(L_cur - L_src) <= 3)
{
break;
}
}

dH = nH;
dS = nS;
dV = nV;

return true;
}


2、类型转换

#include <highgui.h>
#include <opencv.h>

//QImage->IplImage *
IplImage *CImageConvert::ConvertToIplImage(const QImage &img)
{
/*int nChannel = 0;
if (img.format() == QImage::Format_RGB888)nChannel = 3;
if (img.format() == QImage::Format_ARGB32)nChannel = 4;
if (nChannel == 0)return false;
IplImage *iplImg = cvCreateImageHeader(cvSize(img.width(), img.height()), 8, nChannel);
iplImg->imageData = (char*)img.bits();
if (nChannel == 3)
cvConvertImage(iplImg, iplImg, CV_CVTIMG_SWAP_RB);
return iplImg;*/

int width = img.width();
int height = img.height();
CvSize Size;
Size.height = height;
Size.width = width;
IplImage *IplImageBuffer = cvCreateImage(Size, IPL_DEPTH_8U, 3);
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
QRgb rgb = img.pixel(x, y);
cvSet2D(IplImageBuffer, y, x, CV_RGB(qRed(rgb), qGreen(rgb), qBlue(rgb)));
}
}
return IplImageBuffer;
}

//Mat->QImage
QImage CImageConvert::ConvertToQImage(cv::Mat &mat)
{
QImage img;
int nChannel = mat.channels();
if (nChannel == 3)
{
cv::cvtColor(mat, mat, CV_BGR2RGB);
return QImage((const unsigned char*)mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
}
else if (nChannel == 4 || nChannel == 1)
{
return QImage((const unsigned char*)mat.data, mat.cols, mat.rows, QImage::Format_ARGB32);
}
return img;
}
//IplImage *->QImage
QImage CImageConvert::ConvertToQImage(IplImage *iplImg)
{
QImage img;
int nChannel = iplImg->nChannels;
if (nChannel == 3)
{
cvConvertImage(iplImg, iplImg, CV_CVTIMG_SWAP_RB);
return QImage((const unsigned char*)iplImg->imageData, iplImg->width, iplImg->height, QImage::Format_RGB888);
}
else if (nChannel == 4 || nChannel == 1)
{
return QImage((const unsigned char*)iplImg->imageData, iplImg->width, iplImg->height, QImage::Format_ARGB32);
}
return img;
}

//R, G, B:[0..255],integer
//H:[0, 360),double, degrees around color circle
//S:[0, 1], double, 0(shade of gray) to 1(pure color)
//V:[0, 1], double, 0(black) to 1(white)
void RGB2HSV(int R, int G, int B, double &H, double &S, double &V)
{
int Max = std::max(std::max(R, G), B);
int Min = std::min(std::min(R, G), B);
int Delta = Max - Min;

if (Max == 0)
S = 0.0;
else
S = (double)Delta / Max;

if (abs(S) < FLT_EPSILON)
H = 0.0;                       //当S为0时,H无意义, 但可以指定为0
else
{
if (R == Max)                   //yellow to magenta
H = 60 * (G - B) / Delta;
else if (G == Max)              //cyan to yellow
H = 120 + 60 * (B - R) / Delta;
else if (B == Max)               //magenta to cyan
H = 240 + 60 * (R - G) / Delta;
}

if (H<0.0)
H = 360.0 + H;
if (H>360.0)
H -= 360;

V = Max / 255.0;
}

void RGB2HSL(int r, int g, int b, double &H, double &S, double &L)
{
double R, G, B, Max, Min, del_R, del_G, del_B, del_Max;
R = r / 255.0;       //Where RGB values = 0 ÷ 255
G = g / 255.0;
B = b / 255.0;
//
Min = std::min(R, std::min(G, B));    //Min. value of RGB
Max = std::max(R, std::max(G, B));    //Max. value of RGB
del_Max = Max - Min;        //Delta RGB value
//
L = (Max + Min) / 2.0;
//
if (del_Max == 0)           //This is a gray, no chroma...
{
//H = 2.0/3.0;          //Windows下S值为0时,H值始终为160(2/3*240)
H = 0;                  //HSL results = 0 ÷ 1
S = 0;
}
else                        //Chromatic data...
{
if (L < 0.5) S = del_Max / (Max + Min);
else         S = del_Max / (2 - Max - Min);
//
del_R = (((Max - R) / 6.0) + (del_Max / 2.0)) / del_Max;
del_G = (((Max - G) / 6.0) + (del_Max / 2.0)) / del_Max;
del_B = (((Max - B) / 6.0) + (del_Max / 2.0)) / del_Max;
//
if (R == Max) H = del_B - del_G;
else if (G == Max) H = (1.0 / 3.0) + del_R - del_B;
else if (B == Max) H = (2.0 / 3.0) + del_G - del_R;
//
if (H < 0)  H += 1;
if (H > 1)  H -= 1;
}
}

void CImageConvert::RGB2HSL_INT(int r, int g, int b, int &H, int &S, int &L)
{
double h, s, l;
RGB2HSV(r, g, b, h, s, l);
/*H = (h * 255) + 0.5;
S = (s * 255) + 0.5;
L = (l * 255) + 0.5;*/
H = h;
S = s;
L = l;
}

//设置原始的Alpha通道
void CImageConvert::AddAlpha(const QImage &src, QImage &dest)
{
if (src.width() != dest.width()
|| src.height() != dest.height())
{
return;
}
dest.setAlphaChannel(src.
b46b
alphaChannel());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息