前段时间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的矩阵,注意类型为浮点型
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这个值来度量的。从而达到在光线改变的情况下匹配的效果。