EMD(Earth Mover's Distance,土方距離)是一種度量兩個分布差異的距離指標。形象理解:將一堆土(源直方圖)移動成另一堆土(目標直方圖)所需的最小工作量(土量 × 移動距離)。
傳統直方圖匹配(如相關性、卡方)對 bin 位置敏感。光照變化會導致顏色值整體平移,直方圖形狀不變但位置偏移,導致匹配失敗。EMD 關注「形狀轉換的代價」,對平移不敏感,適合光照變化下的圖像匹配。
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
);
[權重, 座標1, 座標2, ...]。對於 2D 直方圖(H-S),每行 3 個值:bin值、H座標、S座標。CV_DIST_L1(曼哈頓)、CV_DIST_L2(歐氏)。float emd = cvCalcEMD2(sig1, sig2, CV_DIST_L2);
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);
圖像檢索、目標跟蹤、顏色恆常性識別等光照變化顯著的計算機視覺任務。