過程:
0)安裝,引入相關庫, 定義取三角形面積的函數
import cv2 as cv
import numpy as np
import math
#通過三頂點直接求三角形面積
def triangle_area(p1, p2, p3):
(x1, y1), (x2, y2), (x3, y3) = p1,p2,p3
return 0.5 * abs(x2 * y3 + x1 * y2 + x3 * y1 - x3 * y2 - x2 * y1 - x1 * y3)
1) 已知輪廓 contours
contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
2)獲取凸包及凸包中心
hull = cv.convexHull(contours)
#繪製凸包中心
hullCenter = np.mean(hull,axis = 0).astype(int)[0]
3)獲取近似多邊形
epsilon = 0.02*cv.arcLength(contours,True)
approx = cv.approxPolyDP(contours,epsilon,True)
cv.polylines(img, [approx], True, (0, 0, 255), 2) #繪製
4)按多邊形的頂點構成的三角形中心的面積加權平均獲取形心
#計算形心(面積中心)
shape_center =(0,0)
areaSum = 0
for pos in range(len(approx) - 2):
#取三角形的三個點
vertex1 = approx[pos][0]
vertex2 = approx[pos+1][0]
vertex3 = approx[pos+2][0]
print("頂點3: " + str(vertex3))
triangle_center = np.mean([vertex1,vertex2,vertex3], axis=0) #計算三角形的中心座標
d1 = np.linalg.norm(vertex1-hullCenter) #獲取三個頂點到凸包中心的距離
d2 = np.linalg.norm(vertex2-hullCenter)
d3 = np.linalg.norm(vertex2-hullCenter)
dc = np.linalg.norm(triangle_center-hullCenter) #計算三角形的中心到凸包中心的距離
farCount = len(list(filter(lambda x:x>dc, [d1,d2,d3]))) #獲取頂點中距離比中心點大的個數
if farCount==1:
continue #三角形只有一個頂點比其形心距離總中心遠, 說明三角形在形狀之外
else:
#print("三角形頂點: " + str(vertex1) + ", " + str(vertex2) + ", " + str(vertex3))
print("三角形中心: " + str(triangle_center) )
tria_area = triangle_area(vertex1,vertex2,vertex3)
print("三角形面積: " + str(tria_area))
areaSum0 = areaSum
areaSum = areaSum + tria_area
shape_center = ( np.multiply(triangle_center, tria_area/areaSum) + np.multiply(shape_center, areaSum0/areaSum) )
shape_center = shape_center.astype(int)
print("形心座標: " + str(shape_center))
cv.circle(img, shape_center, 3, (0,0,255),2)