Fitting a 3D gaussian to a 3D matrix

77 views (last 30 days)
Yatish Yatish
Yatish Yatish on 8 Feb 2021
Edited: Matt J on 10 Feb 2021
I have a 3D matrix that I need to fit with a 3D gaussian function:
I need to get A, and all three σ's as the output after fitting.
I have tried to do it using Least Square fitting as:
[xx,yy,zz]=meshgrid(x,y,z);
Mat(:,:,:,1)=xx;Mat(:,:,:,2)=yy;Mat(:,:,:,3)=zz;
F=@(param,Mat) param(1)*exp(-(Mat(:,:,:,1).^2/(param(2))^2+Mat(:,:,:,2).^2/(param(3))^2+Mat(:,:,:,3).^2/(param(4))^2));
param0=[80000,10,10,10]; % initial parameters
param=lsqcurvefit(F,param0,Mat,D); % D is the 3D matrix that needs to be fit.
But, I get various errors. I don't think my approach is correct. Is there any other way?

Answers (2)

Are Mjaavatten
Are Mjaavatten on 8 Feb 2021
meshgrid arranges the xx and yy output matrices to fit the convention where the surface plots have x on the horizontal axis and y on the vertical, while you want to have x vary in the vertical direction in your matrices.
[yy,xx,zz]=meshgrid(y,x,z);
should fix the problem.
  5 Comments
Are Mjaavatten
Are Mjaavatten on 9 Feb 2021
I made a few minor changes to your code, so now it runs and converges, However, it seems that your Gaussian model does not give a very good fit to the data. The plot shows the D surface, together with the model results, for z = 10. These are typical for other values of z as well. The model results are the relatively flat surface, while the wavy surface is your D data.
D=load('data_25x17x17.mat');
D = D.D;
x=1:1:25;y=1:1:17;z=1:1:17;
[y1,x1,z1]=meshgrid(y,x,z);
Mat(:,:,:,1)=x1;Mat(:,:,:,2)=y1;Mat(:,:,:,3)=z1;
F=@(param,Mat) param(1)*exp(-(Mat(:,:,:,1).^2/(param(2))^2+Mat(:,:,:,2).^2/(param(3))^2+Mat(:,:,:,3).^2/(param(4))^2));
param0=[3e6,8,8,8];
param=lsqcurvefit(F,param0,Mat,D);
DD = F(param,Mat); % Values calculated from converged parameters
figure;
surf(y,x,D(:,:,10));hold on;surf(y,x,DD(:,:,10));xlabel y;ylabel x;title('z = 10 plane')
You may also try other slices, e.g.:
k=25;figure;
surf(y,z,permute(D(k,:,:),[2,3,1]));hold on;surf(y,z,permute(DD(k,:,:),[2,3,1]));
xlabel z;ylabel y;title('x = 25 plane')
It is obvious that the Gaussian model is unable to follow the wavy nature of the data. Maybe you are able to find a better model from you knowledge of the process that produced D.
Good luck.
Yatish Yatish
Yatish Yatish on 10 Feb 2021
The problem was with the matrix that I had attached. It works perfectly for the right 3D data. Thanks a lot for your help! :-)

Sign in to comment.


Matt J
Matt J on 10 Feb 2021
Edited: Matt J on 10 Feb 2021
You can also use gaussfitn,
[xx,yy,zz]=meshgrid(x,y,z);
lbCell={0,[],[], zeros(3)};
ubCell={0,[],[], +diag(inf(1,3))}
param0={0,80000,[0,0,0], (1/10)*eye(3) };
param = gaussfitn([xx(:),yy(:),zz(:)], D(:),param0, lbCell, ubCell)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!