[ 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
댓글을 사용할 수 없습니다.