优化双线性插值/矢量化

时间:2016-05-31 16:30:06

标签: matlab vectorization

我试图减少一组点上图像的双线性插值处理时间。首先,我做了一个正常的循环。因为我已经在调用interp的函数上使用了parfor,所以我无法使用parfor。我试图对函数进行矢量化,它可以工作,但处理时间几乎没有减少。

Any ideas of how can I improve the vectorized version?

一些结果:
编辑 - 结果之前变化很大。我不知道为什么,但现在它们一致,价值观也没有太大变化。 我添加了tmirt2D,因为@ Dev-iL指出了它。他的代码比我的快得多(约3倍),他使用的是C ++。

Interp 2D tester
Time for each point and speed up in '%' based on the reference time.
Array size: 10000. Repeat: 10. Loops: 20
Normal for loop interp: 145.6354 ns (reference time)
Vect interp (in bounds): 68.6679 ns (112.09%)
Vect interp (out boudns): 66.5793 ns (118.74%)
Vect interp nearest (in boudns): 28.2870 ns (414.85%)
Vect interp nearest (out boudns): 26.3854 ns (451.95%)
tmirt2D from File Exchange: 22.6089 ns (544.15%)
Matlab interp2 linear: 921.0408 ns (-84.19%)
Matlab interp2 nearest: 911.7492 ns (-84.03%)

测试代码:

clearvars; clc; close all;
mustCompareMatlab = 1;

tm1 = 0;
tm2 = 0;
tm3 = 0;
tm4 = 0;
tm5 = 0;
tm6 = 0;
tm7 = 0;
tmirt2D = 0;
baseLoopN = 10;
for j=1:baseLoopN
    %% Create data
    dataSize = [1200 1600];
    data = rand(dataSize)*255;

    N = 1e4;
    X = rand(1,N)*dataSize(2);
    Y = rand(1,N)*dataSize(1);

    % Only inside bounds-1 coordinates
    Xin = X(X<dataSize(2)-1);
    Yin = Y(Y<dataSize(1)-1);

    % make X and Y same size

    Xin(end+1:length(X)) = ones(1,length(X)-length(Xin));
    Yin(end+1:length(X)) = ones(1,length(X)-length(Yin));

    % Make sure X and Y have outside bounds values
    X(1) = dataSize(2) + 1;
    Y(1) = dataSize(1) + 1;

    loops = 20;

    % Catch
    interpData = Interp2D(data,X,Y);

    tic
    for i=1:loops
        interpData = Interp2D(data,X,Y);
    end
    tm1 = tm1 + toc;

    %% Only inside bounds coordinates
    % Catch
    interpData = Interp2DVect(data,Xin,Yin);

    tic
    for i=1:loops
        interpData = Interp2DVect(data,Xin,Yin);
    end
    tm2 = tm2 + toc;

    %% inside and outside bounds
    % Catch
    interpData = Interp2DVect(data,X,Y);
    tic
    for i=1:loops
        interpDataInterp2DVect = Interp2DVect(data,X,Y);
    end
    tm3 = tm3 + toc;

    %% inside bounds nearest
    % Catch
    interpData = Interp2DNearest(data,Xin,Yin);
    tic
    for i=1:loops
        interpData = Interp2DNearest(data,Xin,Yin);
    end
    tm4 = tm4 + toc;

    %% inside and outside bounds nearest
    % Catch
    interpData = Interp2DNearest(data,X,Y);
    tic
    for i=1:loops
        interpData = Interp2DNearest(data,X,Y);
    end
    tm5 = tm5 + toc;

    % mirt2D_mexinterp
    % www.mathworks.com/matlabcentral/fileexchange/24183-2d-interpolation
    interpData = mirt2D_mexinterp(data,X,Y);
    tic
    for i=1:loops
        interpDataMirt2D = mirt2D_mexinterp(data,X,Y);
    end
    tmirt2D = tmirt2D + toc;



    %% Matlab interp
    if mustCompareMatlab

        interpData = interp2(data,X,Y,'linear'); %#ok<*NASGU>
        tic
        for i=1:loops
            interpData = interp2(data,Xin,Yin,'linear');
        end
        tm6 = tm6 + toc;

        interpData = interp2(data,X,Y,'nearest');
        tic
        for i=1:loops
            interpData = interp2(data,Xin,Yin,'nearest');
        end
        tm7 = tm7 + toc;

    end
    %%
end
A = interpDataInterp2DVect;
B = interpDataMirt2D;
C = A-B;

fprintf('Interp 2D tester\n');
fprintf('Array size: %d. Repeat: %d. Loops: %d\n',N,baseLoopN,loops);

tm1 = tm1*1e9/(baseLoopN*loops*N);
fprintf('Normal for loop interp: %.4f ns\n',tm1);

tm2 = tm2*1e9/(baseLoopN*loops*N);
fprintf('Vect interp (in bounds): %.4f ns (%.2f%%)\n',tm2,100*(tm1/tm2-1));

tm3 = tm3*1e9/(baseLoopN*loops*N);
fprintf('Vect interp (out boudns): %.4f ns (%.2f%%)\n',tm3,100*(tm1/tm3-1));

tm4 = tm4*1e9/(baseLoopN*loops*N);
fprintf('Vect interp nearest (in boudns): %.4f ns (%.2f%%)\n',tm4,100*(tm1/tm4-1));

tm5 = tm5*1e9/(baseLoopN*loops*N);
fprintf('Vect interp nearest (out boudns): %.4f ns (%.2f%%)\n',tm5,100*(tm1/tm5-1));

tmirt2D = tmirt2D*1e9/(baseLoopN*loops*N);
fprintf('tmirt2D from File Exchange: %.4f ns (%.2f%%)\n',tmirt2D,100*(tm1/tmirt2D-1));

if mustCompareMatlab
    tm6 = tm6*1e9/(baseLoopN*loops*N);
    fprintf('Matlab interp2 linear: %.4f ns (%.2f%%)\n',tm6,100*(tm1/tm6-1));
    tm7 = tm7*1e9/(baseLoopN*loops*N);
    fprintf('Matlab interp2 nearest: %.4f ns (%.2f%%)\n',tm7,100*(tm1/tm7-1));
end

普通版:

function [interpData] = Interp2D(data,X,Y)

[sizY, sizX] = size(data);

interpData =zeros(1,length(X),'like',X);
for item=1:length(X),

    valX=floor(X(item));
    valY=floor(Y(item));
    valYp1=valY+1;
    valXp1=valX+1;

    if (sizY < valYp1)||(sizX < valXp1)|| valX<=0 || valY<=0
        interpData(item)=NaN;

    else
        Inten00=data(valY,valX);
        Inten10=data(valY,valXp1);
        Inten01=data(valYp1,valX);
        Inten11=data(valYp1,valXp1);

        px=(X(item))-valX;
        py=(Y(item))-valY;

        interpData(item)=((1-px)*Inten00+px*Inten10)*(1-py)+((1-px)*Inten01+px*Inten11)*py;
    end
end

矢量化版本:

% Images borders are disconsidered due to simplicity
function [interpData,outBounds] = Interp2DVect(data,X,Y)

[sizeY, sizeX] = size(data);

fX = floor(X);
fY = floor(Y);

sizeOkFlag = ~((sizeY-1 < fY)|(sizeX-1 < fX)| fX <= 0 | fY <= 0);

sizeAllOk = min(sizeOkFlag) >= 1;
outBounds = ~sizeAllOk;
% If we have some invalid points, lets set them to NaN
if ~sizeAllOk
    interpData = nan(1,length(X),'like',X);

    % Prevent invalid data indexes
    fX = fX(sizeOkFlag);
    fY = fY(sizeOkFlag);

    X = X(sizeOkFlag);
    Y = Y(sizeOkFlag);
end

pX = X - fX;
pY = Y - fY;

% We need to get the linear indexes
% www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html
%ids00 = sub2ind(dataSize, fY, fX);
% A fast replacement for sub2ind
% http://tipstrickshowtos.blogspot.com.br/2010/02/fast-replacement-for-sub2ind.html

%idsYX
ids00 = fY + (fX-1).*sizeY;
ids01 = fY + (fX).*sizeY;
ids10 = fY+1 + (fX-1).*sizeY;
ids11 = fY+1 + fX.*sizeY;

if sizeAllOk
    interpData = ((1-pX).*data(ids00) + pX.*data(ids01)).*(1-pY) + ...
        ((1-pX).*data(ids10) + pX.*data(ids11)).*pY;
else
    interpData(sizeOkFlag) = ((1-pX).*data(ids00) + pX.*data(ids01)).*(1-pY) + ...
        ((1-pX).*data(ids10) + pX.*data(ids11)).*pY;
    if (size(X,1) > 1)
        interpData = interpData';
    end
end

最近的版本(仅供比较)

function [interpData] = Interp2DNearest(data,X,Y)

[sizeY, sizeX] = size(data);

X = round(X);
Y = round(Y);

sizeOkFlag = ~((sizeY-1 < Y)|(sizeX-1 < X)| X <= 0 | Y <= 0);
% Slower if use this:
%sizeAllOk = min(sizeOkFlag) >= 1;
% if sizeAllOk
%     ids = Y + (X-1).*sizeY;
%     interpData = data(ids);
% else
interpData = nan(1,length(X),'like',X);
X = X(sizeOkFlag);
Y = Y(sizeOkFlag);
ids = Y + (X-1).*sizeY;
interpData(sizeOkFlag) = data(ids);

0 个答案:

没有答案
相关问题