Python 使用Voronoi中心测量复杂形状

Python 使用Voronoi中心测量复杂形状,python,opencv,numpy,voronoi,Python,Opencv,Numpy,Voronoi,我目前正在使用opencv和python进行一个项目,以尽可能精确地测量通常是弯曲的对象,例如下面显示的箭头 我认为一种策略可能是使用scipy Voronoi函数来获取箭头中心脊椎的点,但我现在遇到了麻烦。这是我的密码: img = cv2.imread('example_rubystreak_2.PNG') img.shape gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,190,2

我目前正在使用opencv和python进行一个项目,以尽可能精确地测量通常是弯曲的对象,例如下面显示的箭头

我认为一种策略可能是使用scipy Voronoi函数来获取箭头中心脊椎的点,但我现在遇到了麻烦。这是我的密码:

img = cv2.imread('example_rubystreak_2.PNG')
img.shape
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,190,255,cv2.THRESH_BINARY)
countimage, contours, hierarchy = cv2.findContours(thresh,1,2)
blank = np.zeros((img.shape[0],img.shape[1],1),np.uint8)
#get max length contour
max_contour = 0
contour_idx = None
for ii in range(len(contours)):
    if len(contours[ii]) > max_contour:
        contour_idx = ii
        max_contour = len(contours[ii])
cv2.drawContours(blank,contours,contour_idx,255,cv2.FILLED,8,hierarchy)
apdp = cv2.approxPolyDP(contours[contour_idx],1,True)
ap = [(a[0][0],a[0][1]) for a in apdp]
vor_ap = Voronoi(ap)
spined = []
for ridge in vor_ap.ridge_vertices:
    if cv2.pointPolygonTest(cnt,tuple(vor_ap.vertices[ridge[0]]),True) <= 0.0 or cv2.pointPolygonTest(cnt,tuple(vor_ap.vertices[ridge[1]]),True) <= 0.0:
        continue
    else:
        if tuple(vor_ap.vertices[ridge[0]]) not in spined:
            spined.append([tuple(vor_ap.vertices[ridge[0]].tolist()),cv2.pointPolygonTest(cnt,tuple(vor_ap.vertices[ridge[0]]),True)])
        if tuple(vor_ap.vertices[ridge[1]]) not in spined:
            spined.append([tuple(vor_ap.vertices[ridge[1]].tolist()),cv2.pointPolygonTest(cnt,tuple(vor_ap.vertices[ridge[1]]),True)])
plt.figure(figsize=(12,12))
plt.scatter([s[0][0] for s in spined],[s[0][1] for s in spined])
plt.plot([a[0] for a in ap],[a[1] for a in ap])
img=cv2.imread('example\u rubystreak\u 2.PNG')
形状
灰色=cv2.CVT颜色(img,cv2.COLOR\U BGR2GRAY)
ret,thresh=cv2.阈值(灰色,190255,cv2.thresh_二进制)
countimage,等高线,层次=cv2.findContours(阈值,1,2)
blank=np.zero((img.shape[0],img.shape[1],1),np.uint8)
#获取最大长度轮廓
最大轮廓=0
等高线_idx=无
对于范围内的ii(透镜(轮廓)):
如果len(等高线[ii])>最大等高线:
等高线_idx=ii
最大轮廓=透镜(轮廓[ii])
cv2.drawContours(空白、等高线、等高线_idx、255、cv2.FILLED、8、层次)
apdp=cv2.approxPolyDP(等高线[contour_idx],1,真)
ap=[(a[0][0],a[0][1])表示apdp中的a]
vor_ap=Voronoi(ap)
有刺=[]
对于vor_ap.ridge_顶点中的脊线:

如果cv2.PointPolyContest(cnt,tuple(vor_ap.vertices[ridge[0]]),则为True)以下是我将尝试的内容的概要:

1) 通过使用三次B样条插值点,找到中心曲线的参数化表示。使用scipy.interpolate.splrep。您可能需要删除不沿中心曲线的异常点,以获得良好的三次样条曲线拟合


2) 获得三次样条曲线后,可以使用微积分中的弧长积分公式计算弧长,并使用曲线端点的积分极限数值计算该积分。为此,您需要获得样条曲线的X和Y一阶导数,它应该能够为您提供。对于由Numpy数组表示的函数,请使用scipy数值积分例程。

感谢您注意@paisancothanks的提示,但我在使用splrep时遇到了问题,因为箭头上的许多点对于单个x值具有多个y值,并且这些曲线并不总是适合进行排序。对于如何处理这个问题,您有什么建议吗?我无法运行您的代码(调用cv2.PointPolyContest中的变量cnt应该是什么?我知道contour,但在执行阶段是哪一个)。我不知道有些X有多个Y,但在这些情况下,取Y的平均值有意义吗?