Matlab 矢量化多重高斯计算

Matlab 矢量化多重高斯计算,matlab,vectorization,gaussian,Matlab,Vectorization,Gaussian,我正在尝试将我的一些代码矢量化,这些代码在图像上添加了许多高斯分布的强度。我目前为每个高斯循环函数“gaussIt2D”,该函数为单个2D高斯向量化: windowSize=10; imSize=[512,512]; %pointsR is an nx2 array of coordinates [x1,y1;x2,y2;...;xn,yn] pointsR=rand(100,2)*511+1; %sigmaR is the standard deviation of the gaussian

我正在尝试将我的一些代码矢量化,这些代码在图像上添加了许多高斯分布的强度。我目前为每个高斯循环函数“gaussIt2D”,该函数为单个2D高斯向量化:

windowSize=10;
imSize=[512,512];
%pointsR is an nx2 array of coordinates [x1,y1;x2,y2;...;xn,yn]
pointsR=rand(100,2)*511+1;
%sigmaR is the standard deviation of the gaussian being created
sigmaR = 1;

outputImage=zeros(imSize);

for n=1:size(pointsR,1)
    rangeX = floor(pointsR(n,1)-windowSize):ceil(pointsR(n,1)+ windowSize);
    rangeX = rangeX(rangeX > 0 & rangeX <= imSize(1));
    rangeY = floor(pointsR(n,2)-windowSize):ceil(pointsR(n,2)+windowSize);
    rangeY = rangeY(rangeY > 0 & rangeY <= imSize(2));
    outputImage(rangeX,rangeY) = outputImage(rangeX,rangeY)+gaussIt2D(rangeX(1),rangeX(end),rangeY(1),rangeY(end),[sigmaR,pointsR(n,1),pointsR(n,2)]);
end

function [result] = gaussIt2D(xInit,xFinal,yInit,yFinal,sigma,xCenter,yCenter)
    %Returns gaussian intenisty values for the region defined by [xInit:xFinal,yInit:yFinal] using the gaussian properties sigma,centerX,centerY

    [gridX,gridY]=ndgrid(xInit:xFinal,yInit:yFinal);

    result=exp( -( (gridX-xCenter).^2 + (gridY-yCenter).^2 ) ./ (2*sigma.^2) );

end
然后我想按照以下形式创建网格和中心:

gridX = [1,2
         1,2
         2,3
         2,3
         3,4
         3,4]

xCenters = [1.2,1.2
            1.2,1.2
            2.8,2.8
            2.8,2.8
            3.1,3.1
            3.1,3.1]
然后,可以将其用于原始函数中使用的相同高斯方程中。然而,生成这些阵列让我很困惑。我现在得到的是:

function [result]=gaussIt2DVectorized(xInits,xFinals,yInits,yFinals,sigmas,xCenters,yCenters)
    %Incomplete
    %Returns gaussian intenisty values for the region defined by 
    %[xInit:xFinal,yInit:yFinal] using the values array:[sigma,centerX,centerY]
    [gridX,gridY]=arrayfun('ndgrid',xInits:xFinals,yInits:yFinals);
    xCenters = repelem(xCenters,numel(xInits(1):xFinals(1)), numel(yInits(1):yFinals(1)));
    yCenters = repelem(yCenters,numel(xInits(1):xFinals(1)), numel(yInits(1):yFinals(1)));

    result=exp( -( (gridX-xCenters).^2 + (gridY-yCenters).^2 ) ./ (2*sigmas^2) );

end
但这实际上并不起作用,而且我还预计在计算不同长度的范围(即xInit:xFinal)时会遇到困难

任何帮助、提示或替代方法都将受到欢迎


谢谢。

由于您无法确定网格的大小是否相同,因此最好将其存储在单元阵列中,而不是将其堆叠在矩阵中。使用cells数组,您仍然可以运行计算,而无需使用cellfun循环

例如:

function [result] = gaussIt2D_better(xInits,xFinals,yInits,yFinals,sigmas,xCenters,yCenters)
    [gridsX, gridsY] = arrayfun(@(x) ndgrid(xInits(x):xFinals(x), yInits(x):yFinals(x)),1:length(xInits),'UniformOutput',0);
    f=@(gridX, gridY, xCenter, yCenter, sigma) exp( -( (gridX-xCenter).^2 + (gridY-yCenter).^2 ) ./ (2*sigma.^2) );
    result=cellfun(f, gridsX, gridsY, num2cell(xCenters), num2cell(yCenters), num2cell(sigmas), 'UniformOutput',0);
end

请注意,在本例中,返回的值是一个与输入向量长度相同的单元格数组,每个数组对应一个结果。

在上面的示例代码中。当您编写sdWindow*sigmaR时,这与WindowsSize相同吗?是的,这是正确的,我在原始代码中将此示例中的sdWindow*sigmaR更改为WindowsSize以使其更清晰。很明显我漏掉了一个,我会修正的。奇怪的是,虽然这是一个矢量化的方法,但它实际上比原来的gaussIt2D函数执行的时间更长。100000分,执行时间延长3%。虽然不需要太长时间,但我还是有点惊讶,因为它不再循环了。这是意料之中的。一般来说,虽然使用arrayfun和cellfun具有代码更短/更整洁的优势,但它不如循环有效。这是解决的问题。如果您关注性能,我建议使用循环。在这种情况下,矢量化并不能节省您的时间。当然,如果您知道所有网格的大小都相同,那么您实际上也可以通过将它们存储在3D矩阵中来利用矢量化来提高性能。但我仍然怀疑,在这种情况下,性能会比循环好得多。
function [result] = gaussIt2D_better(xInits,xFinals,yInits,yFinals,sigmas,xCenters,yCenters)
    [gridsX, gridsY] = arrayfun(@(x) ndgrid(xInits(x):xFinals(x), yInits(x):yFinals(x)),1:length(xInits),'UniformOutput',0);
    f=@(gridX, gridY, xCenter, yCenter, sigma) exp( -( (gridX-xCenter).^2 + (gridY-yCenter).^2 ) ./ (2*sigma.^2) );
    result=cellfun(f, gridsX, gridsY, num2cell(xCenters), num2cell(yCenters), num2cell(sigmas), 'UniformOutput',0);
end