[OpenCV] Otsu's Algorithm 이론 설명 및 C++ Code

2019. 4. 5. 13:42· Programming/OpenCV
반응형

최종 수정 날짜 2019.11.08.

 

연구실에서 차선 검출 및 도로 검출을 위해서 OpenCV로 작업했던 일이 있었니다.

요즘은 ros에서 PCL을 사용해서 라이다 데이터를 이용하는 작업으로 바꼈지만, 이 전에 도로 영역을 검출하기 위해 했던 공부 했던 Otsu's Algorithm 구현 코드를 올리려고 합니다.

 

Otsu's 알고리즘은 영상 이진화 방법 중에 하나입니다. 영상의 이진화 방법은 여러가지 방법이 있는데, 그 중에서도 이 Otsu's 알고리즘은 정말 많이 사용되곤 합니다.

 

우선, 영상의 이진화를 하기 위해서는 임계값을 정해줘야합니다. 흑백영상을 예를 들자면, 일반적으로 흑백 영상의 픽셀값의 범위는 0~255를 가지고 있습니다. 여기서 임계값이 200으로 설정하고 이진화를 한다면 픽셀값이 200을 넘어가면 255, 200을 못 넘는다면 0의 값으로 변경시키며 0 또는 255값만을 가지도록 이진화를 해줄 수가 있습니다. 그런데 영상의 이진화 방법이 참 까다로워질 수 있는 이유는 이진화 결정하는 임계값을 사용자가 정해줘야하는 경우가 있기 때문입니다. 따라서 이러한 시도에는 사용자의 여러 시행착오가 필요하고 개발자로 하여금 인내심을 갖도록 하는 작업이기도 합니다. 이 때 우리가 자동으로 이 임계값을 정하기 위해 사용하는 알고리즘이 Otsu's 알고리즘입니다.

 

임계값을 t라고 가정한다면 t를 기준으로 픽셀값들을 두 집합으로 나누었을 때, 각 집합의 밝기값의 분포가 균등할수록 좋다는 점에 착안하여서 균등성이 제일 높도록 이진화하는 t에게 높은 점수를 줍니다. 이 균등성은 각 그룹의 분산으로 측정을 하고, 분산이 작을수록 균등성이 높습니다. 이 t를 0~255까지 움직이며 모든 경우의 점수를 계산하고 그 중 가장 높은 점수를 가진 t를 최종 임계값으로 취하는 알고리즘입니다.

 

이 알고리즘을 구하기 위해 필요로하는 변수가 가중치, 평균, 분산이고, 이 값들을 구하기 위해 사전에 영상에 대한 정규화된 히스토그램이 구해져있어야합니다. 그래야 이 히스토그램을 통해서 가중치, 평균, 분산값을 구할 수가 있게 됩니다.

 

먼저, 정규화된 히스토그램안에서 임계값 0~t까지의 누적합, t+1부터 255까지 누적합을 구해서 두 개의 가중치를 구합니다. 그리고 0~t까지와 t+1~255까지의 평균을 구하고 평균을 통해 분산을 구해줍니다.

 

그래서 앞 집합의 가중치과 분산을 곱해준 값과 뒷 집합의 가중치와 분산을 곱해준 값을 더해줍니다.

 

이렇게 0~255까지 t를 순회가 끝나면 그 중 가장 높은 값을 가지는 t를 최종 임계값으로 취해주면 됩니다.

 

아래는 C++로 구현한 코드입니다.

구현한 코드는 제가 작업하면서 짠 코드중 Otsu's 알고리즘만 잘라온 것이기 때문에 중간에 이미지나 변수 들은 알아서 변경하셔서 사용하셔야합니다. 나중에 일반화된 코드로 수정하겠습니담.


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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
int Otsu_Thres = 0;
 
    double inter_class_variance = 0;
 
    for (int O_thres = 0; O_thres < 256; O_thres++) {
 
        int alpha = 0, beta = 0;
 
        int sum1 = 0, sum2 = 0;
 
        double mu1 = 0, mu2 = 0;// , var1, var2;
 
 
 
        for (int i = 0; i < O_thres; i++)
 
            sum1 += calcBinary[i];
 
 
 
        sum2 = dst.rows * dst.cols - sum1;
 
        cout << Otsu_Thres << endl;
 
        cout << "sum1 : " << sum1 << endl;
 
        cout << "sum2 : " << sum2 << endl;
 
 
 
        alpha = (double)sum1 / (double)calcBinary.size();
 
        beta = (double)sum2 / (double)calcBinary.size();
 
 
 
        cout << "alpha : " << alpha << endl;
 
        cout << "beta : " << beta << endl;
 
 
 
        // Calc average
 
        for (int m = 0; m < O_thres; m++) {
 
            mu1 += (double)(m * calcBinary[m]) / (double)sum1;
 
        }
 
 
 
        for (int m = O_thres; m < 256; m++) {
 
            mu2 += (double)(m * calcBinary[m]) / (double)sum2;
 
        }
 
 
 
        //cout << "mu1 : " << mu1 << endl;
 
        //cout << "mu2 : " << mu2 << endl;
 
 
 
        /*// Calc variance
 
        for (int v = 0; v < O_thres; v++) {
 
            var1 += (double)(pow((v - mu1), 2) * calcBinary[v]) / (double)sum1;
 
        }
 
 
 
        for (int v = O_thres; v < 256; v++) {
 
            var2 += (double)(pow((v - mu2), 2) * calcBinary[v]) / (double)sum2;
 
        }*/
 
        double temp = alpha * beta * pow((mu1 - mu2), 2);
 
        if (inter_class_variance < temp) {
 
            inter_class_variance = temp;
 
            Otsu_Thres = O_thres;
 
        }
 
}
반응형

'Programming > OpenCV' 카테고리의 다른 글

[OpenCV] MeanShift Clustering C++ Code  (0) 2020.05.13
[OpenCV] QuadTree Clustering C++ Code  (0) 2019.11.25
[OpenCV] KMeans Clustering C++ Code  (0) 2019.11.25
'Programming/OpenCV' 카테고리의 다른 글
  • [OpenCV] MeanShift Clustering C++ Code
  • [OpenCV] QuadTree Clustering C++ Code
  • [OpenCV] KMeans Clustering C++ Code
오뚜깅
오뚜깅
오뚜깅
오뚜깅
오뚜깅
전체
오늘
어제
  • 분류 전체보기
    • 취업인생
    • Programming
      • C & C++
      • Python
      • OpenCV
      • PCL
      • ROS
      • Deep learning
      • Network
    • 알고리즘
      • 이론
      • 백준(BOJ)
      • 프로그래머스(Programmers)
    • Project
    • IT
      • 우분투
    • 일상
      • 말씀 묵상
      • 끄적임
      • 영어 일기

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • tensorflowversion
  • installubuntu
  • OtsuAlgorithm
  • 2292
  • 우분투
  • C++
  • kmeansclustering
  • 딥러닝환경구축
  • c++code
  • clustering
  • cuda9.0
  • imageclustering
  • cudaversion
  • CUDA
  • 백준2231
  • 오츠알고리즘
  • installcudnn
  • DeepLearning
  • pointcloud
  • 백준2798
  • PointCloudLibrary
  • installcuda
  • opencv
  • rospy
  • 사용자지정정규화공식
  • pytorch
  • cuda설치
  • CuDNN
  • cv_bridge
  • graphicdriver

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
오뚜깅
[OpenCV] Otsu's Algorithm 이론 설명 및 C++ Code
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.