ygreenb
yellowgreenblue
ygreenb
전체 방문자
오늘
어제
  • TIL (130)
    • Algorithm & Data Structure (70)
      • 이론 (4)
      • 프로그래머스 (54)
      • 백준 (12)
    • JAVA (4)
    • Android Studio (9)
    • Database (1)
    • WEB (25)
      • HTML+CSS (7)
      • Javascript (5)
      • React (11)
      • Django (1)
      • Node.js (1)
    • Computer Vision (13)
    • Git (8)

블로그 메뉴

  • HOME
  • TAG
  • GITHUB

공지사항

인기 글

태그

  • 코틀린
  • DP
  • Comparator
  • getOrDefault
  • BFS
  • 프로그래머스
  • sort
  • PriorityQueue
  • HashMap
  • dfs
  • Android
  • kotiln
  • git bash
  • 스택/큐
  • 백준
  • reactjs
  • stack
  • 깃허브
  • 프로그래머스 Lv.2
  • 깃
  • 안드로이드
  • git
  • entrySet
  • Queue
  • React
  • 해시
  • Arrays.sort()
  • greedy
  • java
  • compareTo()

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ygreenb

yellowgreenblue

[OpenCV] 영상 분할(Image Segmentation)
Computer Vision

[OpenCV] 영상 분할(Image Segmentation)

2020. 1. 19. 05:30

영상분할(image/video segmentation)이란? 

어떤 디지털 이미지가 주어져있을때, 그 영상을 여러개의 영역으로 분할하는 것이다.

영상분할은 보통 object classification(물체 분류)에 활용되는데, 우리 눈에는 배경과 어떤 물체 영역이 구별되어 보이지만 실제로 밝기값의 차이가 크거나 미미할 수 있다. 이런 이미지를 0과 255같이 2가지의 값으로 분리시켜 물체의 분류가 용이해지도록 하는 것이다.

object classification

입력: gray-scale 이미지

출력: binary image(0과 255 또는 0과 1 같이 2개의 값으로만 이루어진값)


1. Thresholding

영상분할에는 다양한 방법들이 있는데, 그 중 대표적인 방법으로 Thresholding이 있다.

가정

- 분할, 추출하고 싶은 물체와 배경의 밝기값이 다르다.

- 배경영역과 물체영역 내의 밝기값이 단조롭다.(차이가 별로 없다.)

 

1개의 threshold와 2개의 threshold

 

threshoding에선 적절한 threshold를 찾는 것이 가장 중요하다!

고려해야할 문제

  1.  Noise (노이즈)
  2.  Illumination and reflectance (조명이 비균일하게 작용함)

위와 같은 문제를 해결하기 위해, thresholding을 하기전에 smoothing을 적용한다.

Thresholding after applying smoothing

실제로 smoothing을 적용한 후 thresholding을 하면 좀 더 좋은 결과를 얻을 수 있다.

 

2. Global thresholding

: 동일한 threshold을 모든 픽셀에 적용하는 방법

2.1 Basic method

  1. 임의로 하나의 T를 정하고
  2. 이 T를 가지고 segmentation 수행해서 2개의 그룹으로 나눈다.
  3. 각 그룹에 대해서 픽셀들 값들의 평균 m1, m2를 구한다.
  4. 이 평균 m1, m2로 새로운 threshold를 구해준다. T=0.5x(m1+m2)
  5. 이 2개의 T가 매우 유사하다면 종료. 그렇지 않으면(차이가 크다면) 새로 구한 T를 가지고 1-4번을 반복한다.)

2.2 Otsu's method

  • 만약, 굉장히 좋은 threshold를 가지고 하나의 영상을 두개의 그룹으로 분할했다면, 하나의 그룹에 속한 픽셀들의 값은 유사할테고, 또 다른 그룹의 픽셀값들도 유사하다. 그렇다면, 두 그룹값의 밝기값의 차이는 클것이다.
  • 다양한 T를 적용해보고, 그 T를 통해서 얻어진 두개의 영역의 픽셀의 밝기값의 차이를 계산해서 픽셀값의 차이가 크다면 이 T는 좋은 T이다. -> 이 T를 결과로 쓰겠다.
  • 잘 구해졌는지 판단하기 위해서 히스토그램을 이용할것임.
  1. 영상에 대해서 normalized histogram을 계산할것(normalized histogram : 히스토그램 그리고 픽셀수로 각각의 bin을 나눈것)
  2. 주어져있는 후보 t인 k로 between class-variance를 계산한다. (두 영역의 밝기값 차이가 크다면 between class-variance도 크고, 작다면 작을것임)
  3. 즉, 우리가 선택해야하는 t k는 variance가 가장 큰 값일때이다.

 

3. Local (adaptive) thresholding 

: 각 픽셀마다 threshold를 다르게 적용하는 방법.

- 각각의 픽셀에 대한 T를 정할 때, 주변의 픽셀값들의 분포를 토대로 구하는 것.

  • ADAPTIVE_THRESH_MEAN_C : 𝑇 𝑥, 𝑦 = 𝑚𝑒𝑎𝑛 𝑜𝑓 𝑡ℎ𝑒 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 × 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 𝑛𝑒𝑖𝑔ℎ𝑏𝑜𝑟ℎ𝑜𝑜𝑑 𝑜𝑓 𝑥, 𝑦 − 𝐶 (주변 픽셀들의 평균- 상수C를 T로 씀)
  • ADAPTIVE_THRESH_GAUSSIAN_C : 𝑇 𝑥, 𝑦 = 𝑎 𝑤𝑒𝑖𝑔ℎ𝑡𝑒𝑑 𝑠𝑢𝑚(𝑐𝑟𝑜𝑠𝑠 − 𝑐𝑜𝑟𝑟𝑒𝑙𝑎𝑡𝑖𝑜𝑛 𝑤𝑖𝑡ℎ 𝑎 𝐺𝑎𝑢𝑠𝑠𝑖𝑎𝑛 𝑤𝑖𝑛𝑑𝑜𝑛𝑤) 𝑜𝑓 𝑡ℎ𝑒 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 × 𝑏𝑙𝑜𝑐𝑘𝑠𝑖𝑧𝑒 𝑛𝑒𝑖𝑔ℎ𝑏𝑜𝑟ℎ𝑜𝑜𝑑 𝑜𝑓 𝑥, 𝑦 − 𝐶 (가우시안 함수를 활용해서 가중치 평균을 구한 후, 거기서 특정한 상수 C값을 뺀것을 T로 씀)
  • Image partitioning : 임의로 영상을 분할해서, 각 분할된 영역별로 동일한 T를 가지도록 thresholding할 수 있다.

조명이 다양한 영상을 6분할해서 local thresholding함
가로방향으로 음영의 차이가 크게 일어나있는 영상 -> 세로 방향으로 local threshoding을 수행한다.

 

example code

// Basic method

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp> 
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

int main() {
	Mat image, thresh;
	int thresh_T, low_cnt, high_cnt, low_sum, high_sum, i, j, th;
	
	thresh_T = 200; // 초기 T값
	th = 10; // 초기 T값과 다시 구해진 T값의 차이가 일정크기 이하면 멈추는데 사용하는값
	low_cnt = high_cnt = low_sum = high_sum = 0;
	
	image = imread("zx.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) { // 새로운 T값 < 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

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp> 
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

int main() {
	Mat image, result;
	image = imread("zx.png", 0);
	threshold(image, result, 0, 255, THRESH_BINARY | THRESH_OTSU);
	
	imshow("Input image", image);
	imshow("result", result);
	waitKey(0);
}
// Local(Adaptive) Thresholding

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp> 
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;


int main() {
	Mat image, binary, adaptive_binary;
	image = imread("zx.png", 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);
}

 

 

 

이 게시물은 한동대학교 황성수 교수님의 컴퓨터비전 강의를 공부하며 정리한 내용입니다.

'Computer Vision' 카테고리의 다른 글

[OpenCV] 동영상 분할(Video Segmentation)  (0) 2020.01.19
[OpenCV] 컬러영상처리(Color Processing)  (0) 2020.01.19
[OpenCV] 공간 도메인 필터링(Spatial Filtering)  (0) 2020.01.19
[OpenCV] 히스토그램 평활화(Histogram Equalization)  (0) 2020.01.19
[OpenCV] 밝기값 변환(Intensity Transformation)  (0) 2020.01.18
    'Computer Vision' 카테고리의 다른 글
    • [OpenCV] 동영상 분할(Video Segmentation)
    • [OpenCV] 컬러영상처리(Color Processing)
    • [OpenCV] 공간 도메인 필터링(Spatial Filtering)
    • [OpenCV] 히스토그램 평활화(Histogram Equalization)
    ygreenb
    ygreenb
    개발공부기록장

    티스토리툴바