如何使用cv.CalcEMD2(opencv)计算emd流?

时间:2016-06-15 21:18:28

标签: python opencv flow

我知道MATLAB和C可以计算EMD流量。但是,我试图使用python(opencv)通过使用函数cv.CalcEMD2来计算EMD流。有没有机会,如果有人能用cv.CalcEMD2或任何函数给我一个例子来获得EMD流吗?

1 个答案:

答案 0 :(得分:0)

这是一些python代码,用于计算EMD和两个高斯混合的流。我希望有所帮助。

"""
Compute earth mover's distance (EMD) to compare two mixtures of Gaussians

Requires: numpy, cv2, csb
"""
import numpy as np, cv2
from csb.numeric import log_sum_exp

class GMM(object):
    """
    1d mixture of Gaussians
    """
    def __init__(self, K):
        """
        K: number of components
        """
        self.mu = np.zeros(K)
        self.sigma = np.ones(K)
        self.w = np.ones(K)
        self.w/= self.w.sum()

    @property
    def K(self):
        return len(self.mu)

    def log_prob(self, x):
        logp = - 0.5 * np.subtract.outer(x, self.mu)**2 / self.sigma**2. \
           - 0.5 * np.log(2*np.pi*self.sigma**2) + np.log(self.w)

        return log_sum_exp(logp.T,0)

    def __call__(self, x, normed=True):

        logp = self.log_prob(x)
        if np.iterable(x) and normed:
            logp -= log_sum_exp(logp)

        return np.exp(logp)

    def randomize(self, mu_range=(-10, 10.), sigma_range=(0.1, 5.)):

        self.mu[...] = np.random.uniform(*mu_range, size=self.K)
        self.sigma[...] = np.random.uniform(*sigma_range, size=self.K)
        self.w[...] = np.random.random(self.K)
        self.w /= self.w.sum()

def make_signature(x, p):

    P = np.transpose([p,x])
    P64 = cv2.cv.fromarray(np.array(P.tolist()))
    P32 = cv2.cv.CreateMat(P64.rows, P64.cols, cv2.cv.CV_32FC1)
    cv2.cv.Convert(P64, P32)

    return P32

def calc_emd(q, p, x):

    Q = make_signature(x, q)
    P = make_signature(x, p)

    flow = cv2.cv.CreateMat(len(q), len(p), cv2.cv.CV_32F)
    cv2.cv.Set(flow, 0.)

    return cv2.cv.CalcEMD2(P, Q, cv2.cv.CV_DIST_L2, flow=flow), np.asarray(flow[:,:])

if __name__ == '__main__':

    x = np.linspace(-10., 10., 100)

    ## create two mixtures of Gaussians with 3 and 5 components

    f = GMM(3)
    g = GMM(5)

    f.randomize()
    g.randomize()

    ## evaluate mixtures on 1d grid

    q = f(x)
    p = g(x)

    ## compute EMD and flow

    emd, F = calc_emd(q, p, x)

    ## check marginals

    print np.fabs(F.sum(0) - q).max(), np.fabs(F.sum(1)-p).max()