본문으로 바로가기

이진화란?

  • 이미지의 픽셀 값을 0 또는 255 로 만드는 연산이다.

  • 원하는 피사체의 모양을 좀 더 정확히 판단 가능하다.

  • 배경과 물체를 구분한다.

  • 관심 영역, 비관심 영역을 구분한다.

 

cv2.threshold(src, threshold, maxval, type_falg, dst=None) -> retval, dst

  • src: 입력 이미지
  • threshold: 임계값
  • maxval: cv2.THRESH_BINARY 또는 cv2.THRESH_BINARY_INV 방법 사용시 최대값 일반적으로는 255로 지정
  • type: 임계값 함수 동작 지정 또는 자동 임계값 결정 방법 지정
  • retval: 사용된 임계값(type 에서 자동 임계값 결정 방법 사용시 확인 가능)
  • dst: 출력 이미지(src 와 동일)
  • type_flag 종류
  • cv2.THRESH_BINARY:  src(x, y) > threshold 이면 maxval, 그렇지 않으면 0
  • cv2.THRESH_BINARY_INV: src(x, y) > threshold 이면 0, 그렇지 않으면 maxval
  • cv2.THRESH_TRUNC: src(x, y) > threshold 이면 threshold, 그렇지 않으면 src(x, y)
  • cv2.THRESH_TOZERO: src(x, y) > threshold 이면 src(x, y), 그렇지 않으면 0
  • cv2.THRESH_TOZERO_INV: src(x, y) > threshold 이면 0, 그렇지 않으면 src(x, y)
  • cv2.THRESH_OTSU: otsu 알고리즘으로 임계값 결정
  • cv2.THRESH_TRIANGLE: 삼각 알고리즘으로 임계값 결정

 

이진화 구현

넘파이를 이용한 구현

import os
import cv2
import numpy as np

path = os.path.join('image', 'gray_gradient.jpg')
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

thresh_np = np.zeros_like(img)
thresh_np[img > 127] = 255

cv2.imshow('img',img)
cv2.imshow('thresh_np', thresh_np)

cv2.waitKey()
cv2.destroyAllWindows()

 

threshold 를 이용

import os
import cv2
import numpy as np

path = os.path.join('image', 'gray_gradient.jpg')
src = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

bz = np.zeros_like(src)
bz[src > 127] = 255

ret, thresh = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY)

cv2.imshow('src', src)
cv2.imshow('binarization', bz)
cv2.imshow('thresh', thresh)

cv2.waitKey()
cv2.destroyAllWindows()

 

트랙바를 이용하여 임계값에 따른 차이를 비교합니다.

import os
import cv2

path = os.path.join('image', 'sudoku.jpg')
src = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
src = cv2.resize(src, None, fx=2, fy=2)

def onChange(val):
    _, dst = cv2.threshold(src, val, 255, cv2.THRESH_BINARY)
    cv2.imshow('binarization', dst)

cv2.imshow('binarization', src)
cv2.createTrackbar('level', 'binarization', 0, 255, onChange)

cv2.waitKey()
cv2.destroyAllWindows()

 

otsu (cv2.THRESH_OTSU)

otsu 이진화는 자동으로 임계값을 구하는 알고리즘입니다.

  1. 임계값을 임의로 정해서 픽셀들을 두 개의 클래스로 나눔.
  2. 두 클래스의 intensity 의 분포를 반복해서 구하고, 두 클래스의 intensity 분포를 가장 균일하게 하는 임계값을 찾음.

 

cv2.threshold(src, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

import os
import cv2
import numpy as np
import matplotlib.pylab as plt

path = os.path.join('image', 'scaned_paper.jpg')

src = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

t, t_otsu = cv2.threshold(src, 0, 255,  cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print(t)

cv2.imshow('src', src)
cv2.imshow('otsu', t_otsu)

cv2.waitKey()
cv2.destroyAllWindows()

 

otsu 알고리즘이 찾은 임계값은 t 입니다.

t, t_otsu = cv2.threshold(img, 0, 255,  cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print(t)
131.0

 

Adaptive Threshold

적응형 스레시홀드로 이미지를 여러 영역으로 나눈 다음 각각의 임계값을 구하는 과정을 거칩니다.

영상 내 조명이 균일하지 않거나 배경색이 여러가지인 경우 정확한 이진화가 어렵습니다.

 

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None) -> dst

  • src: 입력 이미지
  • maxValue: 임계값 함수 최대값(일반적으로 255)
  • adaptiveMethod: 블록 평균 계산 방법
  • cv2.ADAPTIVE_THRESH_MEAN_C: 산술평균
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 가우시안(Gaussian) 가중치 평균
  • thresholdType: cv2.THRESH_BINARY / cv2.THRESH_BINARY_INV
  • blockSize: 블록 크기 (3 이상의 홀수)
  • C
  • dst: 출력 이미지
import os
import numpy as np
import cv2
import matplotlib.pylab as plt

path = os.path.join('image', 'sudoku.jpg')
src = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

t, t_otsu = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

at = cv2.adaptiveThreshold(src, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 55, 5)

cv2.imshow('src', src)
cv2.imshow('otsu', t_otsu)
cv2.imshow('at', at)

cv2.waitKey()
cv2.destroyAllWindows()

 

트랙바를 이용해서 블록크기에 따른 차이를 비교합니다.

import os
import numpy as np
import cv2

path = os.path.join('image', 'sudoku.jpg')
src = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
src = cv2.resize(src, None, fx=2, fy=2)

def onChange(val):
    if val < 3:
        cv2.imshow('adaptiveThreshold', src)

    if val % 2 == 0:
        val = val - 1

    dst = cv2.adaptiveThreshold(src, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blockSize=val, C=5)
    cv2.imshow('adaptiveThreshold', dst)

cv2.imshow('adaptiveThreshold', src)
cv2.createTrackbar('block size', 'adaptiveThreshold', 0, 200, onChange)

cv2.waitKey()
cv2.destroyAllWindows()