2014-09-23 7 views
2

Мне интересно, как сравнивать, если два пути перекрытия контура, если они похожи.Как сравнить, если два контура пути визуально похожи - Python/Matplotlib

Чтобы уточнить, у меня есть набор 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 в другом ...

+2

1) нарисуйте пути (возможно, здесь может помочь АА). 2) возьмите буфер AGG. 3) возьмите внутренний продукт между двумя изображениями. – tacaswell

ответ

2

Во-первых, я предполагаю здесь вы знаете, что ваши контуры построены в одном масштабе и не переведены, так что это не столько проблема согласования изображений, сколько попытка найти разницу между двумя неудобными фигурами.

Существует несколько способов сделать это, оба из которых должны дать примерно такой же результат. Самый точный способ - взять внутренний продукт между двумя кривыми, но для этого необходимо, чтобы кривые были выровнены и описаны с одинаковым разрешением. Это можно сделать, например, с помощью интерполяции, но это серьезная проблема.

Способ, которым я попробую это здесь, является ярлыком, но он должен дать разумную оценку, которая заключается в построении области между двумя кривыми и суммировании этой области от графика. Чем меньше площадь, тем больше сходны кривые. (То есть, в общем, с кривыми, которые вы используете для внутреннего продукта, с изображениями, которые вы использовали бы в области разницы).

Например, начиная с этих контуров:

enter image description here

Мы заканчиваем с этим сюжетом, и разница сумма в названии:

enter image description here

Вот код (это немного сложно, потому что я не думаю, что есть способ просто заполнить между двумя произвольными параметризованными кривыми, поэтому вместо этого я делаю образы из каждого заполненного одиночного контура, а затем вычитаю их):

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() 
+0

Спасибо! Довольно простая мысль и демонстрация. Большое спасибо. (: – pceccon

0

Добавление:

ax.set_position([0, 0, 1, 1]) 
ax.axis('off') 

к fill_contour() обратного вызова улучшит результаты, как ось, и "мертвые" пространства удаляется из данных, собранных в: fig.savefig(buf, format = 'png'). Я пытаюсь использовать этот метод, чтобы получить перекрывающуюся область двух контуров или контура, вместо этого сделав d = abs(d1+d2), но я не так рад, когда потеряю информацию X и Y.

Смежные вопросы