之所以要写这篇文章,主要是想从Matlab函数的角度给大家一个对EMD直观的理解。EMD是在一定的条件限制下求解最小代价作为直方图等向量的距离。EMD具体内容请参考我第一篇文章。而求解最小代价的过程就是个线性规划问题。
一、Matlab函数解释
这里借用的Matlab函数为linprog(),即求解线性规划的函数。下面为了让大家理解方便,signature的表达严格对应了直方图的bin,也就是说一点都不压缩直方图,每个bin就作为一个signature,所以数据量显得大了些。例如直方图有32个bin,那么signature就是 (1, w1), (2, w2), (3, w3).... (32, w32),w值为每个bin的数量。
matlab的这个函数我的调用方式为:linprog(f, A, b, Aeq, beq),解释如下:
1)函数的目的是求 fT * x的最小值,一定要注意,这里的f相当于上一篇中EMD的距离矩阵D,x相当于EMD的fij,即从一个直方图的第i个bin流到另一个直方图的第j个bin的数量。 由于这个函数的输入f是一维的,下面我把EMD的距离dij和fij都展开。
2)一个限制条件为 A * x <= b
3)另一个限制条件是Aeq * x = beq
二、实例
下面根据一个例子问题构建这个输入数据。
1) 数据:6个bin的一维直方图的EMD距离- 直方图1:[100 0 0 0 120 0]
- 直方图2:[0 100 0 0 0 120]
- 可以直观的看到,这两个直方图其实很像,只是错位了一列而已,而实际的图像也会比较相似。造成这种问题也许是图像的光照发生了一丁点的变化使得像素值给量化到紧邻的bin里了。高大上的EMD应该是100挪到第二个bin,120挪到最后一个bin,代价会最小。下面用线性规划验证这个情况。
2) matlab函数的f对应EMD公式中的d,即代价。x即EMD中的fij。由于EMD中条件不等式中只是对fij的求和限制,相当于权值为1,所以matlab调用中的A中的对应这部分限制条件的有效部分应该是全1。
3) matlab函数的输入参数f的生成:
- 对于颜色空间来说,距离即是bin的欧几里得距离。这里由于是一维直方图,距离可以记为bin的序号的差的绝对值。(如果用bin所对应的颜色值范围的中心,只是一个线性变化问题,不影响结果)
f =
0 1 2 3 4 5
1 0 1 2 3 4
2 1 0 1 2 3
3 2 1 0 1 2
4 3 2 1 0 1
5 4 3 2 1 0
- matlab函数解决的是一维向量计算,所以把上述EMD计算公式打开成一维,
[0 1 2 3 4 5 1 0 1 2 3 4 2 1 0 1 2 3 3 2 1 0 1 2 4 3 2 1 0 1 5 4 3 2 1 0]
4) A的生成,稍微复杂些,它需要表达EMD公式条件中的两个对fij求和的小于等于的不等式(每套不等式都包含bin的个数的判断,即6)。由于把二维向量展开了,fij本身为包含36个元素的一维向量。那么为了表达两个不等式,需要加入12*36维矩阵,每一行对应一个不等式。另外还有第一个不等式即每个fij都要大于等于0,也要融入到A中。
- 第一个不等式:把36列分为6段,每一行赋给其中一段为全1,其他全0
- 第二个不等式:交织的方式赋值,即第7行:1 0 0 0 0 0 1 0 0 0 0 0 1.....;第8行:0 1 0 0 0 00 1 0 0 0 0 0 1 ....,
- 注意上述两个不等式的赋值对应于对i和j的求和。
- 限制每个fij都不小于0很简单,但是它是限制36个搬移量的每一个,所以有36个不等式,所以A中还需要加入36x36的矩阵,每一行去计算某一个搬移量,也就是其中一个位置赋-1(负1使EMD公式中的大于号改变成小于号),其他全零。
5) b的赋值:基于A的赋值,可以很直观的看到,b中第一部分6个值为第一个直方图的每个bin的值,第二部分6个值为第二个直方图的每个bin的值;第三部分36个值为0,那么总共b的元素数量为6+6+36=48。
6) Aeq简单的设置为1x36,所有全为1(EMD等式中的求和没有权值)
7) beq则为一个直方图所有bin的求和。虽然EMD的条件公式中是求两个直方图求和的最小值,但是由于两个直方图的情况相同,这里计算结果为beq=220
8) 调用函数:[x, fval] = linprog(frow, A, b, Aeq, beq),得到结果
- x = -0.0000 100.0000 -0.0000 0.0000 0.0000 0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 0.0000 0.0000 0.0000 -0.0000 -0.0000 -0.0000 0.0000 -0.0000 0.0000 -0.0000 -0.0000 -0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 120.0000 -0.0000 0.0000 -0.0000 -0.0000 -0.0000 0.0000。 可以发现x中只有两个非零值,100, 120,也就是只有两个有效的搬移。
- fval = 220,即代价。这里的输入使用的是WORK而不是归一化后的EMD。这个fval即为最小化的WORK。可以直观的看到,相当于前述的两次搬移,搬移距离1,总移动数量为(100+120),即220。
三、Matlab代码实现
%相当于求和 i
A = zeros(12+36, 36);
for i=1:6
A(i, (i-1)*6+1 : i*6) = 1;
end
% 相当于求和 j
for i=1:6
for j=0:5
A(i+6, j*6+i) = 1;
end
end
for i=1:36
A(i+12, i)= -1;
end
Aeq = ones(1, 36);
beq = 220;
f = [0 1 2 3 4 5; 1 0 1 2 3 4; 2 1 0 1 2 3;3 2 1 0 1 2; 4 3 2 1 0 1;5 4 3 2 1 0];
frow=[f(1,:) f(2,:) f(3,:) f(4,:) f(5,:) f(6,:)];
b = zeros(12+36,1);
b(1:12,1) = [100 0 0 0 120 0 0 100 0 0 0 120]';
[x, fval] = linprog(frow, A, b, Aeq, beq)
相信到此为止,大家应该对EMD有个比较直观的认识了 :)