본문 바로가기

Computer Vision by OpenCV

Binarization: 사진을 흑백영상으로 바꾸기

반응형


Image Binarization (이미지 이진화)


Grey-scale image는 한 픽셀당 8비트 밖에 차지하지 않기 때문에 컬러이미지보다 크기가 작아 처리하기 쉽다. Binary image의 경우, 픽셀이 가질 수 있는 색은 단 2가지, 흰색 혹은 검정색뿐이다. 따라서 한 픽셀당 1비트만 있어도 되기 때문에, Grey-scale image보다 처리가 더 간편하다. 실제로 많은 영상처리 기술들이 binary image를 대상으로 하고 있기 때문에, 입력이미지가 컬러일 경우, 이를 binary image로 변환하는 것이 필요하다. Binary image는 컬러이미지 뿐만 아니라 다양한 영상 (비컬러 메디컬 이미지)들로부터 생성이 가능하므로, 응용범위가 매우 넓다고 할 수 있다.



우선, 컬러 사진을 흑백사진으로 바꾸는 것만 생각해 보자. 우리가 흔히 생각하는 흑백사진은 실은 gray 사진이고, 진정한 흑백사진은 흰색과 검정색, 단 2가지 색으로만 이루어진 영상이다. 컬러이미지를 흑백사진으로 바꾸기 위해서는 그림 1에서 보여진 바와 같이 2단계를 거쳐야 한다. 첫 번째 단계에서는 컬러를 gray-level로 바꾸고, 두 번째 단계에서 gray-level을 흑백(black/white)로 바꾼다. 그림 1.5는 red, green, blue의 컬러이미지가 gray-level을 거쳐 흑백이미지로 바뀌는 과정을 보여준다.



[그림 1. 컬러이미지를 흑백사진으로 바꾸는 단계]



[그림 1.5. 컬러이미지가 gray-level을 거쳐 흑백으로 변화되는 과정]


Thresholding과 Threshold


그림 1.5에서 컬러사진을 gray 사진으로 바꾸는 것은 간단하다. OpenCV에서는 함수 cvtColor( )를 제공한다. 예를 들어 입력 컬러이미지 input_img를 출력 gray-level 이미지 output_img로 바꾸는 것은 다음과 같다.


cvtColor(input_img, output_img, CV_BGR2GRAY);


생성된 gray image의 각  픽셀들은 0~255까지의 값을 갖는다. 0은 검정색, 255는 흰색, 127은 중간정도의 회색으로 생각하면 된다. 이제 gray image를 black & white image (흑백이미지)로 바꾸는 방법에 대해 알아보자.


Gray image를 흑백 이미지로 바꾸는 쉬운 방법은, 각 픽셀값을 검정색 (0) 혹은 흰색 (255)으로 전환하는 것이다. 즉, 0과 255 이 외에는 다른 값을 가지지 못하게 하면 흑백 이미지가 될 것이다. 하지만 어떤 기준으로 픽셀을 검정색 혹은 흰색으로 바꿀 것인가? 한 가지 방법은 어떤 기준값을 세우고, 그 값보다 작으면 검정색, 크면 흰색으로 할 수 있을 것이다. 이렇게 하는 것을 thresholding이라고 하고, 기준값을 threshold(우리말로는 임계값)라고 한다. 아래 그림 2는 주어진 컬러이미지에 대해 threshold = 127로 설정하고 thresholding한 결과이다. 




[그림 2. Threshold=127을 이용한 binary threshing binarization 결과]



Thresholding 결과 생성되는 binary image는 바로 사용되기 보다는 후처리 과정 (post processing)과정을 거쳐서 noise나 불필요한 feature들을 제거하게 된다. 이를 위해 mathematical morphology 방법 등을 이용한다. 후처리 과정이 끝나면, 이미지에서 특정 부분만 골라서 추출하는 segmentation 기술 등을 적용할 수 있는데, 이와 관련해서는 connected component analysis 처리기술이 사용된다. 우선은 thresholding방법에 대해 자세히 알아보고 후처리 방법들은 추후에 설명한다.


Thresholding의 성능개선

Thresholding은 하드웨어 기반으로 수행할 수도 있고, 소프트웨어적으로는 lookup table을 이용해서 할 수도 있다. Lookup table은 크기 256인 일차원 배열인데, 배열의 인덱스는 grey-level값에 해당한다. 각 배열요소의 값은 thresholdinig에 의해 지정할 새로운 값(0 혹은 1, 0 혹은 255)이 된다. 이렇게 되면, 픽셀값을 비교하는 과정없이 배열인덱스로부터 thresholding값을 바로 찾을 수 있기 때문에 속도를 개선시킬 수 있다. 한 장의 이미지 할지라도, 256개 grey-level에 대한 테이블을 만드는 수고는 초대형 이미지의 각 픽셀에 대해 thresholding을 수행할 때의 연산횟수를 고려하면 충분한 가치가 있다. 예를 들어, 1080 * 720 이미지일 경우, thresholding에 필요한 비교 연산의 횟수가 충분히 크기 때문에 테이블을 구성해서 사용하는 편이 훨씬 유리할 수 있다. <<추후 성능비교하는 실험결과를 공개하겠음>>


Threshold의 결정


Thresholding에서 가장 중요한 문제는 threshold V를 어떻게 설정하느냐 하는 것이다. 너무 큰 V값을 설정하면, gray-scale image의 픽셀들이 대부분 0 (검정색)값을 갖게 될 것이고, 반대의 경우에는 255(흰색)가 될 것이다. 여기서는 사진에 따라 적정한 threshold값을 결정하는 방법 들 중 많이 사용되는 대표적인 두 가지에 대해서 살펴보자. 



1. Otsu 방법


이 방법은 threshold V에 의해 이미지의 픽셀들이 두개의 집합(흰색이 될 것과, 검정색이 될 것)으로 나뉘어 질 때, 각 집합에 속한 픽셀들의 값 (원래 픽셀값)으로부터 구해지는 분산이 최소화되는 그런 threshold V를 구하는 것을 목적으로 한다. 말이 좀 어렵기 한데, 분산이 최소화 된다는 것은 비슷한 픽셀값을 가지는 것끼리 같은 집합에 모일 수 있는 threshold V라는 뜻이다.


Otsu방법에 의해 threshold V가 계산되는 과정을 순차적으로 살펴보자. 우선 임의의 값으로 threshold V를 설정한다. 이 때 threshold V에 의해서 이미지의 픽셀들이 검정색으로 될 것과 흰색으로 될 것으로 나뉠 것이다. 검정색이 될 픽셀들의 집합을 black_pixel_set이라고 하고, 흰색이 될 픽셀들의 집합을 white_pixel_set이라고 하자.


우선 black_pixel_set에 속하게 된 픽셀들만을 생각하자. 이 픽셀들은 검정색이 될 것이지만, 원래는 gray-level값을 가지고 있다. 다만, gray-level값이 threshold V보다 작아서 검정색이 될 운명이 된 것이다. 이제 이 가엾은 픽셀들의 원래 gray-level값들을 가지고 평균을 구해보자. 그리고 이 평균을 이용하면 분산도 쉽게 구할 수 있을 것이다. 만약 픽셀값들이 서로 천차만별이면, 분산은 커질 것이고, 서로 비슷비슷하면 분산은 작아질 것이다. 어쨌든 black_pixel_set의 분산은 구했다. 이제 white_pixel_set 픽셀들에 대하여 동일한 계산을 해보면, white_pixel_set의 분산도 구할 수 있다. 이러한 두 개의 분산들은 threshold V를 이용했을 때 구한 것이다. 그런데, 만약 threshold V 대신 다른 threshold W를 사용하면 두 집합의 분산들이 달라질 것이다. threshold V일 때의 분산들이 threshold W일 때의 분산보다 작으면, Otsu방법은 threshold V를 선택한다. 이런 식으로 가능한 모든 threshold 값들에 대해서 분산을 모두 구해보고, 그 중에서 가장 작은 분산을 가지는 threshold를 선택하여 이진화를 진행하는 방법이 Otsu 방법이다.


OpenCV 라이브러리는 함수 threshold( )에서 Otsu 방법을 지원한다. 이 함수를 이용하여 앞의 그림 2의 컬러이미지에 대하여 이진화 결과는 아래 그림 3과 같다. 그림 2와 비교하면, 보다 많은 내용들을 읽을 수 있다.


[그림 3. Otsu방법을 이용한 그림 2의 이진화 결과]



2. Adaptive threshold 방법


두 번째로 살펴볼 threshold를 결정하는 방법은 adaptive threshold 방법이다. 이 방법은 이미지를 같은 크기의 여러 소구역으로 나누고, 각 구역별로 다른 threshold를 이용하는 방법이다. 그야말로 이미지 위치별로 "adaptive" (적응적)인 방법이다. 이런 방법이 나온 이유는 양지와 음지가 모두 들어있는 사진을 상상해보면 이해하기 쉽다. 양지에서는 모든 것이 밝으므로 threshold 값이 높아야 뭔가 구별해 낼 수 있을 것이다. 반대로 음지에서는 모든 것이 어두우므로 threshold값을 어느 정도 낮추는 것이 맞다. 이 경우에 양지와 음지에 각각 따로 threshold를 사용할 수 있도록 하면 좋을 것이다. 이것이 바로 adaptive threshold의 기본 아이디어다.


이를 위해서 이미지를 같은 크기의 여러 구역으로 나누고, 각 구역별로 threshold값을 구한다. 이 때 threshold는 앞서 설명한 Otsu방법에 의해서 구할 수도 있고, 다른 방법을 써도 된다. 각 구역별로 threshold가 정해졌으면, 픽셀에 적용할 threshold는, 그 픽셀에서 가까운 4개 구역의 threshold값들을 interpolation해서 계산한다.


OpenCV's adaptive threshold


OpenCV는 위에서 설명한 adaptive threshold 방법과는 다른 방식으로 adaptive threshold를 구현하고 있다. OpenCV에서 제공하는 함수 adaptiveThreshold( )는 thresholding을 적용하고자 하는 픽셀에 대해 그 주위의 픽셀값들의 평균값과의 차이를 이용한다. 이 차이가 0보다 크면, thresholding결과는 255가 되고, 그렇지 않으면 0으로 설정한다. 주변 픽셀의 범위는 함수의 인수로 지정할 수 있으며, 3, 5, 7,,, 등등의 값을 쓸 수 있다.


함수 adaptiveThreshold( )의 원형은 다음과 같다. (OpenCV 3.1.0, 링크)



- maxValue: thresholding결과 흰색으로 설정할 때 사용하는 값

- adaptiveMethod: 주위 픽셀값들의 평균을 구할 때 사용하는 방법으로 단순평균(ADAPTIVE_THRESH_MEAN_C)과 가우시안 평균 방법(ADAPTIVE_THRESH_GAUSSIAN_C), 두 가지가 가능하다. 가우시안 평균은 weight를 이용하는 방법으로 중앙픽셀에 가까울수록 높은 weight를, 멀어질수록 낮은 weight를 적용하여 평균을 구하는 방법니다.

- tresholdType: thresholding방법을 지정하는 것으로 THRESH_BINARY 혹은 THRESH_BINARY_INV 둘 중 하나가 되어야 한다. THRESH_BINARY_INV는 THRESH_BINARY가 할당하는 값을 반대로 하는 것이다.

- blockSize: 주위 블럭들의 범위 크기

- c: 상수로서 평균값과의 차이를 구하기 전에 빼는 값으로, 보정을 위해 사용한다.


아래 그림은 adaptive thresholding (block size = 101)을 위 그림 2에 적용한 결과이다. 기존 Otsu 방법보다 게시판에 있는 글들이 훨씬 더 많이 드러나는 것을 볼 수 있다.

[그림 3.5. Adaptive thresholding을 그림 2에 적용한 결과]


아래 두 장의 그림은 동일한 이미지에 대해 OpenCV의 adaptiveThreshold( )를 수행한 결과이다. 차이가 있다면 위의 그림은 block size = 101이고, 아래 그림은 block size = 501이다. Block size를 크게 하면, detail이 최소화되는 것을 알 수 있다. 


[그림 4. Adaptive thresholding: block size = 101 ]


[그림 5. Adaptive thresholding: block size = 501]



Band thresholding과 Semi thresholding


이진화 관련해서는 이 외에도 band thresholding 과 semi-thresholding 등이 있다. band thresholding이란 threshold가 범위로 주어지는 thresholding 방법이다. Semi-thresholding은 일반 thresholding의 결과가 흑/백인 반면, gray level로 나오는 것이 특징이다. 예를 들어, threshold값보다 큰 경우에 흰색으로 설정하는 것이 아니라, 픽셀의 원래 gray-level값으로 설정한다.


Multispectral thresholding

컬러 이미지에 직접적으로 thresholding을 어떻게 적용할 것인지에 대해서는 명확히 정해진 방법이 없다. 예를 들어, 컬러 이미지의 r, g, b 채널별로 각각 thresholding을 적용할 수 있고, 컬러 이미지를 그대로 사용하여 3D 컬러공간에서 threshold를 설정할 수도 있다.



반응형