首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

OpenCV EMD(Earth Mover's Distance)詳解:cvCalcEMD2 函數參數與直方圖匹配應用

     編輯:關於C語言

什麼是 EMD?

EMD(Earth Mover's Distance,土方距離)是一種度量兩個分布差異的距離指標。形象理解:將一堆土(源直方圖)移動成另一堆土(目標直方圖)所需的最小工作量(土量 × 移動距離)。

為什麼需要 EMD?

傳統直方圖匹配(如相關性、卡方)對 bin 位置敏感。光照變化會導致顏色值整體平移,直方圖形狀不變但位置偏移,導致匹配失敗。EMD 關注「形狀轉換的代價」,對平移不敏感,適合光照變化下的圖像匹配。

OpenCV cvCalcEMD2 函數詳解

函數原型

float cvCalcEMD2(
    const CvArr* signature1,
    const CvArr* signature2,
    int distance_type,
    CvDistanceFunction distance_func = NULL,
    const CvArr* cost_matrix = NULL,
    CvArr* flow = NULL,
    float* lower_bound = NULL,
    void* userdata = NULL
);

核心參數

  • signature1/2:簽名矩陣(浮點型),每行:[權重, 座標1, 座標2, ...]。對於 2D 直方圖(H-S),每行 3 個值:bin值、H座標、S座標。
  • distance_type:距離類型。CV_DIST_L1(曼哈頓)、CV_DIST_L2(歐氏)。
  • 其餘參數多為可選,高級用法(自定義距離函數、代價矩陣、流輸出、下界估計)。

簡化調用

float emd = cvCalcEMD2(sig1, sig2, CV_DIST_L2);

從直方圖生成 Signature 的關鍵代碼

CvMat* sig1 = cvCreateMat(h_bins * s_bins, 3, CV_32FC1);
CvMat* sig2 = cvCreateMat(h_bins * s_bins, 3, CV_32FC1);

for (int h = 0; h < h_bins; h++) {
    for (int s = 0; s < s_bins; s++) {
        int idx = h * s_bins + s;
        float val1 = cvQueryHistValue_2D(hist1, h, s);
        cvSet2D(sig1, idx, 0, cvScalar(val1));  // bin value
        cvSet2D(sig1, idx, 1, cvScalar(h));     // coordinate H
        cvSet2D(sig1, idx, 2, cvScalar(s));     // coordinate S

        float val2 = cvQueryHistValue_2D(hist2, h, s);
        cvSet2D(sig2, idx, 0, cvScalar(val2));
        cvSet2D(sig2, idx, 1, cvScalar(h));
        cvSet2D(sig2, idx, 2, cvScalar(s));
    }
}

完整計算流程

float emd = cvCalcEMD2(sig1, sig2, CV_DIST_L2);
printf("EMD distance: %f\n", emd);

核心優勢總結

  • 光照不變性:通過「移動代價」而非「位置對比」匹配直方圖
  • 多維支持:任意維度直方圖均適用
  • 物理意義清晰:最小工作量直觀可解釋

應用場景

圖像檢索、目標跟蹤、顏色恆常性識別等光照變化顯著的計算機視覺任務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved