Image Segmentation 영상 분할
- 디지털 영상을 여러 개의 영역으로 분리하는 것이다.
- Object classification
- 입력 영상이 그레이스케일 영상이고 출력 영상은 바이너리 이미지 (0 혹은 255 값으로만 구성된 영상)
Thresholding
- 가정 : 물체와 배경의 밝기 값이 다르다, 배경과 물체 영역 내에서는 밝기 값의 차이가 거의 없다.
- 적절한 threshold를 구하는 것이 중요하다.
- 잡음이 많아질수록 threshold를 구하기 어려워진다.
- 조명이 비균일할때 threshold를 구하기 어려워진다.
Thresholding after applying smoothing
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
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);
}
출처 - 컴퓨터 비전 한동대학교 황성수
'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 |
댓글