[ Python ] Shape Detection
반응형
이미지에서 원하는 영역을 찾기 위해 DeepLearning 기반의 모델을 사용하지만, 매우 간단하게 이미지 연산 방법을 통해 영역을 찾을 수도 있습니다. 그 첫번째로 윤곽선의 속성을 이용하여 모양을 검출하는 방법에 대해 알아 보겠습니다.
- 이미지를 그레이스케일로 변환
- 노이즈를 줄이기 위한 이미지 블러링
- 이미지의 이진화
- 윤곽선 검출
- 추출된 윤곽선을 기준으로 근사 다각형 검출
- Shape 종류 판단
Import packages
import cv2
import imutils
import matplotlib.pyplot as plt
Function declaration
Jupyter Notebook 및 Google Colab에서 이미지를 표시할 수 있도록 Function으로 정의
def img_show(title='image', img=None, figsize=(8 ,5)):
plt.figure(figsize=figsize)
if type(img) == list:
if type(title) == list:
titles = title
else:
titles = []
for i in range(len(img)):
titles.append(title)
for i in range(len(img)):
if len(img[i].shape) <= 2:
rgbImg = cv2.cvtColor(img[i], cv2.COLOR_GRAY2RGB)
else:
rgbImg = cv2.cvtColor(img[i], cv2.COLOR_BGR2RGB)
plt.subplot(1, len(img), i + 1), plt.imshow(rgbImg)
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
else:
if len(img.shape) < 3:
rgbImg = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
else:
rgbImg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(rgbImg)
plt.title(title)
plt.xticks([]), plt.yticks([])
plt.show()
Shape 을 판단하는 Function (이 부분을 수정하여 특정 Shape만 추출을 하는 기능을 구현할 수도 있습니다.)
def shape_label(c):
shape = "unidentified"
# cv2.arcLength를 이용해 윤곽선의 전체 길이를 계산
peri = cv2.arcLength(c, True)
# cv2.approxPolyDP를 활용해 윤곽선의 근사 다각형 검출
approx_poly = cv2.approxPolyDP(c, 0.04 * peri, True)
# 꼭지점이 3개이면 삼각형
if len(approx_poly) == 3:
shape = "triangle"
# 꼭지점이 4개이면 사각형
elif len(approx_poly) == 4:
# 종횡비를 구해서 정사각형 판단
(x, y, w, h) = cv2.boundingRect(approx_poly)
ar = w / float(h)
if ar >= 0.95 and ar <= 1.05:
shape = "square"
else:
shape = "rectangle"
# 꼭지점이 5개이면 오각형
elif len(approx_poly) == 5:
shape = "pentagon"
# 꼭지점이 6개이면 육각형
elif len(approx_poly) == 6:
shape = "hexagon"
# 나머지는 원으로 판단
else:
shape = "circle"
return shape
Load Image
cv2_image = cv2.imread('asset/images/shape.jpg', cv2.IMREAD_COLOR)
img_show('original image', cv2_image)
Shape Detection
아래 과정을 통해 이미지를 그레이스케일로 변환하고 노이즈를 줄이기 위한 이미지 블러링 후 이진화 합니다.
resized = imutils.resize(cv2_image, width=640)
ratio = cv2_image.shape[0] / float(resized.shape[0])
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(blurred, 10, 255, cv2.THRESH_BINARY)[1]
img_show(['GaussianBlur', 'Threshold'], [blurred, thresh])
이진화 이미지에서 윤곽선을 검출합니다.
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
추출된 윤곽선을 기준으로 Shape을 판단하여 이미지에 표시합니다.
더보기
cv2.moments는 객체의 무게 중심이나 면적 등을 계산할 때 유용합니다. 모멘트 종류는 3가지이며 아래와 같이 총 24개의 값을 가집니다.
- 공간 모멘트(Spatial Moments) : m00, m10, m01, m20, m11, m02, m30, m21, m12, m03
- 중심 모멘트(Central Moments) : mu20, mu11, mu02, mu30, mu21, mu12, mu03
- 평준화된 중심 모멘트(Central Normalized Moments) : nu20, nu11, nu02, nu30, nu21, nu03
{'m00': 21314.0,
'm10': 10380260.0,
'm01': 2770943.0,
'm20': 5107832193.666666,
'm11': 1349493701.0,
'm02': 387515034.0,
'm30': 2538712455460.0,
'm21': 664048224844.1666,
'm12': 188726812226.33334,
'm03': 57471376407.5,
'mu20': 52479014.17900467,
'mu11': -1.973632574081421,
'mu02': 27276453.290184796,
'mu30': -26011.04541015625,
'mu21': 565031.7590560913,
'mu12': 773196.0624542236,
'mu03': -6977.8613204956055,
'nu20': 0.11551961832262529,
'nu11': -4.34446578758714e-09,
'nu02': 0.06004239070743966,
'nu30': -3.921889956072085e-07,
'nu21': 8.5194283649921e-06,
'nu12': 1.1658085338737212e-05,
'nu03': -1.0521070489935076e-07}
vis = cv2_image.copy()
for c in cnts:
# cv2.moments를 이용하여 객체의 중심을 계산
M = cv2.moments(c)
cX = int((M["m10"] / M["m00"]) * ratio)
cY = int((M["m01"] / M["m00"]) * ratio)
shape = shape_label(c)
# 이미지에서 객체의 윤곽선과 Shape명을 표시
c = c.astype("float")
c *= ratio
c = c.astype("int")
cv2.drawContours(vis, [c], -1, (0, 255, 0), 10)
cv2.circle(vis, (cX, cY), 20, (0, 255, 0), -1);
cv2.putText(vis, shape, (cX-80, cY-50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 5)
Shape를 표현한 이미지를 확인합니다.
img_show('Shape Detection', vis, figsize=(16,10))
하지만 이러한 이미지 연산 방식은 수동으로 입력하는 매개변수 값에 따라 결과가 달라질 수 있다는 단점이 있다는 점을 참고하시길 바랍니다.
더보기
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
반응형
'Tech & Development > AI' 카테고리의 다른 글
[ Python ] Bright Spot Detection (0) | 2022.11.24 |
---|---|
[ Python ] Color Detection (0) | 2022.11.24 |
Train Swin-Object Detection using Custom Data(without mask) (1) | 2022.08.02 |
CartoonGAN을 이용하여 일본 애니메이션 그림 만들기 (0) | 2022.03.15 |
Object Detection Architecture - 1 or 2 stage detector (0) | 2022.02.16 |
댓글
이 글 공유하기
다른 글
-
[ Python ] Bright Spot Detection
[ Python ] Bright Spot Detection
2022.11.24 -
[ Python ] Color Detection
[ Python ] Color Detection
2022.11.24 -
Train Swin-Object Detection using Custom Data(without mask)
Train Swin-Object Detection using Custom Data(without mask)
2022.08.02 -
CartoonGAN을 이용하여 일본 애니메이션 그림 만들기
CartoonGAN을 이용하여 일본 애니메이션 그림 만들기
2022.03.15