파이썬으로 영상처리_이진화(threshold, Adaptive Threshold, 오츠 알고리즘)

k_minseokVv·2024년 1월 8일
0

OpenCV - Python

목록 보기
9/13
  • 이진화 : 특정 값을 기준으로 흑과 백만 가지게 하는 binary 작업

기본적인 threshold함수 사용

import cv2

img = cv2.imread('book.jpg',cv2.IMREAD_GRAYSCALE)

ret, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 2개의 값을 얻을 수 있음 = cv2.threshold(대상 사진, 임계값(기준점), 임계값보다 클 때 변할 목표, ???)
# 위에선 임계값 127보다 크면 255 하얗게 변하고 그 외엔 검은색으로 변함

cv2.imshow('img',img)
cv2.imshow('binary',binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • Threshoid (임계값) : 기준점과 같은 의미, 주어진 시간과 상황에 따라 기준이 달라질 수 있음을 의미

Trackbar를 활용해 실시간 변화 확인

import cv2

def empty(pos):
    #print(pos)
    pass

img = cv2.imread('book.jpg',cv2.IMREAD_GRAYSCALE)

name = 'Trackbar'
cv2.namedWindow(name) #트랙바를 사용하고자 할 땐 미리 윈도우의  이름을 정의해주어야 한다
cv2.createTrackbar('threshold', name, 127,255, empty)
#cv2.createTrackbar(이름, 창의 이름, 초기값, 최댓값, 이벤트 처리)

while True:
    thresh = cv2.getTrackbarPos('threshold', name) #트랙바이름, 창 이름 둘 다 입력하면 트랙바의 position을 가져얼 수 있음
    ret, binary = cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY)
    
    if not ret:
        break
    
    cv2.imshow(name, binary)
    if cv2.waitKey(1) == ord('q'):
        break
        
cv2.destroyAllWindows()

threshold 작동원리를 확인할 수 있는 코드

  • 맨 우측은 흰색 영역 존재
import cv2

def empty(pos):
    #print(pos)
    pass

img = cv2.imread('위 예시 사진',cv2.IMREAD_GRAYSCALE)

name = 'Trackbar'
cv2.namedWindow(name) #트랙바를 사용하고자 할 땐 미리 윈도우의  이름을 정의해주어야 한다
cv2.createTrackbar('threshold', name, 127,255, empty)
#cv2.createTrackbar(이름, 창의 이름, 초기값, 최댓값, 이벤트 처리)

while True:
    thresh = cv2.getTrackbarPos('threshold', name) #트랙바이름, 창 이름 둘 다 입력하면 트랙바의 position을 가져얼 수 있음
    ret, binary = cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY)
    
    if not ret:
        break
    cv2.imshow('img', img)
    cv2.imshow(name, binary)
    if cv2.waitKey(1) == ord('q'):
        break
        
cv2.destroyAllWindows()
  • 첫번째 검은색은 임계값이 0 이므로 계속 검은색유지
  • 두번째 진한회색은 임계값이 127이므로 127이상부터 검은색
  • 세번째 밝은 회색은 임계값이 195이므로 그전까지 흰색 그 후 검
  • 네번째 흰색은 255까지 흰색 유지

Adaptive Threshold

  • 이미지를 작은 영역으로 나누어서 임계치 적용
  • 동일 이미지 내에서 조명이 다른 영역에 대해서도 좋은 결과를 얻을 수 있다
import cv2

def empty(pos):
    # 트랙바가 변경될 때마다 호출되는 콜백 함수
    pass

img = cv2.imread('book.jpg',cv2.IMREAD_GRAYSCALE) 

name = 'Trackbar'
cv2.namedWindow(name)

cv2.createTrackbar('block_size', name, 25,100, empty) # 'block_size'라는 이름의 트랙바를 생성하고 초기값을 25, 최대값을 100으로 설정
cv2.createTrackbar('c', name, 3,10, empty) # 'c'라는 이름의 트랙바를 생성하고 초기값을 3, 최대값을 10으로 설정

while True: # 무한 루프를 시작
    block_size = cv2.getTrackbarPos('block_size', name) # 'block_size' 트랙바의 현재 위치 값을 가져온다
    c = cv2.getTrackbarPos('c',name) # 'c' 트랙바의 현재 위치 값을 가져온다

    if block_size <= 1: # block_size 값이 1 이하일 경우 3으로 변경, 이는 이진화를 위한 블록 크기가 최소 3이어야 하기 때문
        block_size = 3
    if block_size % 2 == 0: # block_size 값이 짝수일 경우 홀수로 변경, 이는 이진화를 위한 블록 크기가 홀수이어야 함
        block_size += 1

    binary = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, block_size, c) # 적응형 이진화를 적용하여 이진 이미지를 생성
    
    cv2.imshow(name, binary) 
    if cv2.waitKey(1) == ord('q'): 
        break

cv2.destroyAllWindows()

오츠 알고리즘(OTSU Algorithm)

  • Bimodal Image에 사용하기 적합 (최적의 임계치를 자동으로 발견)
    • Bimodal Image(바이모달)이미지란 히스토그램 상에서 두 개의 피크를 치는 형태의 이미지
import cv2

img = cv2.imread('book.jpg',cv2.IMREAD_GRAYSCALE)

ret, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 기본 threshold 함수
ret, otsu = cv2.threshold(img, -1, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
#otsu Algorithm을 사용한 함수
#cv2.threshold(img, 초기값에 무엇을 넣든 오츠에선 무시가 됨, 최댓값, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print('otsu threshold',ret)

cv2.imshow('img',img)
cv2.imshow('binary',binary)
cv2.imshow('otsu',otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • print 결과 : otsu threshold 110.0
profile
C++, Python 활용 중

0개의 댓글