Scipy 和opencv 计算凸包(convexHull)

凸包:在数学中,在实向量空间V中的一组点X的凸包或凸包络是包含X的最小凸集。来自Wikipedia。通俗的来说就是包围一组散点的最小凸边形。

scipy.spatial opencv 分别有计算凸包的函数,scipyconvexHull输入的参数可以是m*2的点坐标。其返回值的属性.verticess是所有凸轮廓点在散点(m*2)中的索引值。

注意:属性.verticess绘制出来的轮廓点是按照逆时针排序

opencv 中,cv2.convexHull可以得到凸包的坐标值/凸包在轮廓的索引值(取决于参数returnPoints=True/Fasle)。同时opencvconvexityDefects函数可计算凸缺陷,即使图像中所有的凹点。其函数返回值是m*4的数组,第一列是起点,第二列是终点,第三列是最远点,第四列是最远点到凸轮廓的距离。

图像的质心----利用图像矩,opencv--- cv2.moments(轮廓)

其中 cx = int(M['m10']/M['m00'])y = int(M['m01']/M['m00'])

Scipy 计算得到的凸包见下图:

Opencv计算凸包:

本次测试图为:

注意:本测试图阈值化的时候注意反转图像,牢记找轮廓是针对的“白像素”

反转和不反转后的图

寻找轮廓函数详解:

cv2.findContours(thresh,0,2)

参数:第一个输入的是binary_image

第二个参数:RetrievalModes

 cv::RETR_EXTERNAL = 0, 外部轮廓用的比较多
  cv::RETR_LIST= 1,
  
cv::RETR_CCOMP= 2,
  
cv::RETR_TREE= 3,
  
cv::RETR_FLOODFILL= 4

第三个参数:ContourApproximationModes

  cv::CHAIN_APPROX_NONE = 1, 轮廓所有点
  cv::CHAIN_APPROX_SIMPLE = 2,
只返回四角的点
  cv::CHAIN_APPROX_TC89_L1= 3,
  
cv::CHAIN_APPROX_TC89_KCOS= 4

轮廓寻找完成后,找出轮廓面积最大的轮廓作为计算凸包的当前轮廓。注意:cnt_max的大小是m*1*2

最终结果图:----凸缺陷检测出来的点(红色点),有一处错误.

程序如下:

# -*- coding: utf-8 -*-
import cv2
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull
##########scipy 凸包################
points = np.random.rand(30, 2)
hull = ConvexHull(points)
plt.plot(points[:,0], points[:,1], 'o')
# hull.vertices 得到凸轮廓坐标的索引值,逆时针画
hull1=hull.vertices.tolist()#要闭合必须再回到起点[0]
hull1.append(hull1[0])
plt.plot(points[hull1,0], points[hull1,1], 'r--^',lw=2)
for i in range(len(hull1)-1):
    plt.text(points[hull1[i],0], points[hull1[i],1],str(i),fontsize=20)
########cv2#########
im=cv2.imread(r"C:\Users\Y\Desktop\star.jpg")
im_gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
_,thresh=cv2.threshold(im_gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
_,cnts,h=cv2.findContours(thresh,0,1)
area=[]
for c in cnts:
    area.append(cv2.contourArea(c))
cnt_max=cnts[np.argsort(-np.array(area))[0]]
hull_cv=cv2.convexHull(cnt_max)
cv2.drawContours(im,[hull_cv],0,(0,0,255),2)
#####寻找凸缺陷********
hull_index=cv2.convexHull(cnt_max,returnPoints = False)
defects = cv2.convexityDefects(cnt_max,hull_index)
for i in range(defects.shape[0]):
    s,e,f,d=defects[i,0]
    far = tuple(cnt_max[f][0])
    cv2.circle(im,far,5,(0,0,255),-1)
##########确定重心###########
#计算图像矩
M=cv2.moments(cnt_max)
cx=M["m10"]/M["m00"]
cy=M["m01"]/M["m00"]
cv2.circle(im,(np.float32(cx),np.float32(cy)),5,(255,0,0),-1)
cv2.putText(im,"center",(np.float32(cx),np.float32(cy)),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),3)
cv2.imshow("tu",im),cv2.waitKey(0)

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_15642411/article/details/79930083