彩色空间互换
文章目录
1.学习目标
- 了解相关颜色空间的基础知识
- 理解彩色空间互换的理论
- 掌握opencv框架下颜色空间相互API的使用
2.算法理论介绍与资料推荐
1.RGB与灰度图相互
RGB颜色空间基于颜色的加法混色原理,从黑色不断叠加Red,Green,Blue的颜色,最终得到白色
将R、G、B三个通道作为笛卡尔坐标系中的X、Y、Z轴,就得到了一种对于颜色的空间描述,如图:
对于彩色图转灰度图,有一个很著名的心理学公式
G
r
a
y
=
R
∗
0.299
+
G
∗
0.587
+
B
∗
0.114
Gray = R*0.299 + G*0.587 + B*0.114
Gray=R∗0.299+G∗0.587+B∗0.114
2.RGB和HSV互转
HSV 是一种将RGB色彩空间中的点在倒圆锥中的表示方法,即
- 色相(Hue)
- 饱和度(Saturation)
- 明度(Value)
有称HSB(B即, Brightness)
-
色相(H)是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等
-
饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值
-
明度(V)取0-max(计算机中HSV取值范围和存储的长度有关)
HSV模型
2.2.1RGB2HSV
V ← max ( R , G , B ) S ← { V − min ( R , G , B ) V if V ≠ 0 0 otherwise H ← { 60 ( G − B ) / ( V − min ( R , G , B ) ) if V = R 120 + 60 ( B − R ) / ( V − min ( R , G , B ) ] if V = G 240 + 60 ( R − G ) / ( V − min ( R , G , B ) ) if V = B \begin{array}{c} \mathrm{V} \leftarrow \max (\mathrm{R}, \mathrm{G}, \mathrm{B}) \\ \\ \mathrm{S} \leftarrow\left\{\begin{array}{ll} \frac{V-\min (\mathrm{R}, \mathrm{G}, \mathrm{B})}{\mathrm{V}} & \text { if } \mathrm{V} \neq 0 \\ 0 &\text { otherwise } \end{array}\right. \\ \\ \mathrm{H} \leftarrow\left\{\begin{array}{ll} 60(\mathrm{G}-\mathrm{B}) /(\mathrm{V}-\min (\mathrm{R}, \mathrm{G}, \mathrm{B})) & \text { if } \mathrm{V}=\mathrm{R} \\ 120+60(\mathrm{B}-\mathrm{R}) /(\mathrm{V}-\min (\mathrm{R}, \mathrm{G}, \mathrm{B})] & \text { if } \mathrm{V}=\mathrm{G} \\ 240+60(\mathrm{R}-\mathrm{G}) /(\mathrm{V}-\min (\mathrm{R}, \mathrm{G}, \mathrm{B})) & \text { if } \mathrm{V}=\mathrm{B} \end{array}\right. \end{array} V←max(R,G,B)S←{VV−min(R,G,B)0 if V=0 otherwise H←⎩⎨⎧60(G−B)/(V−min(R,G,B))120+60(B−R)/(V−min(R,G,B)]240+60(R−G)/(V−min(R,G,B)) if V=R if V=G if V=B
If H < 0 then H ← H + 360. On output 0 ≤ V ≤ 1 , 0 ≤ S ≤ 1 , 0 ≤ H ≤ 360 \text{If} \ \mathrm{H}<0 \text{then}\ \mathrm{H} \leftarrow \mathrm{H}+360 . \text{On output}\ 0 \leq \mathrm{V} \leq 1,0 \leq \mathrm{S} \leq 1,0 \leq \mathrm{H} \leq 360 If H<0then H←H+360.On output 0≤V≤1,0≤S≤1,0≤H≤360
或者
h
=
{
0
∘
if
max
=
min
6
0
∘
×
g
−
b
max
−
min
+
0
∘
,
if
max
=
r
and
g
≥
b
6
0
∘
×
g
−
b
max
−
min
+
36
0
∘
,
if
max
=
r
and
g
<
b
6
0
∘
×
b
−
r
max
−
min
+
12
0
∘
,
if
max
=
g
6
0
∘
×
r
−
g
max
−
min
+
24
0
∘
,
if
max
=
b
s
=
{
0
,
if
max
=
0
max
−
min
max
=
1
−
min
max
,
otherwise
\begin{array}{ll} h=\left\{\begin{array}{ll} 0^{\circ} & \text { if } \max =\min \\ 60^{\circ} \times \frac{g-b}{\max -\min }+0^{\circ}, & \text { if } \max =r \text { and } g \geq b \\ 60^{\circ} \times \frac{g-b}{\max -\min }+360^{\circ}, & \text { if } \max =r \text { and } g<b \\ 60^{\circ} \times \frac{b-r}{\max -\min }+120^{\circ}, & \text { if } \max =g \\ 60^{\circ} \times \frac{r-g}{\max -\min }+240^{\circ}, & \text { if } \max =b \end{array}\right. \\ \\ s=\left\{\begin{array}{ll} 0, & \text { if } \max =0 \\ \frac{\max -\min }{\max }=1-\frac{\min }{\max }, & \text { otherwise } \end{array}\right. \end{array}
h=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧0∘60∘×max−ming−b+0∘,60∘×max−ming−b+360∘,60∘×max−minb−r+120∘,60∘×max−minr−g+240∘, if max=min if max=r and g≥b if max=r and g<b if max=g if max=bs={0,maxmax−min=1−maxmin, if max=0 otherwise
v = m a x v=max v=max
2.2.2HSV2RGB
h i ≡ ⌊ h 60 ⌋ ( m o d 6 ) f = h 60 − h i p = v × ( 1 − s ) q = v × ( 1 − f × s ) t = v × ( 1 − ( 1 − f ) × s ) 对 于 每 个 颜 色 向 量 ( r , g , b ) , ( r , g , b ) = { ( v , t , p ) , if h i = 0 ( q , v , p ) , if h i = 1 ( p , v , t ) , if h i = 2 ( p , q , v ) , if h i = 3 ( t , p , v ) , if h i = 4 ( v , p , q ) , if h i = 5 \begin{aligned} &h_{i} \equiv\left\lfloor\frac{h}{60}\right\rfloor \quad(\bmod 6) \\ &f=\frac{h}{60}-h_{i} \\ &p=v \times(1-s)\\ &q=v \times(1-f \times s)\\ &t=v \times(1-(1-f) \times s)\\ \\ &对于每个颜色向量(r, g, b),\\ &(r, g, b)=\left\{\begin{array}{ll}(v, t, p), & \text { if } h_{i}=0 \\ (q, v, p), & \text { if } h_{i}=1 \\ (p, v, t), & \text { if } h_{i}=2 \\ (p, q, v), & \text { if } h_{i}=3 \\ (t, p, v), & \text { if } h_{i}=4 \\ (v, p, q), & \text { if } h_{i}=5\end{array}\right. \end{aligned} hi≡⌊60h⌋(mod6)f=60h−hip=v×(1−s)q=v×(1−f×s)t=v×(1−(1−f)×s)对于每个颜色向量(r,g,b),(r,g,b)=⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧(v,t,p),(q,v,p),(p,v,t),(p,q,v),(t,p,v),(v,p,q), if hi=0 if hi=1 if hi=2 if hi=3 if hi=4 if hi=5
3.基于opencv的实现
函数cvtColor()
void cvtColor(InputArray src, //输入图片
OutputArray dst, //输出图片
int code, // 颜色空间转换标示符
int dstCn=0) // 目标图像的通道数,该参数为0时,目标图像根据源图像的通道数和具体操 作进行决定
//-----------------------------------------------
code:
1.注意RGB色彩空间默认的通道顺序为BGR
3.1实现示例(c++)
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
Mat img = imread("C:/Users/Administrator/Desktop/opencv/test1.jpg");
if (img.empty())
{
cout << "无法读取图像" << endl;
return 0;
}
//RGB2GHSV
Mat dstImage;
cvtColor(img, dstImage,COLOR_RGB2HSV);
imshow("RGB2HSV",dstImage);
//RGB2GRAY
cvtColor(img, dstImage, COLOR_RGB2GRAY);
imshow("RGB2GRAY", dstImage);
waitKey(0);
return 0;
}
3.2进阶实现(根据原理自己实现)
3.2.1.RGB2GRAY
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat RGB2GRAY(Mat src, bool accelerate = false)
{
/*自定义转换
@src 输入图像
@返回dst 输出图像
*/
CV_Assert(src.channels() == 3);
Mat dst = Mat::zeros(src.size(), CV_8UC1);
Vec3b rgb;
int r = src.rows;
int c = src.cols;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
rgb = src.at<Vec3b>(i, j);
uchar B = rgb[0]; uchar G = rgb[1]; uchar R = rgb[2];
if (accelerate = false)
dst.at<uchar>(i, j) = R * 0.299 + G * 0.587 + B * 0.114; //原式
else
dst.at<uchar>(i, j) = (R * 4898 + G * 9618 + B * 1868) >> 14; //加速
}
return dst;
}
int main(int argc, char* argv[])
{
Mat img = imread("C:/Users/Administrator/Desktop/opencv/test1.jpg");
if (img.empty())
{
cout << "无法读取图像" << endl;
return 0;
}
Mat dst, dst1;
//opencv自带
double t2 = (double)getTickCount(); //测时间
cvtColor(img, dst1, COLOR_RGB2GRAY);
t2 = (double)getTickCount() - t2;
double time2 = (t2 * 1000.) / ((double)getTickFrequency());
cout << "Opencv_rgb2gray=" << time2 << " ms. " << endl;
//RGB2GRAY
double t1 = (double)getTickCount(); //测时间
dst = RGB2GRAY(img, true);
t1 = (double)getTickCount() - t1;
double time1 = (t1 * 1000.) / ((double)getTickFrequency());
cout << "My_rgb2gray=" << time1 << " ms. " << endl;
imshow("img", img);
imshow("My_rgb2gray", dst);
imshow("Opencv_rgb2gray", dst1);
waitKey(0);
return 0;
}
3.2.2.RGB2HCV/HSV2RGB
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat RGB2HSV(Mat src)
{
int row = src.rows;
int col = src.cols;
Mat dst(row, col, CV_32FC3);
for(int i=0;i<row;i++)
for (int j = 0; j < col; j++)
{
float b = src.at<Vec3b>(i, j)[0] / 255.0;
float g = src.at<Vec3b>(i, j)[1] / 255.0;
float r = src.at<Vec3b>(i, j)[2] / 255.0;
float minn = min(r, min(g, b));
float maxx = max(r, max(g, b));
float v, h, s;
v = maxx;
if (v != 0)
s = (v - minn) / v;
else
s = 0;
if (v == r )
h = 60*(g - b) / (v-minn);
else if (v == g)
h = 120 + 60*(b - r) / (v-minn);
else if (v == b)
h = 244 + 60*(r - g) / (v-minn);
else
h = 0;
if (h < 0)
h += 360;
dst.at<Vec3f>(i, j)[0] = h;
dst.at<Vec3f>(i, j)[1] = s;
dst.at<Vec3f>(i, j)[2] = v;
}
return dst;
}
Mat HSV2RGB(Mat src) {
int row = src.rows;
int col = src.cols;
Mat dst(row, col, CV_8UC3);
float r, g, b, h, s, v;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
h = src.at<Vec3f>(i, j)[0];
s = src.at<Vec3f>(i, j)[1];
v = src.at<Vec3f>(i, j)[2];
if (s == 0)
r = g = b = v;
else {
h /= 60;
int offset = floor(h);
float f = h - offset;
float p = v * (1 - s);
float q = v * (1 - s * f);
float t = v * (1 - s * (1 - f));
switch (offset)
{
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
default:
break;
}
}
dst.at<Vec3b>(i, j)[0] = int(b * 255);
dst.at<Vec3b>(i, j)[1] = int(g * 255);
dst.at<Vec3b>(i, j)[2] = int(r * 255);
}
}
return dst;
}
int main(int argc, char* argv[])
{
Mat img = imread("C:/Users/Administrator/Desktop/opencv/test1.jpg");
if (img.empty())
{
cout << "无法读取图像" << endl;
return 0;
}
Mat dst = RGB2HSV(img);
Mat dst1 = HSV2RGB(dst);
imshow("img", img);
imshow("My_rgb2hsv", dst);
imshow("My_hsv2rgb", dst1);
waitKey(0);
return 0;
}