본문 바로가기

Computer Vision by OpenCV

OpenCV: Histogram Equalization: Luminance

반응형



Histogram equalization


영상처리기법 중에 histogram equalization이라는 것이 있다. Histogram은 <<여기>>에서 자세히 설명하고 있다. Equalization이라는 것은 특정값을 가진 픽셀들이 너무 많지 않도록 골고루 퍼트리는 기술이다.  비유를 들자면, 서울에 거주하는 사람이 너무 많으면, 서울과 수도권으로 사람들을 이주시키는 식이다. 자세한 원리는 이 <<블로그를>> 참조하면 된다.




Histogram equalization을 하게 되면, 단일 색으로 보이던 부분들이 구분되어 보여지는 효과가 있다. 예를 들어, 아래 사진을 보자. 어느 도시의 야경을 촬영한 것이다. 왼쪽은 원래 영상이고, 오른쪽이 equalization이 후의 영상이다. 차이점은 밤하늘이 전체적인 검은색 일변도에서 여러 가지 단계를 가진 검정색으로 보이게 된 것이다.




Luminance Histogram Equalization


특히, 영상의 밝기 (Luminance)를 equalization하면 안 보이던 부분들이 아주 잘 보이게 된다. 예를 들어 아래 사진을 보자. 왼쪽 사진에서 집 입구가 전체적으로 어두운 색이서 물체들이 제대로 구분되지 않는다. 이 때  luminance를 기준으로 equalization을 하게 되면 오른쪽 결과와 같이 집 입구가 환해지는 효과를 얻을 수 있다.


이러한 환해지는 효과는 아래 사진들에서도 확인할 수 있다. 다양한 상황을 촬영한 사진들에 대해 Luminance histogram equalization을 수행한 결과들이다.




반대로 너무 환해서 잘 보이지 않았던 부분들은 Luminance histogram equalization을 하게 되면, 어두워지면서 세부특징들을 잘 관찰할 수 있다. 예를 들어 아래 사진에서 바닥의 디테일들이 아주 잘 보이는 것을 알 수 있다.



Implementation


OpenCV가 제공하는 기능들을 이용해서 luminance histogram equalization을 구현해 보자. 우선 영상을 읽어들인다. imread( )는 컬러이미지인 경우 BGR 포맷으로 읽기 때문에, 이것을 HLS 포맷으로 변환할 필요가 있다. 이를 위해 cvtColor( )함수를 사용한다. 라인 36 ~ 39은 HLS 포맷 영상에 대해서 Luminance채널에 대해서만 equalization을 수행하고, 이를 다시 HLS 영상에 넣는 과정이다. 마지막으로 HLS 포맷 영상을 BGR 포맷으로 재변환해야 한다.(라인 40) 왜냐하면 OpenCV는 BGR 영상만 표시가능하기 때문이다. 



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

using namespace cv;
using namespace std;

#define SCALE 0.2


int main(int argc, char** argv)
{
	if (argc != 2)
	{
		cout << " Provide image name to read" << endl;
		return -1;
	}

	Mat inputImg, dispImg, disp2Img;
	Mat hlsImg;

	inputImg = imread(argv[1], IMREAD_COLOR); // read in BGR format

	if (inputImg.data == 0)
	{
		cout << "Unable to read " << argv[1] << endl;
		return 0;
	}

	// inputImg is too large to be shown. 
	// use scaled-down dispImg instead just for display
	// use inputImg for the histogram calculation
	resize(inputImg, dispImg, Size(), SCALE, SCALE, CV_INTER_AREA);

	cvtColor(dispImg, hlsImg, COLOR_BGR2HLS_FULL);

	vector<Mat> channels(hlsImg.channels());
	split(hlsImg, channels);
	equalizeHist(channels[1], channels[1]);
	merge(channels, hlsImg);
	cvtColor(hlsImg, disp2Img, COLOR_HLS2BGR_FULL);

	namedWindow("Original", CV_WINDOW_AUTOSIZE);
	namedWindow("After luminacense equalization", CV_WINDOW_AUTOSIZE);

	moveWindow("Original", 100, 100);
	moveWindow("After luminacense equalization", 120, 120);

	imshow("Original", dispImg);
	imshow("After luminacense equalization", disp2Img);

	waitKey(0);
	return 0;
}


반응형