OpenCV學習筆記-RGB轉HSV

*最弱無敗機龍*

前言


RGB轉HSV,並分離成單通道R/G/B與H/S/V

方法


首先,先回憶上次開圖的方法

1
2
3
4
5
6
7
8
9
10
11
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main() {
IplImage* img = cvLoadImage("test.png", 1); //1表示三通道
namedWindow("test",WINDOW_AUTOSIZE);
cvShowImage("test", img);
cvWaitKey(0);
return 0;
}

接下來在其中加入兩行程式碼

1
2
3
4
//以img的大小製作一個空白的空間
IplImage* hsv = cvCreateImage(cvGetSize(img), 8, 3);
//把img從RGB轉成HSV
cvCvtColor(img, hsv, CV_BGR2HSV);

cvCreateImage(size,depth,channels)
size代表圖像大小
depth為圖像元素的位深度,IPL_DEPTH_8U8代表無符號8位整型
channels代表圖像通道數量

這樣就成功以內建函式的方式轉換了原圖

詳細轉換的方式可參考OpenCV文件
點我到OpenCV

再來為了分離三個通道成R/G/B得先宣告存放空間並把img分離

1
2
3
4
5
6
IplImage* Bimg=cvCreateImage(cvGetSize(img),8,1);
IplImage* Gimg=cvCreateImage(cvGetSize(img),8,1);
IplImage* Rimg=cvCreateImage(cvGetSize(img),8,1);
cvSplit(img, Bimg, Gimg, Rimg, 0);//複製各個通道到三個空間
//目標圖像必須與來源圖像在大小和資料型態上一樣
//輸入多通道,輸出為B,G,R單通道

但這時要注意,圖片因為單通道所以還是灰階的
要再宣告三個三通道的圖片空間

1
2
3
IplImage* pImg1=cvCreateImage(cvGetSize(img),8,3);
IplImage* pImg2=cvCreateImage(cvGetSize(img),8,3);
IplImage* pImg3=cvCreateImage(cvGetSize(img),8,3);

並且把空間初始化

1
2
3
cvSetZero(pImg1);
cvSetZero(pImg2);
cvSetZero(pImg3);

此時,把三個通道合成後可以得到一張完整的圖(R/G/B)

1
2
3
4
5
6
//注意順序是BGR
cvMerge(Bimg,0,0,0,pImg3);
cvMerge(0,Gimg,0,0,pImg2);
cvMerge(0,0,Rimg,0,pImg1);
//將三個通道合成
//輸入参數為B,G,R單通道,最後一個為輸出

最後,開個視窗把圖片輸出就成了
注意這邊是輸出pImg1、pImg2、pImg3

1
2
3
4
5
6
namedWindow("B", WINDOW_AUTOSIZE);
cvShowImage("B", pImg3);
namedWindow("G", WINDOW_AUTOSIZE);
cvShowImage("G", pImg2);
namedWindow("R", WINDOW_AUTOSIZE);
cvShowImage("R", pImg1);

為了分離H/S/V,我們必須也做同樣的事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//利用一開始轉換好的HSV宣告三個單通道圖片空間
IplImage* Himg = cvCreateImage(cvGetSize(hsv), 8, 1);
IplImage* Simg = cvCreateImage(cvGetSize(hsv), 8, 1);
IplImage* Vimg = cvCreateImage(cvGetSize(hsv), 8, 1);

//宣告三個三通道圖片空間
IplImage* HSV1 = cvCreateImage(cvGetSize(hsv), 8, 3);
IplImage* HSV2 = cvCreateImage(cvGetSize(hsv), 8, 3);
IplImage* HSV3 = cvCreateImage(cvGetSize(hsv), 8, 3);

//把hsv複製到三個空間
cvSplit(hsv, Vimg, Simg, Himg, 0);

//把圖片空間初始化
cvSetZero(HSV1);
cvSetZero(HSV2);
cvSetZero(HSV3);

//把三個通道合成,注意順序是VSH
cvMerge(Vimg, 0, 0, 0, HSV3);
cvMerge(0, Simg, 0, 0, HSV2);
cvMerge(0, 0, Himg, 0, HSV1);

輸出後,我們可以得到三張圖,分別是H/S/V

試著一次把所有圖都輸出

整個程式的程式碼可以參考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main() {
IplImage* img = cvLoadImage("test.png", 1); //1表示三通道

//以img的大小製作一個空白的空間
IplImage* hsv = cvCreateImage(cvGetSize(img), 8, 3);
//把img從RGB轉成HSV
cvCvtColor(img, hsv, CV_BGR2HSV);

//轉R/G/B單通道-----------------------
IplImage* Bimg = cvCreateImage(cvGetSize(img), 8, 1);//B單通道灰階
IplImage* Gimg = cvCreateImage(cvGetSize(img), 8, 1);//G單通道灰階
IplImage* Rimg = cvCreateImage(cvGetSize(img), 8, 1);//R單通道灰階
cvSplit(img, Bimg, Gimg, Rimg, 0);

IplImage* pImg1 = cvCreateImage(cvGetSize(img), 8, 3);
IplImage* pImg2 = cvCreateImage(cvGetSize(img), 8, 3);
IplImage* pImg3 = cvCreateImage(cvGetSize(img), 8, 3);
cvSetZero(pImg1);
cvSetZero(pImg2);
cvSetZero(pImg3);
cvMerge(Bimg, 0, 0, 0, pImg3);
cvMerge(0, Gimg, 0, 0, pImg2);
cvMerge(0, 0, Rimg, 0, pImg1);
//----------------------------------------

//轉H/S/V單通道-----------------------
IplImage* Himg = cvCreateImage(cvGetSize(hsv), 8, 1);
IplImage* Simg = cvCreateImage(cvGetSize(hsv), 8, 1);
IplImage* Vimg = cvCreateImage(cvGetSize(hsv), 8, 1);
IplImage* HSV1 = cvCreateImage(cvGetSize(hsv), 8, 3);
IplImage* HSV2 = cvCreateImage(cvGetSize(hsv), 8, 3);
IplImage* HSV3 = cvCreateImage(cvGetSize(hsv), 8, 3);
cvSplit(hsv, Vimg, Simg, Himg, 0);

cvSetZero(HSV1);
cvSetZero(HSV2);
cvSetZero(HSV3);
cvMerge(Vimg, 0, 0, 0, HSV3);
cvMerge(0, Simg, 0, 0, HSV2);
cvMerge(0, 0, Himg, 0, HSV1);
//----------------------------------------

cvNamedWindow("HSV", WINDOW_AUTOSIZE);
cvShowImage("HSV", hsv);

namedWindow("H", WINDOW_AUTOSIZE);
cvShowImage("H", HSV1);
namedWindow("S", WINDOW_AUTOSIZE);
cvShowImage("S", HSV2);
namedWindow("V", WINDOW_AUTOSIZE);
cvShowImage("V", HSV3);


cvNamedWindow("RGB", WINDOW_AUTOSIZE);
cvShowImage("RGB", img);

namedWindow("R", WINDOW_AUTOSIZE);
cvShowImage("R", pImg1);
namedWindow("G", WINDOW_AUTOSIZE);
cvShowImage("G", pImg2);
namedWindow("B", WINDOW_AUTOSIZE);
cvShowImage("B", pImg3);

cvWaitKey(0);

return 0;
}

Reference


[OpenCV] 轉換色彩空間 (Transform Color Space)
基於Opencv下RGB圖像轉HSV,並分離成單通道R/G/B與H/S/V