Exemple #1
0
        private bool HasObjectsWithAutoAperutreCloserThan8PixelsApart()
        {
            for (int i = 0; i < m_StateMachine.MeasuringStars.Count; i++)
            {
                for (int j = i + 1; j < m_StateMachine.MeasuringStars.Count; j++)
                {
                    TrackedObjectConfig obj1 = m_StateMachine.MeasuringStars[i];
                    TrackedObjectConfig obj2 = m_StateMachine.MeasuringStars[j];

                    if (obj1.IsFixedAperture || obj2.IsFixedAperture)
                    {
                        continue;
                    }

                    double dist = ImagePixel.ComputeDistance(
                        obj1.ApertureStartingX, obj2.ApertureStartingX,
                        obj1.ApertureStartingY, obj2.ApertureStartingY);

                    double minDist = 8 + (obj1.ApertureInPixels + obj2.ApertureInPixels) / 2;

                    if (dist <= minDist && !obj1.ProcessInPsfGroup && !obj2.ProcessInPsfGroup)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #2
0
        private bool TryAutoLocateDoubleObject(out ImagePixel newCenter)
        {
            var pixelsFlatList = new List <Tuple <int, int, uint> >();

            for (int x = 0; x < 35; x++)
            {
                for (int y = 0; y < 35; y++)
                {
                    uint pixel = m_ProcessingPixels[x, y];
                    pixelsFlatList.Add(new Tuple <int, int, uint>(x, y, pixel));
                }
            }

            // Sort by brghtness (brigher at the top)
            pixelsFlatList.Sort((x, y) => y.Item3.CompareTo(x.Item3));

            Tuple <int, int, uint> brightProbe1     = pixelsFlatList[0];
            Tuple <int, int, uint> brightProbe2     = pixelsFlatList[1];
            Tuple <int, int, uint> secondPeakProbe1 = null;
            Tuple <int, int, uint> secondPeakProbe2 = null;

            for (int i = 0; i < pixelsFlatList.Count; i++)
            {
                if (secondPeakProbe1 == null &&
                    ImagePixel.ComputeDistance(brightProbe1.Item1, pixelsFlatList[i].Item1, brightProbe1.Item2, pixelsFlatList[i].Item2) > 3)
                {
                    secondPeakProbe1 = pixelsFlatList[i];
                }

                if (secondPeakProbe2 == null &&
                    ImagePixel.ComputeDistance(brightProbe2.Item1, pixelsFlatList[i].Item1, brightProbe2.Item2, pixelsFlatList[i].Item2) > 3)
                {
                    secondPeakProbe2 = pixelsFlatList[i];
                }

                if (secondPeakProbe1 != null && secondPeakProbe2 != null)
                {
                    break;
                }
            }

            if (secondPeakProbe1 != null &&
                IsGoodDoubleObjectFit(brightProbe1, secondPeakProbe1))
            {
                newCenter = new ImagePixel((int)Math.Max(brightProbe1.Item3, secondPeakProbe1.Item3), (brightProbe1.Item1 + secondPeakProbe1.Item1) / 2.0, (brightProbe1.Item2 + secondPeakProbe1.Item2) / 2.0);
                return(true);
            }

            if (secondPeakProbe2 != null &&
                IsGoodDoubleObjectFit(brightProbe2, secondPeakProbe2))
            {
                newCenter = new ImagePixel((int)Math.Max(brightProbe2.Item3, secondPeakProbe2.Item3), (brightProbe2.Item1 + secondPeakProbe2.Item1) / 2.0, (brightProbe2.Item2 + secondPeakProbe2.Item2) / 2.0);
                return(true);
            }

            newCenter = null;
            return(false);
        }
Exemple #3
0
        private void EnsureComputedRefinedData()
        {
            if (!float.IsNaN(m_MinLocateSignal))
            {
                m_LocateObjects.Clear();
                for (int i = 0; i < TrackedObjects.Count; i++)
                {
                    if (
                        (!(TrackedObjects[i] as TrackedObject).IsOccultedStar || !LightCurveReductionContext.Instance.FullDisappearance) &&
                        !TrackedObjects[i].IsOffScreen &&
                        !float.IsNaN((TrackedObjects[i] as TrackedObject).LastFrameX)
                        )
                    {
                        // Don't include targets offscreen, or targets that were not found during the last tracking (could have been off screen)
                        m_LocateObjects.Add((TrackedObjects[i] as TrackedObject).TargetNo);
                    }
                }
                return;
            }

            m_MinLocateSignal = TrackedObjects.Cast <TrackedObject>().Min(o => o.RefinedOrLastSignalLevel == 0 ? 255f : o.RefinedOrLastSignalLevel);

            // Locate all peak pixels with signal higher than (minSignal + medianNoise) / 2
            m_MinLocateSignal = (m_MedianValue + m_MinLocateSignal) / 2f;

            double minDistance = double.MaxValue;

            for (int i = 0; i < TrackedObjects.Count; i++)
            {
                if ((!(TrackedObjects[i] as TrackedObject).IsOccultedStar && !TrackedObjects[i].IsOffScreen) ||
                    !LightCurveReductionContext.Instance.FullDisappearance)
                {
                    m_LocateObjects.Add((TrackedObjects[i] as TrackedObject).TargetNo);
                }

                for (int j = 0; j < TrackedObjects.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    double dist = ImagePixel.ComputeDistance(
                        TrackedObjects[i].OriginalObject.ApertureStartingX,
                        TrackedObjects[j].OriginalObject.ApertureStartingX,
                        TrackedObjects[i].OriginalObject.ApertureStartingY,
                        TrackedObjects[j].OriginalObject.ApertureStartingY);

                    if (minDistance > dist)
                    {
                        minDistance = dist;
                    }
                }
            }

            m_MinLocateDistance = minDistance / 2.0;
        }
Exemple #4
0
        public bool IsCloseEnoughToBelongToTheGroup(TrackedObjectConfig objectToCheck)
        {
            foreach (TrackedObjectConfig existingObject in m_ObjectsInGroup)
            {
                double distance =
                    ImagePixel.ComputeDistance(existingObject.ApertureStartingX, objectToCheck.ApertureStartingX,
                                               existingObject.ApertureStartingY, objectToCheck.ApertureStartingY);

                if (distance < m_FWHM * TangraConfig.Settings.Special.MinDistanceForPhotometricGroupingInFWHM)
                {
                    return(true);
                }
            }

            return(false);
        }
        private bool IncludePixel(int x, int y)
        {
            if (m_Star1Center != null &&
                ImagePixel.ComputeDistance(m_Star1Center.XDouble, x, m_Star1Center.YDouble, y) <= m_Star1MinDistance)
            {
                return(false);
            }

            if (m_Star2Center != null &&
                ImagePixel.ComputeDistance(m_Star2Center.XDouble, x, m_Star2Center.YDouble, y) <= m_Star2MinDistance)
            {
                return(false);
            }

            return(true);
        }
Exemple #6
0
        private bool IsGoodDoubleObjectFit(Tuple <int, int, uint> object1, Tuple <int, int, uint> object2)
        {
            var doubleFit = new DoublePSFFit(100, 100);

            if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
            {
                doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel;
            }
            doubleFit.Fit(m_ProcessingPixels, object1.Item1, object1.Item2, object2.Item1, object2.Item2);

            if (doubleFit.IsSolved &&
                Math.Abs(doubleFit.FWHM1 - doubleFit.FWHM2) < Math.Max(1, Math.Min(doubleFit.FWHM1, doubleFit.FWHM2) * 0.25) &&
                doubleFit.IAmplitude1 > 0 && doubleFit.IAmplitude2 > 0)
            {
                double imaxRatio = doubleFit.IAmplitude1 / doubleFit.IAmplitude2;
                if (imaxRatio > 1)
                {
                    imaxRatio = 1 / imaxRatio;
                }

                if (imaxRatio >= 0.25)
                {
                    // We require at least 1:4 ratio in the maximums for the auto-detection to accept that it has found correctly two objects

                    double distance = ImagePixel.ComputeDistance(object1.Item1, object2.Item1, object1.Item2, object2.Item2);

                    if (distance > doubleFit.FWHM1 && distance > doubleFit.FWHM2)
                    {
                        // We also require at least a FWHM distance between centers for automatic detection
                        m_X1Start = object1.Item1;
                        m_Y1Start = object1.Item2;
                        m_X2Start = object2.Item1;
                        m_Y2Start = object2.Item2;

                        return(true);
                    }
                }

                return(false);
            }

            return(false);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        internal bool IsBrightEnoughtForGuidingStar()
        {
            double signal;
            double sn;

            byte   oneSigmaBg = 0;
            int    from       = 0;
            int    to         = m_ProcessingPixels.GetLength(0);
            double aboveMedianLevelRequired;

            if (LightCurveReductionContext.Instance.DigitalFilter != TangraConfig.PreProcessingFilter.NoFilter)
            {
                from++;
                to--;
            }
            switch (LightCurveReductionContext.Instance.DigitalFilter)
            {
            case TangraConfig.PreProcessingFilter.LowPassFilter:
                aboveMedianLevelRequired = TangraConfig.Settings.Special.AboveMedianThreasholdForGuiding * TangraConfig.Settings.Special.AboveMedianCoeffLP;
                break;

            case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter:
                aboveMedianLevelRequired = TangraConfig.Settings.Special.AboveMedianThreasholdForGuiding * TangraConfig.Settings.Special.AboveMedianCoeffLPD;
                break;

            default:
                aboveMedianLevelRequired = TangraConfig.Settings.Special.AboveMedianThreasholdForGuiding;
                break;
            }

            List <uint> bgBytes = new List <uint>();

            for (int x = from; x < to; x++)
            {
                for (int y = from; y < to; y++)
                {
                    double distanceFromFit = ImagePixel.ComputeDistance(m_Gaussian.XCenter, x, m_Gaussian.YCenter, y);
                    if (distanceFromFit > m_Gaussian.FWHM)
                    {
                        bgBytes.Add(m_ProcessingPixels[x, y]);
                    }
                }
            }
            bgBytes.Sort();
            uint median = 0;

            if (bgBytes.Count > 0)
            {
                median = bgBytes.Count % 2 == 1
                                                                  ? bgBytes[bgBytes.Count / 2]
                                                                  : ((bgBytes[bgBytes.Count / 2] + bgBytes[(bgBytes.Count / 2) - 1]) / 2);
            }

            double var = 0;

            bgBytes.ForEach(b => var += (median - b) * (median - b));
            oneSigmaBg = (byte)Math.Round(Math.Sqrt(var / Math.Max(1, bgBytes.Count - 1)));

            signal = m_Gaussian.IMax - median;
            sn     = signal / oneSigmaBg;

            Trace.WriteLine(string.Format("Signal = {0}, S/N = {1}", signal.ToString("0.00"), sn.ToString("0.00")));

            if (signal >= aboveMedianLevelRequired &&
                sn >= TangraConfig.Settings.Special.SignalNoiseForGuiding)
            {
                return(true);
            }

            Trace.WriteLine(string.Format("Not good for a guiding star: Required Signal = {0}, Required S/N = {1}",
                                          aboveMedianLevelRequired.ToString("0.00"),
                                          TangraConfig.Settings.Special.SignalNoiseForGuiding.ToString("0.00")));

            return(false);
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit)
        {
            IsTrackedSuccessfully = false;
            int searchRadius = (int)Math.Ceiling(Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius));

            PSFFit psfFit = null;

            int startingX = (int)TrackedObject.LastKnownX;
            int startingY = (int)TrackedObject.LastKnownY;

            if (m_RepeatedIntergationPositions * 4 < m_PastFrameNos.Count)
            {
                var expectedPos = GetExpectedPosition(frameNo);
                if (expectedPos != null)
                {
                    startingX = expectedPos.X;
                    startingY = expectedPos.Y;
                }
            }

            var nearbyFeatures = starMap.GetFeaturesInRadius(startingX, startingY, searchRadius).ToArray();

            var nonStarNearbyFeature = new List <StarMapFeature>();

            foreach (var feature in nearbyFeatures)
            {
                var center = feature.GetCenter();
                var referenceStarFeatures = astrometricFit.FitInfo.AllStarPairs.Where(x => x.FitInfo.UsedInSolution).ToList();
                var refStar = referenceStarFeatures.FirstOrDefault(s => Math.Sqrt((s.x - center.X) * (s.x - center.X) + (s.y - center.Y) * (s.y - center.Y)) < 2);

                double raf, def;
                astrometricFit.GetRADEFromImageCoords(center.XDouble, center.YDouble, out raf, out def);
                var pastKnownStar = m_LastFrameStars.FirstOrDefault(s => AngleUtility.Elongation(s.RADeg, s.DEDeg, raf, def) * 3600.0 < 2);

                if (refStar == null && pastKnownStar == null)
                {
                    nonStarNearbyFeature.Add(feature);
                }
            }

            if (nonStarNearbyFeature.Count > 0)
            {
                StarMapFeature closestFeature   = nonStarNearbyFeature[0];
                var            lastKnownCenter  = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY);
                var            smallestDistance = lastKnownCenter.DistanceTo(closestFeature.GetCenter());

                for (int i = 1; i < nonStarNearbyFeature.Count; i++)
                {
                    var distance = lastKnownCenter.DistanceTo(nonStarNearbyFeature[i].GetCenter());
                    if (distance < smallestDistance)
                    {
                        smallestDistance = distance;
                        closestFeature   = nonStarNearbyFeature[i];
                    }
                }

                if (closestFeature != null)
                {
                    var center = closestFeature.GetCenter();
                    AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit);
                }
            }

            if (psfFit == null)
            {
                // The expected location cannot be matched with any brighter feature so it is likely a faint object
                // with no brighter objects around. Lets find the brightest (faint) object in the are and use it
                ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid(startingX, startingY, searchRadius);

                if (centroid != null)
                {
                    AstrometryContext.Current.StarMap.GetPSFFit(centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit);
                }
            }

            if (psfFit != null)
            {
                double ra, de;
                astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de);

                double maxPosDiffArcSec =
                    astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage,
                                                       astrometricFit.Image.CenterXImage + Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.MaxAllowedDefaultMotionInPixels), astrometricFit.Image.CenterYImage);

                if (!double.IsNaN(TrackedObject.RAHours))
                {
                    double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de);
                    if (posDif > maxPosDiffArcSec)
                    {
                        // NOTE: Not a valid measurement
                        Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif));
                        return;
                    }
                }

                TrackedObject.RAHours = ra / 15.0;
                TrackedObject.DEDeg   = de;

                if (TrackedObject.PSFFit != null)
                {
                    m_LastMovementPixels = 1.2 * ImagePixel.ComputeDistance(TrackedObject.LastKnownX, psfFit.XCenter, TrackedObject.LastKnownY, psfFit.YCenter);
                }
                TrackedObject.LastKnownX = psfFit.XCenter;
                TrackedObject.LastKnownY = psfFit.YCenter;
                TrackedObject.PSFFit     = psfFit;

                var lastKnownCenter = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY);
                var thisFrameStars  = astrometricFit.FitInfo.AllStarPairs.Where(x => lastKnownCenter.DistanceTo(x.x, x.y) > 2 * psfFit.FWHM).ToList();
                if (thisFrameStars.Count > 0)
                {
                    m_LastFrameStars = thisFrameStars.Select(x => new Star(x.StarNo, x.RADeg, x.DEDeg, x.Mag) as IStar).ToList();
                }

                IsTrackedSuccessfully = true;
            }

            if (psfFit != null && psfFit.XCenter > 0 && psfFit.YCenter > 0)
            {
                m_PastFramePosX.Add(psfFit.XCenter);
                m_PastFramePosY.Add(psfFit.YCenter);
                m_PastFrameNos.Add(frameNo);
            }
        }
Exemple #11
0
        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+");
            }
        }
Exemple #12
0
        internal bool IdentifyObjects(PSFFit fit1, PSFFit fit2, float minGuidingStarCertainty, out TrackedObjectLight obj1, out TrackedObjectLight obj2)
        {
            // Make sure the two are not too far away and are also not too close
            double centDiff      = ImagePixel.ComputeDistance(fit1.XCenter, fit2.XCenter, fit1.YCenter, fit2.YCenter);
            double oldCentDiff   = ImagePixel.ComputeDistance(LastCenterObject1.XDouble, LastCenterObject2.XDouble, LastCenterObject1.YDouble, LastCenterObject2.YDouble);
            double diffDistRatio = centDiff / oldCentDiff;

            if (diffDistRatio < 0.5 || diffDistRatio > 2 || centDiff < 1 /* Two PSFs in the group are too close (possibly the same) */)
            {
                return(NoMatch(out obj1, out obj2));
            }

            bool fit1Brighter       = fit1.Brightness > fit2.Brightness;
            bool fit1Certain        = fit1.Certainty > minGuidingStarCertainty;
            bool fit2Certain        = fit2.Certainty > minGuidingStarCertainty;
            bool brighterFitCertain = fit1Brighter ? fit1Certain : fit2Certain;

            if (!brighterFitCertain)
            {
                return(NoMatch(out obj1, out obj2));
            }

            double prevX1X2  = LastCenterObject1.XDouble - LastCenterObject2.XDouble;
            double prevY1Y2  = LastCenterObject1.YDouble - LastCenterObject2.YDouble;
            double thisX1X2  = fit1.XCenter - fit2.XCenter;
            double thisY1Y2  = fit1.YCenter - fit2.YCenter;
            double delta1122 = Math.Abs(prevX1X2 - thisX1X2) + Math.Abs(prevY1Y2 - thisY1Y2);
            double delta1212 = Math.Abs(prevX1X2 + thisX1X2) + Math.Abs(prevY1Y2 + thisY1Y2);

            double averageFWHM         = (fit1.FWHM + fit2.FWHM) / 2;
            double maxGoodMatchDist    = 1 + averageFWHM / 4;
            double minGoodDismatchDist = 4 + averageFWHM / 4;

            if (delta1122 < maxGoodMatchDist && delta1212 > minGoodDismatchDist)
            {
                return(Match1122(out obj1, out obj2));
            }
            else if (delta1212 < maxGoodMatchDist && delta1122 > minGoodDismatchDist)
            {
                return(Match1212(out obj1, out obj2));
            }

            bool match1122Ok = (Math.Abs(prevX1X2 - thisX1X2) < Math.Abs(prevX1X2 + thisX1X2)) && (Math.Abs(prevY1Y2 - thisY1Y2) < Math.Abs(prevY1Y2 + thisY1Y2));
            bool match1212Ok = (Math.Abs(prevX1X2 + thisX1X2) < Math.Abs(prevX1X2 - thisX1X2)) && (Math.Abs(prevY1Y2 + thisY1Y2) < Math.Abs(prevY1Y2 - thisY1Y2));

            if ((!match1122Ok && !match1212Ok) || (match1122Ok && match1212Ok))
            {
                return(NoMatch(out obj1, out obj2));
            }

            double d11 = ImagePixel.ComputeDistance(fit1.XCenter, LastCenterObject1.XDouble, fit1.YCenter, LastCenterObject1.YDouble);
            double d22 = ImagePixel.ComputeDistance(fit2.XCenter, LastCenterObject2.XDouble, fit2.YCenter, LastCenterObject2.YDouble);
            double d12 = ImagePixel.ComputeDistance(fit1.XCenter, LastCenterObject2.XDouble, fit1.YCenter, LastCenterObject2.YDouble);
            double d21 = ImagePixel.ComputeDistance(fit2.XCenter, LastCenterObject1.XDouble, fit2.YCenter, LastCenterObject1.YDouble);

            if (d11 < d12 && d22 < d21 && match1122Ok)
            {
                return(Match1122(out obj1, out obj2));
            }
            else if (d11 > d12 && d22 > d21 && match1212Ok)
            {
                return(Match1212(out obj1, out obj2));
            }

            double bDiff  = Math.Abs(fit1.Brightness - fit2.Brightness);
            double bRatio = bDiff / Math.Max((double)fit1.Brightness, (double)fit2.Brightness);

            if (bRatio > 0.5)
            {
                // More than 2 times brightness difference. We can use the brightness to determine identify

                double b11 = Math.Abs(fit1.Brightness - LastCenterObject1.Brightness);
                double b22 = Math.Abs(fit2.Brightness - LastCenterObject2.Brightness);
                double b12 = Math.Abs(fit1.Brightness - LastCenterObject2.Brightness);
                double b21 = Math.Abs(fit2.Brightness - LastCenterObject1.Brightness);

                if (((fit1Brighter && b12 > b11 && fit1Certain) || (!fit1Brighter && b21 > b22 && fit2Certain)) && match1122Ok)
                {
                    return(Match1122(out obj1, out obj2));
                }
                else if (((fit1Brighter && b12 < b11 && fit1Certain) || (!fit1Brighter && b21 < b22 && fit2Certain)) == match1212Ok)
                {
                    return(Match1212(out obj1, out obj2));
                }
            }

            return(NoMatch(out obj1, out obj2));
        }
        private void CalculateAndDisplayBackground(uint[,] backgroundPixels)
        {
            if (backgroundPixels != null)
            {
                int bgWidth  = backgroundPixels.GetLength(0);
                int bgHeight = backgroundPixels.GetLength(1);

                var bgPixels = new List <uint>();

                for (int x = 0; x < bgWidth; x++)
                {
                    for (int y = 0; y < bgHeight; y++)
                    {
                        if (m_PSFFit == null || !m_PSFFit.IsSolved ||
                            ImagePixel.ComputeDistance(m_PSFFit.XCenter, x + bgWidth - m_PSFFit.MatrixSize, m_PSFFit.YCenter, y + bgHeight - m_PSFFit.MatrixSize) > 3 * m_PSFFit.FWHM)
                        {
                            bgPixels.Add(backgroundPixels[x, y]);
                        }
                    }
                }

                bgPixels.Sort();
                double background = 0;
                if (bgPixels.Count > 1)
                {
                    background = m_Bpp < 12
                                                ? bgPixels[bgPixels.Count / 2] // for 8 bit videos Median background works better
                                                : bgPixels.Average(x => x);    // for 12+bit videos average background works better
                }

                double residualsSquareSum = 0;
                foreach (uint bgPixel in bgPixels)
                {
                    residualsSquareSum += (background - bgPixel) * (background - bgPixel);
                }
                double noise = Math.Sqrt(residualsSquareSum / (bgPixels.Count - 1));

                lblBackground.Text = background.ToString("0.0");
                lblNoise.Text      = noise.ToString("0.0");

                if (m_PSFFit != null)
                {
                    double snr = m_PSFFit.GetSNR();
                    lblSNR.Text = snr.ToString("0.0");
                }
                else
                {
                    lblSNR.Text = "N/A";
                }

                if (m_PSFFit != null)
                {
                    lblFitVariance.Text = m_PSFFit.GetVariance().ToString("0.0");
                    lblFWHM.Text        = m_PSFFit.FWHM.ToString("0.0");
                }
                else
                {
                    lblFitVariance.Text = "N/A";
                    lblFWHM.Text        = "N/A";
                }
            }
            else
            {
                lblBackground.Text = "N/A";
                lblNoise.Text      = "N/A";
                lblSNR.Text        = "N/A";
            }
        }
Exemple #14
0
        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;
                }
            }
        }
Exemple #15
0
        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);
        }