1

I am trying to compute the Earth Mover Distance between two histograms I have (x1,x2), using the following snippet I obtained from http://docs.opencv.org/2.4/modules/imgproc/doc/histograms.html:

cv2.cv.CalcEMD2(x1, x2,cv2.cv.CV_DIST_L1)

However I keep getting this error.

TypeError: CvArr argument 'signature1' must be IplImage, CvMat or CvMatND. Use fromarray() to convert numpy arrays to CvMat or cvMatND"

I tried using .fromarray() to convert what I had into a CvMat format with no success yet. Is there something I am doing wrong?

Here are the two types of array i am working with (shortened to three elements for clarity) I tried to convert using cv2.cv.fromarray():

np.histogramdd(data, bins = 80)) 

giving me:

(array([  28.,    5.,    0.]), [array([-1.71194523, -1.66131523, -1.61068523])])

and a normal np array:

[28.    5.    0.]

Neither work for me and neither allow me to compute the Earth mover distance between arrays. Any help would be greatly appreciated!

Ciaran
  • 478
  • 1
  • 8
  • 23

1 Answers1

0

Right, after much trial and error I think this is the solution: (obtained from best answer of How to compute "EMD" for 2 numpy arrays i.e "histogram" using opencv?)

ref = reference np array meas = np array to compare it to

creates histogram of numpy array [[data][weights]], converts it to [data[i],weight[i]] format. Then to a cv array which then converts it into a signal function for the EMD function.

This is not an ideal solution - any further improvements/advice would be greatly appreciated for education purposes!!!

#reference array:
j = np.histogramdd(ref, bins = 80)
a = np.zeros((len(j[0]), 2))
for i, x in enumerate(j[0]):
    a[i][0] = x
    a[i][1] = j[1][0][i]
cv_array_ref = cv2.cv.fromarray(a)

a32 = cv2.cv.CreateMat(cv_array_ref.rows, cv_array_ref.cols,cv2.cv.CV_32FC1)
cv2.cv.Convert(cv_array_ref, a32)


#measured array:

jj = np.histogramdd(amplitude_norm_data[0], bins = 80)
aa = np.zeros((len(jj[0]), 2))
for ii, xx in enumerate(jj[0]):
    aa[ii][0] = xx
    aa[i][1] = jj[1][0][ii]
cv_array_meas = cv2.cv.fromarray(aa)
a322 = cv2.cv.CreateMat(cv_array_meas.rows, cv_array_meas.cols, cv2.cv.CV_32FC1)
cv2.cv.Convert(cv_array_meas, a322)


cv2.cv.CalcEMD2(a32, a322,cv2.cv.CV_DIST_L1)
Community
  • 1
  • 1
Ciaran
  • 478
  • 1
  • 8
  • 23