2013-03-29 6 views
11

Da ich neu bin OpenCV, ich weiß nicht, wie die cv.CalcEMD2 Funktion mit numpy Arrays verwenden.
Ich habe zwei Arrays:Wie berechnet man "EMD" für 2 numpy Arrays, d. H. "Histogramm" mit opencv?

a=[1,2,3,4,5] 
b=[1,2,3,4] 

Wie kann ich numpy array-CVhistogram und von Cvhistogram auf die Funktionsparameter signature übertragen?

Ich möchte jeden, der die Frage beantwortet jede opencv Funktionen durch die bereitgestellte Lösung verwendet zu erklären.

"EMD" == earth mover's distance.

Update: -
auch, wird es hilfreich sein, wenn jemand kann mir sagen, wie, um den cv.CalcEMD2 Parameter d.h "signature" mit numpy Array !!

Hinweis: -
* Für diejenigen, die in dieser Frage interessiert sein könnten, benötigt diese Antwort mehr Tests.

+0

@JaimeCervantes, Ich sah Ihre Lösung über "EMD", aber da ich 'OpenCV' Datenstruktur nicht so gut verstehe, dachte ich, dass Sie Ihre Antwort ändern können, um meine Frage.Thankx. –

+0

in Anbetracht dieser Frage: http://StackOverflow.com/Questions/5101004/Python-Code-for-Earth-movers-distance?lq=1 –

+0

Ich denke, ich weiß, wie es geht, ich werde es über die Wochenende –

Antwort

16

Sie haben Ihre Arrays in Bezug auf Gewichte und Koordinaten zu definieren. Wenn Sie zwei Arrays a = [1,1,0,0,1] und b = [0,1,0,1] haben, die eindimensionale Histogramme darstellen, dann sollten die numpy Arrays wie folgt aussehen:

a = [[1 1] 
    [1 2] 
    [0 3] 
    [0 4] 
    [1 5]] 

b = [[0 1] 
    [1 2] 
    [0 3] 
    [1 4]] 

Beachten Sie, dass die Anzahl der Zeilen unterschiedlich sein kann. Die Anzahl der Spalten sollte den Dimensionen + 1 entsprechen. Die erste Spalte enthält die Gewichtungen und die zweite Spalte enthält die Koordinaten.

Der nächste Schritt ist Ihren Arrays zu einem CV_32FC1 Mat, bevor Sie Eingabe der numpy Array als Signatur an die CalcEMD2 Funktion zu konvertieren. Der Code würde wie folgt aussehen:

from cv2 import * 
import numpy as np 

# Initialize a and b numpy arrays with coordinates and weights 
a = np.zeros((5,2)) 

for i in range(0,5): 
    a[i][1] = i+1 

a[0][0] = 1 
a[1][0] = 1 
a[2][0] = 0 
a[3][0] = 0 
a[4][0] = 1 

b = np.zeros(4,2) 

for i in range(0,4): 
    b[i][1] = i+1 

b[0][0] = 0 
b[1][0] = 1 
b[2][0] = 0 
b[3][0] = 1  

# Convert from numpy array to CV_32FC1 Mat 
a64 = cv.fromarray(a) 
a32 = cv.CreateMat(a64.rows, a64.cols, cv.CV_32FC1) 
cv.Convert(a64, a32) 

b64 = cv.fromarray(b) 
b32 = cv.CreateMat(b64.rows, b64.cols, cv.CV_32FC1) 
cv.Convert(b64, b32) 

# Calculate Earth Mover's 
print cv.CalcEMD2(a32,b32,cv.CV_DIST_L2) 

# Wait for key 
cv.WaitKey(0) 

Beachten Sie, dass der dritte Parameter von CalcEMD2 die euklidische Entfernung CV_DIST_L2 ist. Eine weitere Option für den dritten Parameter ist die Manhattan-Distanz CV_DIST_L1.

Ich möchte auch erwähnen, dass ich den Code schrieb der Erde Mover Abstand von zwei 2D-Histogramme in Python zu berechnen. Sie finden diesen Code here.

+0

Die Zeit ist fast vorbei für das Kopfgeld, wählst du eine Antwort aus? –

+0

Danke, Sicher werde ich, aber ich teste gerade den Code. –

+0

Wenn 'a = [15,23,14]', was ist das entsprechende Array ** mit Koordinaten und Gewichtungen **? –

3

CV.CalcEMD2 erwartet Arrays, die auch das Gewicht für jedes Signal umfassen entsprechend der Dokumentation.

würde ich vorschlagen, Ihre Arrays mit einem Gewicht von 1 zu definieren, etwa so:

a=array([1,1],[2,1],[3,1],[4,1],[5,1]) 
b=array([1,1],[2,1],[3,1],[4,1])