【问题标题】:Python code for Earth mover's Distance推土机距离的 Python 代码
【发布时间】:2011-02-24 06:05:47
【问题描述】:

我正在寻找 Python 中的 Earth Mover 距离(或快速 EMD)实现。 关于在哪里找到它的任何线索,我在网上已经看够了。 我想在我正在做的图像检索项目中使用它。 谢谢。

编辑: 我使用pulp libararies 找到了一个非常好的解决方案。 这个页面也有设置它所需的说明。

【问题讨论】:

  • 也许如果您包含指向该术语定义的链接,您可能会节省您的潜在回答者访问 Google 的机会。
  • 如果它存在于 C 中的某个地方,您可以从 Python 中使用它。
  • 您认为您可以尝试详细说明您找到的解决方案吗?我有同样的问题:)
  • @Will 您是否成功通过我在 EDIT 中提到的链接安装了纸浆库?
  • 地球移动器的距离 (EMD) 也称为 Wasserstein 度量 你可以从scipy.stats 获得 Python 实现:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.wasserstein_distance.html

标签: python image


【解决方案1】:

OpenCv 中有一个出色的 Python 实现。该函数的名称是CalcEMD2,用于比较两张图像的直方图的简单代码如下所示:

#Import OpenCv library
from cv2 import *

### HISTOGRAM FUNCTION #########################################################
def calcHistogram(src):
    # Convert to HSV
    hsv = cv.CreateImage(cv.GetSize(src), 8, 3)
    cv.CvtColor(src, hsv, cv.CV_BGR2HSV)

    # Extract the H and S planes
    size = cv.GetSize(src)
    h_plane = cv.CreateMat(size[1], size[0], cv.CV_8UC1)
    s_plane = cv.CreateMat(size[1], size[0], cv.CV_8UC1)
    cv.Split(hsv, h_plane, s_plane, None, None)
    planes = [h_plane, s_plane]

    #Define numer of bins
    h_bins = 30
    s_bins = 32

    #Define histogram size
    hist_size = [h_bins, s_bins]

    # hue varies from 0 (~0 deg red) to 180 (~360 deg red again */
    h_ranges = [0, 180]

    # saturation varies from 0 (black-gray-white) to 255 (pure spectrum color)
    s_ranges = [0, 255]

    ranges = [h_ranges, s_ranges]

    #Create histogram
    hist = cv.CreateHist([h_bins, s_bins], cv.CV_HIST_ARRAY, ranges, 1)

    #Calc histogram
    cv.CalcHist([cv.GetImage(i) for i in planes], hist)

    cv.NormalizeHist(hist, 1.0)

    #Return histogram
    return hist

### EARTH MOVERS ############################################################
def calcEM(hist1,hist2,h_bins,s_bins):

    #Define number of rows
    numRows = h_bins*s_bins

    sig1 = cv.CreateMat(numRows, 3, cv.CV_32FC1)
    sig2 = cv.CreateMat(numRows, 3, cv.CV_32FC1)    

    for h in range(h_bins):
        for s in range(s_bins): 
            bin_val = cv.QueryHistValue_2D(hist1, h, s)
            cv.Set2D(sig1, h*s_bins+s, 0, cv.Scalar(bin_val))
            cv.Set2D(sig1, h*s_bins+s, 1, cv.Scalar(h))
            cv.Set2D(sig1, h*s_bins+s, 2, cv.Scalar(s))

            bin_val = cv.QueryHistValue_2D(hist2, h, s)
            cv.Set2D(sig2, h*s_bins+s, 0, cv.Scalar(bin_val))
            cv.Set2D(sig2, h*s_bins+s, 1, cv.Scalar(h))
            cv.Set2D(sig2, h*s_bins+s, 2, cv.Scalar(s))

    #This is the important line were the OpenCV EM algorithm is called
    return cv.CalcEMD2(sig1,sig2,cv.CV_DIST_L2)

### MAIN ########################################################################
if __name__=="__main__":
    #Load image 1
    src1 = cv.LoadImage("image1.jpg")

    #Load image 1
    src2 = cv.LoadImage("image2.jpg")

    # Get histograms
    histSrc1= calcHistogram(src1)
    histSrc2= calcHistogram(src2)

    # Compare histograms using earth mover's
    histComp = calcEM(histSrc1,histSrc2,30,32)

    #Print solution
    print(histComp)

我使用 Python 2.7 和 Python(x,y) 测试了与之前的代码非常相似的代码。如果您想了解有关 Earth Mover 的更多信息并希望查看使用 OpenCV 和 C++ 的实现,您可以阅读 Gary Bradski 和 Adrain Kaebler 的“Learning OpenCV”一书的“第 7 章:直方图和匹配”。

【讨论】:

    【解决方案2】:

    这里是计算两个等长一维分布之间的地球移动器距离的python代码

    def emd (a,b):
    earth = 0
    earth1 = 0
    diff = 0
    s= len(a)
    su = []
    diff_array = []
    for i in range (0,s):
        diff = a[i]-b[i]
        diff_array.append(diff)
        diff = 0
    for j in range (0,s):
        earth = (earth + diff_array[j])
        earth1= abs(earth)
        su.append(earth1)
    emd_output = sum(su)/(s-1)
    print(emd_output)
    

    【讨论】:

      猜你喜欢
      • 2018-08-20
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多