본문 바로가기
openCV

[openCV] 영상 분할

by _eunji_ 2020. 1. 18.

Image Segmentation 영상 분할

  • 디지털 영상을 여러 개의 영역으로 분리하는 것이다.
  • Object classification
  • 입력 영상이 그레이스케일 영상이고 출력 영상은 바이너리 이미지 (0 혹은 255 값으로만 구성된 영상)

0 혹은 255의 값으로만 표현 시킴으로써 물체와 배경 분리

Thresholding

  • 가정 : 물체와 배경의 밝기 값이 다르다, 배경과 물체 영역 내에서는 밝기 값의 차이가 거의 없다.
  • 적절한 threshold를 구하는 것이 중요하다.

임계값을 통해 물체와 배경을 분리할 수 있다. 왼쪽 경우에만 출력 영상이 바이너리 이미지이다.

  • 잡음이 많아질수록 threshold를 구하기 어려워진다.
  • 조명이 비균일할때 threshold를 구하기 어려워진다.

Thresholding after applying smoothing

따라서 잡음 이미지에 스무딩이나 가우시안 필터를 수행하고 threshold 값을 찾는다.

thresholding 방법

  • Global thresholding : 동일한 threshold를 모든 픽셀에 적용하는 것
  • Local (adaptive) thresholding : 각 픽셀마다 threshold를 다르게 적용하는 것

 

Global Thresholding

Basic method

  • 1단계 : 임의로 하나의 threshold T를 정한다.
  • 2단계 : T를 활용하여 segmentation을 수행하여 두 개의 그룹으로 분할한다.
  • 3단계 : 각 그룹에 해당하는 픽셀 값의 평균을 구한다. (m1, m2)
  • 4단계 : 새로운 threshold를 계산한다. T=0.5X(m1+m2)
  • 5단계 : 두개의 threshold가 유사하다면 종료하고 차이가 크다면 2~4단계를 반복한다.

 

Otsu’s method

  • 만약 well-threshold로 하나의 영상을 두 개의 영역으로 분할했다면 하나의 그룹에  속한 픽셀 값들은 유사하고 두 그룹 간 밝기 값 차이는 클 것이다.
  • 두 영역의 밝기 값의 차이가 크다면 그 threshold을 임계값으로 사용하는 것이 Otsu’s method 방법이다.
  • 이 방법은 thresholding이 잘 이루어졌는지 판단하기 위해 히스토그램을 활용한다.

  • 1단계 : 영상에 대해 히스토그램 평활화
  • 2단계 : 후보 threshold인 k값으로 thresholing을 수행하고 between-class variance 𝜎^2𝐵 (두 영역의 차이가 크면 between-class variance가 크고 큰 것)
  • 3단계 : between-class variance가 가장 큰 값을 선택

Local(Adaptive) Thresholding

  • 각각의 픽셀 값의 threshold 값을 정할때 주변 픽셀 값들의 분포를 토대로 정하는 것
  • ADAPTIVE_THRESH_MEAN_C : 𝑇 𝑥, 𝑦 = 𝑚𝑒𝑎𝑛 𝑜𝑓 𝑡ℎ𝑒 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 × 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 𝑛𝑒𝑖𝑔ℎ𝑏𝑜𝑟ℎ𝑜𝑜𝑑 𝑜𝑓 𝑥, 𝑦 − C
  • ADAPTIVE_THRESH_GAUSSIAN_C : 𝑇 𝑥, 𝑦 = 𝑎 𝑤𝑒𝑖𝑔ℎ𝑡𝑒𝑑 𝑠𝑢𝑚(𝑐𝑟𝑜𝑠𝑠 − 𝑐𝑜𝑟𝑟𝑒𝑙𝑎𝑡𝑖𝑜𝑛 𝑤𝑖𝑡ℎ 𝑎 𝐺𝑎𝑢𝑠𝑠𝑖𝑎𝑛 𝑤𝑖𝑛𝑑𝑜𝑛𝑤) 𝑜𝑓 𝑡ℎ𝑒 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 × 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 𝑛𝑒𝑖𝑔ℎ𝑏𝑜𝑟ℎ𝑜𝑜𝑑 𝑜𝑓 𝑥, 𝑦 − C

global thresholding을 적용했을때 배경이 흰색임에도 불구하고 배경 부분이 물체로 판단하는 문제가 발생할 수 있는데 local thresholding은 그 문제를 해결 할 수 있다.
임의로 영상을 분할한 후 분할한 영역별로 threshold를 수행할 수 있다.

Basic method

int main() {
		Mat image, thresh;
		int thresh_T, low_cnt, high_cnt, low_sum, high_sum, i, j, th;

		thresh_T = 200;
		th = 10;
		low_cnt = high_cnt = low_sum = high_sum = 0;

		image = imread("lena.png", 0);
		cout << "threshold value:" << thresh_T << endl;

		while (1) {
			for (j = 0; j < image.rows; j++) {
				for (i = 0; i < image.cols; i++) {
					if (image.at<uchar>(j, i) < thresh_T) {
						low_sum += image.at<uchar>(j, i);
						low_cnt++;
					}
					else {
						high_sum += image.at<uchar>(j, i);
						high_cnt++;
					}
                }
			}
			if (abs(thresh_T - (low_sum / low_cnt + high_sum / high_cnt) / 2.0f) < th) {
				break;
			}
			else {
				thresh_T = (low_sum / low_cnt + high_sum / high_cnt) / 2.0f;
				cout << "threshold value:" << thresh_T << endl;
				low_cnt = high_cnt = low_sum = high_sum = 0;
			}
		}
		threshold(image, thresh, thresh_T, 255, THRESH_BINARY);
		
        imshow("Input image", image);
		imshow("thresholding", thresh);
		waitKey(0);
}

Otsu’s algorithm

int main() {
		Mat image, result;
		image = imread("lena.png", 0);
		threshold(image, result, 0, 255, THRESH_BINARY | THRESH_OTSU);
		imshow("Input image", image);
		imshow("result", result);

		waitKey(0);
}

Local(Adaptive) Thresholding

int main() {
		Mat image, binary, adaptive_binary;
		image = imread("opencv.jpg", 0);

		threshold(image, binary, 150, 255, THRESH_BINARY);
		adaptiveThreshold(image, adaptive_binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 85, 15);

		imshow("Input image", image);
		imshow("binary", binary);
		imshow("adaptive binary", adaptive_binary);
		waitKey(0);
}

 

 

출처 - 컴퓨터 비전 한동대학교 황성수

 http://www.kocw.net/home/cview.do?cid=1b1f5b73413060b5

'openCV' 카테고리의 다른 글

[openCV] 형태학적 연산  (0) 2020.01.29
[openCV] 동영상 분할  (0) 2020.01.18
[openCV] 컬러영상 처리  (0) 2020.01.18
[openCV] 공간 도메인 필터링  (0) 2020.01.18
[openCV] 히스토그램 평활화  (0) 2020.01.18

댓글