본문 바로가기
CV(Computer Vision)

관심 영역/ 이진화

by 코낄2 2024. 2. 18.

1. 관심 영역(ROI, Region of Interest)

ROI(Region of Interest)는 영상 내에서 주요 관심이 있는 영역을 가리킵니다. cv2.selectROI() 함수를 사용하여 사용자가 마우스로 관심 있는 영역을 선택할 수 있습니다.

 cv2.selectROI(창이름, 영상, 중앙좌표여부=False)
  • 중앙좌표여부: True일 경우, 선택한 ROI의 중앙좌표로 계산되며, 기본값은 False(왼쪽 상단)입니다.
import cv2

img1 = cv2.imread('./sun.jpg')

# x, y, w, h
x = 182
y = 21
w = 121
h = 112

# 관심 영역만 지정해서 img2에 저장
roi = img1[y: y+h, x: x+w]
img2 = roi.copy()

# img1의 특정 위치에 따로 저장해둔 roi 붙이기
img1[y: y+h, x+w: x+w+w] =roi

# img1 특정 영역에 직사각형 그리기
# cv2.rectangle(img1, (x,y, w+w, h),(255, 255, 0), 2)
cv2.rectangle(img1, (x,y), (x+w+w, y+h),(255, 255, 0), 2)

cv2.imshow('img', img1)
cv2.imshow('roi', img2)

cv2.waitKey()

ROI / ROI를 붙여넣고, 직사각형을 그린 img1


문제.

sun.jpg 영상에서 원하는 ROI부분을 마우스로 선택하고 선택된 ROI를 창으로 출력

import cv2
img1 = cv2.imread('./sun.jpg')

cv2.imshow('img',img1)

oldx = oldy = 0

def on_mouse(event, x, y, flags, param):
    global oldx, oldy
    if event == cv2.EVENT_LBUTTONDOWN:
        oldx, oldy = x, y
        print('좌측상단 좌표: %d, %d' % (x,y))
    elif event == cv2.EVENT_MOUSEMOVE:
        if flags & cv2.EVENT_FLAG_LBUTTON:  # 마우스가 눌리고 있는 상태 & 왼쪽 버튼이 눌러져있는 상태
            img2 = img1.copy()
            cv2.rectangle(img2, (oldx, oldy), (x, y), (0, 255, 0), 3)
            cv2.imshow('img',img2)
    elif event == cv2.EVENT_LBUTTONUP:
        print('우측하단 좌표: %d, %d' % (x, y))
        roi = img1[oldy: y, oldx: x]
        cv2.imshow('img', img1)
        cv2.imshow('roi', roi)


cv2.setMouseCallback('img', on_mouse)

cv2.waitKey()
✔️ 디테일 더하기!

import cv2

isDrag = False
oldx = oldy = w = h = 0
color = (255, 0, 0)
img_copy = None

def on_mouse(event, x, y, flags, param):
    global oldx, oldy, w, h, isDrag, img_copy
    if event == cv2.EVENT_LBUTTONDOWN:
        isDrag = True
        oldx = x
        oldy = y
    elif event == cv2.EVENT_MOUSEMOVE:
        if isDrag:
            img_copy = img.copy()
            cv2.rectangle(img_copy, (oldx, oldy), (x,y), color, 3)
            cv2.imshow('img', img_copy)
    elif event == cv2.EVENT_LBUTTONUP:
        if isDrag:
            isDrag = False
            w = x - oldx
            h = y - oldy
            if w > 0 and h > 0:
                cv2.rectangle(img_copy, (oldx,oldy), (x,y), color, 3)
                cv2.imshow('img', img_copy)
                roi = img[oldy: oldy+h, oldx: oldx+w]
                cv2.imshow('roi',roi)
            else:
                cv2.imshow('img', img)
        else:
            cv2.imshow('img', img)
            print('영역이 잘못 되었음.')

img = cv2.imread('./sun.jpg')
cv2.imshow('img', img)
cv2.setMouseCallback('img', on_mouse)
cv2.waitKey()

2. 영상의 이진화(Binarization)

영상의 이진화는 픽셀을 검은색 또는 흰색과 같이 두 개의 값으로 나누는 작업입니다. 주로 배경과 객체를 구분하거나 관심 영역과 비관심 영역을 구분할 때 사용됩니다. 이진화 연산을 위해 임계값을 사용합니다. (영상의 이진화 연산을 할 떄 나누는 특정값을 임계값이라고 함)

  • 함수 및 플래그:
    • cv2.THRESH_BINARY: 픽셀값이 임계값을 넘으면 최대값으로 지정하고 넘지 못하면 0으로 지정
    • cv2.THRESH_BINARY_INV : cv2.THRESH_BINARY의 반대(임계값 넘으면 0, 넘지 못하면 최대값)
    • cv2.THRESH_TRUNC: 픽셀값이 임계값을 넘으면 최대값으로 지정하고, 넘지 못하면 원래값을 유지
    • cv2.THRESH_TOZERO: 픽셀값이 임계값을 넘으면 원래 값을 유지하고, 넘지 못하면 0으로 지정
    • cv2.THRESH_TOZERO_INV : cv2.THRESH_TOZERO의 반대(임계값을 넘으면 0, 넘지 못하면 원래값)
import cv2
import matplotlib.pyplot as plt

src = cv2.imread('./cells.png', cv2.IMREAD_GRAYSCALE)
hist = cv2.calcHist([src], [0], None, [256], [0, 255])

a, dst1 = cv2.threshold(src, 100, 255, cv2.THRESH_BINARY)
b, dst2 = cv2.threshold(src, 210, 255, cv2.THRESH_BINARY)

cv2.imshow('src',src)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)


plt.plot(hist)
plt.show()
cv2.waitKey()

3. 오츠의 이진화 알고리즘

오츠의 이진화 알고리즘은 영상 처리에서 자동으로 임계값을 결정하여 이진화를 수행하는 알고리즘 중 하나입니다. 이 알고리즘은 영상의 히스토그램을 분석하여 두 부류의 분산(분포의 균일성)이 가장 크게 되도록 하는 임계값을 선택합니다. 

cv2.threshold(영상, 임계값, 최대값, 플래그 | cv2.THRESH_OTSU)
# 임계값은 0으로 넣어주면 됨.
  •  
import cv2

src = cv2.imread('./rice.png', cv2.IMREAD_GRAYSCALE)

th, dst = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print('otsu: ', th)

cv2.imshow('src', src)
cv2.waitKey()cv2.imshow('dst', dst)

4. 지역 이진화

지역 이진화는 균일하지 않은 조명 환경에서 사용하는 이진화 방법입니다. 전체 구역을 여러 부분으로 나누고 각 부분에 대해 이진화를 적용하여 결과를 결합합니다. 각 영역에 적합한 여러 임계값을 사용할 수 있습니다.

import cv2
import numpy as np

src = cv2.imread('./rice.png', cv2.IMREAD_GRAYSCALE)

# 전역 이진화
_, dst1 = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

# 지역 이진화
dst2 = np.zeros(src.shape, np.uint8)
bw = src.shape[1] // 4
bh = src.shape[0] // 4

for y in range(4):
    for x in range(4):
        src_ = src[y*bh: (y+1)*bh, x*bw:(x+1)*bw]
        dst_ = dst2[y*bh: (y+1)*bh, x*bw:(x+1)*bw]
        cv2.threshold(src_, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU, dst_)
cv2.imshow('src',src)
cv2.imshow('dst1',dst1)
cv2.imshow('dst2',dst2)
cv2.waitKey()

'CV(Computer Vision)' 카테고리의 다른 글

필터링/컨투어링  (0) 2024.02.26
영상의 변환/ 적응형 이진화/ 유사도  (0) 2024.02.25
이미지 처리 기법  (0) 2024.02.16
영상처리 기초 : 화소처리  (0) 2024.02.10
동영상 처리  (0) 2024.02.09