본문 바로가기
Study/Python

[Python]OpenCV - 2 이진화

by YoungD 2023. 10. 20.
 
 
In [1]:
#from google.colab import drive
#drive.mount('/content/drive')
In [2]:
#%cd /content/drive/MyDrive/Colab Notebooks/opencv

Gray와 Binary 이미지

  • 시각은 색상정보에 대해 잘못된 정보를 보내주는 경우가 많음
    • 밤에 색상을 볼때 정확한 색상을 보여주지 못함 - 명도 (검정색이 섞이는 것)
    • 색상에 빛을 강하게 비추는 경우 정확한 색상을 보여주지 못함 - 채도 (흰색이 섞이는 것)
  • 칼라는 너무 많은 정보를 가지고 있기때문에 연산량이 많음
    • 실시간 처리가 어려움
    • 따라서 gray 이미지나 binary 이미지로 변환해서 처리하는 것이 일반적

  • gray 이미지 : 0-255로 된 픽섹로만 구성된 흑백이미지
  • binary(이진) 이미지 : 0(검정색)과 255(흰색)으로만 구성된 이미지 (마스크 패턴, 필터링)
  • 칼라 → gray 이미지 변환 방법 2가지
    • imread()로 이미지를 읽을 때 변환해서 읽는 방법
      • img = cv2.imread(파일명, cv2.IMREAD_GRAYSCALE)
    • 칼라 이미지로 읽어서 cvtColor() 변환하는 방법 → 칼라 이미지가 필요한 경우 (출력)
      • img_gray = cv2.cvtColor(이미지객체, cv2.COLOR_BGR2GRAY)

  • matplotlib 라이브러리의 colormap
    • 기본값 : viridis

gray 이미지 만들기

imread()를 사용해서 gray 이미지로 변환해서 읽는 방법

In [3]:
import cv2
import matplotlib.pyplot as plt

img_gray = cv2.imread("./images/image.jpg", cv2.IMREAD_GRAYSCALE)

plt.imshow(img_gray, cmap="gray")
plt.xticks([])
plt.yticks([])
plt.show()

칼라이미지로 읽어서 gray 이미지로 변환하는 방법

In [4]:
import cv2
import matplotlib.pyplot as plt

img = cv2.imread("./images/image.jpg")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_gray, cmap="gray")
plt.xticks([])
plt.yticks([])
plt.show()

이진 (Binary) 이미지 만들기

  • 이진 이미지는 픽셀값이 0과 1(255)로만 구성
  • 이진 이미지의 필요 : 배경과 객체의 구분, 관심영역과 비관심 영역의 구분, 마스크 생성 등
  • _, thr = cv2.threshold(img, threshold_value, value, flag)
    • img : Grayscale 이미지
    • threshold_value : 픽셀 문턱값 (0과 1로 나누기 위한 기준값)
    • value : 문턱값보다 클 때 적용되는 값
    • flag : 문턱값 적용 방법
  • flag : 문턱값 적용 방법
    • cv2.THRESH_BINARY : 픽셀값이 문턱값보다 크면 value, 아니면 0을 할당
    • cv2.THRESH_BINARY_INV : 픽셀값이 문턱값보다 크면 0, 아니면 value를 할당
    • cv2.THRESH_TRUNC : 픽셀값이 문턱값보다 크면 문턱값, 아니면 픽셀값을 그대로 할당
    • cv2.THRESH_TOZERO : 픽셀값이 문턱값보다 크면 픽셀값, 아니면 0을 할당
    • cv2.THRESH_TOZERO_INV : 픽셀값이 문턱값보다 크면 0, 아니면 픽셀값을 할당
In [5]:
# 128 보다 작으면 검정색(0), 크면 흰색(255)로 변환
# 반환 : 기준값과 변환된 이미지
_, th_img = cv2.threshold(img_gray, 128,255, cv2.THRESH_BINARY)

plt.imshow(th_img, cmap="gray")
plt.xticks([])
plt.yticks([])
plt.show()
In [6]:
# 실습
  • threshold_value는 영상의 히스토그램에서 픽셀값들을 구분할 수 있는 값을 설정
    • 예를들어 아래와 같이 픽셀값들이 100과 150에 몰려 있으므로 130정도가 적당
실습문제

○ threshold() 함수를 이용하여 다른 이미지를 아래와 같이 변환해보자.
 

임계값 결정하기 1 : OTSU 알고리즘

  • 이진 이미지를 만들때 가장 중요한 요소 : 임계값 설정
  • OTSU의 이진화 알고리즘
    • 임계값을 임의로 정하고 픽셀을 두 분류로 나눔
    • 두 분류의 명암 분포를 구하는 작업을 반복
    • 두 분류의 명암 분포가 가장 균일할 때의 임계값을 선택
  • OTSU의 이진화 알고리즘 적용하기
    • 임계값을 -1로하고 옵션을 THRESH_OTSU로 설정하여 이진화
  • 단점 : 모든 경우의 수를 조사해야 하므로 속도가 느림
In [7]:
# th : otsu로 결정된 threshold_value 값
th, th_img = cv2.threshold(img_gray, -1, 255,
                          cv2.THRESH_BINARY | cv2.THRESH_OTSU)

plt.imshow(th_img, cmap="gray")
plt.title(th)
plt.xticks([])
plt.yticks([])
plt.show()

임계값 결정하기 2 : 적응형 thresholding

  • 전체 이미지를 이용하면 일정하지 않는 조명, 배경색이 여러개인 경우 하나의 임계값으로 선명한 이진 이미지를 만들기 어려움
  • 적응형 thresholding
    • 이미지를 여러 영역으로 나눔
    • 해당 영역의 픽셀 값만 활용하여 임계값을 계산
    • 각 영역별로 이진화를 진행
    • </td></tr>

 

  • cv2.adaptiveThreshold(img, value, method, type_flag, block_size, C)
    • img : 입력영상
    • value : 임계값을 만족하는 픽셀에 적용할 값
    • method : 임계값 결정 방법
    • cv2.ADAPTIVE_THRESH_MEAN_C : 이웃 픽셀의 평균으로 결정
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 가우시안 분포에 따른 가중치의 합으로 결정
    • type_flag : 스레시홀딩 적용 방법 (cv2.threshod()와 동일)
    • block_size : 영역으로 나눌 블록의 크기(n x n), 홀수
    • C : 계산된 임계값 결과에서 가감할 상수(음수 가능)
In [8]:
block_size = 9
c = 5

th_img1 = cv2.adaptiveThreshold(img_gray, 255,
                              cv2.ADAPTIVE_THRESH_MEAN_C,
                              cv2.THRESH_BINARY, block_size, c)

th_img2 = cv2.adaptiveThreshold(img_gray, 255,
                               cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                               cv2.THRESH_BINARY, block_size, c)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.title("mean")
plt.imshow(th_img1, cmap="gray")
plt.xticks([])
plt.yticks([])

plt.subplot(1, 2, 2)
plt.title("gaussian")
plt.imshow(th_img2, cmap="gray")
plt.xticks([])
plt.yticks([])
Out[8]:
([], [])
  • 실행 결과
    • THRESH_OTSU : 분류가 잘 되지 않음
    • ADAPTIVE_THRESH_MEAN_C : 선명하지만 잡음이 많음
    • ADAPTIVE_THRESH_GAUSSIAN_C : 잡음은 적지만 선명도가 떨어짐
 
요약
○ 칼라이미지를 gray 이미지로 변환하는 방법 - imread() 함수로 직접 변환하는 방법 - 칼라이미지로 읽은 후에 cvtColor() 함수로 변환하는 방법 ○ gray 이미지를 binary로 변환하는 방법 - threshold() 함수를 사용하는 방법 - OTSU 이진화 알고리즘을 사용하는 방법 - adaptiveThreshold() 함수를 사용하는 방법

'Study > Python' 카테고리의 다른 글

[Python] OpenCV - 4 Flask  (0) 2023.10.24
[OpenCV] - 3 동영상 로드 및 저장  (1) 2023.10.23
[Python] OpenCV - 1 이미지 로드 및 저장  (1) 2023.10.19
[Python] Train Data 실습  (0) 2023.10.18
[Python] Numpy 배열  (1) 2023.10.17