[Python] opencv - 이미지 경계선, 윤곽선

개발log·2024년 3월 9일
0

Python

목록 보기
16/17
post-thumbnail

이미지 검출

경계선

  • cv2.Canny(img, 150, 200): 대상 이미지, minVal(하위임계값), maxVal(상위임계값)
import cv2
img = cv2.imread('../OpenCV/snowman.png')
# 대상 이미지, minVal(하위임계값), maxVal(상위임계값)
# 픽셀이 하위 임계값보다 작으면 경계선으로 간주하지 않는다.
canny = cv2.Canny(img, 150, 200)

cv2.imshow('img', img)
cv2.imshow('canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

Trackbar를 통한 이미지 경계선 검출

  • threshold1, threshold2 조정에 따라 경계선이 달라짐
import cv2
img = cv2.imread('../OpenCV/snowman.png')

def empty(pos):
    pass
name = "Trackbar"
cv2.namedWindow(name)
cv2.createTrackbar('threshold1', name, 0, 255, empty) #minVal
cv2.createTrackbar('threshold2', name, 0, 255, empty) #maxVal

while True:
    threshold1 = cv2.getTrackbarPos('threshold1', name)
    threshold2 = cv2.getTrackbarPos('threshold2', name)

    canny = cv2.Canny(img, threshold1, threshold2)

    cv2.imshow('img', img)
    cv2.imshow(name, canny)

    if cv2.waitKey(1) == ord('q'):
        break
cv2.destroyAllWindows()

윤곽선

경계선을 연결한 선

  • cv2.findContours(): 윤곽선 검출하는 함수
  • contours, hierarchy = cv2.findContours(otsu, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE): 이미지, 윤곽선 찾는 '모드', 윤곽선 찾을 때 사용하는 근사치 방법(메소드)
  • cv2.drawContours(): 윤곽선을 그리는 함수
  • cv2.drawContours(target, contours, -1, COLOR, 2): 대상 이미지, 윤곽선 정보, 인덱스 값(해당 윤곽선), 색, 두께
import cv2
img = cv2.imread('../OpenCV/card.png')
target = img.copy() # 사본 이미지

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, otsu = cv2.threshold(gray, -1, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
# cv2.findContours() = 윤곽선 검출하는 함수
# 윤곽선 정보, 윤곽선 계층 구조            #이미지, 윤곽선 찾는 모드, 윤곽선 찾을 때 사용하는 근사치 방법
contours, hierarchy = cv2.findContours(otsu, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

# 윤곽선 그리기
COLOR = (0,200,0) # 녹색
# 대상 이미지, 윤곽선 정보, 인덱스 값(해당 윤곽선), 색, 두께
# -1이면 모든 윤곽선
cv2.drawContours(target, contours, -1, COLOR, 2)

cv2.imshow('img', img)
cv2.imshow('gray', gray)
cv2.imshow('otsu', otsu)
cv2.imshow('contour', target)
cv2.waitKey(0)
cv2.destroyAllWindows()

모드 - 윤곽선 찾기

  • cv2.RETR_EXTERNAL: 가장 외곽의 윤곽선만
  • cv2.RETR_LIST: 모든 윤곽선 찾기(계층 정보 없음)
  • cv2.RETR_TREE: 모든 윤곽선 찾기(계층 구조를 트리 구조로 생성)

메소드 - 윤곽선 찾기

  • cv2.CHAIN_APPROX_NONE: 근사값을 계산하지 않고 모든 좌표를 제공
  • cv2.CHAIN_APPROX_SIMPLE: 꼭짓점 좌표만 제공

경계 사각형

  • 윤곽선 경계면을 둘러싸는 사각형
  • boundingRect(): x, y, width, height 값 반환
import cv2
img = cv2.imread('../OpenCV/card.png')
target = img.copy() # 사본 이미지

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, otsu = cv2.threshold(gray, -1, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)

contours, hierarchy = cv2.findContours(otsu, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
print(hierarchy)

COLOR = (0,200,0) # 녹색

for cnt in contours:
    x, y, width, height = cv2.boundingRect(cnt)
    # 사각형 그리기
    cv2.rectangle(target, (x,y), (x+width, y+height), COLOR, 2)

cv2.imshow('img', img)
cv2.imshow('gray', gray)
cv2.imshow('otsu', otsu)
cv2.imshow('contour', target)
cv2.waitKey(0)
cv2.destroyAllWindows()

면적

  • contourArea(): 윤곽선의 면적
import cv2
img = cv2.imread('../OpenCV/card.png')
target = img.copy() # 사본 이미지

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, otsu = cv2.threshold(gray, -1, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)

contours, hierarchy = cv2.findContours(otsu, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
print(hierarchy)

COLOR = (0,200,0) # 녹색

for cnt in contours:
    # 카드 한장 크기: 가로 130*세로 205 = 26,650
    if cv2.contourArea(cnt)>25000:
        x, y, width, height = cv2.boundingRect(cnt)
        cv2.rectangle(target, (x,y), (x+width, y+height), COLOR, 2)

cv2.imshow('img', img)
cv2.imshow('contour', target)
cv2.waitKey(0)
cv2.destroyAllWindows()

추출한 이미지 개별 저장하기

idx=1
for cnt in contours:
    if cv2.contourArea(cnt)>25000:
        x, y, width, height = cv2.boundingRect(cnt)
        cv2.rectangle(target, (x,y), (x+width, y+height), COLOR, 2)
        
        crop = img[y:y+height, x:x+width]
        cv2.imshow(f'cardCrop_{idx}, crop) 
        cv2.imwrite(f'cardCrop_{idx}.png, crop) # 파일 저장
        idx+=1
profile
나의 개발 저장소

0개의 댓글