I am looking for 2-D fitting code for LabVIEW. I can make use of code for an arbitrary function, but I specifically need to fit a CCD image to a general 2-D Gaussian profile. The image spot is not circular and the major axis can be at an arbitrary angle with respect to the image x and y axes. If you have any such code or pointers to some or to how to develop it myself (preferably without becoming a Levenberg-Marquardt expert), I'd be forever grateful.
OK, this seems easy enough starting with one of my existing examples. Basically, you need a model with 6 parameters:
I did a quick modification of my old model and it seems to work. Do you have a typical example data set so I can test?
OK, here's a quick attempt (LabVIEW 2009), using the above mentioned set of six parameters.
There is some ambiguity, because the two principal width are interchangeable and would correspond to a 90 degree rotation. I added some cleanup code that sorts the widths and align the angle with the larger width.
Currently, the reference definition for the rotation is somewhat arbitrary, and the principal Gaussian widths are defined as 2*sigma for code simplicity. Statisticians like widths in terms of standard deviations, while spectroscopists prefer widths defined as width at half height. (If you also need an offset, that would be easy to add later, resulting in seven parameters). The current model VI can be easily adapted for all this with minor changes. I don't know what you want!
Note that the current calculation is a bit slow. I have parallelized the main model loop to speed things up a bit on multicore hardware. I am sure the speed can be significantly improved.
Still, this should get you started. From my limited testing, it seems pretty robust and converges with a wide range of simulated data. Of course if the two principal width are very similar, the angle will have a large error. If the widths are identical, the angle will probably be random.
I streamlined the model code a little bit causing a 3-4x increase in fitting speed for the default data. There is probably still quite a bit of slack left.
(Of course the default image size currently is ~300x250, meaning that the y-size is ~75k. The speed could be dramatically improved if we could just select the area of interest instead of fitting 5% important points and 95% of irrelevant background data. )
Thanks for this great example. I am trying to do a 2D nonlinear curve fit to some data from a camera, and I am looking at your code and the NI example "Fit gaussian surface with offset". I am having a hard time understanding how the curve fitting inputs "X", "Y", and "data" are used here. It seems quite different from how I would set up a 1D fit, and I don't understand the format of what is going into these inputs. Some explanation or some example code that just takes some already existing 2D array and converts it to the required input would be very helpful. Specifically I have an image that I convert to an array via ImageToArray and want to put this in a format where I can enter it into your program.
I am having a hard time understanding how the curve fitting inputs "X", "Y", and "data" are used here.
Well, I don't even use the x input. X is not in any of the fitting algorithms, only in the model and is an optional input. As you will see, our model has no need for x.
All the model needs to be able to do is generate a set of simulated values based on the parameters that correspond to an equally arranged set of datapoints from your image. These are the "Y' values. You have a 2D array of data, but the fitting VIs require a 1D array. Using reshape array with a size equal to the product of the image dimension will arrange the same data as a 1D array. Similarly, the model calculates a matching image, then also rehapes it to a 1D array.
The fitting VI will compare the two 1D arrays (data vs model) and adjust the parameters until the two 1D arrays agree as much as possible.
In order to calculate the model, the 2D dimension of the image needs to be known. The data variant input can be used to inform the model about any other information that are needed. In this particluar case we use it to relay information about the image size from the toplevel to the model. A variant is a generic container that can hold any kind of data (a cluster of two I32 scalars in this particular case). Of course the model needs to be able to convert the variant back to the original cluster, so for that it needs to know what the datatype is. Thus we wire a cluster with the correct structure (values are irrelevant) to the type input of "variant to data". Like magic, the output is again a cluster of two I32 values that we now can tap for the 2D model computations.
The model is defined via a strictly typed static VI reference. You can click that reference to edit the model VI. We use the same model also via "call by reference node" in order to calculate the image based on the initial guess parameters.
Specifically I have an image that I convert to an array via ImageToArray and want to put this in a format where I can enter it into your program.
As I said, all you need to do is reshape to a 1D array with a size equivalent to the number of pixels in the image.
What is your LabVIEW version?
Thank you very much for your great example! I adapted it so that I can fit images from a camera.
You write here that you have improved the model for better performance.
Could I maybe get this improved version? That would be great!
Thank you very much for everything!