public ImagePixel GetPSFFit(int x, int y, int fitMatrixSize, PSFFittingMethod method, out PSFFit psfFit) { psfFit = new PSFFit(x, y); psfFit.FittingMethod = method; int dimention = 2 * (fitMatrixSize / 2) + 1; uint[,] data = new uint[dimention, dimention]; int halfWidth = dimention / 2; #if ASTROMETRY_DEBUG Trace.Assert(2 * halfWidth + 1 == dimention); #endif PixelAreaOperation2(x, y, halfWidth, delegate(int x1, int y1, uint z) { data[x1 - x + halfWidth, y1 - y + halfWidth] = z; }); psfFit.Fit(data); if (psfFit.IsSolved) { ImagePixel psfPixel = new ImagePixel((int)Math.Min(m_Pixelmap.MaxSignalValue, (uint)Math.Round(psfFit.IMax)), psfFit.XCenter, psfFit.YCenter); psfPixel.SignalNoise = psfFit.Certainty; return(psfPixel); } return(null); }
public static void PSFPhotometry(FitInfo astrometricFit, List <IStar> catalogueStars, AstroImage currentAstroImage, Rectangle osdRectToExclude, Rectangle rectToInclude, bool limitByInclusion) { StringBuilder output = new StringBuilder(); foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs) { uint[,] data = currentAstroImage.GetMeasurableAreaPixels( (int)Math.Round(pair.x), (int)Math.Round(pair.y), 9); if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) { continue; } if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) { continue; } PSFFit gaussian = new PSFFit((int)Math.Round(pair.x), (int)Math.Round(pair.y)); gaussian.Fit(data); if (gaussian.IsSolved) { IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo); if (star != null && !double.IsNaN(star.MagR)) { output.AppendLine(string.Format("{0}, {1}, {2}, {3}, {4}", pair.StarNo, star.MagR, gaussian.R0, gaussian.IMax, gaussian.I0)); } } } File.WriteAllText(@"C:\PSF_Photo.csv", output.ToString()); }
private void HandleHotPixelDefinitionClick(MouseEventArgs e) { var pixels = frmFullSizePreview.CurrFrame.GetPixelsArea(e.X, e.Y, 35); PSFFit fit = new PSFFit(e.X, e.Y); fit.Fit(pixels); if (fit.IsSolved && fit.Certainty > 1 && fit.IMax > frmFullSizePreview.CurrFrame.MaxSignalValue / 2.0) { var sample = frmFullSizePreview.CurrFrame.GetPixelsArea((int)Math.Round(fit.XCenter), (int)Math.Round(fit.YCenter), 7); HotPixelCorrector.RegisterHotPixelSample(sample, frmFullSizePreview.CurrFrame.Pixelmap.MaxSignalValue); m_ExpectHotPixelDefinition = false; FrameAdjustmentsPreview.Instance.ExpectHotPixelClick(false, true); pnlHotPixelControls.Enabled = true; HotPixelCorrector.LocateHotPixels(frmFullSizePreview.CurrFrame, Math.Max(0, tbDepth.Value)); FrameAdjustmentsPreview.Instance.Update(); } else { MessageBox.Show( ParentForm, "The location you clicked doesn't appear to contain a hot pixel. Please try again.\r\n\r\nIf necessary adjust the brightness and contrast of the image first.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void CalculateSingleObjectPSF() { m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_OriginalCenter.X, m_OriginalCenter.Y, 35); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_OriginalCenter.X, m_OriginalCenter.Y, 35); var psfFit = new PSFFit(m_OriginalCenter.X, m_OriginalCenter.Y); psfFit.Fit(m_ProcessingPixels); if (psfFit.IsSolved) { m_Gaussian = psfFit; m_FWHM = (float)m_Gaussian.FWHM; m_X0 = m_Gaussian.X0_Matrix; m_Y0 = m_Gaussian.Y0_Matrix; m_X0Center = (float)psfFit.XCenter; m_Y0Center = (float)psfFit.YCenter; if (m_Aperture == null) { if (TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM) { m_Aperture = (float)(m_Gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture); } else { m_Aperture = (float)(TangraConfig.Settings.Photometry.DefaultSignalAperture); } } else if ( TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM && m_Aperture < (float)(psfFit.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture)) { // When the default aperture size is in FWHM we always use the largest aperture so far m_Aperture = (float)(psfFit.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture); } nudAperture1.SetNUDValue(m_Aperture.Value); m_Aperture1 = null; m_Aperture2 = null; m_DoubleGaussian = null; } }
public double GetIntencity(ImagePixel center, out bool isSaturated) { isSaturated = false; uint[,] data = m_CurrentAstroImage.GetMeasurableAreaPixels(center.X, center.Y, 17); PSFFit fit = new PSFFit(center.X, center.Y); fit.Fit(data, PSF_FIT_AREA_SIZE); if (!fit.IsSolved) { return(double.NaN); } int areaSize = m_Filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19; int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); data = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize); uint[,] backgroundPixels = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35); m_Measurer.MeasureObject( center, data, backgroundPixels, m_CurrentAstroImage.Pixelmap.BitPixCamera, m_Filter, m_PhotometryReductionMethod, m_PsfQuadrature, m_PsfFittingMethod, m_MeasurementAperture ?? (float)Aperture(fit.FWHM), fit.FWHM, (float)m_EmpericalFWHM, new FakeIMeasuredObject(fit), null, null, false); isSaturated = m_Measurer.HasSaturatedPixels; return(m_Measurer.TotalReading - m_Measurer.TotalBackground); }
private void PlotAperturePreview() { if (m_MeasurementContext.ObjectToMeasure != null) { float x0 = m_MeasurementContext.ObjectToMeasure.X0; float y0 = m_MeasurementContext.ObjectToMeasure.Y0; // x0 and y0 were measured on the first frame but we may have moved to a different frame due to positioning to the first frame of integration period // so we determine the position of the object on the current frame in order to draw the aperture nicely centered var fit = new PSFFit((int)x0, (int)y0); fit.Fit(m_VideoController.GetCurrentAstroImage(false).GetMeasurableAreaPixels((int)x0, (int)y0)); if (fit.IsSolved) { x0 = (float)fit.XCenter; y0 = (float)fit.YCenter; } byte[,] bmpPixels = m_VideoController.GetCurrentAstroImage(false).GetMeasurableAreaDisplayBitmapPixels((int)x0, (int)y0, 85); Bitmap bmp = Pixelmap.ConstructBitmapFromBitmapPixels(bmpPixels, 85, 85); using (Graphics g = Graphics.FromImage(pboxAperturePreview.Image)) { g.DrawImage(bmp, 0, 0); float xCenter = (x0 - (int)x0) + 42; float yCenter = (y0 - (int)y0) + 42; float radius = (float)nudAperture.Value; g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); radius = (float)(nudAperture.Value + nudGap.Value); g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); radius = (float)(nudAperture.Value + nudGap.Value + nudAnnulus.Value); g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); g.Save(); } pboxAperturePreview.Invalidate(); } }
private void frmRunMultiFrameSpectroscopy_Load(object sender, EventArgs e) { IImagePixel starCenter = m_VideoOperation.SelectedStar; m_SpectraReader = new SpectraReader(m_AstroImage, m_VideoOperation.SelectedStarBestAngle, 1); m_Spectra = m_SpectraReader.ReadSpectra((float)starCenter.XDouble, (float)starCenter.YDouble, (int)nudAreaWing.Value, (int)nudBackgroundWing.Value, (int)nudBackgroundGap.Value, PixelCombineMethod.Average); m_Mapper = new RotationMapper(m_AstroImage.Width, m_AstroImage.Height, m_VideoOperation.SelectedStarBestAngle); uint[,] pixels = m_AstroImage.GetMeasurableAreaPixels(starCenter.X, starCenter.Y, 35); m_ZeroOrderPsf = new PSFFit(starCenter.X, starCenter.Y); m_ZeroOrderPsf.Fit(pixels); m_Spectra.ZeroOrderFWHM = (float)m_ZeroOrderPsf.FWHM; PlotMeasurementAreas(); PlotAlignTarget(); nudDivisor.SetNUDValue((decimal)m_AstroImage.Pixelmap.MaxSignalValue); nudMultiplier.Value = 1024; }
private void TrackSingleStar(int frameNo, IAstroImage astroImage) { TrackedStar.NewFrame(); float expectedX; float expectedY; GetExpectedXY(out expectedX, out expectedY); uint[,] pixels = astroImage.GetPixelsArea((int)expectedX, (int)expectedY, FIT_AREA); // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int)expectedX, (int)expectedY); gaussian.Fit(pixels, FIT_AREA); IImagePixel firstCenter = new ImagePixel((int)gaussian.XCenter, (int)gaussian.YCenter); pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, FIT_AREA); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, TrackedStar.PsfFitMatrixSize); if (gaussian.IsSolved) { TrackedStar.PSFFit = gaussian; TrackedStar.ThisFrameX = (float)gaussian.XCenter; TrackedStar.ThisFrameY = (float)gaussian.YCenter; TrackedStar.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty; TrackedStar.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); } else { TrackedStar.ThisFrameX = expectedX; TrackedStar.ThisFrameY = expectedY; TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve second PSF", m_FrameNo, TrackedStar.TargetNo)); TrackedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } }
public void Test12BitData() { string DATA_SER = "EQAAABEAAABqAQAAkAEAABgBAACuAQAAnQEAAMgBAABfAQAAbQEAALYBAAAJAQAAcAEAACMBAAA5AQAAWAEAAFMBAADVAQAAkQEAAFABAAAbAQAAYgEAAFwBAABTAQAAMgEAAH8BAABSAQAA1AEAAGoBAAC6AQAAnAEAAN4BAACKAQAAswEAAKUBAABhAQAAvwEAAE0BAABLAQAA9QAAAIoBAABWAQAAkwEAAOwBAACCAQAAxQEAAJYBAAD1AQAApgEAAPcBAACuAQAAawEAAEgBAAAZAQAAXAEAAF4BAAD0AQAA1QEAAH8BAADbAQAARwEAALkBAAAhAgAASgIAAMMBAAANAgAApgEAAGgBAAAWAQAADQEAAB4BAABiAQAAagEAABsBAABYAQAAuQEAAPgBAACgAgAAdgIAAMsCAAAKAwAABQMAALkCAAD9AQAAdgEAAKABAABoAQAAdwEAAD4BAABqAQAAaAEAAKUBAAC2AQAApgEAAFgDAACAAwAA6gMAALgEAACbBAAAMwMAAMMCAAAEAgAAoAEAAJYBAAAyAQAAWQEAADkBAABbAQAAdgEAAHwBAACpAQAAewIAACcEAABiBQAATgYAAL8FAABIBAAAkgMAALkBAAClAQAA2wEAANgAAAB8AQAAfAEAAO8AAABEAQAAjgEAAPcBAABEAgAASAMAAE0FAABLBgAADwYAACoEAAArAwAAugEAAEsBAACfAQAAfwEAABgBAABSAQAALQEAABABAADVAQAAWwEAANIBAACOAgAA8AMAANIFAAAuBQAAUwMAACQCAADaAQAAogEAAKMBAABFAQAA/gAAALMBAABNAQAAAQEAAG4BAAAyAQAAcwEAAE8CAAC8AgAA0wMAANoDAADDAgAAGgIAAOUBAAC/AQAAUwEAADUBAACsAQAADwEAACEBAADxAAAAYgEAABABAACrAQAApgEAANcBAAD6AQAAwwIAABACAABtAQAAEAEAAF4BAAB0AQAAWAEAAA8BAABkAQAAzwAAAD4BAABuAQAABgEAAOsBAACjAQAA9wAAAJEBAABiAQAAOwEAAJcBAADxAAAAXwEAAIsBAACvAQAAQQEAAGoBAABFAQAAeQEAALMBAAApAQAAbgEAAFYBAABtAQAA5gEAAJEBAAAkAQAA3gAAADMBAACzAQAAEwEAABkBAABLAQAAQQEAAE0BAACvAAAAzAAAACkBAABeAQAADwEAAFMBAACIAQAAUgEAANIBAACjAQAAEwEAADgBAAD+AAAAMwEAAEEBAAAqAQAAPAEAAF8BAABnAQAAdwEAAGoBAAAAAQAAOAEAAKUBAAAMAQAArAAAAAEBAABlAQAA4wAAADMBAACiAQAAHgEAACkBAAAqAQAAGAEAACcBAAADAQAAlwEAAEIBAAA8AQAA3gAAADMBAACoAQAAegEAAGEBAAApAQAAlgEAAHwBAABZAQAAIQEAAGIBAADaAAAAPgEAADIBAAA/AQAAZwEAAIoBAAA5AQAAywAAAGoBAACBAQAAIQEAAEgBAAA8AQAA"; uint[,] data = DATA_SER.FromBase64String(); int width = data.GetLength(0); int height = data.GetLength(1); int MAX = 255; uint[,] data_8bit = new uint[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { data_8bit[x, y] = (uint)Math.Max(0, Math.Min(MAX, Math.Round(data[x, y] * MAX * 1.0f / 4095))); } } PSFFit.DataRange = PSFFittingDataRange.DataRange12Bit; var psfFit8bit = new PSFFit(100, 100); psfFit8bit.Fit(data_8bit); Console.WriteLine(string.Format("8Bit: ({0}, {1})", psfFit8bit.XCenter, psfFit8bit.YCenter)); PSFFit.DataRange = PSFFittingDataRange.DataRange12Bit; var psfFit = new PSFFit(100, 100); psfFit.Fit(data); Console.WriteLine(string.Format("12Bit: ({0}, {1})", psfFit.XCenter, psfFit.YCenter)); Assert.AreEqual(psfFit8bit.XCenter, psfFit.XCenter, 0.01); Assert.AreEqual(psfFit8bit.YCenter, psfFit.YCenter, 0.01); }
internal static PSFFit GetPSFFitForPeakPixel( uint[,] data, PotentialStarStruct starToTest, float aboveNoiseLevelRequired, double minFWHM, double maxFWHM) { int STAR_MATRIX_FIT = TangraConfig.Settings.Special.StarFinderFitArea; double MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER = TangraConfig.Settings.Special.StarFinderMinDistanceOfPeakPixelFromCenter; PSFFit fit = new PSFFit(starToTest.X, starToTest.Y); int fitMatrix = (int)Math.Min(data.GetLength(0), STAR_MATRIX_FIT + 2); // Get a matrix with 1 pixel larger each way and set the border pixels to zero fit.Fit(data, fitMatrix, starToTest.X, starToTest.Y, true); if (fit.IsSolved) { double distanceFromCenter = ImagePixel.ComputeDistance(fit.X0_Matrix, fitMatrix / 2, fit.Y0_Matrix, fitMatrix / 2); if (fit.Certainty > 0 && fit.FWHM >= minFWHM && fit.FWHM <= maxFWHM && distanceFromCenter < MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER && fit.IMax > aboveNoiseLevelRequired) { //not good for lost tracking allow higher FWHM // This object passes all tests to be furhter considered as a star return(fit); } } return(null); }
protected virtual void TrackSingleStar(int frameNo, IAstroImage astroImage) { OccultedStar.NewFrame(); m_NotCertain = false; float expectedX; float expectedY; GetExpectedXY(out expectedX, out expectedY); uint[,] pixels = astroImage.GetPixelsArea((int)expectedX, (int)expectedY, 17); // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int)expectedX, (int)expectedY); gaussian.Fit(pixels, 17); IImagePixel firstCenter = gaussian.IsSolved ? new ImagePixel((int)gaussian.XCenter, (int)gaussian.YCenter) : astroImage.GetCentroid((int)expectedX, (int)expectedY, 17, m_MedianValue); if (firstCenter != null) { // Do a second fit pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, 17); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, OccultedStar.PsfFitMatrixSize); if (gaussian.IsSolved) { double signal = gaussian.IMax - gaussian.I0; if (signal < 0) { signal = 0; } double brightnessFluctoation = signal > OccultedStar.RefinedOrLastSignalLevel ? signal / OccultedStar.RefinedOrLastSignalLevel : OccultedStar.RefinedOrLastSignalLevel / signal; //double brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; double fluckDiff = Math.Abs(brightnessFluctoation) / m_AllowedSignalFluctoation; if (fluckDiff < 1 || (LightCurveReductionContext.Instance.HighFlickeringOrLargeStars && !LightCurveReductionContext.Instance.FullDisappearance && !LightCurveReductionContext.Instance.IsDriftThrough)) { OccultedStar.PSFFit = gaussian; OccultedStar.ThisFrameX = (float)gaussian.XCenter; OccultedStar.ThisFrameY = (float)gaussian.YCenter; OccultedStar.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; OccultedStar.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); } else { m_NotCertain = true; // This is the Occulted Star, so no brightness fluctoations can be used as excuses! FitObjectInLimitedArea(OccultedStar, astroImage, expectedX, expectedY); OccultedStar.SetIsLocated( LightCurveReductionContext.Instance.FullDisappearance || OccultedStar.PSFFit != null, LightCurveReductionContext.Instance.FullDisappearance || OccultedStar.PSFFit != null ? NotMeasuredReasons.TrackedSuccessfully : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar); m_NotCertain = !OccultedStar.IsLocated; if (m_PreviousPositions.Count > 1 && LightCurveReductionContext.Instance.FullDisappearance && LightCurveReductionContext.Instance.IsDriftThrough) { var prevSignals = m_PreviousPositions.Select(x => x.Brightness).ToList(); var prevSignalMedian = prevSignals.Median(); var prevSignalSigma = Math.Sqrt(prevSignals.Sum(x => (x - prevSignalMedian) * (x - prevSignalMedian)) / (m_PreviousPositions.Count - 1)); var bigBrightnessVariation = (Math.Abs(signal - prevSignalMedian) > prevSignalSigma); m_NotCertain = m_NotCertain || bigBrightnessVariation; } if (m_NotCertain) { OccultedStar.ThisFrameX = expectedX; OccultedStar.ThisFrameY = expectedY; OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; } } } else { OccultedStar.ThisFrameX = expectedX; OccultedStar.ThisFrameY = expectedY; OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve second PSF", m_FrameNo, OccultedStar.TargetNo)); OccultedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } } else { OccultedStar.ThisFrameX = expectedX; OccultedStar.ThisFrameY = expectedY; OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve first PSF", m_FrameNo, OccultedStar.TargetNo)); OccultedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } }
private void InitStarAmplitudeModelling(ModelConfig modelConfig, float accuracy, int bitPix, uint maxSignalValue) { if (m_MagnitudeToPeakDict != null) { return; } m_MagnitudeToPeakDict = new Dictionary <double, int>(); m_MagnitudeToPeakMags = new List <double>(); m_MagnitudeToPeakPeaks = new List <int>(); var mea = new MeasurementsHelper( bitPix, TangraConfig.BackgroundMethod.BackgroundMedian, TangraConfig.Settings.Photometry.SubPixelSquareSize, TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue)); float apertureSize = APERTURE; float annulusInnerRadius = (GAP + APERTURE) / APERTURE; int annulusMinPixels = (int)(Math.PI * (Math.Pow(ANNULUS + GAP + APERTURE, 2) - Math.Pow(GAP + APERTURE, 2))); mea.SetCoreProperties(annulusInnerRadius, annulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */); int peak = (int)(maxSignalValue - (modelConfig.NoiseMean + modelConfig.DarkFrameMean) * modelConfig.Integration); int TOTAL_STEPS = 100; double step = Math.Log10(peak) / TOTAL_STEPS; double zeroMag = double.NaN; for (int ii = 0; ii < TOTAL_STEPS; ii++) { int amplitude = (int)Math.Round(Math.Pow(10, Math.Log10(peak) - ii * step)); Pixelmap pixmap = new Pixelmap(64, 64, bitPix, new uint[64 * 64], null, null); VideoModelUtils.GenerateStar(pixmap, 32, 32, (float)modelConfig.FWHM, amplitude, 0 /* Gaussian */); PSFFit fit = new PSFFit(32, 32); AstroImage img = new AstroImage(pixmap); uint[,] data = img.GetMeasurableAreaPixels(32, 32, 17); uint[,] backgroundPixels = img.GetMeasurableAreaPixels(32, 32, 35); fit.Fit(data); var result = mea.MeasureObject(new ImagePixel(32, 32), data, backgroundPixels, pixmap.BitPixCamera, TangraConfig.PreProcessingFilter.NoFilter, TangraConfig.PhotometryReductionMethod.AperturePhotometry, TangraConfig.PsfQuadrature.NumericalInAperture, TangraConfig.PsfFittingMethod.DirectNonLinearFit, apertureSize, modelConfig.FWHM, (float)modelConfig.FWHM, new FakeIMeasuredObject(fit), null, null, false); if (result == NotMeasuredReasons.TrackedSuccessfully && !mea.HasSaturatedPixels) { // Add value for fitting double measurement = mea.TotalReading - mea.TotalBackground; if (double.IsNaN(zeroMag)) { zeroMag = modelConfig.BrighestUnsaturatedStarMag + 2.5 * Math.Log10(measurement); } double magnitude = -2.5 * Math.Log10(measurement) + zeroMag; m_MagnitudeToPeakDict[magnitude] = amplitude; m_MagnitudeToPeakMags.Add(magnitude); m_MagnitudeToPeakPeaks.Add(amplitude); } } }
public static List <PSFFit> GetStarsInArea( ref uint[,] data, int bpp, uint maxSignalValue, TangraConfig.PreProcessingFilter filter, List <PotentialStarStruct> allPotentialStars, List <PSFFit> allFoundStars, uint aboveNoiseLevelRequired, double minDistanceInPixels, bool useLPDFilter, Rectangle excludeArea, FilterPotentialStars filterCallback) { double minFWHM = TangraConfig.Settings.Special.StarFinderMinFWHM; double maxFWHM = TangraConfig.Settings.Special.StarFinderMaxFWHM; int STAR_MATRIX_FIT = TangraConfig.Settings.Special.StarFinderFitArea; Stopwatch sw = new Stopwatch(); sw.Start(); uint[,] lpdData; List <PotentialStarStruct> potentialStars = GetPeakPixelsInArea( data, out lpdData, bpp, maxSignalValue, aboveNoiseLevelRequired, minDistanceInPixels, useLPDFilter, excludeArea); if (filterCallback != null) { filterCallback(potentialStars); } sw.Stop(); Trace.WriteLine(string.Format("GetPeakPixelsInArea: {0} sec", sw.Elapsed.TotalSeconds.ToString("0.00"))); if (potentialStars.Count > 3) { // Only include the 3 brightest stars. The other ones cannot be stars potentialStars.Sort((x, y) => y.Z.CompareTo(x.Z)); potentialStars = potentialStars.Take(3).ToList(); } // Debugging purposes if (allPotentialStars != null) { allPotentialStars.AddRange(potentialStars); } uint[,] lpData = data; List <PSFFit> foundStars = new List <PSFFit>(); double MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER = TangraConfig.Settings.Special.StarFinderMinDistanceOfPeakPixelFromCenter; sw.Reset(); sw.Start(); foreach (PotentialStarStruct starToTest in potentialStars) { PSFFit fit = new PSFFit(starToTest.X, starToTest.Y); int fitMatrix = (int)Math.Min(data.GetLength(0), STAR_MATRIX_FIT + 2); // Get a matrix with 1 pixel larger each way and set the border pixels to zero fit.Fit(lpData, fitMatrix, starToTest.X, starToTest.Y, true); if (fit.IsSolved) { double distanceFromCenter = ImagePixel.ComputeDistance(fit.X0_Matrix, fitMatrix / 2, fit.Y0_Matrix, fitMatrix / 2); if (fit.Certainty > 0 && fit.FWHM >= minFWHM && fit.FWHM <= maxFWHM && distanceFromCenter < MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER && fit.IMax > aboveNoiseLevelRequired) { // This object passes all tests to be furhter considered as a star foundStars.Add(fit); } } if (allFoundStars != null) { allFoundStars.Add(fit); } } foundStars.Sort((f1, f2) => f1.IMax.CompareTo(f2.IMax)); PSFFit[] testStars = foundStars.ToArray(); for (int i = 0; i < testStars.Length; i++) { PSFFit fainterStar = testStars[i]; for (int j = i + 1; j < testStars.Length; j++) { PSFFit brighterStar = testStars[j]; if (fainterStar.UniqueId == brighterStar.UniqueId) { continue; } // If a the max of a fainter star is inside the fit of a brighter star // then see if it is simply not a point of the other star double dist = Math.Sqrt((fainterStar.XCenter - brighterStar.XCenter) * (fainterStar.XCenter - brighterStar.XCenter) + (fainterStar.YCenter - brighterStar.YCenter) * (fainterStar.YCenter - brighterStar.YCenter)); if (dist <= minDistanceInPixels) { if (foundStars.Contains(fainterStar)) { foundStars.Remove(fainterStar); } } } } sw.Stop(); Trace.WriteLine(string.Format("Doing PSFFitting: {0} sec", sw.Elapsed.TotalSeconds.ToString("0.00"))); switch (filter) { case TangraConfig.PreProcessingFilter.NoFilter: break; case TangraConfig.PreProcessingFilter.LowPassFilter: data = lpData; break; case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter: data = lpdData; break; } return(foundStars); }
public NotMeasuredReasons MeasureObject( IImagePixel center, uint[,] data, uint[,] backgroundPixels, int bpp, TangraConfig.PreProcessingFilter filter, TangraConfig.PhotometryReductionMethod reductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, float aperture, double refinedFWHM, float refinedAverageFWHM, IMeasurableObject measurableObject, IImagePixel[] objectsInGroup, float[] aperturesInGroup, bool fullDisappearance) { // NOTE: This is how the center of the pixel area passed in data and background arrays is determined // TODO: Pass the center as an argument int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); float msrX0 = (float)center.XDouble; float msrY0 = (float)center.YDouble; float bgAnnulusFactor = 1; switch (filter) { case TangraConfig.PreProcessingFilter.LowPassFilter: data = ImageFilters.LowPassFilter(data, bpp, true); backgroundPixels = ImageFilters.LowPassFilter(backgroundPixels, bpp, true); break; case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter: data = ImageFilters.LowPassDifferenceFilter(data, bpp, true); backgroundPixels = ImageFilters.LowPassDifferenceFilter(backgroundPixels, bpp, true); break; default: break; } float modelFWHM = float.NaN; if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { if (TangraConfig.Settings.Photometry.UseUserSpecifiedFWHM) { modelFWHM = TangraConfig.Settings.Photometry.UserSpecifiedFWHM; } else { modelFWHM = refinedAverageFWHM; } } DoublePSFFit doublefit = null; PSFFit fit = null; IBackgroundModelProvider backgroundModel = null; // 1 - Fit a PSF to the current obejct if (objectsInGroup != null && objectsInGroup.Length == 2) { // 1A - When this is a star group int x1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].XDouble - center.XDouble); int y1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].YDouble - center.YDouble); int x2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].XDouble - center.XDouble); int y2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].YDouble - center.YDouble); doublefit = new DoublePSFFit(centerX, centerY); if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel && !float.IsNaN(modelFWHM)) { doublefit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; doublefit.SetAveragedModelFWHM(modelFWHM); } doublefit.Fit(data, x1, y1, x2, y2); PSFFit star1 = doublefit.GetGaussian1(); PSFFit star2 = doublefit.GetGaussian2(); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(data, star1, star2); doublefit.Fit(data, bg3dFit, x1, y1, x2, y2); star1 = doublefit.GetGaussian1(); star2 = doublefit.GetGaussian2(); backgroundModel = bg3dFit; } double d1 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X1Center, measurableObject.Center.YDouble, doublefit.Y1Center); double d2 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X2Center, measurableObject.Center.YDouble, doublefit.Y2Center); fit = (d1 < d2) ? star1 : star2; if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry) { // NOTE: If aperture photometry is used, we measure the double object in a single larger aperture centered at the middle double alpha = Math.Atan((star2.YCenter - star1.YCenter) / (star2.XCenter - star1.XCenter)); float dx = (float)((star1.FWHM - star2.FWHM) * Math.Cos(alpha)); float dy = (float)((star1.FWHM - star2.FWHM) * Math.Sin(alpha)); msrX0 = (float)(star1.XCenter - star1.FWHM + star2.XCenter + star2.FWHM) / 2.0f - dx; msrY0 = (float)(star1.YCenter - star1.FWHM + star2.YCenter + star2.FWHM) / 2.0f - dy; aperture = aperturesInGroup.Sum(); bgAnnulusFactor = 0.67f; } } else if (reductionMethod != TangraConfig.PhotometryReductionMethod.AperturePhotometry) { // 1B - When this is a single star fit = new PSFFit(centerX, centerY); if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel && !float.IsNaN(modelFWHM)) { fit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; fit.SetAveragedModelFWHM(modelFWHM); } fit.Fit(data, measurableObject.PsfFittingMatrixSize); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { // If 3D Poly Background is used then fit the background, and supply it to the PSF Fitting var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(backgroundPixels, fit, null); backgroundModel = bg3dFit; if (psfFittingMethod != TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { /* 3D Poly modelling works in a direct fit only with non-linear fitting */ fit.Fit(backgroundPixels, bg3dFit, measurableObject.PsfFittingMatrixSize); } } } else if ( reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry && m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { // 1C - Single star with aperture photometry and 3D Poly Background var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(backgroundPixels, (float)(centerX - msrX0 + 17), (float)(centerY - msrY0 + 17), 2 * aperture); backgroundModel = bg3dFit; } // 2 - Do the actual photometric measurements (signal and background) based on the selected methods if (reductionMethod == TangraConfig.PhotometryReductionMethod.PsfPhotometry) { // 2A - PSF Photometry if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.DirectNonLinearFit) { return(DoNonLinearProfileFittingPhotometry( fit, data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, refinedFWHM, bgAnnulusFactor)); } else if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { return(DoLinearProfileFittingOfAveragedMoodelPhotometry( fit, data, centerX, centerY, msrX0, msrY0, modelFWHM, aperture, measurableObject.PsfFittingMatrixSize, psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, bgAnnulusFactor, backgroundModel)); } else { throw new NotImplementedException(); } } else if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry) { return(DoAperturePhotometry( data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, backgroundPixels, bgAnnulusFactor, backgroundModel, measurableObject.Center.X, measurableObject.Center.Y)); } else if (reductionMethod == TangraConfig.PhotometryReductionMethod.OptimalExtraction) { return(DoOptimalExtractionPhotometry( fit, data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, refinedFWHM, bgAnnulusFactor)); } else { throw new ArgumentOutOfRangeException("reductionMethod"); } }
private void GenerateFrame(Pixelmap pixmap, List <IStar> stars, ModelConfig modelConfig) { var mea = new MeasurementsHelper( pixmap.BitPixCamera, TangraConfig.BackgroundMethod.BackgroundMedian, TangraConfig.Settings.Photometry.SubPixelSquareSize, TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(pixmap.BitPixCamera, pixmap.MaxSignalValue)); float apertureSize = APERTURE; float annulusInnerRadius = (GAP + APERTURE) / APERTURE; int annulusMinPixels = (int)(Math.PI * (Math.Pow(ANNULUS + GAP + APERTURE, 2) - Math.Pow(GAP + APERTURE, 2))); mea.SetCoreProperties(annulusInnerRadius, annulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */); var measurements = new Dictionary <IStar, double>(); foreach (IStar star in stars) { double x, y; GetOnPlateCoordinates(star.RADeg, star.DEDeg, modelConfig, out x, out y); if (x < 0 || x > modelConfig.FrameWidth || y < 0 || y > modelConfig.FrameHeight) { continue; } float starMag = GetStarMag(star, modelConfig.PhotometricFilter); float iMax = ModelStarAmplitude(star, starMag, modelConfig, pixmap.BitPixCamera, pixmap.MaxSignalValue); if (!float.IsNaN(iMax)) { VideoModelUtils.GenerateStar(pixmap, (float)x, (float)y, (float)modelConfig.FWHM, iMax, 0 /*Use Gaussian */); if (modelConfig.CheckMagnitudes) { var image = new AstroImage(pixmap); uint[,] data = image.GetMeasurableAreaPixels((int)x, (int)y, 17); uint[,] backgroundPixels = image.GetMeasurableAreaPixels((int)x, (int)y, 35); PSFFit fit = new PSFFit((int)x, (int)y); fit.Fit(data); var result = mea.MeasureObject(new ImagePixel(x, y), data, backgroundPixels, pixmap.BitPixCamera, TangraConfig.PreProcessingFilter.NoFilter, TangraConfig.PhotometryReductionMethod.AperturePhotometry, TangraConfig.PsfQuadrature.NumericalInAperture, TangraConfig.PsfFittingMethod.DirectNonLinearFit, apertureSize, modelConfig.FWHM, (float)modelConfig.FWHM, new FakeIMeasuredObject(fit), null, null, false); if (result == NotMeasuredReasons.TrackedSuccessfully && !mea.HasSaturatedPixels) { // Add value for fitting measurements.Add(star, mea.TotalReading - mea.TotalBackground); } } } } if (modelConfig.CheckMagnitudes) { CalculateGagnitudeFit(measurements, modelConfig.BVSlope); } }
public override void NextFrame(int frameNo, IAstroImage astroImage) { IsTrackedSuccessfully = false; // For each of the non manualy positioned Tracked objects do a PSF fit in the area of its previous location for (int i = 0; i < m_TrackedObjectGroups.Count; i++) { TrackedObjectGroup objectGroup = m_TrackedObjectGroups[i]; objectGroup.NextFrame(); if (objectGroup.TrackLater) { // Group position will be determined after the rest of the stars are found } else { if (objectGroup.IsSingleObject) { TrackedObjectLight trackedObject = (TrackedObjectLight)objectGroup.SingleObject; uint[,] pixels = astroImage.GetPixelsArea(objectGroup.SingleObjectLastCenter.X, objectGroup.SingleObjectLastCenter.Y, 17); var fit = new PSFFit(objectGroup.SingleObjectLastCenter.X, objectGroup.SingleObjectLastCenter.Y); fit.FittingMethod = PSFFittingMethod.NonLinearFit; fit.Fit(pixels); if (fit.IsSolved) { if (fit.Certainty < GUIDING_STAR_MIN_CERTAINTY) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } else if (fit.FWHM < STELLAR_OBJECT_MIN_FWHM || fit.FWHM > STELLAR_OBJECT_MAX_FWHM) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FWHMOutOfRange); } else if (TangraConfig.Settings.Tracking.CheckElongation && fit.ElongationPercentage > STELLAR_OBJECT_MAX_ELONGATION) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectTooElongated); } else { trackedObject.SetTrackedObjectMatch(fit); trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); } } } else { string dbg = ""; int areaCenterX = (objectGroup.LastCenterObject1.X + objectGroup.LastCenterObject2.X) / 2; int areaCenterY = (objectGroup.LastCenterObject1.Y + objectGroup.LastCenterObject2.Y) / 2; uint[,] pixels = astroImage.GetPixelsArea(areaCenterX, areaCenterY, 35); var doubleFit = new DoublePSFFit(areaCenterX, areaCenterY); int x1 = objectGroup.LastCenterObject1.X - areaCenterX + 17; int y1 = objectGroup.LastCenterObject1.Y - areaCenterY + 17; int x2 = objectGroup.LastCenterObject2.X - areaCenterX + 17; int y2 = objectGroup.LastCenterObject2.Y - areaCenterY + 17; if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; } doubleFit.Fit(pixels, x1, y1, x2, y2); if (doubleFit.IsSolved) { PSFFit fit1 = doubleFit.GetGaussian1(); PSFFit fit2 = doubleFit.GetGaussian2(); TrackedObjectLight trackedObject1; TrackedObjectLight trackedObject2; bool groupIdentified = objectGroup.IdentifyObjects(fit1, fit2, GUIDING_STAR_MIN_CERTAINTY, out trackedObject1, out trackedObject2); if (!groupIdentified) { dbg += "Ni-"; objectGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); //Bitmap bmp = new Bitmap(100, 200); //using (Graphics g = Graphics.FromImage(bmp)) //{ // doubleFit.DrawInternalPoints(g, new Rectangle(0, 0, 100, 200), 5, 5, Brushes.Lime, Brushes.Yellow, 8); // g.Save(); //} //bmp.Save(@"D:\Hristo\mutual_double_fit.bmp"); m_FailedGroupFits++; } else { PSFFit[] fits = new PSFFit[] { fit1, fit2 }; TrackedObjectLight[] trackedObjects = new TrackedObjectLight[] { trackedObject1, trackedObject2 }; int tooSmallCertainties = 0; int errors = 0; for (int j = 0; j < 2; j++) { PSFFit fit = fits[j]; TrackedObjectLight trackedObject = trackedObjects[j]; if (fit.Certainty < GUIDING_STAR_MIN_CERTAINTY) { tooSmallCertainties++; trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "TsGs-"; } else if (fit.FWHM < STELLAR_OBJECT_MIN_FWHM || fit.FWHM > STELLAR_OBJECT_MAX_FWHM) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FWHMOutOfRange); dbg += "Fw-"; errors++; } else if (TangraConfig.Settings.Tracking.CheckElongation && fit.ElongationPercentage > STELLAR_OBJECT_MAX_ELONGATION) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectTooElongated); dbg += "Elo-"; errors++; } else { trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "Ts-"; } } if (tooSmallCertainties == 2) { trackedObjects[0].SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); trackedObjects[1].SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); errors++; m_FailedGroupFits++; dbg += "Uncer-"; } if (errors == 0) { if (objectGroup.CheckIdentifiedObjects(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter)) { trackedObjects[0].SetTrackedObjectMatch(fits[0]); trackedObjects[1].SetTrackedObjectMatch(fits[1]); m_FailedGroupFits = 0; dbg += "Id-"; double dist = ImagePixel.ComputeDistance(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter); if (dist < 2) { Trace.WriteLine("TOO CLOSE"); } if (dist > 16) { Trace.WriteLine("TOO FAR"); } } else { dbg += "NoId-"; } } } } else { dbg += "NoSlv-"; } objectGroup.ValidatePosition(); Trace.WriteLine(dbg); } } } bool atLeastOneGroupLocated = false; for (int i = 0; i < m_TrackedObjectGroups.Count; i++) { TrackedObjectGroup trackedGroup = m_TrackedObjectGroups[i]; if (!trackedGroup.IsSingleObject && trackedGroup.LastCenterObject1 != null && trackedGroup.LastCenterObject2 != null) { Trace.WriteLine(string.Format("({0}, {1}, {2}) ({3},{4},{5}) [{6},{7}]", trackedGroup.LastCenterObject1.XDouble, trackedGroup.LastCenterObject1.YDouble, trackedGroup.LastCenterObject1.Brightness, trackedGroup.LastCenterObject2.XDouble, trackedGroup.LastCenterObject2.YDouble, trackedGroup.LastCenterObject2.Brightness, trackedGroup.LastCenterObject1.XDouble - trackedGroup.LastCenterObject2.XDouble, trackedGroup.LastCenterObject1.YDouble - trackedGroup.LastCenterObject2.YDouble)); } bool containsFullyDisappearingTarget = trackedGroup.ContainsOcultedStar && m_IsFullDisappearance; if (!containsFullyDisappearingTarget && trackedGroup.IsLocated) { atLeastOneGroupLocated = true; } if (!containsFullyDisappearingTarget) { continue; } int numReferences = 0; double x_double; double y_double; if (trackedGroup.IsSingleObject && m_IsFullDisappearance) { // This is the case for single fully disappearing targets double totalX = 0; double totalY = 0; numReferences = 0; for (int j = 0; j < m_TrackedObjectGroups.Count; j++) { TrackedObjectGroup referenceGroup = (TrackedObjectGroup)m_TrackedObjectGroups[j]; if (referenceGroup.IsLocated) { totalX += (trackedGroup.BrigherOriginalObject.ApertureStartingX - referenceGroup.BrigherOriginalObject.ApertureStartingX) + referenceGroup.BrigherObjectLastCenter.XDouble; totalY += (trackedGroup.BrigherOriginalObject.ApertureStartingY - referenceGroup.BrigherOriginalObject.ApertureStartingY) + referenceGroup.BrigherObjectLastCenter.YDouble; numReferences++; atLeastOneGroupLocated = true; } } x_double = totalX / numReferences; y_double = totalY / numReferences; } else { // The fully disappearing target is in a group. The other target would have been located. We use the last known position of the other targets numReferences = 1; x_double = trackedGroup.NonOccultedObjectLastCenter.XDouble; y_double = trackedGroup.NonOccultedObjectLastCenter.YDouble; } if (numReferences == 0) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.FitSuspectAsNoGuidingStarsAreLocated); } else { int x = (int)(Math.Round(x_double)); int y = (int)(Math.Round(y_double)); uint[,] pixels = astroImage.GetPixelsArea(x, y, 35); if (trackedGroup.IsSingleObject) { PSFFit fit = new PSFFit(x, y); fit.Fit(pixels); if (fit.IsSolved && fit.Certainty > STELLAR_OBJECT_MIN_CERTAINTY) { trackedGroup.SingleObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); trackedGroup.SingleObject.SetTrackedObjectMatch(fit); } else if (m_IsFullDisappearance) { trackedGroup.SingleObject.SetIsTracked(false, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound); } else { trackedGroup.SingleObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } } else { string dbg = ""; DoublePSFFit doubleFit = new DoublePSFFit(x, y); int x1 = trackedGroup.LastCenterObject1.X - x + 17; int y1 = trackedGroup.LastCenterObject1.Y - y + 17; int x2 = trackedGroup.LastCenterObject2.X - x + 17; int y2 = trackedGroup.LastCenterObject2.Y - y + 17; if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; } doubleFit.Fit(pixels, x1, y1, x2, y2); if (doubleFit.IsSolved) { PSFFit fit1 = doubleFit.GetGaussian1(); PSFFit fit2 = doubleFit.GetGaussian2(); IImagePixel center1 = null; IImagePixel center2 = null; TrackedObjectLight trackedObject1; TrackedObjectLight trackedObject2; bool resortToBrightness = false; bool groupIdentified = trackedGroup.IdentifyObjects(fit1, fit2, GUIDING_STAR_MIN_CERTAINTY, out trackedObject1, out trackedObject2); if (!groupIdentified && m_IsFullDisappearance) { dbg += "ReBr::"; groupIdentified = trackedGroup.IdentifyBrightObject(fit1, fit2, STELLAR_OBJECT_MIN_CERTAINTY, out trackedObject1, out trackedObject2, out center1, out center2); resortToBrightness = true; } if (!groupIdentified) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); dbg += "PsF::"; } else { PSFFit[] fits = new PSFFit[] { fit1, fit2 }; IImagePixel[] centers = new IImagePixel[] { center1, center2 }; TrackedObjectLight[] trackedObjects = new TrackedObjectLight[] { trackedObject1, trackedObject2 }; bool objectCheckSuccessful = resortToBrightness ? trackedGroup.CheckIdentifiedObjects(center1.XDouble, center2.XDouble, center1.YDouble, center2.YDouble) : trackedGroup.CheckIdentifiedObjects(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter); if (objectCheckSuccessful) { dbg += "ChS::"; bool atLeastOneOK = (fit1.IsSolved && fit1.Certainty > GUIDING_STAR_MIN_CERTAINTY) || (fit2.IsSolved && fit2.Certainty > GUIDING_STAR_MIN_CERTAINTY); double dist = ImagePixel.ComputeDistance(fit1.XCenter, fit2.XCenter, fit1.YCenter, fit2.YCenter); if (!atLeastOneOK || ((dist < 2 || dist > 16) && !resortToBrightness)) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); } int cntOk = 0; for (int j = 0; j < 2; j++) { PSFFit fit = fits[j]; IImagePixel center = centers[j]; TrackedObjectLight trackedObject = trackedObjects[j]; if (fit.IsSolved && fit.Certainty > STELLAR_OBJECT_MIN_CERTAINTY) { if (resortToBrightness && trackedObject.IsOccultedStar) { trackedObject.SetIsTracked(true, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound, center, fit.Certainty); dbg += "OccDi::"; } else { trackedObject.SetTrackedObjectMatch(fit); trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "TrSuc::"; } cntOk++; } else if (m_IsFullDisappearance && trackedObject.IsOccultedStar) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound, resortToBrightness ? center : null, 1); dbg += "BadCerSuc::"; } else { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall, resortToBrightness ? center : null, resortToBrightness ? fit.Certainty : (double?)null); dbg += "BadCerNOSuc::"; } } if (cntOk == 2) { m_FailedGroupFits = 0; } } else { trackedObjects[0].SetIsTracked(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); trackedObjects[1].SetIsTracked(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); m_FailedGroupFits++; dbg += "ChU::"; } } } else { m_FailedGroupFits++; dbg += "NoFi::"; } trackedGroup.ValidatePosition(); Trace.WriteLine(dbg); } } } IsTrackedSuccessfully = atLeastOneGroupLocated; if (IsTrackedSuccessfully) { RefinedAverageFWHM = m_TrackedObjects.Cast <TrackedObjectLight>().Average(x => x.RefinedFWHM); } if (m_FailedGroupFits > 10) { Trace.WriteLine("ERR~10+"); } }
internal NotMeasuredReasons DoAperturePhotometry( uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float aperture, int matrixSize, uint[,] backgroundArea, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel, int centerX = 0, int centerY = 0) { if (matrix.GetLength(0) != 17 && matrix.GetLength(0) != 35) { throw new ApplicationException("Measurement error. Correlation: AFP-101"); } int side = matrix.GetLength(0); float halfSide = 1.0f * side / 2f; m_HasSaturatedPixels = false; m_PSFBackground = double.NaN; m_FoundBestPSFFit = null; m_XCenter = x0 - x0Int + halfSide; m_YCenter = y0 - y0Int + halfSide; m_Aperture = aperture; m_PixelData = matrix; m_TotalPixels = 0; m_TotalReading = GetReading( m_Aperture, m_PixelData, side, side, m_XCenter, m_YCenter, null, ref m_TotalPixels, centerX - 8, centerY - 8); if (m_TotalPixels > 0) { if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { PSFFit fit = new PSFFit(x0Int, y0Int); fit.Fit(matrix, matrixSize); if (!fit.IsSolved) { m_TotalBackground = 0; } else { m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)fit.I0); } } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { int offset = (35 - side) / 2; m_TotalBackground = Get3DPolynomialBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, backgroundModel); } else if (m_BackgroundMethod != TangraConfig.BackgroundMethod.PSFBackground) { int offset = (35 - side) / 2; if (GetImagePixelsCallback != null) { backgroundArea = GetImagePixelsCallback(x0Int, y0Int, 71); offset += 17; } double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor); m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)bgFromAnnulus); } else { throw new ApplicationException("Measurement error. Correlation: AFP-102"); } return(NotMeasuredReasons.MeasuredSuccessfully); } else { m_TotalBackground = 0; m_TotalReading = 0; return(NotMeasuredReasons.NoPixelsToMeasure); } }
private void FindBestFit( float x0, float y0, Filter filter, uint[,] matrix, int bpp, bool findBestMatrixSize, ref int matrixSize, bool fixedAperture, bool doCentroidFitForFixedAperture) { m_HasSaturatedPixels = false; m_PSFBackground = double.NaN; m_FoundBestPSFFit = null; m_PixelData = null; if (filter == Filter.LPD) { m_PixelData = ImageFilters.LowPassDifferenceFilter(matrix, bpp); } else if (filter == Filter.LP) { m_PixelData = ImageFilters.LowPassFilter(matrix, bpp, false); } else { m_PixelData = matrix; } int x0i = (int)Math.Round(x0); int y0i = (int)Math.Round(y0); bool isSolved = false; Trace.Assert(m_PixelData.GetLength(0) == m_PixelData.GetLength(1)); int halfDataSize = (int)Math.Ceiling(m_PixelData.GetLength(0) / 2.0); if (findBestMatrixSize) { if (!fixedAperture) { PSFFit fit = new PSFFit(x0i, y0i); #region Copy only the matix around the PFS Fit Area do { int halfSize = matrixSize / 2; uint[,] fitAreaMatrix = new uint[matrixSize, matrixSize]; int xx = 0, yy = 0; for (int y = halfDataSize - halfSize; y <= halfDataSize + halfSize; y++) { xx = 0; for (int x = halfDataSize - halfSize; x <= halfDataSize + halfSize; x++) { fitAreaMatrix[xx, yy] = m_PixelData[x, y]; xx++; } yy++; } fit.Fit(fitAreaMatrix); m_XCenter = fit.X0_Matrix + halfDataSize - halfSize; m_YCenter = fit.Y0_Matrix + halfDataSize - halfSize; if (!findBestMatrixSize) { break; } if (Math.Sqrt((m_XCenter - halfDataSize) * (m_XCenter - halfDataSize) + (m_YCenter - halfDataSize) * (m_YCenter - halfDataSize)) < BestMatrixSizeDistanceDifferenceTolerance) { break; } matrixSize -= 2; } while (matrixSize > 0); #endregion isSolved = fit.IsSolved; if (isSolved) { m_FoundBestPSFFit = fit; } } else { // Fixed Aperture if (doCentroidFitForFixedAperture) { //"Do a 5x5 centroid cenetring, then get the new byte[,] around this new center, and then pass for measuring with a fixed aperture value"); } m_XCenter = halfDataSize - 1; m_YCenter = halfDataSize - 1; } } else { m_XCenter = halfDataSize - 1; m_YCenter = halfDataSize - 1; } m_TotalReading = 0; m_TotalBackground = 0; m_PSFBackground = 0; }
public static StarMagnitudeFit PerformFit( IAstrometryController astrometryController, IVideoController videoController, int bitPix, uint maxSignalValue, FitInfo astrometricFit, TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, TangraConfig.BackgroundMethod photometryBackgroundMethod, TangraConfig.PreProcessingFilter filter, List <IStar> catalogueStars, Guid magnitudeBandId, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, float?aperture, float?annulusInnerRadius, int?annulusMinPixels, ref float empericalPSFR0) { uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue); MeasurementsHelper measurer = new MeasurementsHelper( bitPix, photometryBackgroundMethod, TangraConfig.Settings.Photometry.SubPixelSquareSize, saturatedValue); measurer.SetCoreProperties( annulusInnerRadius ?? TangraConfig.Settings.Photometry.AnnulusInnerRadius, annulusMinPixels ?? TangraConfig.Settings.Photometry.AnnulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */); var bgProvider = new BackgroundProvider(videoController); measurer.GetImagePixelsCallback += new MeasurementsHelper.GetImagePixelsDelegate(bgProvider.measurer_GetImagePixelsCallback); List <double> intencities = new List <double>(); List <double> magnitudes = new List <double>(); List <double> colours = new List <double>(); List <double> residuals = new List <double>(); List <bool> saturatedFlags = new List <bool>(); List <IStar> stars = new List <IStar>(); List <PSFFit> gaussians = new List <PSFFit>(); List <MagFitRecord> fitRecords = new List <MagFitRecord>(); AstroImage currentAstroImage = videoController.GetCurrentAstroImage(false); Rectangle osdRectToExclude = astrometryController.OSDRectToExclude; Rectangle rectToInclude = astrometryController.RectToInclude; bool limitByInclusion = astrometryController.LimitByInclusion; int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry; double a = double.NaN; double b = double.NaN; double c = double.NaN; int excludedStars = 0; double empericalFWHM = double.NaN; try { foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs) { if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) { continue; } if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) { continue; } IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo); if (star == null || double.IsNaN(star.Mag) || star.Mag == 0) { continue; } uint[,] data = currentAstroImage.GetMeasurableAreaPixels((int)pair.x, (int)pair.y, matSize); PSFFit fit = new PSFFit((int)pair.x, (int)pair.y); fit.Fit(data, PSF_FIT_AREA_SIZE); if (!fit.IsSolved) { continue; } MagFitRecord record = new MagFitRecord(); record.Star = star; record.Pair = pair; record.PsfFit = fit; record.Saturation = IsSaturated(data, matSize, saturatedValue); if (!EXCLUDE_SATURATED_STARS || !record.Saturation) { fitRecords.Add(record); } } // We need the average R0 if it hasn't been determined yet if (float.IsNaN(empericalPSFR0)) { empericalPSFR0 = 0; foreach (MagFitRecord rec in fitRecords) { empericalPSFR0 += (float)rec.PsfFit.R0; } empericalPSFR0 /= fitRecords.Count; } empericalFWHM = 2 * Math.Sqrt(Math.Log(2)) * empericalPSFR0; foreach (MagFitRecord record in fitRecords) { ImagePixel center = new ImagePixel(255, record.Pair.x, record.Pair.y); int areaSize = filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19; int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); uint[,] data = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize); uint[,] backgroundPixels = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35); measurer.MeasureObject( center, data, backgroundPixels, currentAstroImage.Pixelmap.BitPixCamera, filter, photometryReductionMethod, psfQuadrature, psfFittingMethod, aperture != null ? aperture.Value : (float)Aperture(record.PsfFit.FWHM), record.PsfFit.FWHM, (float)empericalFWHM, new FakeIMeasuredObject(record.PsfFit), null, null, false); double intensity = measurer.TotalReading - measurer.TotalBackground; if (intensity > 0) { var mag = record.Star.GetMagnitudeForBand(magnitudeBandId); var clr = record.Star.MagJ - record.Star.MagK; if (!double.IsNaN(mag) && !double.IsNaN(clr) && !double.IsInfinity(mag) && !double.IsInfinity(clr)) { intencities.Add(intensity); magnitudes.Add(record.Star.GetMagnitudeForBand(magnitudeBandId)); colours.Add(record.Star.MagJ - record.Star.MagK); gaussians.Add(record.PsfFit); stars.Add(record.Star); saturatedFlags.Add(measurer.HasSaturatedPixels || record.PsfFit.IMax >= measurer.SaturationValue); } } } // Remove stars with unusual PSF fit radii (once only) double sum = 0; for (int i = 0; i < gaussians.Count; i++) { sum += gaussians[i].R0; } double averageR = sum / gaussians.Count; residuals.Clear(); sum = 0; for (int i = 0; i < gaussians.Count; i++) { residuals.Add(averageR - gaussians[i].R0); sum += (averageR - gaussians[i].R0) * (averageR - gaussians[i].R0); } double stdDev = Math.Sqrt(sum) / gaussians.Count; if (EXCLUDE_BAD_RESIDUALS) { for (int i = residuals.Count - 1; i >= 0; i--) { if (Math.Abs(residuals[i]) > 6 * stdDev) { intencities.RemoveAt(i); magnitudes.RemoveAt(i); colours.RemoveAt(i); stars.RemoveAt(i); gaussians.RemoveAt(i); saturatedFlags.RemoveAt(i); } } } double maxResidual = Math.Max(0.1, TangraConfig.Settings.Photometry.MaxResidualStellarMags); for (int itter = 1; itter <= MAX_ITERR; itter++) { residuals.Clear(); SafeMatrix A = new SafeMatrix(intencities.Count, 3); SafeMatrix X = new SafeMatrix(intencities.Count, 1); int idx = 0; for (int i = 0; i < intencities.Count; i++) { A[idx, 0] = magnitudes[i]; A[idx, 1] = colours[i]; A[idx, 2] = 1; X[idx, 0] = -2.5 * Math.Log10(intencities[i]); idx++; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; double Ka = bx[0, 0]; double Kb = bx[1, 0]; double Kc = bx[2, 0]; // -2.5 * a * Log(Median-Intensity) = A * Mv + B * Mjk + C - b // -2.5 * Log(Median-Intensity) = Ka * Mv + Kb * Mjk + Kc // Mv = -2.5 * a * Log(Median-Intensity) - b * Mjk - c a = 1 / Ka; b = -Kb / Ka; c = -Kc / Ka; int starsExcludedThisTime = 0; if (EXCLUDE_BAD_RESIDUALS) { List <int> indexesToRemove = new List <int>(); for (int i = 0; i < intencities.Count; i++) { double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c; double diff = Math.Abs(computed - magnitudes[i]); if (itter < MAX_ITERR) { if (Math.Abs(diff) > maxResidual) { indexesToRemove.Add(i); } } else { residuals.Add(diff); } } for (int i = indexesToRemove.Count - 1; i >= 0; i--) { int idxToRemove = indexesToRemove[i]; intencities.RemoveAt(idxToRemove); magnitudes.RemoveAt(idxToRemove); colours.RemoveAt(idxToRemove); stars.RemoveAt(idxToRemove); gaussians.RemoveAt(idxToRemove); saturatedFlags.RemoveAt(idxToRemove); excludedStars++; starsExcludedThisTime++; } } if (starsExcludedThisTime == 0) { break; } } } catch (Exception ex) { Trace.WriteLine(ex.ToString()); } return(new StarMagnitudeFit( currentAstroImage, bitPix, intencities, magnitudes, colours, stars, gaussians, new List <double>(), saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM, photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture)); }
public void NextFrame(int frameNo, IAstroImage astroImage) { m_IsTrackedSuccessfully = false; StarMap starMap = new StarMap(); starMap.FindBestMap( m_StarMapConfig, (AstroImage)astroImage, Rectangle.Empty, new Rectangle(0, 0, astroImage.Width, astroImage.Height), AstrometryContext.Current.LimitByInclusion); if (starMap.Features.Count >= 5) { starMap.Features.Sort((x, y) => y.PixelCount.CompareTo(x.PixelCount)); int featuresToConsider = Math.Min(10, starMap.Features.Count); var featureDistances = new List <List <double> >(); for (int i = 0; i < featuresToConsider; i++) { var dist = new List <double>(); for (int j = 0; j < featuresToConsider; j++) { dist.Add(double.NaN); } featureDistances.Add(dist); } var pivotDistances = new List <List <double> >(); for (int i = 0; i < featuresToConsider; i++) { pivotDistances.Add(new List <double>(UNINITIALIZED_DISTANCES)); } for (int i = 0; i < featuresToConsider; i++) { var feature_i = starMap.Features[i]; for (int j = i + 1; j < featuresToConsider; j++) { var feature_j = starMap.Features[j]; double distance = feature_j.GetCenter().DistanceTo(feature_i.GetCenter()); pivotDistances[i][j] = distance; pivotDistances[j][i] = distance; } } Dictionary <int, int> pivotMap = IdentifyPivots(pivotDistances); int identifiedObjects = 0; for (int i = 0; i < m_TrackedObjects.Count; i++) { ((TrackedObject)m_TrackedObjects[i]).NewFrame(); var xVals = new List <double>(); var yVals = new List <double>(); foreach (int key in pivotMap.Keys) { int mapsToSourceFeatureId = pivotMap[key]; xVals.Add(starMap.Features[key].GetCenter().XDouble + m_TrackedObjectsPivotDistancesX[i][mapsToSourceFeatureId]); yVals.Add(starMap.Features[key].GetCenter().YDouble + m_TrackedObjectsPivotDistancesY[i][mapsToSourceFeatureId]); } double x0 = xVals.Median(); double y0 = yVals.Median(); double sigmaX = Math.Sqrt(xVals.Select(x => (x - x0) * (x - x0)).Sum()) / (xVals.Count - 1); double sigmaY = Math.Sqrt(yVals.Select(y => (y - y0) * (y - y0)).Sum()) / (yVals.Count - 1); if (!double.IsNaN(x0) && !double.IsNaN(y0) && xVals.Count > 1 && (sigmaX > m_FWHMAverage || sigmaY > m_FWHMAverage)) { // Some of the pivots may have been misidentified. Remove all entries with too large residuals and try again xVals.RemoveAll(x => Math.Abs(x - x0) > sigmaX); yVals.RemoveAll(y => Math.Abs(y - y0) > sigmaY); if (xVals.Count > 1) { x0 = xVals.Median(); y0 = yVals.Median(); sigmaX = Math.Sqrt(xVals.Select(x => (x - x0) * (x - x0)).Sum()) / (xVals.Count - 1); sigmaY = Math.Sqrt(yVals.Select(y => (y - y0) * (y - y0)).Sum()) / (yVals.Count - 1); } } if (!double.IsNaN(x0) && !double.IsNaN(y0) && xVals.Count > 1 && (sigmaX > m_FWHMAverage || sigmaY > m_FWHMAverage)) { // There is something really wrong about this. Reject the position and fail the frame m_TrackedObjects[i].SetIsTracked(false, NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance, null, null); } else { PSFFit fit = new PSFFit((int)x0, (int)y0); uint[,] data = ((AstroImage)astroImage).GetMeasurableAreaPixels((int)x0, (int)y0); fit.Fit(data); if (fit.IsSolved) { m_TrackedObjects[i].SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully, new ImagePixel(fit.XCenter, fit.YCenter), fit.Certainty); ((TrackedObject)m_TrackedObjects[i]).ThisFrameX = (float)fit.XCenter; ((TrackedObject)m_TrackedObjects[i]).ThisFrameY = (float)fit.YCenter; ((TrackedObjectBase)m_TrackedObjects[i]).PSFFit = fit; identifiedObjects++; } else { m_TrackedObjects[i].SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed, null, null); } } } m_IsTrackedSuccessfully = identifiedObjects == m_TrackedObjects.Count; if (m_IsTrackedSuccessfully) { UpdatePivotDistances(starMap, pivotMap); } } }
public bool InitializeNewTracking(IAstroImage astroImage) { m_StarMapConfig = new StarMapInternalConfig(StarMapInternalConfig.Default); m_StarMapConfig.CustomMaxSignalValue = astroImage.GetPixelmapPixels().Max(); m_StarMapConfig.CustomOptimumStarsValue = 25; m_StarMapConfig.IsFITSFile = true; StarMap starMap = new StarMap(); starMap.FindBestMap( m_StarMapConfig, (AstroImage)astroImage, Rectangle.Empty, new Rectangle(0, 0, astroImage.Width, astroImage.Height), AstrometryContext.Current.LimitByInclusion); if (starMap.Features.Count < 10) { MessageBox.Show("Cannot initialize object tracking as less than 10 stars can be identified in the field"); return(false); } // Build a signature of the largest 10 features (pivots) m_PivotDistances.Clear(); for (int i = 0; i < 10; i++) { m_PivotDistances.Add(new List <double>(UNINITIALIZED_DISTANCES)); } double fwhmSum = 0; int fwhmCount = 0; starMap.Features.Sort((x, y) => y.PixelCount.CompareTo(x.PixelCount)); for (int i = 0; i < 10; i++) { var feature_i = starMap.Features[i]; for (int j = i + 1; j < 10; j++) { var feature_j = starMap.Features[j]; double distance = feature_j.GetCenter().DistanceTo(feature_i.GetCenter()); m_PivotDistances[i][j] = distance; m_PivotDistances[j][i] = distance; } int x0 = feature_i.GetCenter().X; int y0 = feature_i.GetCenter().Y; PSFFit fit = new PSFFit((int)x0, (int)y0); uint[,] data = ((AstroImage)astroImage).GetMeasurableAreaPixels((int)x0, (int)y0); fit.Fit(data); if (fit.IsSolved) { fwhmSum += fit.FWHM; fwhmCount++; } } m_FWHMAverage = (float)(fwhmSum / fwhmCount); for (int i = 0; i < m_TrackedObjects.Count; i++) { m_TrackedObjectsPivotDistancesX[i] = new List <double>(); m_TrackedObjectsPivotDistancesY[i] = new List <double>(); for (int j = 0; j < 10; j++) { m_TrackedObjectsPivotDistancesX[i].Add(m_TrackedObjects[i].Center.XDouble - starMap.Features[j].GetCenter().XDouble); m_TrackedObjectsPivotDistancesY[i].Add(m_TrackedObjects[i].Center.YDouble - starMap.Features[j].GetCenter().YDouble); } int x0 = m_TrackedObjects[i].Center.X; int y0 = m_TrackedObjects[i].Center.Y; PSFFit fit = new PSFFit((int)x0, (int)y0); uint[,] data = ((AstroImage)astroImage).GetMeasurableAreaPixels((int)x0, (int)y0); fit.Fit(data); if (fit.IsSolved) { SetTargetFWHM(i, (float)fit.FWHM); } } m_TargetPivotDistancesListX.Clear(); m_TargetPivotDistancesListY.Clear(); return(true); }
public override void NextFrame(int frameNo, IAstroImage astroImage) { IsTrackedSuccessfully = false; // For each of the non manualy positioned Tracked objects do a PSF fit in the area of its previous location for (int i = 0; i < m_TrackedObjects.Count; i++) { TrackedObjectLight trackedObject = (TrackedObjectLight)m_TrackedObjects[i]; trackedObject.NextFrame(); if (trackedObject.OriginalObject.IsFixedAperture || (trackedObject.OriginalObject.IsOcultedStar() && m_IsFullDisappearance)) { // Star position will be determined after the rest of the stars are found } else { uint[,] pixels = astroImage.GetPixelsArea(trackedObject.Center.X, trackedObject.Center.Y, 17); var fit = new PSFFit(trackedObject.Center.X, trackedObject.Center.Y); fit.FittingMethod = TangraConfig.Settings.Tracking.CheckElongation ? PSFFittingMethod.NonLinearAsymetricFit : PSFFittingMethod.NonLinearFit; fit.Fit(pixels); if (fit.IsSolved) { if (fit.Certainty < GUIDING_STAR_MIN_CERTAINTY) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } else if (fit.FWHM < STELLAR_OBJECT_MIN_FWHM || fit.FWHM > STELLAR_OBJECT_MAX_FWHM) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FWHMOutOfRange); } else if (TangraConfig.Settings.Tracking.CheckElongation && fit.ElongationPercentage > STELLAR_OBJECT_MAX_ELONGATION) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectTooElongated); } else { trackedObject.SetTrackedObjectMatch(fit); trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); } } } } bool atLeastOneObjectLocated = false; for (int i = 0; i < m_TrackedObjects.Count; i++) { TrackedObjectLight trackedObject = (TrackedObjectLight)m_TrackedObjects[i]; bool needsRelativePositioning = trackedObject.OriginalObject.IsFixedAperture || (trackedObject.OriginalObject.IsOcultedStar() && m_IsFullDisappearance); if (!needsRelativePositioning && trackedObject.IsLocated) { atLeastOneObjectLocated = true; } if (!needsRelativePositioning) { continue; } double totalX = 0; double totalY = 0; int numReferences = 0; for (int j = 0; j < m_TrackedObjects.Count; j++) { TrackedObjectLight referenceObject = (TrackedObjectLight)m_TrackedObjects[j]; if (referenceObject.IsLocated) { totalX += (trackedObject.OriginalObject.ApertureStartingX - referenceObject.OriginalObject.ApertureStartingX) + referenceObject.Center.XDouble; totalY += (trackedObject.OriginalObject.ApertureStartingY - referenceObject.OriginalObject.ApertureStartingY) + referenceObject.Center.YDouble; numReferences++; atLeastOneObjectLocated = true; } } if (numReferences == 0) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FitSuspectAsNoGuidingStarsAreLocated); } else { double x_double = totalX / numReferences; double y_double = totalY / numReferences; if (trackedObject.OriginalObject.IsFixedAperture) { trackedObject.SetIsTracked(true, NotMeasuredReasons.FixedObject, new ImagePixel(x_double, y_double), 1); } else if (trackedObject.OriginalObject.IsOcultedStar()) { int x = (int)(Math.Round(totalX / numReferences)); int y = (int)(Math.Round(totalY / numReferences)); int matrixSize = (int)(Math.Round(trackedObject.OriginalObject.ApertureInPixels * 1.5)); if (matrixSize % 2 == 0) { matrixSize++; } if (matrixSize > 17) { matrixSize = 17; } uint[,] pixels = astroImage.GetPixelsArea(x, y, matrixSize); PSFFit fit = new PSFFit(x, y); fit.Fit(pixels); if (fit.IsSolved && fit.Certainty > STELLAR_OBJECT_MIN_CERTAINTY) { trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); trackedObject.SetTrackedObjectMatch(fit); } else if (m_IsFullDisappearance) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound); } else { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } } } } IsTrackedSuccessfully = atLeastOneObjectLocated; }