귀퉁이 서재

OpenCV - 4. 도형 그리기 본문

OpenCV

OpenCV - 4. 도형 그리기

Baek Kyun Shin 2020. 9. 12. 00:00

이번 포스팅에서는 이미지에 도형을 그리는 방법에 대해 알아보겠습니다. 이번 포스팅 역시 '파이썬으로 만드는 OpenCV 프로젝트(이세우 저)'를 정리한 것임을 밝힙니다.

코드: https://github.com/BaekKyunShin/OpenCV_Project_Python/tree/master/02.interface

직선 그리기

우선, 아래와 같이 빈 도화지 같은 하얀 이미지를 준비합니다. (blank_500.jpg) 이곳에 다양한 직선을 그려보겠습니다.

blank_500.jpg

cv2.line(img, start, end, color, thickness, lineType) 함수를 호출하여 다양한 선을 그릴 수 있습니다. 파라미터는 아래와 같습니다.

img: 그림을 그릴 이미지 파일
start: 선 시작 좌표(ex; (0,0))
end: 선 종료 좌표(ex; (500. 500))
color: BGR형태의 선 색상 (ex; (255, 0, 0) -> Blue)
thickness (int): 선의 두께. pixel (default=1)
lineType: 선 그리기 형식 (cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA)

주의할 점은 color가 RGB 형태가 아니라 BGR 형태입니다. 순서가 반대임을 유의해야 합니다. 아래의 코드를 실행하면 빈 이미지인 blank_500.jpg에 다양한 직선을 그립니다.

# 다양한 직선 그리기(draw_line.py)

import cv2

img = cv2.imread('../img/blank_500.jpg')

cv2.line(img, (50, 50), (150, 50), (255,0,0))   # 파란색 1픽셀 선
cv2.line(img, (200, 50), (300, 50), (0,255,0))  # 초록색 1픽셀 선
cv2.line(img, (350, 50), (450, 50), (0,0,255))  # 빨간색 1픽셀 선

# 하늘색(파랑+초록) 10픽셀 선      
cv2.line(img, (100, 100), (400, 100), (255,255,0), 10)          
# 분홍(파랑+빨강) 10픽셀 선      
cv2.line(img, (100, 150), (400, 150), (255,0,255), 10)          
# 노랑(초록+빨강) 10픽셀 선      
cv2.line(img, (100, 200), (400, 200), (0,255,255), 10)          
# 회색(파랑+초록+빨강) 10픽셀 선  
cv2.line(img, (100, 250), (400, 250), (200,200,200), 10)        
# 검정 10픽셀 선    
cv2.line(img, (100, 300), (400, 300), (0,0,0), 10)                    

# 4연결 선
cv2.line(img, (100, 350), (400, 400), (0,0,255), 20, cv2.LINE_4)   
# 8연결 선
cv2.line(img, (100, 400), (400, 450), (0,0,255), 20, cv2.LINE_8)    
# 안티에일리어싱 선 
cv2.line(img, (100, 450), (400, 500), (0,0,255), 20, cv2.LINE_AA)   
# 이미지 전체에 대각선 
cv2.line(img, (0,0), (500,500), (0,0,255))                      

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

cv2.LINE_4와 cv2.LINE_8 파라미터를 전달하면 픽셀이 깨져 보입니다. (맨 아래에서 두 번째, 세 번째 빨간 줄) cv2.LINE_AA는 픽셀이 깨져서 발생하는 계단 현상을 최소화하는 연결 선을 그려줍니다. (맨 아래 빨간 줄)

사각형 그리기

사각형은 cv2.rectangle(img, start, end, color, thickness, lineType) 함수를 호출하여 그릴 수 있습니다. 파라미터는 아래와 같습니다.

img: 그림을 그릴 이미지 파일 
start: 사각형 시작 꼭짓점 좌표(ex; (0,0)) 
end: 사각형 종료 꼭짓점 좌표(ex; (500. 500)) 
color: BGR형태의 선 색상 (ex; (255, 0, 0) -> Blue) 
thickness (int): 선의 두께. pixel (default=1,  사각형 전체를 색상으로 채우기=-1)
lineType: 선 그리기 형식 (cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA)

# 사각형 그리기(draw_rect.py)

import cv2

img = cv2.imread('../img/blank_500.jpg')

# 좌상, 우하 좌표로 사각형 그리기, 선 두께는 default 1
cv2.rectangle(img, (50, 50), (150, 150), (255,0,0) )        
# 우하, 좌상 좌표로 사각형 그리기, 선 두께 10
cv2.rectangle(img, (300, 300), (100, 100), (0,255,0), 10 )  
# 우상, 좌하 좌표로 사각형 채워 그리기 ---①
cv2.rectangle(img, (450, 200), (200, 450), (0,0,255), -1 )  

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

다각형 그리기

다각형은 cv2.polylines(img, pts, isClosed, color, thickness, lineType) 함수를 호출하여 그릴 수 있습니다.

img: 그림을 그릴 이미지 파일 
pts: 연결할 꼭짓점 좌표, Numpy array
isClosed: 닫힌 도형 여부, True/False
color: BGR형태의 선 색상 (ex; (255, 0, 0) -> Blue) 
thickness (int): 선의 두께. pixel (default=1)
lineType: 선 그리기 형식 (cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA)

isClosed 매개변수는 닫힌 도형을 그릴지, 열린 도형을 그릴지 여부를 결정합니다. True일 경우 닫힌 도형을 그리기 때문에 첫 꼭짓점과 마지막 꼭짓점을 서로 연결합니다. 반면 False일 경우 열린 도형을 그리기 때문에 첫 꼭짓점과 마지막 꼭짓점을 서로 연결하지 않습니다.

# 다각형 그리기(draw_poly)

import cv2
import numpy as np                          # 좌표 표현을 위한 numpy 모듈  ---①

img = cv2.imread('../img/blank_500.jpg')

# Numpy array로 좌표 생성 ---②
# 번개 모양 선 좌표
pts1 = np.array([[50,50], [150,150], [100,140],[200,240]], dtype=np.int32) 
# 삼각형 좌표
pts2 = np.array([[350,50], [250,200], [450,200]], dtype=np.int32) 
# 삼각형 좌표
pts3 = np.array([[150,300], [50,450], [250,450]], dtype=np.int32) 
# 5각형 좌표
pts4 = np.array([[350,250], [450,350], [400,450], [300,450], [250,350]],\
                 dtype=np.int32) 

# 다각형 그리기 ---③
cv2.polylines(img, [pts1], False, (255,0,0))       # 번개 모양 선 그리기
cv2.polylines(img, [pts2], False, (0,0,0), 10)     # 3각형 열린 선 그리기 ---④
cv2.polylines(img, [pts3], True, (0,0,255), 10)    # 3각형 닫힌 도형 그리기 ---⑤
cv2.polylines(img, [pts4], True, (0,0,0))          # 5각형 닫힌 도형 그리기

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

원, 타원, 호 그리기

cv2.circle(img, center, radius, color, thickness, lineType) 함수는 원을 그려주고, 
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType) 함수는 타원을 그려줍니다.

cv2.circle() 함수의 매개변수는 직관적입니다. center는 원의 중심 좌표(x, y)이며, radius는 원의 반지름입니다. color는 색상, thickness는 두께, lineType은 선 타입입니다. cv2.ellipse() 함수의 매개변수가 좀 헷갈릴 수 있습니다. 우선, img, color, thickness, lineType은 cv2.line()과 동일합니다. 그 이외의 매개변수는 아래와 같습니다.

center: 타원의 중심 좌표 (x, y)
axes: 타원의 중심에서 가장 긴 축의 길이와 가장 짧은 축의 길이
angle: 타원의 기준 축 회전 각도
startAngle: 타원의 호가 시작하는 각도
endAngle: 타원의 호가 끝나는 각도

# 원, 타원, 호 그리기(draw_circle.py)

import cv2

img = cv2.imread('../img/blank_500.jpg')

# 원점(150,150), 반지름 100 ---①
cv2.circle(img, (150, 150), 100, (255,0,0))     
# 원점(300,150), 반지름 70 ---②
cv2.circle(img, (300, 150), 70, (0,255,0), 5)   
# 원점(400,150), 반지름 50, 채우기 ---③
cv2.circle(img, (400, 150), 50, (0,0,255), -1)  

# 원점(50,300), 반지름(50), 회전 0, 0도 부터 360도 그리기 ---④
cv2.ellipse(img, (50, 300), (50, 50), 0, 0, 360, (0,0,255))    
# 원점(150, 300), 아래 반원 그리기 ---⑤
cv2.ellipse(img, (150, 300), (50, 50), 0, 0, 180, (255,0,0))    
#원점(200, 300), 윗 반원 그리기 ---⑥
cv2.ellipse(img, (200, 300), (50, 50), 0, 181, 360, (0,0,255))    

# 원점(325, 300), 반지름(75,50) 납작한 타원 그리기 ---⑦
cv2.ellipse(img, (325, 300), (75, 50), 0, 0, 360, (0,255,0))    
# 원점(450,300), 반지름(50,75) 홀쭉한 타원 그리기 ---⑧
cv2.ellipse(img, (450, 300), (50, 75), 0, 0, 360, (255,0,255))    

# 원점(50, 425), 반지름(50,75), 회전 15도 ---⑨
cv2.ellipse(img, (50, 425), (50, 75), 15, 0, 360, (0,0,0))    
# 원점(200,425), 반지름(50,75), 회전 45도 ---⑩
cv2.ellipse(img, (200, 425), (50, 75), 45, 0, 360, (0,0,0))    

# 원점(350,425), 홀쭉한 타원 45도 회전 후 아랫 반원 그리기 ---⑪
cv2.ellipse(img, (350, 425), (50, 75), 45, 0, 180, (0,0,255))    
# 원점(400,425), 홀쭉한 타원 45도 회전 후 윗 반원 그리기 ---⑫
cv2.ellipse(img, (400, 425), (50, 75), 45, 181, 360, (255,0,0))    

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

글 쓰기

cv2.putText(img, text, org, font, fontScale, color, thickness, lineType) 함수는 이미지에 문자열을 표시합니다. 

매개변수 중 text는 표시할 문자열이며, org는 문자열을 표시할 위치(좌측 하단 기준) (x, y)이며, font는 글꼴(cv2.FONT_XXXX 형식)이며, fontScale은 글꼴 크기입니다.

아래 코드는 다양한 글꼴, 크기, 위치를 갖는 글씨를 그려줍니다. 맨 아래 부분의 코드는 글꼴과 이탤릭체를 동시에 적용하는 방법을 보여줍니다.

# 글 쓰기 (draw_text.py)

import cv2

img = cv2.imread('../img/blank_500.jpg')

# sans-serif small
cv2.putText(img, "Plain", (50, 30), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0,0))            
# sans-serif normal
cv2.putText(img, "Simplex", (50, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0,0))        
# sans-serif bold
cv2.putText(img, "Duplex", (50, 110), cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0,0))         
# sans-serif normall X2  ---①
cv2.putText(img, "Simplex", (200, 110), cv2.FONT_HERSHEY_SIMPLEX, 2, (0,0,250)) 

# serif small
cv2.putText(img, "Complex Small", (50, 180), cv2.FONT_HERSHEY_COMPLEX_SMALL, \
            1, (0, 0,0))   
# serif normal
cv2.putText(img, "Complex", (50, 220), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0,0))
# serif bold
cv2.putText(img, "Triplex", (50, 260), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0,0))               
# serif normal X2  ---②
cv2.putText(img, "Complex", (200, 260), cv2.FONT_HERSHEY_TRIPLEX, 2, (0,0,255))               

# hand-wringing sans-serif
cv2.putText(img, "Script Simplex", (50, 330), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, \
            1, (0, 0,0)) 
# hand-wringing serif
cv2.putText(img, "Script Complex", (50, 370), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, \
            1, (0, 0,0)) 

# sans-serif + italic ---③
cv2.putText(img, "Plain Italic", (50, 430), \
            cv2.FONT_HERSHEY_PLAIN | cv2.FONT_ITALIC, 1, (0, 0,0)) 
# sarif + italic
cv2.putText(img, "Complex Italic", (50, 470), \
            cv2.FONT_HERSHEY_COMPLEX | cv2.FONT_ITALIC, 1, (0, 0,0)) 

cv2.imshow('draw text', img)
cv2.waitKey()
cv2.destroyAllWindows()

 

Comments