본문 바로가기

Computer Vision by OpenCV

OpenCV 3D histogram (3차원 히스토그램)

반응형

3차원 히스토그램 (3 dimensional histogram)


지금까지는 1차원 히스토그램을 이용해왔다. 즉 픽셀이 가질 수 있는 값 별로 몇 개씩의 픽셀들이 실제로 그 값을 가졌는지를 계산했다.


그러나, 컬러이미지의 경우, 하나의 픽셀은 R, G, B 혹은 H, L, S의 3가지 값을 가지기 때문에 1차원 히스토그램이 적절하지 않다. 그래서 3차원 히스토그램을 이용해야 한다. 3차원은 아래 그림과 같이 생각하면 된다. 아래는 HLS 포맷의 이미지의 픽셀들을 H, L, S를 축으로 하는 3차원 히스토그램으로 나타낸 것이다. 좌표 (H, L, S)의 값은 그 조합을 가지는 픽셀들의 갯수이다. 




그런데, H, L, S가 가질 수 있는 값들의 조합이 너무나 많다. 예를 들어, 각각이 20개씩의 값만 가진다 하더라도 20*20*20 = 8000개의 조합이 나온다. 그래서 각 축의 histogram bin의 개수를 4개, 8개, 혹은 적절한 값으로 하면 적당한 복잡도의 히스토그램을 얻을 수 있다.


3D 히스토그램을 그리는 순서도

  1. RGB이미지를 읽어들인다.
  2. HLS포맷으로 전환한다.
  3. H, L, S를 각 축으로 하고, 각 축마다 8개의 bin이 있는 3차원 histogram을 계산한다.
  4. 계산된 histogram의 값을 출력한다.


 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
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

#define SCALE 0.2
#define NUM 5
#define BINS 8

int main(int argc, char** argv)
{
	// the names of images to be compared each other
	string imgNames[NUM] = { "img_dotonbori.jpg", "img_eiffel.jpg", "img2_beach.jpg", "img2_garden.jpg", "img2_grapefarm.jpg" };

	//for (int i = 0; i < NUM; i++)
	//{
	//	cout << imgNames[i] << endl;
	//}

	// read all images and convert to HLS format
	Mat imgs[NUM];
	Mat imgsHLS[NUM];
	for (int i = 0; i < NUM; i++)
	{
		imgs[i] = imread(imgNames[i], IMREAD_COLOR);
		if (imgs[i].data == 0)
		{
			cout << "Unable to read " << imgNames[i] << endl;
			return 0;
		}
		cvtColor(imgs[i], imgsHLS[i], COLOR_BGR2HLS);
	}

	//cout << "Succeeded to read all images" << endl;

	// compute 3D histogram
	Mat histogram[NUM];

	int channel_numbers[] = { 0, 1, 2 };
	for (int i = 0; i < NUM; i++)
	{
		int* number_bins = new int[imgsHLS[i].channels()];
		for (int ch = 0; ch < imgsHLS[i].channels(); ch++)
		{
			number_bins[ch] = BINS;
		}
		float ch_range[] = { 0.0, 255.0 };
		const float *channel_ranges[] = { ch_range, ch_range, ch_range };
		calcHist(&imgsHLS[i], 1, channel_numbers, Mat(), histogram[i], imgsHLS[i].channels(), number_bins, channel_ranges);
		cout << imgNames[i] << "-----------------------" << endl;
		for (int x = 0; x < BINS; x++)
		{
			for (int y = 0; y < BINS; y++)
			{
				for (int z = 0; z < BINS; z++)
				{
					cout << histogram[i].at<float>(x, y, z) << " ";
				}
			}
		}
		cout << endl;
	}
	return 0;
}


반응형