[OpenCV] 04-9. Contours (3)
🐍Python/OpenCV

[OpenCV] 04-9. Contours (3)

728x90
반응형

< Contour Properties >

여기서는 고체성(Solidity), 등가 지름(Equivalent Diameter), 마스크 이미지, 평균 강도등과 같이 자주 사용되는 물체의 특성을 추출하는 방법을 배울 것이다. 자세한 내용은 Matlab regionprops문서에서 확인할 수 있다. Matlab regionprops documentation.

1. Aspect Ratio

이 비율은 객체의 bounding rect의 높이에 대한 폭의 비율이다.

AspectRatio=WidthHeight

x,y,w,h = cv2.boundRect(cnt)
aspect_ratio = float(w)/h

2. Extent

Extent는 bounding rec 영역에 대한 contour 영역의 비율이다.

Extent=ObjectAreaBounding Rectangle Area

area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w*h
extent = float(area) / rect_area

3. Solidity

Solidity는 convex hull 영역에 대한 contour 영역의 비율이다.

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area

4. Equivalent Diameter

Equivalent Diameter는 contour영역과 같은 원의 지름이다.

Equivalent Diameter=4×Contour Areaπ

area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)

5. Orientation

Orientation은 객체가 향하는 각도이다. 다음의 방법은 또한 주축의 길이와 보조축의 길이를 알려준다.

(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)

6. Mask and Pixel Points

어떤 경우에선, 우리는 그 객체를 구성하는 모든 점이 필요할 것 이다. 다음처럼 할 수 있다.

mask = np.zeros(imgray,shape,np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonzero(mask)

여기서는 Numpy를 사용하는 방법, OpenCV를 사용하는 방법 등 두 가지가 있다. 결과는 같지만 약간의 차이가 있다. Numpy는 (행,열) 형식으로 좌표를 제공하고 OpenCV는 (x,y) 형식으로 좌표를 제공한다.

7. Maximum Value, Minimum Value and their locations

마스크 이미지를 사용하여 이 파라미터들을 찾을 수 있다.

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray,mask = mask)

8. Mean Color or Mean Intensity

객체의 평균 색을 차즐 수 있다. 또는 흑백 모드에서의 객체의 평균 강도가 될 수 있다. 마스크를 써서 사용할 수 있다.

mean_val = cv2.mean(img,mask=mask)

9. Extreme Points

Extreme Points는 객체의 topmost, bottommost, rightmost, leftmost 점을 말한다.

leftmost = tuple(cnt[cnt[:,:,0], argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

예를 들어 다음의 결과와 같다.


위의 사진에서 “ㅅ” 글자에서의 극단점들을 찾은 것이다. 코드는 다음과 같다.

import cv2
import numpy as np

img = cv2.imread('./images/charm.jpg')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgray = cv2.GaussianBlur(imgray,(5,5),0)

ret, thr = cv2.threshold(imgray,45,255,cv2.THRESH_BINARY)
thr = cv2.erode(thr, None, iterations=2)
thr = cv2.dilate(thr, None, iterations=2)

contours,_ = cv2.findContours(thr,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# cnt = max(contours,key=cv2.contourArea)
cnt = contours[4]

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

cv2.drawContours(imgray,[cnt],-1,(0,255,255),2)
cv2.circle(img,leftmost,8,(0,0,255),-1)     # 빨간색
cv2.circle(img,rightmost,8,(0,255,0),-1)    # 초록색
cv2.circle(img,topmost,8,(255,0,0),-1)      # 파란색
cv2.circle(img,bottommost,8,(255,255,0),-1)   # 하늘색

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


728x90
반응형