【问题标题】:How to compute "EMD" for 2 numpy arrays i.e "histogram" using opencv?如何使用opencv计算2个numpy数组的“EMD”,即“直方图”?
【发布时间】:2013-03-20 08:05:37
【问题描述】:

由于我是 opencv 新手,我不知道如何将 cv.CalcEMD2 函数与 numpy 数组一起使用。
我有两个数组:

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

如何将numpy array 转移到CVhistogram 并从Cvhistogram 转移到函数参数signature

我希望任何回答问题的人通过提供的解决方案解释任何使用过的opencv 函数。

“EMD”== earth mover's distance.

更新:-
另外,如果有人能告诉我如何使用numpy 数组设置cv.CalcEMD2 参数,即"signature",将会很有帮助!!

注意:-
* 对于可能对此问题感兴趣的人,此答案需要更多测试。

【问题讨论】:

  • @JaimeCervantes,我看到了你关于“EMD”的解决方案,但由于我不太了解OpenCV 数据结构,我想你可以修改你的答案以适合我的问题。谢谢。
  • 我觉得我知道怎么做了,我周末去看看
  • @JaimeCervantes 我希望如此。我期待您的回答。

标签: python opencv numpy histogram earthdistance


【解决方案1】:

CV.CalcEMD2 需要根据文档还包含每个信号权重的数组。

我建议将您的数组定义为权重 1,如下所示:

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

【讨论】:

    【解决方案2】:

    您必须根据权重和坐标定义数组。如果您有两个表示一维直方图的数组 a = [1,1,0,0,1] 和 b = [0,1,0,1],那么 numpy 数组应该如下所示:

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

    请注意,行数可以不同。列数应该是维度+1。第一列包含权重,第二列包含坐标。

    下一步是在将 numpy 数组作为签名输入到 CalcEMD2 函数之前,将数组转换为 CV_32FC1 Mat。代码如下所示:

    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)
    

    注意CalcEMD2的第三个参数是欧几里得距离CV_DIST_L2。第三个参数的另一个选项是曼哈顿距离 CV_DIST_L1。

    我还想提一下,我编写了代码来计算地球移动器在 Python 中的两个 2D 直方图的距离。你可以找到这个代码here

    【讨论】:

    • 赏金时间快结束了,你选择答案了吗?
    • 如果a=[15,23,14],对应的数组有坐标和权重是什么?
    • 测试代码,返回“0.0”。尽管两个数组之间存在差异,这是否正常?
    • 如果数组不同,应该有一个大于零的距离。我用我的代码测试了不同的数组,它正在工作。
    • 不幸的是,函数cv.CalcEMD2在OpenCV 3.0.0-beta中消失了,替换函数EMDdoes not have Python bindings
    【解决方案3】:

    我知道 OP 想使用 OpenCV 测量 Earth Mover's Distance,但如果您想使用 Scipy 进行测量,您可以使用以下方法(Wasserstein 距离也称为 Earth Mover 距离):

    from scipy.stats import wasserstein_distance
    from scipy.ndimage import imread
    import numpy as np
    
    def get_histogram(img):
      '''
      Get the histogram of an image. For an 8-bit, grayscale image, the
      histogram will be a 256 unit vector in which the nth value indicates
      the percent of the pixels in the image with the given darkness level.
      The histogram's values sum to 1.
      '''
      h, w = img.shape
      hist = [0.0] * 256
      for i in range(h):
        for j in range(w):
          hist[img[i, j]] += 1
      return np.array(hist) / (h * w)
    
    a = imread('a.jpg')
    b = imread('b.jpg')
    a_hist = get_histogram(a)
    b_hist = get_histogram(b)
    dist = wasserstein_distance(a_hist, b_hist)
    print(dist)
    

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      • 2019-02-10
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      相关资源
      最近更新 更多