前段時間cwj649956781說他不理解cvCalEMD2函數作用,因為時間關系,到現在才回復,實在是抱歉!
1.What is EMD?
所謂的EMD實際上就是Earth Mover's Distance的縮寫也就是陸地移動距離
2.EMD有何用?
1)原因:
因為光線變化能夠導致圖像的顏色值漂移,雖然沒有改變顏色直方圖的形狀,但是卻改變了顏色值的位置,會導致匹配失敗。
2)結果:
所以我們就需要利用EMD來解決這個問題。利用直方圖的距離測量來代替直方圖的匹配策略,這樣仍然可以像直方圖對比一樣對比兩個直方圖的距離
3)EMD實質:
實際上就是度量怎麼樣將一個直方圖的形狀轉換到另一個直方圖的形狀,包括移動直方圖的部分或者全部到一個新的位置,可以在任何維度的直方圖上進行度量。
3.如何計算EMD?
opencv中給出了這樣的函數,如下所示:
函數:
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)參數解釋:
函數中又許多默認參數了,因此可以簡化為
float cvCalcEMD2(
const CvArr* signature1,
const CvArr* signature2,
int distance_type
);
其中distance_type為距離類型
可以是曼哈頓距離(CV_DIST_L1)
歐氏距離((CV_DIST_L2);
其中signature數組為浮點型
每行包括直方圖的bin(形象點說也就是有多少個棍子)以及坐標。
2)關於如何生成signature?
learning opencv中給出了一個例子
給定兩個直方圖hist1和hist2
如何轉換他們為signature?接下來我們借助代碼來說明問題。
CvMat* sig1,sig2;
int numrows = h_bins*s_bins;
//用於存放signature的矩陣,注意類型為浮點型 www.2cto.com
sig1 = cvCreateMat(numrows, 3, CV_32FC1); //1 count + 2 coords = 3
sig2 = cvCreateMat(numrows, 3, CV_32FC1); //sigs are of type float.
for( int h = 0; h < h_bins; h++ ) {
for( int s = 0; s < s_bins; s++ ) {
float bin_val = cvQueryHistValue_2D( hist1, h, s );
cvSet2D(sig1,h*s_bins + s,0,cvScalar(bin_val)); //bin value
cvSet2D(sig1,h*s_bins + s,1,cvScalar(h)); //Coord 1
cvSet2D(sig1,h*s_bins + s,2,cvScalar(s)); //Coord 2
bin_val = cvQueryHistValue_2D( hist2, h, s );
cvSet2D(sig2,h*s_bins + s,0,cvScalar(bin_val)); //bin value
cvSet2D(sig2,h*s_bins + s,1,cvScalar(h)); //Coord 1
cvSet2D(sig2,h*s_bins + s,2,cvScalar(s)); //Coord 2
}
}
3)計算EMD:
搞定完了signature,接下來就可以計算了
float emd = cvCalcEMD2(sig1,sig2,CV_DIST_L2);
printf(“%f; ”,emd);
所得到的就是距離度量EMD了
4.思考:
實際上EMD這個東西是在光線變化導致的不能匹配的情況下,仍然能夠計算出兩個直方圖之間的關聯性,當然是通過emd這個值來度量的。從而達到在光線改變的情況下匹配的效果。