1. 오츠 이진화
- 영상을 구성하는 값들을 0과 255 두 가지 값으로 분리(Segmentaion)
- 화소값의 분포에 따라 자동적으로 값을 선택하는 이진화 방법
- 즉, 흰색과 검은색으로 영상이 분리가 된다.
- 이득 함수 = 클래스1일 확률 * 클래스2일 확률 *(클래스1의 평균 - 클래스 2의 평균)^2
- 임계값 = 이득함수를 최대로 하는 히스토그램 레벨
2. 소스 코드
import os
import cv2
import numpy as np
_MAX_HISTO_ = 256
def calc_histo(img_src):
histo_info = np.zeros(_MAX_HISTO_)
src_height = img_src.shape[0]
src_width = img_src.shape[1]
for h in range(src_height):
for w in range(src_width):
histo_info[img_src[h,w]] += 1
return histo_info
def draw_histo(histo_info):
img_histo = np.zeros([256, _MAX_HISTO_], dtype=np.uint8)
histo_height = img_histo.shape[0]
max_histo = max(histo_info)
for i in range(_MAX_HISTO_):
cv2.line(img_histo, (i, histo_height), (i, int(histo_height-histo_info[i]/max_histo*histo_height)), 255, 1)
return img_histo
#이진화를 수행하는 함수
def my_thresh(src, thresh_val):
src_height = np.shape(src)[0]
src_width = np.shape(src)[1]
dst = np.zeros(np.shape(src), dtype=np.uint8)
for h in range(src_height):
for w in range(src_width):
dst[h,w] = 0 if src[h,w] <= thresh_val else 255
return dst
#오츠 이진화 함수
def otsu_thresh(src):
src_height = np.shape(src)[0]
src_width = np.shape(src)[1]
#히스토그램 계산
hist = calc_histo(src)
# 히스토그램을 정규화 하여 픽셀 값에 대한 등장 확률 계싼
hist_prob = hist/(src_height*src_width)
#픽셀 값 등장 확률을 누적하여 히스토그램 범위에 해당하는 등장확률 chist와
#0~255까지 히스토그램에 대해 누적된 픽셀의 평균 픽셀 값 cxhist를 계산
chist = np.zeros(_MAX_HISTO_)
cxhist = np.zeros(_MAX_HISTO_)
chist[0] = hist_prob[0]
cxhist[0] = 0
for i in range(1, _MAX_HISTO_):
chist[i] = chist[i-1] + hist_prob[i]
cxhist[i] = cxhist[i-1] + hist_prob[i]*i
thresh_val = 0
max_profit = 0
#전체 영상에 대한 평균픽셀값은 cxhist의 256번째 값에 해당
global_mean = cxhist[_MAX_HISTO_-1]
for i in range(_MAX_HISTO_):
#클래스 1에 해당하는 픽셀이 등장할 때까지 continue수행(divide by zero 방지)
if chist[i] == 0: continue;
#각 클래스에 해당하는 픽셀이 등장할 확률 계산
cls1_prob = chist[i]
cls2_prob = 1 - chist[i]
#더이상 클래스 2로 들어갈 픽셀이 존재하지 않을 경우 종료(divide by zero 방지)
if cls2_prob == 0: break
cls1_mean = cxhist[i] / cls1_prob
cls2_mean = (global_mean - cxhist[i]) / cls2_prob
#위에서 말했던 이득함수 구현
profit = cls1_prob*cls2_prob*(cls1_mean - cls2_mean)**2
#얻어지는 이득값이 이전의 최대이득값보다 큰 경우 임계깞과 최대이득값을 갱신
if profit > max_profit:
max_profit = profit
thresh_val = i
#계산된 값을 사용하여 이진화를 수행한 결과 이미지 반환
print('thresh_val :', thresh_val)
return my_thresh(src, thresh_val)
#현재 실행되고 있는 경로 값을 얻어서 이미지 경로를 조합
cur_path=os.getcwd()
img_name = 'house.jpg'
image_path=os.path.join(cur_path, img_name)
#그레이스케일로 이미지 읽고 히스토그램 이미지 생성
img_src = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
img_histo_src = draw_histo(calc_histo(img_src))
#오츠 이진화 수행
img_otsu = otsu_thresh(img_src)
#이미지 보여주기
cv2.imshow('src', img_src)
cv2.imshow('src_histo', img_histo_src)
cv2.imshow('otsu', img_otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 결과
'IT > 영상처리' 카테고리의 다른 글
[영상처리:Python] OpenCV를 이용한 얼굴 인식(Face Detection) 잠금 해제 및 Web Browser 실행 예제 (1) | 2019.06.22 |
---|---|
[영상처리/OpenCV-Python] 색상 공간 변환(RGB~HSI) 구현하기 (1) | 2019.04.14 |
[영상처리/OpenCV-Python] Maximally Stable Extreme Regions 구현하기 (0) | 2019.04.13 |
[영상처리/OpenCV-Python] 가우시안 노이즈 영상 이미지를 더하여 노이즈 줄이기 (2) | 2019.04.01 |
영상처리 OpenCV 히스토그램 평활화 및 CLAHE 적용 히스토그램 그리기 (0) | 2019.03.31 |
영상처리 OpenCV 이미지 히스토그램 그리기 (0) | 2019.03.25 |
영상처리 SSD 관련 예제 문제(2) (0) | 2019.03.20 |
[영상처리] - 파이썬(Python)을 이용한 이미지 채널정보 접근 (0) | 2019.03.18 |
최근댓글