[opencv] contours와 도형 검출

정예슬·2023년 2월 13일
0

vision

목록 보기
4/21

draw contours

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread('./data/shapes.png')
image_copy = image.copy()

# to gray scale
imgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# to binary with threshold 
ret, imthres = cv2.threshold(imgray, 40, 255, cv2.THRESH_BINARY_INV)

plt.imshow(imthres)
plt.show()

# draw contours

cv2.drawContours(image, contour, -1, (0, 255, 0), 4)
cv2.drawContours(image_copy, contour2, -1, (0, 255, 0), 4)

for i in contour :
    for j in i :
        cv2.circle(image, tuple(j[0]), 1, (255, 0, 0), -1)
        
# result
cv2.imshow('CHAIN_APPROX_NONE', image) # contour의 모든 점(all coordinates)
cv2.imshow('CHAIN_APPROX_SIMPLE', image_copy) # contour의 끝 점만(# only vertexs)
cv2.waitKey(0)
cv2.destroyAllWindows()


HoughCircles

image = cv2.imread('./data/ban_sign.jpg')

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# gaussian blur
blur = cv2.GaussianBlur(gray, (19,19), 0)

plt.imshow(cv2.cvtColor(blur, cv2.COLOR_GRAY2RGB))
plt.show()

circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 
                           1.5, 30, None, 200)

if circles is not None :
    circles = np.uint16(np.around(circles))
    
    for i in circles[0,:] :
        cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
        cv2.circle(image, (i[0], i[1]), 2, (0, 0, 255), 5)
        
# result
cv2.imshow('hough circle', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


convexhull

# convexhull

image = cv2.imread('./data/hands.jpg')[:1100,:]
image = cv2.resize(image, (0, 0), fx=0.5, fy=0.5)
image_copy = image.copy()


gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# blur = cv2.GaussianBlur(gray, (11,11), 0)

blur = cv2.GaussianBlur(gray, (9,9), 0)

ret, thr = cv2.threshold(blur, 170 , 255, cv2.THRESH_BINARY_INV)
plt.imshow(thr)

contours, heiarchy = cv2.findContours(thr, cv2.RETR_EXTERNAL,
                                     cv2.CHAIN_APPROX_NONE)[-2:]

contour = contours[0]

cv2.drawContours(image, contour, -1, (255, 0, 255), 5)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()

# 볼록 선체(convexhull) 찾기
# --> 한 부분도 오목하지 않은 상태
hull = cv2.convexHull(contour, returnPoints=False)
defects = cv2.convexityDefects(contour, hull)

for i in range(defects.shape[0]) :
    startP, endP, farthestP, dist = defects[i, 0]
    farthest = tuple(contour[farthestP][0]) # 가장 먼 지점 좌표
    dist = dist / 256.0 # 부동 소수점 변환
    # 1보다 거리가 큰경우
    if dist > 1 :
        cv2.circle(image_copy,farthest, 5, (0, 0, 255), -1)
cv2.imshow('contour', image)
cv2.imshow('contex hull', image_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()


matchShapes

target = cv2.imread('./data/cross_walk_sign.jpg')
shapes = cv2.imread('./data/shapes.png')

tgray = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
sgray = cv2.cvtColor(shapes, cv2.COLOR_BGR2GRAY)

ret, tar_thr = cv2.threshold(tgray, 120, 255, cv2.THRESH_BINARY_INV)
ret, sha_thr = cv2.threshold(sgray, 120, 255, cv2.THRESH_BINARY_INV)

contours_target, _ = cv2.findContours(tar_thr, cv2.RETR_EXTERNAL, 
                                     cv2.CHAIN_APPROX_SIMPLE)[-2:]
contours_shape, _ = cv2.findContours(sha_thr, cv2.RETR_EXTERNAL, 
                                     cv2.CHAIN_APPROX_SIMPLE)[-2:]

# match
matches = []
for c in contours_shape :
    match = cv2.matchShapes(contours_target[0], c, cv2.CONTOURS_MATCH_I2, 0.0)
    matches.append((match, c))
    cv2.putText(shapes, f"{match:.2f}", tuple(c[0][0]),
               cv2.FONT_HERSHEY_PLAIN, 1, (0,0,255), 1)
               
# 숫자가 0에 가까울수록 좋은 match    
matches.sort(key=lambda x : x[0])


cv2.drawContours(shapes, [matches[0][1]], -1, (0, 255, 0), 3)
cv2.imshow('target', target)
cv2.imshow('shapes', shapes)
cv2.waitKey(0)
cv2.destroyAllWindows()


approxPolyDP

image = cv2.imread('./data/signs.jpeg')
image_copy = image.copy()

imgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(imgray, (3,3), 0)
ret, thr = cv2.threshold(imgray, 110, 255, cv2.THRESH_BINARY_INV)

plt.imshow(cv2.cvtColor(thr, cv2.COLOR_BGR2RGB ))

contours, _ = cv2.findContours(thr,
                              cv2.RETR_EXTERNAL,
                              cv2.CHAIN_APPROX_SIMPLE)[-2:]

for cont in contours : 
    # 근사 컨투어
    approx = cv2.approxPolyDP(cont, 0.005*cv2.arcLength(contour,True), True)
    # 꼭지점 개수에 따라 도형 판별
    vertex = len(approx)
    if vertex >= 3 :
        print(vertex)
        cv2.drawContours(image_copy, [approx], -1, (0, 255, 0), 5)
        
        # find center
        mmt = cv2.moments(cont)
        cx, cy = int(mmt['m10']/mmt['m00']), int(mmt['m01']/mmt['m00'])
        
        if vertex == 3 :
            cv2.putText(image_copy, 'Triangle', (cx, cy+200), cv2.FONT_HERSHEY_COMPLEX_SMALL,
                       2, (0, 255, 0 ), 2)
            
        if vertex > 6 :
            cv2.putText(image_copy, 'Circle', (cx, cy+200), cv2.FONT_HERSHEY_COMPLEX_SMALL,
                       2, (0, 255, 0), 2)            
    
plt.imshow( cv2.cvtColor(image_copy, cv2.COLOR_BGR2RGB ))

profile
춘식이랑 함께하는 개발일지

0개의 댓글