Matlab计算大规模图片数据集的L1距离



比较两幅图片之间的距离或者相似性,我们常以Matlab pdist函数或者pdist2函数计算。计算大规模图片数据集的两两图片之间的距离,很自然想到双重for循环完成了。不过,这很慢:

function KMatrix = getL1( X, Y ) %L1距离

m = size(X,1);  n = size(Y,1);

KMatrix = zeros(m,n);

for i = 1: m %按行

for j = 1: n

KMatrix(i,j) = sum( abs( X(i,:)-Y(j,:)) );

end

fprintf('%d.',i); if mod(i,10)==0, fprintf('\n'); end

end

其中,X、Y分别是图片集X、Y的特征文件矩阵。


以L1距离为例,特征文件是4096维的RGB彩色描述子,两万幅图片之间的L1距离矩阵20000×20000,在 8CPU + 16GB内存的X64 Windows 7系统上计算,MATLAB 2012b运行时间5小时。比较慢。


向量化是一个考虑。不过,童鞋们,如何向量化呢?这个比起点积要复杂一点点。通过一行一行计算距离,去掉一个内循环:

function KMatrix = getL1( X, Y ) %L1距离 向量化

m = size(X,1);  n = size(Y,1);

nOnes = ones(1,n); KMatrix = zeros(m,n);

for i = 1: m %按行

   xi = X(i,:);  xi = xi( nOnes, : );

   KMatrix(i,:) = sum( abs( xi-Y),2 );%计算一行L1距离

   fprintf('%d.',i); if mod(i,10)==0, fprintf('\n'); end

end


似乎无法继续向量化了?还好,arrayfun帮助我们继续向量化。

function KMatrix = getL1( X, Y ) %L1距离 arrayfun向量化

m = size(X,1);  n = size(Y,1);

KMatrix = zeros(m,n);

CC = arrayfun(@(i) getL1Vec(X(i,:), Y, i), 1:m, 'UniformOutput', false);%只能得到Cells

for i = 1: m %Cells->矩阵,极快

   KMatrix(i,:) = CC{i};

end


end


function KVec = getL1Vec(XVec, Y, i)%第i行L1

n = size(Y,1);

nOnes = ones(1,n);

XVec = XVec( nOnes, : );

   KVec = sum( abs( XVec-Y),2 );%计算一行L1距离

   fprintf('%d.', i);if mod(i,10)==0, fprintf('\n'); end

end


至此,arrayfun完成了向量化。计算L1距离没有循环了。只是Cells转换为矩阵,有一个循环,极快。不是瓶颈。



向量化还能否改进下?

似乎内存优化不够,试试matlab函数:bsxfun(),改善:

n = size(Y,1);

nOnes = ones(1,n);

XVec = XVec( nOnes, : );

   KVec = sum( abs( XVec-Y),2 );%计算一行L1距离


于是,得到:

function KMatrix = getL1( X, Y ) %L1距离

m = size(X,1);  n = size(Y,1);

KMatrix = zeros(m,n);

CC = arrayfun(@(i) getL1Vec(X(i,:), Y, i), 1:m, 'UniformOutput', false);%只能得到Cells

for i = 1: m %Cells->矩阵,极快

   KMatrix(i,:) = CC{i};

end


end


function KVec = getL1Vec(XVec, Y, i)%第i行L1

   KVec = sum( abs(bsxfun(@minus,XVec,Y)),2 );

   fprintf('%d.', i);if mod(i,10)==0, fprintf('\n'); end

end

完成了。在 8CPU + 16GB内存的X64 Windows 7系统上计算,MATLAB 2012b运行时间3小时。节省了2个小时。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章