public Tracker(List<TrackedObjectConfig> trackedObjects) { TrackedObjects = new List<ITrackedObject>(); int i = -1; foreach(TrackedObjectConfig originalObject in trackedObjects) { i++; TrackedObject trackedObject = new TrackedObject((byte)i, originalObject); TrackedObjects.Add(trackedObject); TrackedObjectsByTargetId.Add(trackedObject.TargetNo, trackedObject); if (IsLocateFirstObject(originalObject)) { LocateFirstObjects.Add(trackedObject); LocateFirstObjectsTargetIds.Add(trackedObject.TargetNo); } else LocateSecondObjects.Add(trackedObject); if (trackedObject.IsOccultedStar) OccultedStar = trackedObject; } m_AllowedSignalFluctoation = LightCurveReductionContext.Instance.HighFlickeringOrLargeStars ? 1.90f : 1.30f; //if this is not an aperture photometry we MUST have a PSF fit anyway so // also fit objects with fixed aperture. Also not allow fixed apertures to be added // when the object is faint and there is no good fit. Test with first guiding and second faint occulted. RefinedFWHM = new float[trackedObjects.Count]; }
public StarFieldTracker(List<TrackedObjectConfig> measuringStars) { int i = -1; foreach (var originalObject in measuringStars) { i++; TrackedObject trackedObject = new TrackedObject((byte)i, originalObject); TrackedObjects.Add(trackedObject); TrackedObjectsByTargetId.Add(trackedObject.TargetNo, trackedObject); } }
private void LocateNonGuidingObject(IAstroImage astroImage, TrackedObject trackedObject, IImagePixel newStaringPos) { trackedObject.SetIsLocated(false, NotMeasuredReasons.UnknownReason); double averageX = 0; double averageY = 0; GetAverageObjectPositionsFromGuidingStars(trackedObject, newStaringPos, out averageX, out averageY); trackedObject.ThisFrameX = (float)averageX; trackedObject.ThisFrameY = (float)averageY; trackedObject.PSFFit = null; trackedObject.ThisSignalLevel = float.NaN; trackedObject.ThisFrameCertainty = float.NaN; List<TrackedObject> resolvedGuidingStars = LocateFirstObjects.FindAll(o => o.IsLocated); if (resolvedGuidingStars.Count == 0) { if (m_Refining) trackedObject.RegisterRefinedPosition(newStaringPos, float.NaN, double.NaN); } else { FitObjectInLimitedArea(trackedObject, astroImage, (float) averageX, (float) averageY); if (m_Refining) trackedObject.RegisterRefinedPosition( new ImagePixel((int)trackedObject.ThisSignalLevel, trackedObject.ThisFrameX, trackedObject.ThisFrameY), trackedObject.ThisSignalLevel, trackedObject.PSFFit != null ? trackedObject.PSFFit.FWHM : double.NaN); } }
private void LocateNonGuidingObject(IAstroImage astroImage, TrackedObject trackedObject) { IImagePixel prevPos = trackedObject.HasRefinedPositions ? trackedObject.LastRefinedPosition : trackedObject.LastKnownGoodPosition != null ? trackedObject.LastKnownGoodPosition : trackedObject.OriginalObject.AsImagePixel; IImagePixel newStaringPos = m_AllGuidingStarsFailed ? prevPos : new ImagePixel(prevPos.Brightness, prevPos.XDouble + m_LastFrameDeltaX, prevPos.YDouble + m_LastFrameDeltaY); if (trackedObject.OriginalObject.IsWeakSignalObject) { LocateNonGuidingObject(astroImage, trackedObject, newStaringPos); } else if (trackedObject.OriginalObject.IsFixedAperture) { LocateFixedApertureObject(astroImage, trackedObject, newStaringPos); } else if ( trackedObject.OriginalObject.TrackingType == TrackingType.OccultedStar && LightCurveReductionContext.Instance.FullDisappearance && !trackedObject.OriginalObject.IsCloseToOtherStars) { LocateFullDisappearingObject(astroImage, trackedObject, newStaringPos); } else { LocateSingleNonGuidingObject(astroImage, trackedObject, newStaringPos); } }
private void LocateFullDisappearingObject(IAstroImage astroImage, TrackedObject trackedObject, IImagePixel newStaringPos) { if (m_Refining) // Full disapearance is not expected during refining LocateNonGuidingObject(astroImage, trackedObject, newStaringPos); else { double averageX, averageY; GetAverageObjectPositionsFromGuidingStars(trackedObject, newStaringPos, out averageX, out averageY); trackedObject.ThisFrameX = (float)averageX + 0.5f; trackedObject.ThisFrameY = (float)averageY + 0.5f; trackedObject.PSFFit = null; trackedObject.ThisSignalLevel = float.NaN; trackedObject.ThisFrameCertainty = 1; int x0 = (int) Math.Round(averageX); int y0 = (int) Math.Round(averageY); trackedObject.SetIsLocated(false, NotMeasuredReasons.UnknownReason); PSFFit gaussian = null; int smallestMatrixSize = (int)Math.Round(trackedObject.OriginalObject.ApertureInPixels * 2); if (smallestMatrixSize % 2 == 0) smallestMatrixSize++; // If this is not an aperture photometry we still derive a PSF uint[,] pixels = astroImage.GetPixelsArea(x0, y0, 17); for (int i = trackedObject.PsfFitMatrixSize; i >= smallestMatrixSize; i -= 2) { int borderZeroes = (trackedObject.PsfFitMatrixSize - i) / 2; for (int x = 0; x < pixels.GetLength(0); x++) { for (int y = 0; y < borderZeroes; y++) { pixels[x, y] = 0; pixels[x, pixels.GetLength(1) - y - 1] = 0; } } for (int y = 0; y < pixels.GetLength(1); y++) { for (int x = 0; x < borderZeroes; x++) { pixels[x, y] = 0; pixels[pixels.GetLength(0) - x - 1, y] = 0; } } gaussian = new PSFFit(x0, y0); gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); if (gaussian.IsSolved) { double dist = ImagePixel.ComputeDistance((float)gaussian.XCenter, (float)averageX, (float)gaussian.YCenter, (float)averageY); if (dist <= PositionTolerance) { trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); break; } else trackedObject.SetIsLocated(false, NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance); } else trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } if (gaussian != null) { if (!trackedObject.IsLocated) trackedObject.SetIsLocated(true, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound); trackedObject.PSFFit = gaussian; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; } } }
private void LocateFixedApertureObject(IAstroImage astroImage, TrackedObject trackedObject, IImagePixel newStaringPos) { double averageX = 0; double averageY = 0; GetAverageObjectPositionsFromGuidingStars(trackedObject, newStaringPos, out averageX, out averageY); trackedObject.SetIsLocated(true, NotMeasuredReasons.FixedObject); trackedObject.ThisFrameX = (float)averageX; trackedObject.ThisFrameY = (float)averageY; trackedObject.PSFFit = null; trackedObject.ThisSignalLevel = float.NaN; trackedObject.ThisFrameCertainty = float.NaN; }
private void GetAverageObjectPositionsFromGuidingStars(TrackedObject trackedObject, IImagePixel newStaringPos, out double averageX, out double averageY) { List<TrackedObject> resolvedGuidingStars = LocateFirstObjects.FindAll(o => o.IsLocated); if (resolvedGuidingStars.Count == 0) { averageX = newStaringPos.XDouble; averageY = newStaringPos.YDouble; } else { averageX = 0; averageY = 0; foreach (TrackedObject resolvedGuidingStar in resolvedGuidingStars) { if (m_Refining) { averageX += (resolvedGuidingStar.ThisFrameX + trackedObject.OriginalObject.ApertureStartingX - resolvedGuidingStar.OriginalObject.ApertureStartingX); averageY += (resolvedGuidingStar.ThisFrameY + trackedObject.OriginalObject.ApertureStartingY - resolvedGuidingStar.OriginalObject.ApertureStartingY); } else { LocationVector vec = resolvedGuidingStar.OtherGuidingStarsLocationVectors[trackedObject.TargetNo]; averageX += (resolvedGuidingStar.ThisFrameX + vec.DeltaXToAdd); averageY += (resolvedGuidingStar.ThisFrameY + vec.DeltaYToAdd); } } averageX /= resolvedGuidingStars.Count; averageY /= resolvedGuidingStars.Count; } }
public override void NextFrame(int frameNo, IAstroImage astroImage) { base.NextFrame(frameNo, astroImage); #region run the full star recognition recovery if enabled if (TangraConfig.Settings.Tracking.RecoverFromLostTracking && m_RefiningFramesLeft <= 0) { bool notAllStarsLocated = TrackedObjects.Exists(o => !o.IsLocated); bool notAllLocateFirstStarsLocated = LocateFirstObjects.Exists(o => !o.IsLocated); if (notAllLocateFirstStarsLocated && LocateFirstObjects.Count > 1) { LocateStarsWithStarRecognition(astroImage); } // TODO: Use the notAllStarsLocated to troubleshoot the pattern recognition alignment } #endregion bool allGuidingStarsLocated = true; foreach (TrackedObject trackedObject in LocateFirstObjects) { if (!trackedObject.IsLocated && !trackedObject.IsOffScreen) { allGuidingStarsLocated = false; } } if (m_RefiningFramesLeft > 0) { if (allGuidingStarsLocated) { m_RefiningFramesLeft--; } } else { m_IsTrackedSuccessfully = LocateFirstObjects.Count > 0 ? allGuidingStarsLocated : OccultedStar.IsLocated; } if (!m_Refining && (LocateFirstObjects.Count > 0 && allGuidingStarsLocated) && (LightCurveReductionContext.Instance.FieldRotation || LightCurveReductionContext.Instance.LightCurveReductionType == LightCurveReductionType.MutualEvent)) { for (int i = 0; i < TrackedObjects.Count; i++) { TrackedObject obj1 = TrackedObjects[i] as TrackedObject; for (int j = 0; j < TrackedObjects.Count; j++) { if (i == j) { continue; } TrackedObject obj2 = TrackedObjects[j] as TrackedObject; long pairId = (((long)obj1.TargetNo) << 32) + (long)obj2.TargetNo; double oldDistance = m_RefinedDistances[pairId]; double newDistance = ImagePixel.ComputeDistance( obj1.Center.XDouble, obj2.Center.XDouble, obj1.Center.YDouble, obj2.Center.YDouble); m_RefinedDistances[pairId] = (oldDistance + newDistance) / 2.0; LocationVector vector = obj1.OtherGuidingStarsLocationVectors[obj2.TargetNo]; vector.DeltaXToAdd = (vector.DeltaXToAdd + obj2.Center.XDouble - obj1.Center.XDouble) / 2; vector.DeltaYToAdd = (vector.DeltaYToAdd + obj2.Center.YDouble - obj1.Center.YDouble) / 2; } } } if (!m_IsTrackedSuccessfully) { // If the tracking has failed, then some objects may be offscreen and have NaN position // So inherit the IsOffScreen flag from the previous position foreach (TrackedObject obj in TrackedObjects) { if (m_IsOffScreenPrev[obj.TargetNo] && double.IsNaN(obj.Center.XDouble)) { obj.SetIsLocated(false, NotMeasuredReasons.ObjectExpectedPositionIsOffScreen); } } } else { foreach (TrackedObject obj in TrackedObjects) { m_IsOffScreenPrev[obj.TargetNo] = obj.IsOffScreen; } } }
protected void FitObjectInLimitedArea(TrackedObject trackedObject, IAstroImage astroImage, float startingX, float startingY) { int smallestMatrixSize = (int)Math.Round(trackedObject.OriginalObject.ApertureInPixels * 2); if (smallestMatrixSize % 2 == 0) smallestMatrixSize++; // If this is not an aperture photometry we still derive a PSF uint[,] pixels = astroImage.GetPixelsArea((int)Math.Round(startingX), (int)Math.Round(startingY), 17); bool isFSPSolved = false; bool isTooFar = true; for (int i = Math.Max(trackedObject.PsfFitMatrixSize, smallestMatrixSize); i >= smallestMatrixSize; i -= 2) { int borderZeroes = (trackedObject.PsfFitMatrixSize - i) / 2; for (int x = 0; x < pixels.GetLength(0); x++) { for (int y = 0; y < borderZeroes; y++) { pixels[x, y] = 0; pixels[x, pixels.GetLength(1) - y - 1] = 0; } } for (int y = 0; y < pixels.GetLength(1); y++) { for (int x = 0; x < borderZeroes; x++) { pixels[x, y] = 0; pixels[pixels.GetLength(0) - x - 1, y] = 0; } } PSFFit gaussian = new PSFFit((int)Math.Round(startingX), (int)Math.Round(startingY)); gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); isFSPSolved = gaussian.IsSolved; isTooFar = true; if (gaussian.IsSolved) { trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; double dist = ImagePixel.ComputeDistance((float)gaussian.XCenter, (float)startingX, (float)gaussian.YCenter, (float)startingY); if (dist <= PositionTolerance) { isTooFar = false; trackedObject.PSFFit = gaussian; trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); return; } } } trackedObject.PSFFit = null; trackedObject.ThisFrameX = startingX; trackedObject.ThisFrameY = startingY; trackedObject.SetIsLocated(false, !isFSPSolved ? NotMeasuredReasons.PSFFittingFailed : isTooFar ? NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance : NotMeasuredReasons.UnknownReason); }
private void LocateSingleNonGuidingObject(IAstroImage astroImage, TrackedObject trackedObject, IImagePixel newStaringPos) { LocateNonGuidingObject(astroImage, trackedObject, newStaringPos); }
private void LocateTwoStarsWithStarRecognition( List<CandidatePair> candidates, IAstroImage astroImage, TrackedObject trackedObject1, TrackedObject trackedObject2) { try { if (candidates.Count > 0) { candidates.Sort((c1, c2) => c2.Weight.CompareTo(c1.Weight)); CandidatePair bestPair = candidates[0]; bestPair.Object1.PSFFit = bestPair.Star1; bestPair.Object1.ThisFrameX = (float)bestPair.Star1.XCenter; bestPair.Object1.ThisFrameY = (float)bestPair.Star1.YCenter; bestPair.Object1.ThisFrameCertainty = (float) bestPair.Star1.Certainty; bestPair.Object1.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfullyAfterStarRecognition); bestPair.Object2.PSFFit = bestPair.Star2; bestPair.Object2.ThisFrameX = (float)bestPair.Star2.XCenter; bestPair.Object2.ThisFrameY = (float)bestPair.Star2.YCenter; bestPair.Object2.ThisFrameCertainty = (float)bestPair.Star2.Certainty; bestPair.Object2.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfullyAfterStarRecognition); ReLocateNonGuidingObjects(astroImage); } else { trackedObject1.SetIsLocated(false, NotMeasuredReasons.FailedToLocateAfterStarRecognition); trackedObject2.SetIsLocated(false, NotMeasuredReasons.FailedToLocateAfterStarRecognition); } } finally { AutoDiscoveredStars.Clear(); } }
private void LocateTwoStarsWithStarRecognition( List<PotentialStarStruct> stars, IAstroImage astroImage, uint[,] pixels, TrackedObject trackedObject1, TrackedObject trackedObject2) { List<CandidatePair> candidates = LocateStarPairsWithStarRecognition(trackedObject1, trackedObject2, stars, pixels); LocateTwoStarsWithStarRecognition(candidates, astroImage, trackedObject1, trackedObject2); }
private List<CandidatePair> LocateStarPairsWithStarRecognition(TrackedObject trackedObject1, TrackedObject trackedObject2, List<PotentialStarStruct> stars, uint[,] pixels) { List<CandidatePair> candidates = new List<CandidatePair>(); double minFWHM = (1 - TangraConfig.Settings.Special.LostTrackingFWHMCoeff) * m_AverageFWHM; double maxFWHM = (1 + TangraConfig.Settings.Special.LostTrackingFWHMCoeff) * m_AverageFWHM; if (trackedObject1.TargetNo != trackedObject2.TargetNo && trackedObject1.LastKnownGoodPosition != null && trackedObject2.LastKnownGoodPosition != null) { double deltaX = trackedObject1.LastKnownGoodPosition.X - trackedObject2.LastKnownGoodPosition.X; double deltaY = trackedObject1.LastKnownGoodPosition.Y - trackedObject2.LastKnownGoodPosition.Y; // Looking for two stars with the same distance and similar brighness for (int i = 0; i < stars.Count; i++) { for (int j = 0; j < stars.Count; j++) { if (i == j) continue; double deltaXStars = stars[i].X - stars[j].X; double deltaYStars = stars[i].Y - stars[j].Y; if (Math.Abs(deltaX - deltaXStars) < TangraConfig.Settings.Special.LostTrackingPositionToleranceCoeff * PositionTolerance && Math.Abs(deltaY - deltaYStars) < TangraConfig.Settings.Special.LostTrackingPositionToleranceCoeff * PositionTolerance) { // Now compute PSFFits from the pixels PSFFit fit1 = AstroImage.GetPSFFitForPeakPixel(pixels, stars[i], m_MinLocateSignal, minFWHM, maxFWHM); PSFFit fit2 = AstroImage.GetPSFFitForPeakPixel(pixels, stars[j], m_MinLocateSignal, minFWHM, maxFWHM); if (fit1 != null && fit2 != null) { AutoDiscoveredStars.Add(fit1); AutoDiscoveredStars.Add(fit2); deltaXStars = fit1.XCenter - fit2.XCenter; deltaYStars = fit1.YCenter - fit2.YCenter; if (Math.Abs(deltaX - deltaXStars) < PositionTolerance && Math.Abs(deltaY - deltaYStars) < PositionTolerance) { // Compute a certainty and add to the candidates dictionary CandidatePair pair = new CandidatePair(); pair.Star1 = fit1; pair.Star2 = fit2; pair.Object1 = trackedObject1; pair.Object2 = trackedObject2; int[] BRIGTHNESS_MATCH_WEIGTH = new int[] { 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 }; int weight = (trackedObject1.IsGuidingStar ? 2 : 0) + (trackedObject2.IsGuidingStar ? 2 : 0); double d1 = pair.Star1.IMax - pair.Star1.I0; double d2 = pair.Star2.IMax - pair.Star2.I0; d1 = pair.Object1.RefinedOrLastSignalLevel / d1; if (d1 > 1) d1 = 1 / d1; int d1i = Math.Min(10, (int)Math.Round((1 - d1) * 10)); weight += BRIGTHNESS_MATCH_WEIGTH[d1i]; d2 = pair.Object2.RefinedOrLastSignalLevel / d2; if (d2 > 1) d2 = 1 / d2; int d2i = Math.Min(10, (int)Math.Round((1 - d2) * 10)); weight += BRIGTHNESS_MATCH_WEIGTH[d2i]; double distanceFromLastKnownGoodPosition = ImagePixel.ComputeDistance( pair.Star1.XCenter, pair.Object1.LastKnownGoodPosition.XDouble, pair.Star1.YCenter, pair.Object1.LastKnownGoodPosition.YDouble); int closeToPrevCoeff = LightCurveReductionContext.Instance.WindOrShaking ? 2 : 1; int closeToPrevPosWeighting = 0; if (distanceFromLastKnownGoodPosition < 4 * closeToPrevCoeff) closeToPrevPosWeighting = 3; else if (distanceFromLastKnownGoodPosition < 8 * closeToPrevCoeff) closeToPrevPosWeighting = 2; else if (distanceFromLastKnownGoodPosition < 16 * closeToPrevCoeff) closeToPrevPosWeighting = 1; else if (distanceFromLastKnownGoodPosition > 32 * closeToPrevCoeff) closeToPrevPosWeighting = -1; weight += closeToPrevPosWeighting; pair.Weight = weight; candidates.Add(pair); } else Trace.WriteLine("Pair with close distances has been rejected."); } } } } } return candidates; }
public SpectroscopyStarTracker(TrackedObjectConfig starConfig) { TrackedStar = new TrackedObject(0, starConfig); TrackedStar.LastKnownGoodPosition = new ImagePixel(starConfig.ApertureStartingX, starConfig.ApertureStartingY); }
private void LocateObjectAsGuidingStar(IAstroImage astroImage, TrackedObject trackedObject, bool useLowPassFilter) { trackedObject.SetIsLocated(false, NotMeasuredReasons.UnknownReason); int bestMaxFixAreaSize = !float.IsNaN(trackedObject.OriginalObject.RefinedFWHM) ? (int)(6 * trackedObject.OriginalObject.RefinedFWHM) : 17; if (bestMaxFixAreaSize > 17) bestMaxFixAreaSize = 35; // We only support FSP Fitting of 17 or 35 square matrixes if (bestMaxFixAreaSize < 17) bestMaxFixAreaSize = 17; // Try all fits from 5 to 15. Find the one with the highest peak, then do a fit around this area with the configured psf matrix size uint[,] pixels; if (useLowPassFilter) { pixels = astroImage.GetPixelsArea((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize + 2); pixels = EnhanceByteAreaForSearch(pixels); } else { pixels = astroImage.GetPixelsArea((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize); } // 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)trackedObject.LastFrameX, (int)trackedObject.LastFrameY); gaussian.Fit(pixels, bestMaxFixAreaSize); if (gaussian.Certainty < TangraConfig.Settings.Special.MinGuidingStarCertainty && (trackedObject.LastKnownGoodPsfCertainty > TangraConfig.Settings.Special.GoodGuidingStarCertainty || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars)) { // We have a problem. Try to find the star in the area using other means IImagePixel centroid = astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize, m_MedianValue); if (centroid != null) { double maxAllowedDistance = !float.IsNaN(trackedObject.OriginalObject.RefinedFWHM) ? 2 * trackedObject.OriginalObject.RefinedFWHM : 3 * TangraConfig.Settings.Special.LostTrackingMinDistance; if (LightCurveReductionContext.Instance.WindOrShaking) maxAllowedDistance *= 1.5; if (centroid.DistanceTo(new ImagePixel((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY)) < maxAllowedDistance) { pixels = astroImage.GetPixelsArea(centroid.X, centroid.Y, bestMaxFixAreaSize); gaussian = new PSFFit(centroid.X, centroid.Y); gaussian.Fit(pixels, bestMaxFixAreaSize); } } } IImagePixel firstCenter = gaussian.IsSolved ? new ImagePixel(gaussian.Brightness, (int)gaussian.XCenter, (int)gaussian.YCenter) : astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize, m_MedianValue); if (!gaussian.IsSolved || gaussian.Certainty < TangraConfig.Settings.Special.MinGuidingStarCertainty) firstCenter = null; if (firstCenter != null) { // Do a second fit pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, bestMaxFixAreaSize); int secondFitAreaSize = Math.Max(trackedObject.PsfFitMatrixSize, (int)Math.Round(gaussian.FWHM * 2.5)); if (secondFitAreaSize % 2 == 0) secondFitAreaSize++; secondFitAreaSize = Math.Min(17, secondFitAreaSize); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, secondFitAreaSize); if (gaussian.IsSolved) { double signal = gaussian.IMax - gaussian.I0; if (signal < 0) signal = 0; double brightnessFluctoation = signal > trackedObject.RefinedOrLastSignalLevel ? signal / trackedObject.RefinedOrLastSignalLevel : trackedObject.RefinedOrLastSignalLevel / signal; //double brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; double fluckDiff = Math.Abs(brightnessFluctoation)/m_AllowedSignalFluctoation; //if (trackedObject.LastSignalLevel != 0 && // fluckDiff > 1 && // LightCurveReductionContext.Instance.WindOrShaking) //{ // // If the located object is not similar brightness as expected, then search for our object in a wider area // try // { // IImagePixel centroid = astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, 14, m_MedianValueStart); // pixels = astroImage.GetPixelsArea(centroid.X, centroid.Y, 17); // gaussian = new PSFFit(centroid.X, centroid.Y); // gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); // if (gaussian.IsSolved) // { // signal = gaussian.IMax - gaussian.I0; if (signal < 0) signal = 0; // brightnessFluctoation = signal > trackedObject.RefinedOrLastSignalLevel // ? signal / trackedObject.RefinedOrLastSignalLevel // : trackedObject.RefinedOrLastSignalLevel / signal; // //brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; // fluckDiff = Math.Abs(brightnessFluctoation) / m_AllowedSignalFluctoation; // } // else // { // Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding.WindOrShaking]. Cannot solve third PSF", m_FrameNo, trackedObject.TargetNo)); // } // } // catch { } //} if (!trackedObject.HasRefinedPositions || fluckDiff < 1 || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars) { trackedObject.PSFFit = gaussian; trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameCertainty = (float) gaussian.Certainty; trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); if (m_Refining) { trackedObject.RegisterRefinedPosition(trackedObject.Center, trackedObject.ThisSignalLevel, gaussian.FWHM); } } else { if (useLowPassFilter) { // Only show the warning the second time around Trace.WriteLine( string.Format( "Frame {0}: Guiding target #{1} is suspect because the brightness fluctuation is too big: {2}", m_FrameNo, trackedObject.TargetNo, fluckDiff.ToString("0.00"))); trackedObject.SetIsLocated(false, NotMeasuredReasons.GuidingStarBrightnessFluctoationTooHigh); } } } else { Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding]. Cannot solve second PSF", m_FrameNo, trackedObject.TargetNo)); trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } } else { Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding]. Cannot solve first PSF", m_FrameNo, trackedObject.TargetNo)); trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } if (!trackedObject.IsLocated) { // Could not locate the object this time trackedObject.ThisSignalLevel = trackedObject.LastSignalLevel; if (m_Refining) { // Use the last known coordinates for refining frames trackedObject.ThisFrameX = trackedObject.LastFrameX; trackedObject.ThisFrameY = trackedObject.LastFrameY; trackedObject.ThisSignalLevel = trackedObject.LastSignalLevel; trackedObject.ThisFrameCertainty = (float)trackedObject.LastKnownGoodPsfCertainty; trackedObject.RegisterRefinedPosition(ImagePixel.Unspecified, float.NaN, double.NaN); } else { // Make the position invalid, which will cause the distance check for this object to fail // which will trigger another fitting later on. Eventually the previous position may be still used trackedObject.ThisFrameX = float.NaN; trackedObject.ThisFrameY = float.NaN; trackedObject.ThisFrameCertainty = float.NaN; } } }
protected PSFFit GetBestFitGaussian(AstroImage astroImage, TrackedObject guidingStar) { // Try all fits from 5 to 15. Find the one with the highest peak, then do a fit around this area with the configured psf matrix size uint[,] pixels = astroImage.GetMeasurableAreaPixels((int)guidingStar.LastFrameX, (int)guidingStar.LastFrameY); PSFFit bestGaussian = null; if (!guidingStar.OriginalObject.IsCloseToOtherStars) { // There is only one object in the area, just do a whide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, pixels.GetLength(0)); if (gaussian.IsSolved) { bestGaussian = gaussian; } } else { // There is more than one object in the area. We need a smarter way to find the one we need. if (guidingStar.IsOccultedStar) { for (int matSize = 5; matSize < 15; matSize += 2) { PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, matSize); if (gaussian.IsSolved) { if (bestGaussian == null || bestGaussian.IMax < gaussian.IMax) { bestGaussian = gaussian; } } } } else { PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, guidingStar.PsfFitMatrixSize); } } if (bestGaussian != null) { pixels = astroImage.GetMeasurableAreaPixels((int)bestGaussian.XCenter, (int)bestGaussian.YCenter); bestGaussian = new PSFFit((int)bestGaussian.XCenter, (int)bestGaussian.YCenter); bestGaussian.Fit(pixels, guidingStar.PsfFitMatrixSize); } return bestGaussian; }
public double ComputeRefinedDistances(TrackedObject obj2, out double vectorX, out double vectorY) { double refinedDistance = double.NaN; if (this.OriginalObject.IsFixedAperture || obj2.OriginalObject.IsFixedAperture) { // For manually placed apertures, return the initial distances vectorX = obj2.OriginalObject.ApertureStartingX - this.OriginalObject.ApertureStartingX; vectorY = obj2.OriginalObject.ApertureStartingY - this.OriginalObject.ApertureStartingY; return Math.Sqrt(vectorX * vectorX + vectorY * vectorY); } List<double> distances = new List<double>(); double xVector = 0; double yVector = 0; for (int k = 0; k < RefiningPositions.Count; k++) { IImagePixel pos1 = RefiningPositions[k]; IImagePixel pos2 = obj2.RefiningPositions[k]; if (pos1.IsSpecified && pos2.IsSpecified) { // Compute and average the distance double dist = Math.Sqrt((pos1.XDouble - pos2.XDouble) * (pos1.XDouble - pos2.XDouble) + (pos1.YDouble - pos2.YDouble) * (pos1.YDouble - pos2.YDouble)); distances.Add(dist); xVector += (pos2.XDouble - pos1.XDouble); yVector += (pos2.YDouble - pos1.YDouble); } } // Get the median and add in the final dict distances.Sort(); if (distances.Count % 2 == 1) refinedDistance = distances[distances.Count / 2]; else if (distances.Count > 0) refinedDistance = 0.5 * (distances[(distances.Count / 2) - 1] + distances[distances.Count / 2]); vectorX = xVector / distances.Count; vectorY = yVector / distances.Count; return refinedDistance; }
private List <CandidatePair> LocateStarPairsWithStarRecognition(TrackedObject trackedObject1, TrackedObject trackedObject2, List <PotentialStarStruct> stars, uint[,] pixels) { List <CandidatePair> candidates = new List <CandidatePair>(); double minFWHM = (1 - TangraConfig.Settings.Special.LostTrackingFWHMCoeff) * m_AverageFWHM; double maxFWHM = (1 + TangraConfig.Settings.Special.LostTrackingFWHMCoeff) * m_AverageFWHM; if (trackedObject1.TargetNo != trackedObject2.TargetNo && trackedObject1.LastKnownGoodPosition != null && trackedObject2.LastKnownGoodPosition != null) { double deltaX = trackedObject1.LastKnownGoodPosition.X - trackedObject2.LastKnownGoodPosition.X; double deltaY = trackedObject1.LastKnownGoodPosition.Y - trackedObject2.LastKnownGoodPosition.Y; // Looking for two stars with the same distance and similar brighness for (int i = 0; i < stars.Count; i++) { for (int j = 0; j < stars.Count; j++) { if (i == j) { continue; } double deltaXStars = stars[i].X - stars[j].X; double deltaYStars = stars[i].Y - stars[j].Y; if (Math.Abs(deltaX - deltaXStars) < TangraConfig.Settings.Special.LostTrackingPositionToleranceCoeff * PositionTolerance && Math.Abs(deltaY - deltaYStars) < TangraConfig.Settings.Special.LostTrackingPositionToleranceCoeff * PositionTolerance) { // Now compute PSFFits from the pixels PSFFit fit1 = AstroImage.GetPSFFitForPeakPixel(pixels, stars[i], m_MinLocateSignal, minFWHM, maxFWHM); PSFFit fit2 = AstroImage.GetPSFFitForPeakPixel(pixels, stars[j], m_MinLocateSignal, minFWHM, maxFWHM); if (fit1 != null && fit2 != null) { AutoDiscoveredStars.Add(fit1); AutoDiscoveredStars.Add(fit2); deltaXStars = fit1.XCenter - fit2.XCenter; deltaYStars = fit1.YCenter - fit2.YCenter; if (Math.Abs(deltaX - deltaXStars) < PositionTolerance && Math.Abs(deltaY - deltaYStars) < PositionTolerance) { // Compute a certainty and add to the candidates dictionary CandidatePair pair = new CandidatePair(); pair.Star1 = fit1; pair.Star2 = fit2; pair.Object1 = trackedObject1; pair.Object2 = trackedObject2; int[] BRIGTHNESS_MATCH_WEIGTH = new int[] { 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 }; int weight = (trackedObject1.IsGuidingStar ? 2 : 0) + (trackedObject2.IsGuidingStar ? 2 : 0); double d1 = pair.Star1.IMax - pair.Star1.I0; double d2 = pair.Star2.IMax - pair.Star2.I0; d1 = pair.Object1.RefinedOrLastSignalLevel / d1; if (d1 > 1) { d1 = 1 / d1; } int d1i = Math.Min(10, (int)Math.Round((1 - d1) * 10)); weight += BRIGTHNESS_MATCH_WEIGTH[d1i]; d2 = pair.Object2.RefinedOrLastSignalLevel / d2; if (d2 > 1) { d2 = 1 / d2; } int d2i = Math.Min(10, (int)Math.Round((1 - d2) * 10)); weight += BRIGTHNESS_MATCH_WEIGTH[d2i]; double distanceFromLastKnownGoodPosition = ImagePixel.ComputeDistance( pair.Star1.XCenter, pair.Object1.LastKnownGoodPosition.XDouble, pair.Star1.YCenter, pair.Object1.LastKnownGoodPosition.YDouble); int closeToPrevCoeff = LightCurveReductionContext.Instance.WindOrShaking ? 2 : 1; int closeToPrevPosWeighting = 0; if (distanceFromLastKnownGoodPosition < 4 * closeToPrevCoeff) { closeToPrevPosWeighting = 3; } else if (distanceFromLastKnownGoodPosition < 8 * closeToPrevCoeff) { closeToPrevPosWeighting = 2; } else if (distanceFromLastKnownGoodPosition < 16 * closeToPrevCoeff) { closeToPrevPosWeighting = 1; } else if (distanceFromLastKnownGoodPosition > 32 * closeToPrevCoeff) { closeToPrevPosWeighting = -1; } weight += closeToPrevPosWeighting; pair.Weight = weight; candidates.Add(pair); } else { Trace.WriteLine("Pair with close distances has been rejected."); } } } } } } return(candidates); }