public FitStarTest(string name, string imagePath, GaussianFitOptions options) { this.Options = star => options; this.Name = star => $"{name} - {options.Desc(star)}"; LoadImage(imagePath); }
/// <summary> /// Find a sigma value for the Gaussian Point Distribution Function that produces less error /// </summary> /// <param name="image"></param> /// <param name="star"></param> /// <param name="starReference"></param> /// <param name="options"></param> static GaussianFit FindGaussianPSF(ushort[] image, int iWidth, int iHeight, StarInfo star, int starReference, GaussianFitOptions options) { var peak = star.Peak; var width = GaussianSigmaFromSample(star.Peak, 2, image[(star.Y + 1) * iWidth + star.X + 1]); var widthStep = 1.0; var iterations = 0; // happens when the star is saturated if (double.IsInfinity(width) || width == 0) { width = 5.0; } var x1 = star.X - options.Radius; var x2 = star.X + options.Radius; var y1 = star.Y - options.Radius; var y2 = star.Y + options.Radius; if (x1 < 0 || y1 < 0 || x2 > iWidth || y2 > iHeight) { return(new GaussianFit { Result = GaussianFitResult.Clipped }); } for (iterations = 0; iterations < options.MaxIterations && Math.Abs(widthStep) > options.MinimumChangeThreshold; iterations++) { var direction = GradientTowardsMinimalErrorForGaussian(peak, width, image, iWidth, iHeight, star, options); widthStep = options.IterationStepSize * direction[0]; width = width + widthStep; if (width < 0) { width = 1.0; } } return(new GaussianFit { Width = width, Peak = peak, Iterations = iterations, StarReference = starReference, Result = iterations == options.MaxIterations ? GaussianFitResult.IterationsMaxed : GaussianFitResult.StepMinimumReached }); }
/// <summary> /// /// </summary> /// <param name="image"></param> /// <param name="iWidth"></param> /// <param name="iHeight"></param> /// <param name="star"></param> /// <param name="starReference"></param> /// <param name="options"></param> /// <returns></returns> public static GaussianFit FindStarGaussianPSF(ushort[] image, int iWidth, int iHeight, StarInfo star, int starReference, GaussianFitOptions options) { return(FindGaussianPSF(image, iWidth, iHeight, star, starReference, options)); }
/// <summary> /// /// </summary> /// <param name="image"></param> /// <param name="stars"></param> /// <param name="options"></param> /// <returns></returns> public static List <GaussianFit> FindStarGaussianPSF(ushort[] image, int iWidth, int iHeight, List <StarInfo> stars, GaussianFitOptions options) { var results = new List <GaussianFit>(); foreach (var star in stars) { results.Add(FindStarGaussianPSF(image, iWidth, iHeight, star, stars.IndexOf(star), options)); } return(results); }
public static double GaussianFitError(double peak, double width, ushort[] pixels, int iWidth, int iHeight, StarInfo star, GaussianFitOptions options) { var samples = (options.Radius * 2.0) * (options.Radius * 2.0) - 1; var x1 = star.X - options.Radius; var x2 = star.X + options.Radius; var y1 = star.Y - options.Radius; var y2 = star.Y + options.Radius; var error = 0.0; for (var y = y1; y < y2; y++) { for (var x = x1; x < x2; x++) { if (x == star.X && y == star.Y) { continue; } var distanceSquared = (x - star.X) * (x - star.X) + (y - star.Y) * (y - star.Y); if (distanceSquared <= options.Radius * 2) { var prediction = GaussianAmplitudeFromPSF(distanceSquared, peak, width); error += (prediction - pixels[y * iWidth + x]) * (prediction - pixels[y * iWidth + x]); } } } return(error); }
public static double[] GradientTowardsMinimalErrorForGaussian(double peak, double sigma, ushort[] pixels, int iWidth, int iHeight, StarInfo star, GaussianFitOptions options) { var vec = new double[1]; var samples = (options.Radius * 2.0) * (options.Radius * 2.0) - 1; var x1 = star.X - options.Radius; var x2 = star.X + options.Radius; var y1 = star.Y - options.Radius; var y2 = star.Y + options.Radius; for (var y = y1; y < y2; y++) { for (var x = x1; x < x2; x++) { if (x == star.X && y == star.Y) { continue; } var distanceSquared = (x - star.X) * (x - star.X) + (y - star.Y) * (y - star.Y); if (distanceSquared <= options.Radius * 2) { var sample = pixels[y * iWidth + x]; var sigmaSample = GaussianSigmaFromSample(peak, distanceSquared, sample); var sChange = GaussianSigmaErrorSlopeFunction(distanceSquared, peak, sigmaSample, sigma); vec[0] += (-1 * sChange); samples++; } } } vec[0] /= samples; return(vec); }