我想知道如果两个路径的轮廓重叠,如果它们相似则如何比较。
更具体地说,我有一组 n 实现,每个实现都有其轮廓级别。我需要在 l 级别验证每个轮廓的稳定性。要做到这一点,我必须计算它通过偶然发生的次数。
到目前为止,我正在研究这段代码:
def iso_contours(scalar_fields):
#TODO : access the paths by level (0, 1, 2 ...)
default = 0
contours = {}
contours_number = 0
for scalar_field in scalar_fields:
cs = plt.contour(scalar_field)
for collection in cs.collections:
paths = collection.get_paths()
for path in paths:
num = contours.get(path, default)
contours[path] = num + 1
contours_number += 1
contours.update((x, y/float(contours_number)) for x, y in contours.items())
return contours
然而,即使有两条相同的路径,它们也被视为不同。
所以,我想知道如果给出两条路径,我可以确定它们是否在视觉上相似。 正如@unutbu提醒我的那样,我不能只比较顶点,因为顶点可能有不同的顺序,或者一条路径中可能有1000个顶点而另一条路径中可能有100个顶点...
答案 0 :(得分:2)
首先,我假设你知道你的轮廓被绘制成相同的比例并且没有被翻译,所以这不是图像匹配的问题,因为试图找到两个笨拙的形状之间的差异。
有几种方法可以做到这一点,两者都应该给出大致相同的结果。最准确的方法是在两条曲线之间取内积,但这需要将曲线对齐并将其描述为相同的分辨率。例如,这可以通过插值来完成,但这是一个很大的麻烦。
我在这里尝试的方法是一种捷径,但它应该给出一个合理的估计,即绘制两条曲线之间的区域并从图中求和该区域。面积越小,曲线越相似。 (也就是说,总而言之,使用内部产品的曲线,使用差异区域的图像)。
例如,从这些轮廓开始:
我们以这个情节结束,差异是标题中的总和:
这里是代码(它有点复杂,因为我不认为有一种方法可以简单地填充两条任意参数化曲线,所以我从每个填充的单曲中制作图像轮廓然后减去它们):
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import matplotlib.cm as cm
import numpy as np
import io
import Image
xmin, xmax, ymin, ymax = -3, 6, -2, 3
delta = 0.025
x = np.arange(xmin, xmax, delta)
y = np.arange(ymin, ymax, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
def f(a, b):
return 10.*(a*Z2 - b*Z1)
def fill_contour(cs):
v = cs.collections[0].get_paths()[0].vertices
fig = plt.figure()
ax = fig.add_subplot(111)
ax.fill(v[:,0], v[:,1], 'k')
ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax)
buf = io.BytesIO()
fig.savefig(buf, format = 'png')
buf.seek(0)
im = Image.open(buf).convert('L')
r = np.asarray(im).astype(np.int)
r/=max(r.flat)
return r
figc = plt.figure()
axc = figc.add_subplot(111)
c0 = .07
cs1 = axc.contour(X, Y, f(.6 ,.7), [c0], colors='r')
cs2 = axc.contour(X, Y, f(.8, 1.2), [c0], colors='g')
figd = plt.figure()
axd = figd.add_subplot(111)
d1 = fill_contour(cs1)
d2 = fill_contour(cs2)
d = abs(d1-d2)
im = axd.imshow(d, cmap=cm.gray)
figd.colorbar(im)
axd.set_title( "sum = %i" % np.sum(d.flat))
figc.show()
figd.show()
答案 1 :(得分:0)
添加:
ax.set_position([0, 0, 1, 1])
ax.axis('off')
到fill_contour()回调将改善结果,因为轴和"死"从fig.savefig(buf, format = 'png')
收集的数据中删除了空格。我试图使用这种方法来获得两个轮廓或轮廓f的重叠区域,而不是d = abs(d1+d2)
,但我没有那么高兴,因为我丢失了X和Y信息。