python numpy opencv 計算輪廓/多邊形的形心

過程:

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) 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章