I want to draw a gaussian in two dimension centered in the middle of the matrix with matlab. Right now I am doing with
for i = 1:size2
for j = 1:size2
gauss(i,j)=A*exp(-1/(sigma^2)*((i-round(size2/2))^2 (j-round(size2/2))^2)); %gaussiana
end
end
but it can be extremely slow.
In matlab I have not found any function, what is the fastest way to do it? Is a mex file a valuable option?
CodePudding user response:
Vectorizing the gaussian computation using meshgrid is relatively trivial.
There is even an Octave implementation in Wikipedia.
The implementation is:
[X, Y] = meshgrid(1:size2, 1:size2);
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 (X-size2/2).^2));
Note: I replaced the round(size2/2)
with size2/2
because the rounding is not part of the formula.
Trick for converting 1D gaussian into 2D gaussian:
For making the computation a little bit faster we can create 1D gaussian, and compute the 2D gaussian out of it:
x = 1:size2;
G1 = sqrt(A)*exp(-1/(sigma^2)*(x-size2/2).^2); % Create 1D gaussian
G2 = G1'*G1; % Compute the 2D gaussian out of 1D gaussian.
Testing:
size2 = 101;
A = 10;
sigma = 50;
gauss = zeros(size2);
for y = 1:size2
for x = 1:size2
gauss(y,x)=A*exp(-1/(sigma^2)*((y-size2/2)^2 (x-size2/2)^2)); %gaussiana
end
end
[X, Y] = meshgrid(1:size2, 1:size2);
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 (X-size2/2).^2));
disp(['sum abs diff (G, gauss) = ' num2str(sum(abs(G(:) - gauss(:))))])
x = 1:size2;
G1 = sqrt(A)*exp(-1/(sigma^2)*(x-size2/2).^2);
G2 = G1'*G1;
disp(['sum abs diff (G1, G2) = ' num2str(sum(abs(G2(:) - G(:))))])
Output:
sum abs diff (G, gauss) = 0
sum abs diff (G1, G2) = 7.1436e-12
Update:
According to Cris comment "meshgrid is no longer needed".
Since MATLAB r2016b we can use the following code:
X = 1:size2;
Y = X';
G = A*exp(-1/(sigma^2)*((Y-size2/2).^2 (X-size2/2).^2));
The implementation relays on a feature named "implicit singleton expansion" or Implicit Expansion.