목차
contour : 이미지에서 동일한 색상 또는 강도를 가진 영역의 경계를 나타내는 곡선.
openCV에서는 contour를 이용하여 물체의 외곽선을 감지하고 분석하는 데 사용함.

steps
1. convert the image into Gray Scale
2. Find the edges in the image using Canny Edge Detector
3. Find and Draw the Contours
4. Find the Corner Points
1. convert the image into Gray Scale
2. Find the edges in the image using Canny Edge Detector
import cv2
image = cv2.imread("../Resources/Images/shapes.png")
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imageCanny = cv2.Canny(imageGray, 50, 50)
# cv2.imshow("Image", image)
# cv2.imshow("Gray Image", imageGray)
cv2.imshow("Canny Image", imageCanny)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. Find and Draw the Contours
cv2.findContours() 함수는 이미지에서 윤곽선을 찾아주는 함수이다. 컨투어는 같은 색이나 강도를 가진 픽섹들의 경계를 연결한 선이다.
hierarchy는 계층구조를 나타낸다. 어떤 컨투어가 다른 컨투어의 내부에 있는지 등의 관계를 알려준다.
hierarchy = [[Next, Previous, First_Child, Parent], ...]
'''
Next 같은 레벨에서 다음 컨투어의 인덱스 (없으면 -1)
Previous 같은 레벨에서 이전 컨투어의 인덱스 (없으면 -1)
First_Child 해당 컨투어의 첫 번째 자식 컨투어 인덱스 (없으면 -1)
Parent 해당 컨투어의 부모 컨투어 인덱스 (없으면 -1)
'''
import cv2
image = cv2.imread("../Resources/Images/shapes.png")
imageCopy = image.copy()
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imageCanny = cv2.Canny(imageGray, 50, 50)
# cv2.imshow("Image", image)
# cv2.imshow("Gray Image", imageGray)
# cv2.imshow("Canny Image", imageCanny)
#Find the Contours
'''
🔹 cv2.RETR_EXTERNAL
가장 바깥쪽 윤곽선만 찾음 (내부 윤곽선 무시)
👉 객체 외곽만 감지할 때 유용
🔹 cv2.RETR_LIST
모든 윤곽선을 찾지만 계층 구조 없음
👉 단순히 모든 윤곽선을 리스트로 받음
🔹 cv2.RETR_TREE
모든 컨투어 + 계층 정보 포함
👉 계층 구조를 분석할 때 사용 (예: 내부 윤곽이 있는 도형)
'''
contours, hirearchy = cv2.findContours(imageCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
#각 컨투어를 구성하는 점들의 배열
print(cnt)
# -1 :모든 컨투어를 그리겠다는 의미
cv2.drawContours(imageCopy, cnt, -1, (255,0,0), 5)
cv2.imshow("Contour Image", imageCopy)
cv2.waitKey(0)
cv2.destroyAllWindows()


면적 계산하기 contourArea
for cnt in contours:
#개별 컨투어의 면적 계산하여 좌표배열 출력
area = cv2.contourArea(cnt)
print(area)
#각 컨투어를 구성하는 점들의 배열
print(cnt)
# -1 :모든 컨투어를 그리겠다는 의미
if area > 10000:
cv2.drawContours(imageCopy, cnt, -1, (255,0,0), 5)

4. Find the Corner Points
근사 다각형으로 변환
for cnt in contours:
#개별 컨투어의 면적 계산하여 좌표배열 출력
area = cv2.contourArea(cnt)
#print(area)
#각 컨투어를 구성하는 점들의 배열
#print(cnt)
# -1 :모든 컨투어를 그리겠다는 의미
if area > 10000:
cv2.drawContours(imageCopy, cnt, -1, (255,0,0), 5)
#calculate the curve length(윤곽선의 길이)
#닫힌 윤곽선인가? = True/False
peri = cv2.arcLength(cnt, True)
#print(peri)
#Corner Points 근사 다각형으로 변환하는 역할
# 원본컨투어, 근사 오차(입실론), 닫힌 도형인가?
'''
epsilon이 작으면 원본과 거의 같은 모양.
epsilon이 크면 꼭짓점 개수가 줄어들어 단순한 형태가 됨.
epsilon = 0.01 * peri → 원래 형태 유지 (점이 많음).
epsilon = 0.05 * peri → 사각형으로 근사.
epsilon = 0.1 * peri → 삼각형으로 단순화될 수도 있음.
'''
#근사 오차 (2% 허용)
approx = cv2.approxPolyDP(cnt, 0.02*peri, True)
print(len(approx))
cv2.drawContours(imageCopy, approx, -1, (0,0,255), 10)

bounding box 그리기
#Creating Bounding Boxes around each shapes
x, y, w, h = cv2.boundingRect(approx)
cv2.rectangle(imageCopy, (x,y), (x+w, y+h), (0,100,0), 2)

이름 넣기
import cv2
image = cv2.imread("../Resources/Images/shapes.png")
imageCopy = image.copy()
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imageCanny = cv2.Canny(imageGray, 50, 50)
# cv2.imshow("Image", image)
# cv2.imshow("Gray Image", imageGray)
# cv2.imshow("Canny Image", imageCanny)
contours, hirearchy = cv2.findContours(imageCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
#개별 컨투어의 면적 계산하여 좌표배열 출력
area = cv2.contourArea(cnt)
#print(area)
#각 컨투어를 구성하는 점들의 배열
#print(cnt)
# -1 :모든 컨투어를 그리겠다는 의미
if area > 1000:
cv2.drawContours(imageCopy, cnt, -1, (255,0,0), 5)
#calculate the curve length(윤곽선의 길이)
#닫힌 윤곽선인가? = True/False
peri = cv2.arcLength(cnt, True)
#print(peri)
#Corner Points 근사 다각형으로 변환하는 역할
# 원본컨투어, 근사 오차(입실론), 닫힌 도형인가?
approx = cv2.approxPolyDP(cnt, 0.02*peri, True)
print(len(approx))
cv2.drawContours(imageCopy, approx, -1, (0,0,255), 10)
#Creating Bounding Boxes around each shapes
x, y, w, h = cv2.boundingRect(approx)
cv2.rectangle(imageCopy, (x,y), (x+w, y+h), (0,100,0), 2)
if len(approx) == 3:
objType = "Triangle"
elif len(approx) >4:
objType = "Circle"
elif len(approx) ==4:
# 가로세로 비율 계산
aspRatio = w/h
if aspRatio >0.98 and aspRatio <1.03:
objType = "Square"
else:
objType = "Rectangle"
else:
objType = "None"
cv2.putText(imageCopy, objType, (x +(w//2), y+(h//2)), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,0,0), 1)
cv2.imshow("Contour Image", imageCopy)
cv2.waitKey(0)
cv2.destroyAllWindows()

openCV 기초 shape detection, contour, approx, 다각형 찾기, bounding 그리기
'머신러닝 > openCV' 카테고리의 다른 글
openCV 기초, mediapipe 설치 에러 해결하기, dll문제 (0) | 2025.03.04 |
---|---|
OpenCV 기초, 스캐너 만들기 (0) | 2025.02.23 |
openCV 기초, join, 사진 합치기 쌓기, 색깔 감지하기, bitwise_and, mask (0) | 2025.02.20 |
OpenCV 기초, Wrap perspective, flatten, 사진 펼치기, 스캔 (0) | 2025.02.19 |
openCV 기초, 가우시안 블러, BGR, blur, edge, dialation, erosion, resize, crop, draw, input text, color (1) | 2025.02.19 |