在进行HSV和RGB转换之前大致了解一下两者的区别。
HSV颜色模型是根据颜色的直观特征所创立的一种颜色模型,它的名字就代表了这个模型的三个参数H,S,V。模型为六棱锥,三个参数就在上面不同维度进行表示。模型如下。原图来源百度百科。前者是空间模型,后者是模型概念图
H(Hue):色调。采用角度表示,在模型中为棱锥的底面,因此范围就是0~360度,如图所示,不同的角度规定了不同的颜色。0度表示红色,每隔120度分别为绿色和蓝色,对应三基色RGB,他们两两之间又以60度为间隔加入互补色,由0度逆时针开始分别为黄色,青色和品红色(紫色)。
S(Saturation):饱和度。定义为接近光谱色的程度。取值范围是0~1(图片为IPL_DEPTH_32F类型)或0~255(图片为IPL_DEPTH_8UC类型),饱和度越高颜色越深,白色的饱和度为0,。
V(Value):明度。颜色的明暗程度,范围0~1,0为黑色,1为白色。图片类型不同的情况同S。
RGB模型为三维立体图,模型如下所示。每隔维度的取值范围是0~255,0为黑色,255为白色。
两者之间具有密切的关联,当RGB的模型沿着原点的对角线,即黑色点与白色点的连线为垂直轴观察就会转换至HSV的模型。
RGB->HSV的转换关系如下。
max=max(R,G,B)
min=min(R,G,B)
H= 0 (max=min)
60 x (G-R) / (max-min) + 60 (min=B)
60 x (B-G) / (max-min) + 180 (min=R)
60 x (R-B) / (max-min) + 300 (min=G)
S = Max - Min
V = Max
或者是
max=max(R,G,B)
min=min(R,G,B)
H = (G-B)/(max-min)* 60 (R = max)
120+(B-R)/(max-min)* 60 (G = max)
240 +(R-G)/(max-min)* 60 (B = max)
H+ 360 (H < 0)
S=(max-min)/max
V=max(R,G,B)
HSV->RGB的转换关系如下。https://blog.csdn.net/qq_45391763/article/details/103450672
代码如下。
#include"iostream"
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace cv;
using namespace std;
Mat BGR2HSV(Mat bgrimg){
int bgrimgcol = bgrimg.cols;
int bgrimgrow = bgrimg.rows;
float r, g, b;
float h, s, v;
float Max, Min;
Mat hsvimg = Mat::zeros(bgrimgrow, bgrimgcol, CV_32FC3);
for (int j = 0; j < bgrimgrow; j++) {
for (int i = 0; i < bgrimgcol; i++) {
r = (float)bgrimg.at<Vec3b>(j, i)[2]/255;
g = (float)bgrimg.at<Vec3b>(j, i)[1]/255;
b = (float)bgrimg.at<Vec3b>(j, i)[0]/255;
Max = max(r, max(g, b));
Min = min(r, min(g, b));
if (Max == Min) {
h = 0;
}
else if (Min == b) {
h = 60 * (g - r) / (Max - Min) + 60;
}
else if (Min == r) {
h = 60 * (b - g) / (Max - Min) + 180;
}
else if (Min == g) {
h = 60 * (r - b) / (Max - Min) + 300;
}
s = Max - Min;
v = Max;
hsvimg.at<Vec3f>(j, i)[0] = h;
hsvimg.at<Vec3f>(j, i)[1] = s;
hsvimg.at<Vec3f>(j, i)[2] = v;
}
}
return hsvimg;
}
void main(){
Mat img = imread("ck567.jpg", IMREAD_COLOR);
Mat out = BGR2HSV(img);
imshow("sample",out);
waitKey(0);
destroyAllWindows();
}
HSV转换BGR的函数如下
Mat HSV2BGR(Mat hsvimg){
int hsvimgcol = hsvimg.cols;
int hsvimgrow = hsvimg.rows;
Mat hsv = Mat::zeros(hsvimgrow, hsvimgcol, CV_8UC3);
float h, s, v;
double c, h_, x;
double r, g, b;
for (int y = 0; y < hsvimgrow; y++) {
for (int x = 0; x < hsvimgcol; x++) {
h = hsvimg.at<Vec3f>(y, x)[0];
s = hsvimg.at<Vec3f>(y, x)[1];
v = hsvimg.at<Vec3f>(y, x)[2];
c = s;
h_ = h / 60;
x = c * (1 - abs(fmod(h_, 2) - 1));
r = g = b = v - c;
if (h_ < 1) {
r += c;
g += x;
}
else if (h_ < 2) {
r += x;
g += c;
}
else if (h_ < 3) {
g += c;
b += x;
}
else if (h_ < 4) {
g += x;
b += c;
}
else if (h_ < 5) {
r += x;
b += c;
}
else if (h_ < 6) {
r += c;
b += x;
}
//以上代码可用switch结构代替
hsv.at<Vec3b>(y, x)[0] = (uchar)(b * 255);
hsv.at<Vec3b>(y, x)[1] = (uchar)(g * 255);
hsv.at<Vec3b>(y, x)[2] = (uchar)(r * 255);
}
}
return hsv;
}