예제 #1
0
        public void Test2_NearSouthPole()
        {
            var matrix = new CCDMatrix(8.6, 8.3, 752, 582);
            var astroPlate = new AstroPlate(matrix, 720, 576, 16);

            var userStars = new Dictionary<ImagePixel, IStar>();

            var star1 = new TestStar(670000669, 14.040622402203727, -76.691539882008868, 13.389);
            var pixel1 = new ImagePixel(111.28789147012657, 170.18336583345945);
            userStars.Add(pixel1, star1);

            var star2 = new TestStar(680000642, 13.3447869927272, -76.594950217617452, 9.932);
            var pixel2 = new ImagePixel(575.00594900921817, 446.45890095859744);
            userStars.Add(pixel2, star2);

            var star3 = new TestStar(670000641, 13.550035599758042, -76.722167259223085, 13.842);
            var pixel3 = new ImagePixel(425.86138030460097, 63.057739094752051);
            userStars.Add(pixel3, star3);

            var newAstro = new ThreeStarAstrometry(astroPlate, userStars, 2);
            Assert.IsTrue(newAstro.Success);
            Assert.AreEqual(-76.6498, newAstro.DE0Deg, 0.0001);
            Assert.AreEqual(13.6644, newAstro.RA0Deg, 0.0001);

            double ra, de;
            newAstro.GetRADEFromImageCoords(111.28789147012657, 170.18336583345945, out ra, out de);
            Assert.AreEqual(14.0406224, ra, 0.0000001);
            Assert.AreEqual(-76.6915398, de, 0.0000001);

            double x, y;
            newAstro.GetImageCoordsFromRADE(14.040622402203727, -76.691539882008868, out x, out y);
            Assert.AreEqual(111.2879, x, 0.0001);
            Assert.AreEqual(170.1833, y, 0.0001);
        }
예제 #2
0
        public static ImagePixel CreateImagePixelWithFeatureId(int featureId, int brightness, double x, double y)
        {
            var rv = new ImagePixel(brightness, x, y);

            rv.FeautureId = featureId;

            return(rv);
        }
예제 #3
0
 public ObjectClickEventArgs(ImagePixel pixel, PSFFit gausian, Point location, bool shiftHeld, bool ctrlHeld, MouseEventArgs mouseEventArgs)
 {
     ClickLocation = location;
     Pixel = pixel;
     Gausian = gausian;
     Shift = shiftHeld;
     Control = ctrlHeld;
     MouseEventArgs = mouseEventArgs;
 }
예제 #4
0
        public void SetTrackedObjectMatch(PSFFit psfFitMatched)
        {
            PSFFit = psfFitMatched;
            Center = new ImagePixel((int)psfFitMatched.IMax, psfFitMatched.XCenter, psfFitMatched.YCenter);
            IsLocated = true;
            NotMeasuredReasons = NotMeasuredReasons.TrackedSuccessfully;

            if (PSFFit != null && PSFFit.IsSolved)
            {
                LastKnownGoodPosition = new ImagePixel(Center.Brightness, Center.XDouble, Center.YDouble);
                LastKnownGoodPsfCertainty = PSFFit.Certainty;
            }
        }
예제 #5
0
        public PyramidEntry(int i, int j, int k, ImagePixel iPixel, ImagePixel jPixel, ImagePixel kPixel, ulong iStarNo, ulong jStarNo, ulong kStarNo)
        {
            Xi = iPixel.XDouble;
            Yi = iPixel.YDouble;
            Xj = jPixel.XDouble;
            Yj = jPixel.YDouble;
            Xk = kPixel.XDouble;
            Yk = kPixel.YDouble;

            SNi = iStarNo;
            SNj = jStarNo;
            SNk = kStarNo;

            this.i = i;
            this.j = j;
            this.k = k;
        }
예제 #6
0
        public void Test1()
        {
            var matrix = new CCDMatrix(8.6, 8.3, 752, 582);
            var astroPlate = new AstroPlate(matrix, 720, 576, 8);

            var userStars = new Dictionary<ImagePixel, IStar>();

            var star1 = new TestStar(2890001240, 18.528885242458674, -32.262447583319769, 11.033);
            var pixel1 = new ImagePixel(72.0519465443632, 240.48754416283302);
            userStars.Add(pixel1, star1);

            var star2 = new TestStar(2890001234, 18.353495385568369, -32.296976944037546, 12.294);
            var pixel2 = new ImagePixel(421.79863331879409, 329.57539665223919);
            userStars.Add(pixel2, star2);

            var star3 = new TestStar(2890001229, 18.284537781225755, -32.213242615932892, 10.882);
            var pixel3 = new ImagePixel(559.51676838260289, 114.86160161500557);
            userStars.Add(pixel3, star3);

            var plateSolve = DirectTransRotAstrometry.SolveByThreeStars(astroPlate, userStars, 2);

            Assert.IsNotNull(plateSolve);
            Assert.AreEqual(1.2836, plateSolve.Aspect, 0.0001);
            Assert.AreEqual(-32.2808, plateSolve.DE0Deg, 0.0001);
            Assert.AreEqual(18.3845, plateSolve.RA0Deg, 0.0001);
            Assert.AreEqual(179.9401, plateSolve.EtaDeg, 0.0001);
            Assert.AreEqual(0.00, plateSolve.Residual, 0.01);

            var newAstro = new ThreeStarAstrometry(astroPlate, userStars, 2);
            Assert.IsTrue(newAstro.Success);

            Assert.AreEqual(-32.2808, newAstro.DE0Deg, 0.0001);
            Assert.AreEqual(18.3845, newAstro.RA0Deg, 0.0001);

            double ra, de;
            newAstro.GetRADEFromImageCoords(72.0519465443632, 240.48754416283302, out ra, out de);
            Assert.AreEqual(18.5288852, ra, 0.0000001);
            Assert.AreEqual(-32.2624475, de, 0.0000001);

            double x, y;
            newAstro.GetImageCoordsFromRADE(18.528885242458674, -32.262447583319769, out x, out y);
            Assert.AreEqual(72.0519, x, 0.0001);
            Assert.AreEqual(240.4875, y, 0.0001);
        }
예제 #7
0
        internal NotMeasuredReasons DoNonLinearProfileFittingPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0,
            float aperture, int matrixSize, bool useNumericalQadrature,
            bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            double refinedFWHM, float bgAnnulusFactor)
        {
            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            if (fit.IsSolved)
            {
                SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor);
            }
            else
            {
                m_Aperture        = aperture;
                m_XCenter         = (float)fit.X0_Matrix;
                m_YCenter         = (float)fit.Y0_Matrix;
                m_TotalReading    = 0;
                m_TotalBackground = 0;
            }

            if (!fit.IsSolved ||                                               // The PSF solution failed, mark the reading invalid
                (distance > tolerance && !mayBeOcculted) ||                    // If this doesn't look like a full disappearance, then make the reading invalid
                (fit.FWHM < 0.5 * refinedFWHM || fit.FWHM > 1.5 * refinedFWHM) // The FWHM is too small or too large, make the reading invalid
                )
            {
                return(!fit.IsSolved
                        ? NotMeasuredReasons.MeasurementPSFFittingFailed
                        : (distance > tolerance && !mayBeOcculted)
                            ? NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar
                            : NotMeasuredReasons.FWHMOutOfRange);
            }
            else
            {
                return(NotMeasuredReasons.MeasuredSuccessfully);
            }
        }
예제 #8
0
        internal NotMeasuredReasons DoLinearProfileFittingOfAveragedMoodelPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float modelFWHM,
            float aperture, int matrixSize, bool useNumericalQadrature,
            bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            float bgAnnulusFactor,
            IBackgroundModelProvider backgroundModel)
        {
            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            // We first go and do the measurement anyway
            if (fit.IsSolved)
            {
                SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor, backgroundModel);
            }
            else
            {
                m_Aperture        = aperture;
                m_XCenter         = (float)fit.X0_Matrix;
                m_YCenter         = (float)fit.Y0_Matrix;
                m_TotalReading    = 0;
                m_TotalBackground = 0;
            }

            if (!fit.IsSolved ||                         // The PSF solution failed, mark the reading invalid
                (distance > tolerance && !mayBeOcculted) // If this doesn't look like a full disappearance, then make the reading invalid
                )
            {
                return(!fit.IsSolved
                                                ? NotMeasuredReasons.MeasurementPSFFittingFailed
                                                : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar);
            }
            else
            {
                return(NotMeasuredReasons.MeasuredSuccessfully);
            }
        }
예제 #9
0
        private void TrackSingleStar(int frameNo, IAstroImage astroImage)
        {
            TrackedStar.NewFrame();
            float expectedX;
            float expectedY;

            GetExpectedXY(out expectedX, out expectedY);

            uint[,] pixels = astroImage.GetPixelsArea((int)expectedX, (int)expectedY, FIT_AREA);

            // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size
            PSFFit gaussian = new PSFFit((int)expectedX, (int)expectedY);
            gaussian.Fit(pixels, FIT_AREA);

            IImagePixel firstCenter = new ImagePixel((int)gaussian.XCenter, (int)gaussian.YCenter);

            pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, FIT_AREA);
            gaussian = new PSFFit(firstCenter.X, firstCenter.Y);
            gaussian.Fit(pixels, TrackedStar.PsfFitMatrixSize);
            if (gaussian.IsSolved)
            {
                TrackedStar.PSFFit = gaussian;
                TrackedStar.ThisFrameX = (float)gaussian.XCenter;
                TrackedStar.ThisFrameY = (float)gaussian.YCenter;
                TrackedStar.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0);
                TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty;
                TrackedStar.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully);
            }
            else
            {
                TrackedStar.ThisFrameX = expectedX;
                TrackedStar.ThisFrameY = expectedY;
                TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty;

                Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve second PSF", m_FrameNo, TrackedStar.TargetNo));
                TrackedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed);
            }
        }
예제 #10
0
            public static void PreProcessingAddRemoveHotPixels(uint[,] model, ImagePixel[] pixels, uint imageMedian, uint maxPixelValue)
            {
                uint[] xPos = pixels.Select(x => (uint)x.X).ToArray();
                uint[] yPos = pixels.Select(x => (uint)x.Y).ToArray();
                uint[] flatModel = Pixelmap.ConvertFromXYToFlatArray(model, 7, 7);

                PreProcessingAddRemoveHotPixels(flatModel, (uint)xPos.Length, xPos, yPos, imageMedian, maxPixelValue);
            }
예제 #11
0
        public void MergePixels(StarMapFeature mergeWith)
        {
            bool pixelsMerged = false;

            foreach (ulong idx in mergeWith.m_Pixels.Keys)
            {
                if (!this.m_Pixels.ContainsKey(idx))
                {
                    this.m_Pixels.Add(idx, mergeWith.m_Pixels[idx]);
                    pixelsMerged = true;
                }
            }

            if (pixelsMerged)
                m_Merges++;

            m_Center = null;
        }
예제 #12
0
        public override void DoManualFrameCorrection(int targetId, int deltaX, int deltaY)
        {
            int firstFrameId = m_PreviousPositionFrameIds[0];
            float expectedX = (float)m_LinearFitX.ComputeY(m_FrameNo - firstFrameId);
            float expectedY = (float)m_LinearFitY.ComputeY(m_FrameNo - firstFrameId);

            m_PreviousPositions.Clear();
            m_PreviousPositionFrameIds.Clear();

            ImagePixel newCenter = new ImagePixel(expectedX + deltaX, expectedY + deltaY);
            m_PreviousPositions.Add(newCenter);
            m_PreviousPositionFrameIds.Add(m_FrameNo);

            m_PreviousPositions.Add(newCenter);
            m_PreviousPositionFrameIds.Add(m_FrameNo - 1);

            m_PreviousPositions.Add(newCenter);
            m_PreviousPositionFrameIds.Add(m_FrameNo - 2);

            DoLinearFit();
        }
예제 #13
0
        public static StarMagnitudeFit PerformFit(
			IAstrometryController astrometryController,
			IVideoController videoController,
			int bitPix,
            uint maxSignalValue,
			FitInfo astrometricFit,
			TangraConfig.PhotometryReductionMethod photometryReductionMethod,
			TangraConfig.PsfQuadrature psfQuadrature,
			TangraConfig.PsfFittingMethod psfFittingMethod,
			TangraConfig.BackgroundMethod photometryBackgroundMethod,
			TangraConfig.PreProcessingFilter filter,
			List<IStar> catalogueStars,
            Guid magnitudeBandId,
			float encodingGamma,
			TangraConfig.KnownCameraResponse reverseCameraResponse,
			float? aperture,
			float? annulusInnerRadius,
			int? annulusMinPixels,
			ref float empericalPSFR0)
        {
            uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue);

            MeasurementsHelper measurer = new MeasurementsHelper(
                bitPix,
                photometryBackgroundMethod,
                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                saturatedValue);

            measurer.SetCoreProperties(
                annulusInnerRadius ?? TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                annulusMinPixels ?? TangraConfig.Settings.Photometry.AnnulusMinPixels,
                CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev,
                2 /* TODO: This must be configurable */);

            var bgProvider = new BackgroundProvider(videoController);
            measurer.GetImagePixelsCallback += new MeasurementsHelper.GetImagePixelsDelegate(bgProvider.measurer_GetImagePixelsCallback);

            List<double> intencities = new List<double>();
            List<double> magnitudes = new List<double>();
            List<double> colours = new List<double>();
            List<double> residuals = new List<double>();
            List<bool> saturatedFlags = new List<bool>();
            List<IStar> stars = new List<IStar>();
            List<PSFFit> gaussians = new List<PSFFit>();

            List<MagFitRecord> fitRecords = new List<MagFitRecord>();

            AstroImage currentAstroImage = videoController.GetCurrentAstroImage(false);
            Rectangle osdRectToExclude = astrometryController.OSDRectToExclude;
            Rectangle rectToInclude = astrometryController.RectToInclude;
            bool limitByInclusion = astrometryController.LimitByInclusion;

            int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry;

            double a = double.NaN;
            double b = double.NaN;
            double c = double.NaN;
            int excludedStars = 0;
            double empericalFWHM = double.NaN;

            try
            {
                foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs)
                {
                    if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) continue;
                    if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) continue;

                    IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo);
                    if (star == null || double.IsNaN(star.Mag) || star.Mag == 0) continue;

                    uint[,] data = currentAstroImage.GetMeasurableAreaPixels((int)pair.x, (int)pair.y, matSize);

                    PSFFit fit = new PSFFit((int)pair.x, (int)pair.y);
                    fit.Fit(data, PSF_FIT_AREA_SIZE);
                    if (!fit.IsSolved) continue;

                    MagFitRecord record = new MagFitRecord();
                    record.Star = star;
                    record.Pair = pair;
                    record.PsfFit = fit;
                    record.Saturation = IsSaturated(data, matSize, saturatedValue);

                    if (!EXCLUDE_SATURATED_STARS || !record.Saturation)
                        fitRecords.Add(record);
                }

                // We need the average R0 if it hasn't been determined yet
                if (float.IsNaN(empericalPSFR0))
                {
                    empericalPSFR0 = 0;
                    foreach (MagFitRecord rec in fitRecords)
                    {
                        empericalPSFR0 += (float)rec.PsfFit.R0;
                    }
                    empericalPSFR0 /= fitRecords.Count;
                }

                empericalFWHM = 2 * Math.Sqrt(Math.Log(2)) * empericalPSFR0;

                foreach (MagFitRecord record in fitRecords)
                {
                    ImagePixel center = new ImagePixel(255, record.Pair.x, record.Pair.y);
                    int areaSize = filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19;

                    int centerX = (int)Math.Round(center.XDouble);
                    int centerY = (int)Math.Round(center.YDouble);

                    uint[,] data = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize);
                    uint[,] backgroundPixels = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35);

                    measurer.MeasureObject(
                        center,
                        data,
                        backgroundPixels,
                        currentAstroImage.Pixelmap.BitPixCamera,
                        filter,
                        photometryReductionMethod,
                        psfQuadrature,
                        psfFittingMethod,
                        aperture != null ? aperture.Value : (float)Aperture(record.PsfFit.FWHM),
                        record.PsfFit.FWHM,
                        (float)empericalFWHM,
                        new FakeIMeasuredObject(record.PsfFit),
                        null,
                        null,
                        false);

                    double intensity = measurer.TotalReading - measurer.TotalBackground;
                    if (intensity > 0)
                    {
                        var mag = record.Star.GetMagnitudeForBand(magnitudeBandId);
                        var clr = record.Star.MagJ - record.Star.MagK;

                        if (!double.IsNaN(mag) && !double.IsNaN(clr) && !double.IsInfinity(mag) && !double.IsInfinity(clr))
                        {
                            intencities.Add(intensity);
                            magnitudes.Add(record.Star.GetMagnitudeForBand(magnitudeBandId));
                            colours.Add(record.Star.MagJ - record.Star.MagK);

                            gaussians.Add(record.PsfFit);
                            stars.Add(record.Star);
                            saturatedFlags.Add(measurer.HasSaturatedPixels || record.PsfFit.IMax >= measurer.SaturationValue);
                        }
                    }
                }

                // Remove stars with unusual PSF fit radii (once only)
                double sum = 0;
                for (int i = 0; i < gaussians.Count; i++)
                {
                    sum += gaussians[i].R0;
                }
                double averageR = sum / gaussians.Count;

                residuals.Clear();
                sum = 0;
                for (int i = 0; i < gaussians.Count; i++)
                {
                    residuals.Add(averageR - gaussians[i].R0);
                    sum += (averageR - gaussians[i].R0) * (averageR - gaussians[i].R0);
                }
                double stdDev = Math.Sqrt(sum) / gaussians.Count;

                if (EXCLUDE_BAD_RESIDUALS)
                {
                    for (int i = residuals.Count - 1; i >= 0; i--)
                    {
                        if (Math.Abs(residuals[i]) > 6 * stdDev)
                        {
                            intencities.RemoveAt(i);
                            magnitudes.RemoveAt(i);
                            colours.RemoveAt(i);
                            stars.RemoveAt(i);
                            gaussians.RemoveAt(i);
                            saturatedFlags.RemoveAt(i);
                        }
                    }
                }

                double maxResidual = Math.Max(0.1, TangraConfig.Settings.Photometry.MaxResidualStellarMags);

                for (int itter = 1; itter <= MAX_ITERR; itter++)
                {
                    residuals.Clear();

                    SafeMatrix A = new SafeMatrix(intencities.Count, 3);
                    SafeMatrix X = new SafeMatrix(intencities.Count, 1);

                    int idx = 0;
                    for (int i = 0; i < intencities.Count; i++)
                    {
                        A[idx, 0] = magnitudes[i];
                        A[idx, 1] = colours[i];
                        A[idx, 2] = 1;

                        X[idx, 0] = -2.5 * Math.Log10(intencities[i]);

                        idx++;
                    }

                    SafeMatrix a_T = A.Transpose();
                    SafeMatrix aa = a_T * A;
                    SafeMatrix aa_inv = aa.Inverse();
                    SafeMatrix bx = (aa_inv * a_T) * X;

                    double Ka = bx[0, 0];
                    double Kb = bx[1, 0];
                    double Kc = bx[2, 0];

                    // -2.5 * a * Log(Median-Intensity) = A * Mv + B * Mjk + C - b
                    // -2.5 * Log(Median-Intensity) = Ka * Mv + Kb * Mjk + Kc
                    // Mv = -2.5 * a * Log(Median-Intensity) - b * Mjk - c
                    a = 1 / Ka;
                    b = -Kb / Ka;
                    c = -Kc / Ka;

                    int starsExcludedThisTime = 0;

                    if (EXCLUDE_BAD_RESIDUALS)
                    {
                        List<int> indexesToRemove = new List<int>();
                        for (int i = 0; i < intencities.Count; i++)
                        {
                            double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c;

                            double diff = Math.Abs(computed - magnitudes[i]);
                            if (itter < MAX_ITERR)
                            {
                                if (Math.Abs(diff) > maxResidual)
                                {
                                    indexesToRemove.Add(i);
                                }
                            }
                            else
                                residuals.Add(diff);
                        }

                        for (int i = indexesToRemove.Count - 1; i >= 0; i--)
                        {
                            int idxToRemove = indexesToRemove[i];
                            intencities.RemoveAt(idxToRemove);
                            magnitudes.RemoveAt(idxToRemove);
                            colours.RemoveAt(idxToRemove);
                            stars.RemoveAt(idxToRemove);
                            gaussians.RemoveAt(idxToRemove);
                            saturatedFlags.RemoveAt(idxToRemove);

                            excludedStars++;
                            starsExcludedThisTime++;
                        }
                    }

                    if (starsExcludedThisTime == 0)
                        break;
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
            }

            return new StarMagnitudeFit(
                currentAstroImage,
                bitPix,
                intencities, magnitudes, colours, stars, gaussians, new List<double>(),
                saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM,
                photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture);
        }
예제 #14
0
 public byte[,] GetMeasurableAreaDisplayBitmapPixels(ImagePixel center)
 {
     return GetMeasurableAreaDisplayBitmapPixels(center.X, center.Y);
 }
예제 #15
0
        private ImagePixel GetExpectedPosition(int frameNo)
        {
            ImagePixel rv = null;

            var intervalValues = new Dictionary<int, List<ImagePixel>>();
            var intervalMedians = new Dictionary<int, ImagePixel>();

            int earliestFrame = m_PastFrameNos[0];
            for (int i = 0; i < m_PastFrameNos.Count; i++)
            {
                int integrationInterval = (m_PastFrameNos[i] - earliestFrame) / m_MeasurementContext.IntegratedFramesCount;

                List<ImagePixel> intPoints;
                if (!intervalValues.TryGetValue(integrationInterval, out intPoints))
                {
                    intPoints = new List<ImagePixel>();
                    intervalValues.Add(integrationInterval, intPoints);
                }

                intPoints.Add(new ImagePixel(m_PastFramePosX[i], m_PastFramePosY[i]));
            }

            var calcBucketX = new List<double>();
            var calcBucketY = new List<double>();
            foreach (int key in intervalValues.Keys)
            {
                calcBucketX.Clear();
                calcBucketY.Clear();

                intervalValues[key].ForEach(v =>
                {
                    calcBucketX.Add(v.XDouble);
                    calcBucketY.Add(v.YDouble);
                });

                double xMed = calcBucketX.Median();
                double yMed = calcBucketY.Median();

                intervalMedians.Add(key, new ImagePixel(xMed, yMed));
            }

            var xMotion = new LinearRegression();
            var yMotion = new LinearRegression();

            foreach (int intInt in intervalMedians.Keys)
            {
                long t = intInt;
                double x = intervalMedians[intInt].XDouble;
                double y = intervalMedians[intInt].YDouble;
                if (x > 0 && y > 0)
                {
                    xMotion.AddDataPoint(t, x);
                    yMotion.AddDataPoint(t, y);
                }
            }

            try
            {
                xMotion.Solve();
                yMotion.Solve();

                int currIntInterval = (frameNo - earliestFrame) / m_MeasurementContext.IntegratedFramesCount;

                rv = new ImagePixel(xMotion.ComputeY(currIntInterval), yMotion.ComputeY(currIntInterval));
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.GetFullStackTrace());
            }

            return rv;
        }
예제 #16
0
        private bool GetFitInMatrix(ITrackedObjectPsfFit gaussian, ref int matirxSize, float preselectedAperture)
        {
            rbGuidingStar.Text = "Guiding Star";
            m_IsBrightEnoughForAutoGuidingStar = false;

            if (m_Aperture == null)
            {
                if (gaussian != null && !double.IsNaN(gaussian.FWHM) && TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM)
                    m_Aperture = (float)(gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture);
                else
                    m_Aperture = (float)(TangraConfig.Settings.Photometry.DefaultSignalAperture);
            }
            else if (
                gaussian != null && !double.IsNaN(gaussian.FWHM) && TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM &&
                m_Aperture < (float)(gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture))
            {
                m_Aperture = (float) (gaussian.FWHM*TangraConfig.Settings.Photometry.DefaultSignalAperture);
            }

            nudFitMatrixSize.ValueChanged -= nudFitMatrixSize_ValueChanged;
            try
            {
                uint[,] autoStarsPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center.X, m_Center.Y, 35);
                m_AutoStarsInLargerArea = StarFinder.GetStarsInArea(
                    ref autoStarsPixels,
                    m_AstroImage.Pixelmap.BitPixCamera,
                    m_AstroImage.Pixelmap.MaxSignalValue,
                    m_AstroImage.MedianNoise,
                    LightCurveReductionContext.Instance.DigitalFilter);

                m_ProcessingPixels = ImageFilters.CutArrayEdges(autoStarsPixels, 9);
                m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center.X, m_Center.Y, 17);

                m_AutoStarsInArea = new List<PSFFit>();
                foreach (PSFFit autoStar in m_AutoStarsInLargerArea)
                {
                    if (autoStar.XCenter > 9 && autoStar.XCenter < 9 + 17 &&
                        autoStar.YCenter > 9 && autoStar.YCenter < 9 + 17)
                    {
                        // Don't change original star so use a clone
                        PSFFit clone = autoStar.Clone();
                        clone.SetNewFieldCenterFrom35PixMatrix(8, 8);
                        m_AutoStarsInArea.Add(clone);
                    }
                }

                int oldMatirxSize = matirxSize;

                if (m_AutoStarsInArea.Count == 0)
                {
                    rbGuidingStar.Text = "Guiding Star";

                    // There are no stars that are bright enough. Simply let the user do what they want, but still try to default to a sensible aperture size
                    MeasurementsHelper measurement = ReduceLightCurveOperation.DoConfiguredMeasurement(m_ProcessingPixels, m_Aperture.Value, m_AstroImage.Pixelmap.BitPixCamera, m_AstroImage.Pixelmap.MaxSignalValue, 3.0, ref matirxSize);

                    if (measurement.FoundBestPSFFit != null &&
                        measurement.FoundBestPSFFit.IsSolved &&
                        measurement.FoundBestPSFFit.Certainty > 0.1)
                    {
                        m_X0 = measurement.XCenter;
                        m_Y0 = measurement.YCenter;
                        m_FWHM = (float) measurement.FoundBestPSFFit.FWHM;
                    }
                    else
                    {
                        m_X0 = 8;
                        m_Y0 = 8;
                        m_FWHM = 6;
                    }

                    m_Gaussian = null;
                    nudFitMatrixSize.SetNUDValue(11);
                }
                else if (m_AutoStarsInArea.Count == 1)
                {
                    // There is exactly one good star found. Go and do a fit in a wider area
                    double bestFindTolerance = 3.0;

                    for (int i = 0; i < 2; i++)
                    {
                        MeasurementsHelper measurement = ReduceLightCurveOperation.DoConfiguredMeasurement(m_ProcessingPixels, m_Aperture.Value, m_AstroImage.Pixelmap.BitPixCamera, m_AstroImage.Pixelmap.MaxSignalValue, bestFindTolerance, ref matirxSize);
                        if (measurement != null && matirxSize != -1)
                        {
                            if (matirxSize < 5)
                            {
                                // Do a centroid in the full area, and get another matix centered at the centroid
                                ImagePixel centroid = new ImagePixel(m_Center.X, m_Center.Y);

                                m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(centroid);
                                m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(centroid);

                                m_X0 = centroid.X;
                                m_Y0 = centroid.Y;
                                m_FWHM = 6;
                                m_Gaussian = null;

                                nudFitMatrixSize.SetNUDValue(11);
                            }
                            else
                            {
                                m_X0 = measurement.XCenter;
                                m_Y0 = measurement.YCenter;
                                if (measurement.FoundBestPSFFit != null)
                                {
                                    m_FWHM = (float)measurement.FoundBestPSFFit.FWHM;
                                    m_Gaussian = measurement.FoundBestPSFFit;
                                }
                                else
                                {
                                    m_FWHM = 6;
                                    m_Gaussian = null;
                                }
                                m_ProcessingPixels = measurement.PixelData;
                                nudFitMatrixSize.SetNUDValue(matirxSize);
                            }
                        }
                        else
                        {
                            matirxSize = oldMatirxSize;
                            return false;
                        }

                        if (m_Gaussian != null)
                        {
                            if (IsBrightEnoughtForGuidingStar())
                            {
                                rbGuidingStar.Text = "Guiding/Comparison Star";
                                m_IsBrightEnoughForAutoGuidingStar = true;
                            }

                            break;
                        }
                    }
                }
                else if (m_AutoStarsInArea.Count > 1)
                {
                    rbGuidingStar.Text = "Guiding Star";

                    // There are more stars found.
                    double xBest = m_Gaussian != null
                                      ? m_Gaussian.XCenter
                                      : m_IsEdit ? ObjectToAdd.ApertureMatrixX0
                                                 : 8.5;

                    double yBest = m_Gaussian != null
                                      ? m_Gaussian.YCenter
                                      : m_IsEdit ? ObjectToAdd.ApertureMatrixY0
                                                 : 8.5;

                    // by default use the one closest to the original location
                    PSFFit closestFit = m_AutoStarsInArea[0];
                    double closestDist = double.MaxValue;
                    foreach (PSFFit star in m_AutoStarsInArea)
                    {
                        double dist =
                            Math.Sqrt((star.XCenter - xBest) * (star.XCenter - xBest) +
                                      (star.YCenter - yBest) * (star.YCenter - yBest));
                        if (closestDist > dist)
                        {
                            closestDist = dist;
                            closestFit = star;
                        }
                    }

                    m_X0 = (float)closestFit.XCenter;
                    m_Y0 = (float)closestFit.YCenter;
                    m_FWHM = (float)closestFit.FWHM;
                    m_Gaussian = closestFit;

                    nudFitMatrixSize.SetNUDValue(m_IsEdit ? ObjectToAdd.PsfFitMatrixSize : closestFit.MatrixSize);
                }

                //if (m_Gaussian == null && gaussian.Certainty > 0.1 && ImagePixel.ComputeDistance(gaussian.X0_Matrix, 8, gaussian.Y0_Matrix, 8) < 3)
                //{
                //	// Id we failed to locate a bright enough autostar, but the default Gaussian is still certain enough and close enought to the center, we present it as a starting point
                //	m_X0 = (float)gaussian.X0_Matrix;
                //	m_Y0 = (float)gaussian.Y0_Matrix;
                //	m_FWHM = (float)gaussian.FWHM;
                //	m_Gaussian = gaussian;
                //}

                decimal appVal;
                if (float.IsNaN(preselectedAperture))
                {
                    if (float.IsNaN(m_Aperture.Value))
                    {
                        appVal = Convert.ToDecimal(TangraConfig.Settings.Photometry.DefaultSignalAperture);
                    }
                    else
                    {
                        appVal = Convert.ToDecimal(m_Aperture.Value);
                        if (nudAperture1.Maximum < appVal) nudAperture1.Maximum = appVal + 1;
                    }
                }
                else
                    appVal = (decimal)preselectedAperture;

                if ((float)appVal > m_Aperture) m_Aperture = (float)appVal;

                nudAperture1.SetNUDValue(Math.Round(appVal, 2));

                PlotSingleTargetPixels();

                PlotGaussian();

                return true;
            }
            finally
            {
                nudFitMatrixSize.ValueChanged += nudFitMatrixSize_ValueChanged;
            }
        }
예제 #17
0
        public NotMeasuredReasons MeasureObject(
            IImagePixel center,
            uint[,] data,
            uint[,] backgroundPixels,
            int bpp,
            TangraConfig.PreProcessingFilter filter,
            TangraConfig.PhotometryReductionMethod reductionMethod,
            TangraConfig.PsfQuadrature psfQuadrature,
            TangraConfig.PsfFittingMethod psfFittingMethod,
            float aperture,
            double refinedFWHM,
            float refinedAverageFWHM,
            IMeasurableObject measurableObject,
            IImagePixel[] objectsInGroup,
            float[] aperturesInGroup,
            bool fullDisappearance)
        {
            // NOTE: This is how the center of the pixel area passed in data and background arrays is determined
            // TODO: Pass the center as an argument
            int centerX = (int)Math.Round(center.XDouble);
            int centerY = (int)Math.Round(center.YDouble);

            float msrX0 = (float)center.XDouble;
            float msrY0 = (float)center.YDouble;

            float bgAnnulusFactor = 1;

            switch (filter)
            {
            case TangraConfig.PreProcessingFilter.LowPassFilter:
                data             = ImageFilters.LowPassFilter(data, bpp, true);
                backgroundPixels = ImageFilters.LowPassFilter(backgroundPixels, bpp, true);
                break;

            case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter:
                data             = ImageFilters.LowPassDifferenceFilter(data, bpp, true);
                backgroundPixels = ImageFilters.LowPassDifferenceFilter(backgroundPixels, bpp, true);
                break;

            default:
                break;
            }

            float modelFWHM = float.NaN;

            if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
            {
                if (TangraConfig.Settings.Photometry.UseUserSpecifiedFWHM)
                {
                    modelFWHM = TangraConfig.Settings.Photometry.UserSpecifiedFWHM;
                }
                else
                {
                    modelFWHM = refinedAverageFWHM;
                }
            }

            DoublePSFFit             doublefit       = null;
            PSFFit                   fit             = null;
            IBackgroundModelProvider backgroundModel = null;

            // 1 - Fit a PSF to the current obejct
            if (objectsInGroup != null && objectsInGroup.Length == 2)
            {
                // 1A - When this is a star group
                int x1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].XDouble - center.XDouble);
                int y1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].YDouble - center.YDouble);
                int x2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].XDouble - center.XDouble);
                int y2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].YDouble - center.YDouble);
                doublefit = new DoublePSFFit(centerX, centerY);

                if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel &&
                    !float.IsNaN(modelFWHM))
                {
                    doublefit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel;
                    doublefit.SetAveragedModelFWHM(modelFWHM);
                }

                doublefit.Fit(data, x1, y1, x2, y2);

                PSFFit star1 = doublefit.GetGaussian1();
                PSFFit star2 = doublefit.GetGaussian2();

                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    var bg3dFit = new Background3DPolynomialFit();
                    bg3dFit.Fit(data, star1, star2);

                    doublefit.Fit(data, bg3dFit, x1, y1, x2, y2);

                    star1           = doublefit.GetGaussian1();
                    star2           = doublefit.GetGaussian2();
                    backgroundModel = bg3dFit;
                }

                double d1 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X1Center, measurableObject.Center.YDouble, doublefit.Y1Center);
                double d2 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X2Center, measurableObject.Center.YDouble, doublefit.Y2Center);

                fit = (d1 < d2) ? star1 : star2;

                if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry)
                {
                    // NOTE: If aperture photometry is used, we measure the double object in a single larger aperture centered at the middle
                    double alpha = Math.Atan((star2.YCenter - star1.YCenter) / (star2.XCenter - star1.XCenter));

                    float dx = (float)((star1.FWHM - star2.FWHM) * Math.Cos(alpha));
                    float dy = (float)((star1.FWHM - star2.FWHM) * Math.Sin(alpha));

                    msrX0 = (float)(star1.XCenter - star1.FWHM + star2.XCenter + star2.FWHM) / 2.0f - dx;
                    msrY0 = (float)(star1.YCenter - star1.FWHM + star2.YCenter + star2.FWHM) / 2.0f - dy;

                    aperture        = aperturesInGroup.Sum();
                    bgAnnulusFactor = 0.67f;
                }
            }
            else if (reductionMethod != TangraConfig.PhotometryReductionMethod.AperturePhotometry)
            {
                // 1B - When this is a single star
                fit = new PSFFit(centerX, centerY);

                if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel &&
                    !float.IsNaN(modelFWHM))
                {
                    fit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel;
                    fit.SetAveragedModelFWHM(modelFWHM);
                }

                fit.Fit(data, measurableObject.PsfFittingMatrixSize);

                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    // If 3D Poly Background is used then fit the background, and supply it to the PSF Fitting
                    var bg3dFit = new Background3DPolynomialFit();
                    bg3dFit.Fit(backgroundPixels, fit, null);

                    backgroundModel = bg3dFit;

                    if (psfFittingMethod != TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
                    {
                        /* 3D Poly modelling works in a direct fit only with non-linear fitting */
                        fit.Fit(backgroundPixels, bg3dFit, measurableObject.PsfFittingMatrixSize);
                    }
                }
            }
            else if (
                reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry &&
                m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
            {
                // 1C - Single star with aperture photometry and 3D Poly Background
                var bg3dFit = new Background3DPolynomialFit();
                bg3dFit.Fit(backgroundPixels, (float)(centerX - msrX0 + 17), (float)(centerY - msrY0 + 17), 2 * aperture);

                backgroundModel = bg3dFit;
            }

            // 2 - Do the actual photometric measurements (signal and background) based on the selected methods
            if (reductionMethod == TangraConfig.PhotometryReductionMethod.PsfPhotometry)
            {
                // 2A - PSF Photometry
                if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.DirectNonLinearFit)
                {
                    return(DoNonLinearProfileFittingPhotometry(
                               fit,
                               data, centerX, centerY, msrX0, msrY0,
                               aperture,
                               measurableObject.PsfFittingMatrixSize,
                               psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture,
                               measurableObject.IsOccultedStar && fullDisappearance,
                               backgroundPixels,
                               measurableObject.MayHaveDisappeared,
                               refinedFWHM,
                               bgAnnulusFactor));
                }
                else if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
                {
                    return(DoLinearProfileFittingOfAveragedMoodelPhotometry(
                               fit,
                               data, centerX, centerY, msrX0, msrY0, modelFWHM,
                               aperture,
                               measurableObject.PsfFittingMatrixSize,
                               psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture,
                               measurableObject.IsOccultedStar && fullDisappearance,
                               backgroundPixels,
                               measurableObject.MayHaveDisappeared,
                               bgAnnulusFactor, backgroundModel));
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry)
            {
                return(DoAperturePhotometry(
                           data, centerX, centerY, msrX0, msrY0,
                           aperture,
                           measurableObject.PsfFittingMatrixSize,
                           backgroundPixels, bgAnnulusFactor, backgroundModel,
                           measurableObject.Center.X, measurableObject.Center.Y));
            }
            else if (reductionMethod == TangraConfig.PhotometryReductionMethod.OptimalExtraction)
            {
                return(DoOptimalExtractionPhotometry(
                           fit,
                           data, centerX, centerY, msrX0, msrY0,
                           aperture,
                           measurableObject.PsfFittingMatrixSize,
                           measurableObject.IsOccultedStar && fullDisappearance,
                           backgroundPixels,
                           measurableObject.MayHaveDisappeared,
                           refinedFWHM, bgAnnulusFactor));
            }
            else
            {
                throw new ArgumentOutOfRangeException("reductionMethod");
            }
        }
예제 #18
0
        internal NotMeasuredReasons DoOptimalExtractionPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0,
            float aperture, int matrixSize, bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            double refinedFWHM, float bgAnnulusFactor)
        {
            // Proceed as with PSF Non linear, Then find the variance of the PSF fit and use a weight based on the residuals of the PSF fit
            // Signal[x, y] = PSF(x, y) + weight * Residual(x, y)


            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            float psfBackground = (float)fit.I0;

            // almost like aperture
            if (matrix.GetLength(0) != 17 && matrix.GetLength(0) != 35)
            {
                throw new ApplicationException("Measurement error. Correlation: AFP-101B");
            }

            int   side     = matrix.GetLength(0);
            float halfSide = side * 1f / 2f;

            m_HasSaturatedPixels = false;
            m_PSFBackground      = double.NaN;
            m_FoundBestPSFFit    = null;
            m_XCenter            = x0 - x0Int + halfSide;
            m_YCenter            = y0 - y0Int + halfSide;
            m_Aperture           = aperture;
            m_PixelData          = matrix;

            m_TotalPixels = 0;

            double varR0Sq = fit.GetVariance();

            varR0Sq = varR0Sq * varR0Sq * 2;

            double deltaX = fit.X0_Matrix - m_XCenter;
            double deltaY = fit.Y0_Matrix - m_YCenter;

            m_TotalReading = GetReading(
                m_Aperture,
                m_PixelData, side, side,
                m_XCenter, m_YCenter,
                delegate(int x, int y)
            {
                double videoPixel = m_PixelData[x, y];
                double psfValue   = fit.GetValue(x + deltaX, y + deltaY);
                if (fit.UsesBackgroundModel)
                {
                    psfValue += fit.GetFittedBackgroundModelValue(x + deltaX, y + deltaY);
                }
                double residual = videoPixel - psfValue;

                double weight = Math.Exp(-residual * residual / varR0Sq);
                return(psfValue + residual * weight);
            },
                ref m_TotalPixels);

            if (m_TotalPixels > 0)
            {
                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground)
                {
                    if (float.IsNaN(psfBackground))
                    {
                        m_TotalBackground = 0;
                    }
                    else
                    {
                        m_TotalBackground = (uint)Math.Round(m_TotalPixels * psfBackground);
                    }
                }
                else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    if (!fit.UsesBackgroundModel)
                    {
                        throw new InvalidOperationException("3D-Polynomial was not applied correctly.");
                    }

                    m_TotalBackground = Integration.IntegrationOverCircularArea(
                        (x, y) => fit.GetFittedBackgroundModelValue(x, y),
                        m_Aperture);
                }
                else if (m_BackgroundMethod != TangraConfig.BackgroundMethod.PSFBackground)
                {
                    int    offset        = (35 - fit.MatrixSize) / 2;
                    double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor);
                    m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)bgFromAnnulus);
                }
                else
                {
                    throw new ApplicationException("Measurement error. Correlation: AFP-102B");
                }

                if (!fit.IsSolved ||                                                 // The PSF solution failed, mark the reading invalid
                    (distance > tolerance && !mayBeOcculted) ||                      // If this doesn't look like a full disappearance, then make the reading invalid
                    (fit.FWHM < 0.75 * refinedFWHM || fit.FWHM > 1.25 * refinedFWHM) // The FWHM is too small or too large, make the reading invalid
                    )
                {
                    return(!fit.IsSolved
                            ? NotMeasuredReasons.MeasurementPSFFittingFailed
                            : (distance > tolerance && !mayBeOcculted)
                                ? NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar
                                : NotMeasuredReasons.FWHMOutOfRange);
                }
            }
            else
            {
                // We can't do much here, but this should never happen (??)
                m_TotalBackground = 0;
                m_TotalReading    = 0;

                return(NotMeasuredReasons.NoPixelsToMeasure);
            }

            return(NotMeasuredReasons.MeasuredSuccessfully);
        }
예제 #19
0
		private bool CheckTriangleWithRatios(int i, int j, int k, ImagePixel iCenter, ImagePixel jCenter, ImagePixel kCenter, double toleranceInArcSec)
		{
			double dijMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dijMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dikMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dikMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double djkMax = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double djkMin = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
			
			
			// Candidates for the matches
			int idxIJLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dijMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)];
			int idxIJUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dijMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)];
			int idxIKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dikMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)];
			int idxIKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dikMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)];
			int idxJKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(djkMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)];
			int idxJKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(djkMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)];

            ulong iDebugStarNo = 0, jDebugStarNo = 0, kDebugStarNo = 0;
			bool debugStarMatch = false;
			if (DebugResolvedStars != null)
			{
				if (DebugResolvedStars.TryGetValue(i, out iDebugStarNo) &&
					DebugResolvedStars.TryGetValue(j, out jDebugStarNo) &&
					DebugResolvedStars.TryGetValue(k, out kDebugStarNo))
				{
                    IStar iStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == iDebugStarNo);
                    IStar jStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == jDebugStarNo);
                    IStar kStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == kDebugStarNo);

#if ASTROMETRY_DEBUG
                    Trace.Assert(iStarAllDbg != null);
                    Trace.Assert(jStarAllDbg != null);
                    Trace.Assert(kStarAllDbg != null);
#endif

                    IStar iStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == iDebugStarNo);
                    IStar jStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == jDebugStarNo);
                    IStar kStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == kDebugStarNo);

                    if (iStarDbg != null && jStarDbg != null && kStarDbg != null)
                    {
                        debugStarMatch = true;

                        DistanceEntry deIJDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == iDebugStarNo && e.Star2.StarNo == jDebugStarNo) || (e.Star1.StarNo == jDebugStarNo && e.Star2.StarNo == iDebugStarNo));
                        DistanceEntry deIKDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == iDebugStarNo && e.Star2.StarNo == kDebugStarNo) || (e.Star1.StarNo == kDebugStarNo && e.Star2.StarNo == iDebugStarNo));
                        DistanceEntry deJKDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == kDebugStarNo && e.Star2.StarNo == jDebugStarNo) || (e.Star1.StarNo == jDebugStarNo && e.Star2.StarNo == kDebugStarNo));

#if ASTROMETRY_DEBUG
                        Trace.Assert(deIJDbg != null);
                        Trace.Assert(deIKDbg != null);
                        Trace.Assert(deJKDbg != null);
#endif

                        double dijDbg = AngleUtility.Elongation(iStarDbg.RADeg, iStarDbg.DEDeg, jStarDbg.RADeg, jStarDbg.DEDeg) * 3600;
                        double dikDbg = AngleUtility.Elongation(iStarDbg.RADeg, iStarDbg.DEDeg, kStarDbg.RADeg, kStarDbg.DEDeg) * 3600;
                        double djkDbg = AngleUtility.Elongation(kStarDbg.RADeg, kStarDbg.DEDeg, jStarDbg.RADeg, jStarDbg.DEDeg) * 3600;

#if ASTROMETRY_DEBUG
                        Trace.Assert(Math.Abs(dijDbg - deIJDbg.DistanceArcSec) < 1);
                        Trace.Assert(Math.Abs(dikDbg - deIKDbg.DistanceArcSec) < 1);
                        Trace.Assert(Math.Abs(djkDbg - deJKDbg.DistanceArcSec) < 1);
#endif
                        //TODO: Find the real focal length, then find the difference in percentages

                        //NOTE: Stars are not included because initial focal length is not correct !!!
#if ASTROMETRY_DEBUG
                        Trace.Assert(dijMax > dijDbg);
                        Trace.Assert(dijMin < dijDbg);
                        Trace.Assert(dikMax > dikDbg);
                        Trace.Assert(dikMin < dikDbg);
                        Trace.Assert(djkMax > djkDbg);
                        Trace.Assert(djkMin < djkDbg);
#endif                        
                    }
                    else
                    {
#if ASTROMETRY_DEBUG
                        if (iStarDbg == null)
                            Trace.Assert((iStarAllDbg.Mag > m_PyramidMaxMag) || (iStarAllDbg.Mag < m_PyramidMinMag));

                        if (jStarDbg == null)
                            Trace.Assert((jStarAllDbg.Mag > m_PyramidMaxMag) || (jStarAllDbg.Mag < m_PyramidMinMag));

                        if (kStarDbg == null)
                            Trace.Assert((kStarAllDbg.Mag > m_PyramidMaxMag) || (kStarAllDbg.Mag < m_PyramidMinMag));
#endif
                    }
				}
			}

			DistanceEntry ijEntry = null;
			DistanceEntry ikEntry = null;
			DistanceEntry jkEntry = null;

			for (int ij = idxIJLower; ij <= idxIJUpper; ij++)
			{
				ijEntry = m_Entries[ij];

				if (debugStarMatch)
				{
					if ((ijEntry.Star1.StarNo == iDebugStarNo && ijEntry.Star2.StarNo == jDebugStarNo) ||
						(ijEntry.Star1.StarNo == jDebugStarNo && ijEntry.Star2.StarNo == iDebugStarNo))
					{
#if ASTROMETRY_DEBUG
						Trace.Assert(ijEntry.DistanceArcSec + toleranceInArcSec >= dijMin);
						Trace.Assert(ijEntry.DistanceArcSec - toleranceInArcSec <= dijMax);
#endif
					}
				}

				if (ijEntry.DistanceArcSec + toleranceInArcSec < dijMin) continue;
				if (ijEntry.DistanceArcSec - toleranceInArcSec > dijMax) continue;

				for (int ik = idxIKLower; ik <= idxIKUpper; ik++)
				{
					ikEntry = m_Entries[ik];

				    bool debugIKPairFound = false;
					if (debugStarMatch)
					{
						if ((ikEntry.Star1.StarNo == iDebugStarNo && ikEntry.Star2.StarNo == kDebugStarNo) ||
							(ikEntry.Star1.StarNo == kDebugStarNo && ikEntry.Star2.StarNo == iDebugStarNo))
						{
#if ASTROMETRY_DEBUG
							Trace.Assert(ikEntry.DistanceArcSec + toleranceInArcSec >= dikMin);
							Trace.Assert(ikEntry.DistanceArcSec - toleranceInArcSec <= dikMax);
							Trace.Assert(Math.Abs(ijEntry.DistanceArcSec - (dijMin / dikMin) * ikEntry.DistanceArcSec) < toleranceInArcSec);
#endif
						    debugIKPairFound = true;
						}
					}

					if (ikEntry.DistanceArcSec + toleranceInArcSec < dikMin) continue;
					if (ikEntry.DistanceArcSec - toleranceInArcSec > dikMax) continue;

					if (ikEntry.Star1.StarNo != ijEntry.Star1.StarNo &&
						ikEntry.Star1.StarNo != ijEntry.Star2.StarNo &&
						ikEntry.Star2.StarNo != ijEntry.Star1.StarNo &&
						ikEntry.Star2.StarNo != ijEntry.Star2.StarNo)
					{
						// There is no possible (i, j, k) configuration that involves the same 3 stars
						continue;
					}

					double ratioDifference = Math.Abs(ijEntry.DistanceArcSec - (dijMin/dikMin) * ikEntry.DistanceArcSec);
					if (ratioDifference > toleranceInArcSec) continue;
					

					// Ratios are preserved when changing the focal length (with linear fit) so check the ratios here
					double fittedFocalLength = 
						m_PlateConfig.GetFocalLengthFromMatch(
							ijEntry.DistanceArcSec, ikEntry.DistanceArcSec, 
							iCenter, jCenter, kCenter, 
							toleranceInArcSec, m_Settings.PyramidFocalLengthAllowance);

                    if (debugIKPairFound)
					{
#if ASTROMETRY_DEBUG
					    Trace.Assert(!double.IsNaN(fittedFocalLength));
#endif
					}

					if (double.IsNaN(fittedFocalLength)) continue;

					double djk = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength);

                    ulong iStarNo = uint.MaxValue;
                    ulong needIdx1 = uint.MaxValue;
                    ulong needIdx2 = uint.MaxValue;
					if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo)
					{
						// ik_1 = ij_1 = (i)
						iStarNo = ikEntry.Star1.StarNo;
						needIdx1 = ikEntry.Star2.StarNo;
						needIdx2 = ijEntry.Star2.StarNo;
					}
					else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo)
					{
						// ik_1 = ij_2 = (i)
						iStarNo = ikEntry.Star1.StarNo;
						needIdx1 = ikEntry.Star2.StarNo; // (k)
						needIdx2 = ijEntry.Star1.StarNo; // (j)
					}
					else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo)
					{
						// ik_2 = ij_1 = (i)
						iStarNo = ikEntry.Star2.StarNo;
						needIdx1 = ikEntry.Star1.StarNo; // (k)
						needIdx2 = ijEntry.Star2.StarNo; // (j)
					}
					else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo)
					{
						// ik_2 = ij_2 = (i)
						iStarNo = ikEntry.Star2.StarNo;
						needIdx1 = ikEntry.Star1.StarNo; // (k)
						needIdx2 = ijEntry.Star1.StarNo; // (j)
					}
					else
						continue;

					if (needIdx1 == needIdx2) continue;

					jkEntry = m_Entries.Where(e => 
						(e.Star1.StarNo == needIdx1 && e.Star2.StarNo == needIdx2) ||
						(e.Star1.StarNo == needIdx2 && e.Star2.StarNo == needIdx1)).FirstOrDefault();

                    if (debugIKPairFound)
                    {
#if ASTROMETRY_DEBUG
                        Trace.Assert(jkEntry != null);
#endif

                        if (jkEntry != null)
                        {
#if ASTROMETRY_DEBUG
                            Trace.Assert(jkEntry.DistanceArcSec + toleranceInArcSec >= djk);
                            Trace.Assert(jkEntry.DistanceArcSec - toleranceInArcSec <= djk);

                            Trace.Assert(jkEntry.DistanceArcSec + toleranceInArcSec >= djkMin);
                            Trace.Assert(jkEntry.DistanceArcSec - toleranceInArcSec <= djkMax);                            
#endif
                        }
                    }

                    if (jkEntry != null)
                    {
                        ulong jStarNo = ulong.MinValue;
                        ulong kStarNo = ulong.MinValue;

                        if (jkEntry.DistanceArcSec + toleranceInArcSec < djkMin) continue;
                        if (jkEntry.DistanceArcSec - toleranceInArcSec > djkMax) continue;

                        if (jkEntry.DistanceArcSec + toleranceInArcSec < djk) continue;
                        if (jkEntry.DistanceArcSec - toleranceInArcSec > djk) continue;

                        if (jkEntry.Star1.StarNo == needIdx1 &&
                            jkEntry.Star2.StarNo == needIdx2)
                        {
							
                            m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry,
														   iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec);
                            if (m_Solution == null)
                                continue;

                            jStarNo = needIdx1;
                            kStarNo = needIdx2;
                        }

                        if (jkEntry.Star1.StarNo == needIdx2 &&
                            jkEntry.Star2.StarNo == needIdx1)
                        {
                            m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry,
														   iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec);
                            if (m_Solution == null)
                                continue;

                            jStarNo = needIdx2;
                            kStarNo = needIdx1;
                        }

                        if (m_Solution != null)
                        {
                            if (TangraConfig.Settings.Astrometry.PyramidNumberOfPivots == 3)
                                // Exist the initial alignment with only 3 candidate pivots
                                return true;

                            for (int l = 0; l < m_StarMap.Features.Count; l++)
                            {
                                var piramid = m_StarMap.Features[l];
                                if (piramid.FeatureId == i || piramid.FeatureId == j || piramid.FeatureId == k)
                                    continue;

                                var lCenter = piramid.GetCenter();

                                // NOTE: Continue until a set of distances is found in the cache for the 4-th pivot
                                double dli = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, iCenter.XDouble, iCenter.YDouble, fittedFocalLength);
                                double dlj = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, jCenter.XDouble, jCenter.YDouble, fittedFocalLength);
                                double dlk = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength);

                                List<DistanceEntry> ilCandidates = m_DistancesByMagnitude
                                    .Where(e =>
                                        (e.Star1.StarNo == iStarNo || e.Star2.StarNo == iStarNo) &&
                                        e.DistanceArcSec < dli + toleranceInArcSec && e.DistanceArcSec > dli - toleranceInArcSec)
                                    .ToList();

                                foreach (var cand_il in ilCandidates)
                                {
                                    var lStar = cand_il.Star1.StarNo == iStarNo ? cand_il.Star2 : cand_il.Star1;

                                    List<DistanceEntry> jlCandidates = m_DistancesByMagnitude
                                    .Where(e =>
                                        ((e.Star1.StarNo == jStarNo && e.Star2.StarNo == lStar.StarNo) ||
                                         (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == jStarNo)) &&
                                        e.DistanceArcSec < dlj + toleranceInArcSec && e.DistanceArcSec > dlj - toleranceInArcSec)
                                    .ToList();

                                    List<DistanceEntry> klCandidates = m_DistancesByMagnitude
                                        .Where(e =>
                                            ((e.Star1.StarNo == kStarNo && e.Star2.StarNo == lStar.StarNo) ||
                                             (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == kStarNo)) &&
                                            e.DistanceArcSec < dlk + toleranceInArcSec && e.DistanceArcSec > dlk - toleranceInArcSec)
                                        .ToList();

                                    if (jlCandidates.Count > 0 && klCandidates.Count > 0)
                                    {
                                        if (klCandidates.Count > 0)
                                            return true;
                                    }
                                }
                            }
                        }
                    }
//#if DEBUG
//                                int bestKId = -1;
//                                double bestDiff = double.MaxValue;
//#endif
//                    for (int jk = idxJKLower; jk <= idxJKUpper; jk++)
//                    {
//                        jkEntry = m_Entries[jk];
//#if DEBUG

//                                    double diff = Math.Abs(jkEntry.DistanceArcSec - djk);
//                                    if (diff < bestDiff)
//                                    {
//                                        bestDiff = diff;
//                                        bestKId = jk;
//                                    }
//#endif


//                    }

//#if DEBUG
//                                jkEntry = m_Entries[bestKId];
//                                Debug.WriteLine(
//                                    string.Format("3-rd star match failed by {0}\" ({1}, {2}, {3}) -> ({4}: {5}, {6}); [{7},{8}]",
//                                    bestDiff, i, j, k,
//                                    foundIdx0, needIdx1, needIdx2,
//                                    jkEntry.Star1.StarNo, jkEntry.Star2.StarNo));
//#endif
				}
			}


			return false;
		}
예제 #20
0
        public override void MouseClick(ObjectClickEventArgs e)
        {
            if (m_OperationState == SpectroscopyState.ChoosingStar && e.Gausian != null && e.Gausian.IsSolved && e.Gausian.Certainty > 0.2)
            {
                float bestAngle = m_SpectroscopyController.LocateSpectraAngle(e.Gausian);

                if (float.IsNaN(bestAngle))
                {
                    SelectedStar = new ImagePixel(e.Gausian.XCenter, e.Gausian.YCenter);
                    SelectedStarFWHM = e.Gausian.FWHM;
                    m_SelectedStarGaussian = e.Gausian;
                    MeasurementAreaWing = (int)(2 * Math.Ceiling(SelectedStarFWHM));
                    BackgroundAreaWing = MeasurementAreaWing;
                    BackgroundAreaGap = 5;

                    SelectedAnglePoint = Point.Empty;
                    m_ControlPanel.ClearSpectra();

                    m_OperationState = SpectroscopyState.ChoosingAngleManually;
                }
                else
                {
                    SelectedStar = new ImagePixel(e.Gausian.XCenter, e.Gausian.YCenter);
                    SelectedStarFWHM = e.Gausian.FWHM;
                    m_SelectedStarGaussian = e.Gausian;
                    MeasurementAreaWing = (int)(2 * Math.Ceiling(SelectedStarFWHM));
                    BackgroundAreaWing = MeasurementAreaWing;
                    BackgroundAreaGap = 5;

                    SetBestAngle(bestAngle);
                }

                m_VideoController.RedrawCurrentFrame(false, true);
            }
            else if (m_OperationState == SpectroscopyState.ChoosingAngleManually && SelectedStar != null)
            {
                double atanAgnle = 180 * Math.Atan((SelectedStar.YDouble - e.Pixel.YDouble)/(e.Pixel.XDouble - SelectedStar.XDouble)) / Math.PI;
                if (atanAgnle < 0) atanAgnle = 360 + atanAgnle;
                int roughAngle = (int) atanAgnle;
                float bestAngle = m_SpectroscopyController.LocateSpectraAngle(e.Gausian, roughAngle);
                if (!float.IsNaN(bestAngle))
                {
                    SetBestAngle(bestAngle);
                    m_VideoController.RedrawCurrentFrame(false, true);
                }
            }
        }
예제 #21
0
        internal frmAddOrEditSingleTarget(int objectId, ImagePixel center, PSFFit gaussian, LCStateMachine state, VideoController videoController)
        {
            InitializeComponent();

            m_VideoController = videoController;

            m_AutocenteredApertureAvailable = true;

            Text = "Add Object";
            btnAdd.Text = "Add";
            btnDontAdd.Text = "Don't Add";
            btnDelete.Visible = false;
            m_IsEdit = false;

            nudFitMatrixSize.Value = 11;
            nudFitMatrixSize.Maximum = 15;

            m_ObjectId = objectId;
            m_State = state;
            m_AstroImage = m_State.VideoOperation.m_StackedAstroImage;

            ObjectToAdd = new TrackedObjectConfig();

            m_Center = new ImagePixel(center);

            Initialize();

            if (rbOccultedStar.Enabled)
                SelectedObjectType = TrackingType.OccultedStar;
            else
                SelectedObjectType = TrackingType.GuidingStar;

            // Apply filtering to the processing pixels according to the configured default filter value
            int matirxSize = (int)nudFitMatrixSize.Value;

            GetFitInMatrix(gaussian, ref matirxSize);

            nudFitMatrixSize.Maximum = matirxSize;

            if (SelectedObjectType != TrackingType.OccultedStar)
                SetHeightAndType();
        }
예제 #22
0
 public TrackedObjectLight(byte targetNo, TrackedObjectConfig originalObject)
     : base(targetNo, originalObject)
 {
     Center = new ImagePixel(originalObject.OriginalFieldCenterX, originalObject.OriginalFieldCenterY);
 }
예제 #23
0
        internal frmAddOrEditSingleTarget(int objectId, TrackedObjectConfig selectedObject, LCStateMachine state, VideoController videoController)
        {
            InitializeComponent();

            m_VideoController = videoController;

            m_AutocenteredApertureAvailable = true;

            Text = "Edit Object";

            btnAdd.Text = "Save";
            btnDontAdd.Text = "Cancel";
            btnDelete.Visible = true;
            m_IsEdit = true;

            m_ObjectId = objectId;
            m_State = state;
            m_AstroImage = m_State.VideoOperation.m_StackedAstroImage;

            ObjectToAdd = selectedObject;

            if (selectedObject.TrackingType != TrackingType.ComparisonStar)
                nudFitMatrixSize.SetNUDValue(selectedObject.PsfFitMatrixSize);

            m_Center = new ImagePixel(
                selectedObject.OriginalFieldCenterX,
                selectedObject.OriginalFieldCenterY);

            if (ObjectToAdd.PositionTolerance > 0)
                nudPositionTolerance.SetNUDValue((decimal)ObjectToAdd.PositionTolerance);

            Initialize();

            if (!selectedObject.IsWeakSignalObject && !selectedObject.IsFixedAperture)
            {
                int matrixSize = selectedObject.PsfFitMatrixSize;
                GetFitInMatrix(selectedObject.Gaussian, ref matrixSize, selectedObject.ApertureInPixels);
                selectedObject.PsfFitMatrixSize = matrixSize;
            }
            else
            {
                m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center);
                m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center);

                m_FWHM = 6;
                m_Gaussian = null;
                m_X0 = selectedObject.ApertureMatrixX0;
                m_Y0 = selectedObject.ApertureMatrixY0;
                dx = selectedObject.ApertureDX;
                dy = selectedObject.ApertureDY;

                PlotSingleTargetPixels();

                nudAperture1.SetNUDValue((decimal) Math.Round(ObjectToAdd.ApertureInPixels, 2));
            }

            SetHeightAndType();

            if (selectedObject.TrackingType == TrackingType.GuidingStar)
                SelectedObjectType = TrackingType.GuidingStar;
            else if (selectedObject.TrackingType == TrackingType.OccultedStar)
                SelectedObjectType = TrackingType.OccultedStar;
        }
예제 #24
0
        internal void LoadFromNativeData(NativeTrackedObjectInfo trackingInfo, NativePsfFitInfo psfInfo, double[] residuals)
        {
            Center = new ImagePixel(trackingInfo.CenterX, trackingInfo.CenterY);
            LastKnownGoodPosition = new ImagePixel(trackingInfo.LastGoodPositionX, trackingInfo.LastGoodPositionY);
            LastKnownGoodPsfCertainty = trackingInfo.LastGoodPsfCertainty;
            IsLocated = trackingInfo.IsLocated == 1;
            IsOffScreen = trackingInfo.IsOffScreen == 1;
            m_TrackingFlags = TranslateTrackingFlags((NativeTrackerNotMeasuredReasons)trackingInfo.TrackingFlags);

            m_NativePsfFit.LoadFromNativePsfFitInfo(psfInfo, residuals);
        }
예제 #25
0
        public ImagePixel GetCentroid(int x, int y, int radius, bool doPeakPixelFirst, uint noiseLevel)
        {
            uint minimum = m_Pixelmap.MaxPixelValue;
            uint maximum = 0;
            int xMax = x, yMax = y;
            PixelAreaOperation(x, y, radius,
                               delegate(int x1, int y1, uint z)
                               {
                                   if (minimum > z) minimum = z;
                                   if (maximum < z)
                                   {
                                       maximum = z;

                                       if (doPeakPixelFirst)
                                       {
                                           xMax = x1;
                                           yMax = y1;
                                       }
                                   }
                               });

            if (maximum < noiseLevel) return null;

            double xx = xMax;
            double yy = yMax;
            double deltax = 0;
            double deltay = 0;

            for (int itter = 0; itter < 10; itter++)
            {
                xx += deltax;
                yy += deltay;

                double sumMomentumX = 0;
                double sumMomentumY = 0;
                double sumIntensity = 0;

                PixelAreaOperation(xMax, yMax, radius,
                                   delegate(int x1, int y1, uint z)
                                   {
                                       uint diff = Math.Max(z - minimum, 0);
                                       sumMomentumX += diff * (x1 - xx);
                                       sumMomentumY += diff * (y1 - yy);
                                       sumIntensity += diff;
                                   });

                deltax = sumMomentumX / sumIntensity;
                deltay = sumMomentumY / sumIntensity;
            }

            if (double.IsNaN(xx) || double.IsNaN(yy))
                return null;

            ImagePixel retVal = new ImagePixel(xx, yy);

            retVal.SignalNoise = retVal.Brightness * 1.0 / noiseLevel;

            return retVal;
        }
예제 #26
0
 public void AddStar(ImagePixel plateStar, IStar celestialPyramidStarEntry)
 {
     AddStar(plateStar, celestialPyramidStarEntry, null);
 }
예제 #27
0
 public uint[,] GetMeasurableAreaPixels(ImagePixel center)
 {
     return GetMeasurableAreaPixels(center.X, center.Y);
 }
예제 #28
0
 public void AddStar(ImagePixel plateStar, IStar celestialPyramidStarEntry, int featureId)
 {
     var starPair = AddStar(plateStar, celestialPyramidStarEntry, null);
     starPair.FeatureId = featureId;
 }
예제 #29
0
        public double GetIntencity(ImagePixel center, out bool isSaturated)
        {
            isSaturated = false;

            uint[,] data = m_CurrentAstroImage.GetMeasurableAreaPixels(center.X, center.Y, 17);

            PSFFit fit = new PSFFit(center.X, center.Y);
            fit.Fit(data, PSF_FIT_AREA_SIZE);
            if (!fit.IsSolved)
                return double.NaN;

            int areaSize = m_Filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19;

            int centerX = (int)Math.Round(center.XDouble);
            int centerY = (int)Math.Round(center.YDouble);

            data = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize);
            uint[,] backgroundPixels = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35);

            m_Measurer.MeasureObject(
                center,
                data,
                backgroundPixels,
                m_CurrentAstroImage.Pixelmap.BitPixCamera,
                m_Filter,
                m_PhotometryReductionMethod,
                m_PsfQuadrature,
                m_PsfFittingMethod,
                m_MeasurementAperture ?? (float)Aperture(fit.FWHM),
                fit.FWHM,
                (float)m_EmpericalFWHM,
                new FakeIMeasuredObject(fit),
                null, null,
                false);

            isSaturated = m_Measurer.HasSaturatedPixels;

            return m_Measurer.TotalReading - m_Measurer.TotalBackground;
        }
예제 #30
0
        public PlateConstStarPair AddStar(ImagePixel plateStar, IStar celestialPyramidStarEntry, StarMapFeature feature)
        {
            double detectionCertainty = plateStar.SignalNoise;

            PlateConstStarPair starPair =
                AddStar(
                    plateStar.XDouble,
                    celestialPyramidStarEntry.RADeg,
                    plateStar.YDouble,
                    celestialPyramidStarEntry.DEDeg,
                    celestialPyramidStarEntry.Mag,
                    plateStar.Brightness,
                    detectionCertainty,
                    plateStar.IsSaturated);

            #if ASTROMETRY_DEBUG
            Trace.Assert(m_Pairs.Find((pair) => pair.StarNo == celestialPyramidStarEntry.StarNo) == null);
            #endif

            starPair.StarNo = celestialPyramidStarEntry.StarNo;
            starPair.FeatureId = feature != null ? feature.FeatureId : -1;
            starPair.RADeg = celestialPyramidStarEntry.RADeg;
            starPair.DEDeg = celestialPyramidStarEntry.DEDeg;

            return starPair;
        }
예제 #31
0
        public ImagePixel GetCenter()
        {
            if (m_Center == null)
            {
                if (m_MaxBrightnessPixels == 1)
                {
                    int y = (int)(m_MaxBrightnessFirstKey / (ulong)m_Width);
                    int x = (int)(m_MaxBrightnessFirstKey % (ulong)m_Width);

                    m_Center = ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, x, y);
                }
                else
                {
                    int minX = int.MaxValue;
                    int minY = int.MaxValue;
                    int maxX = int.MinValue;
                    int maxY = int.MinValue;

                    foreach (ulong key in m_Pixels.Keys)
                    {
                        if (m_Pixels[key] < m_MaxBrightness) continue;

                        int y = (int)(key / (ulong)m_Width);
                        int x = (int)(key % (ulong)m_Width);

                        if (minX > x) minX = x;
                        if (minY > y) minY = y;
                        if (maxX < x) maxX = x;
                        if (maxY < y) maxY = y;
                    }

                    int midX = (maxX + minX) / 2;
                    bool singleMidX = ((maxX + minX) % 2) == 0;
                    int midY = (maxY + minY) / 2;
                    bool singleMidY = ((maxY + minY) % 2) == 0;

                    List<ImagePixel> checkPixels = new List<ImagePixel>();

                    if (singleMidX && singleMidY)
                    {
                        ulong midIdx = (ulong)(m_Width * midY + midX);
                        if (!m_Pixels.ContainsKey(midIdx))
                        {
                            // TODO: Send a warning of irregularly shaped feature
                        }

                        return ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY);
                    }
                    else if (singleMidX)
                    {
                        // Analyse 2 possible center points
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY));
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY + 1));
                    }
                    else if (singleMidY)
                    {
                        // Analyse 2 possible center points
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY));
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX + 1, midY));
                    }
                    else
                    {
                        // Analyse 4 possible center points
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY));
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX, midY + 1));
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX + 1, midY));
                        checkPixels.Add(ImagePixel.CreateImagePixelWithFeatureId(this.FeatureId, (int)m_MaxBrightness, midX + 1, midY + 1));
                    }

                    m_Center = null;

                    long centerBrightness = 0;

                    foreach (ImagePixel pixel in checkPixels)
                    {
                        long totalBrightness = 0;
                        for (int i = -1; i <= 1; i++)
                            for (int j = -1; j <= 1; j++)
                            {
                                totalBrightness += this[pixel.X + i, pixel.Y + j];
                            }

                        if (centerBrightness < totalBrightness)
                        {
                            centerBrightness = totalBrightness;
                            m_Center = pixel;
                        }
                    }
                }
            }

            return m_Center;
        }
예제 #32
0
		private bool CheckTrianglesWithRatiosByMagnitude(int i, int j, int k, ImagePixel iCenter, ImagePixel jCenter, ImagePixel kCenter, double toleranceInArcSec)
		{
		    if (iCenter == null || jCenter == null || kCenter == null) return false;

			double dijMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dijMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dikMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double dikMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double djkMax = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
            double djkMin = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength);
			
			List<DistanceEntry> ijCandidates = m_DistancesByMagnitude
				.Where(e => e.DistanceArcSec > dijMin && e.DistanceArcSec < dijMax).ToList();

		    if (m_ManualPairs != null && m_ManualPairs.Count <= 3) 
                LimitIJtoManualPairs(ijCandidates);

			bool debugFieldIdentified = true;
			bool debug = false;
            ulong debugiStarNo = 0;
            ulong debugjStarNo = 0;
            ulong debugkStarNo = 0;
			if (DebugResolvedStars != null)
			{
				if (DebugResolvedStars.ContainsKey(i) &&
					DebugResolvedStars.ContainsKey(j) &&
					DebugResolvedStars.ContainsKey(k))
				{
					debugiStarNo = DebugResolvedStars[i];
					debugjStarNo = DebugResolvedStars[j];
					debugkStarNo = DebugResolvedStars[k];

					debug = true;
					debugFieldIdentified = false;
				}
			}

			try
			{
				if (debug)
				{
					// The ijCandidates must contain the IJ pair
					DistanceEntry rightijEntry = ijCandidates.FirstOrDefault(c =>
						(c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugjStarNo) ||
						(c.Star1.StarNo == debugjStarNo && c.Star2.StarNo == debugiStarNo));

					if(rightijEntry == null)
					{
						DistanceEntry masterijEntry = 
							m_DistancesByMagnitude.FirstOrDefault(c =>
						        (c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugjStarNo) ||
						        (c.Star1.StarNo == debugjStarNo && c.Star2.StarNo == debugiStarNo));

						Trace.Assert(masterijEntry != null);
					}
				}

				foreach (DistanceEntry ijEntry in ijCandidates)
				{
					List<DistanceEntry> ikCandidates = m_DistancesByMagnitude
						.Where(e =>
							(e.Star1.StarNo == ijEntry.Star1.StarNo || e.Star2.StarNo == ijEntry.Star1.StarNo ||
							 e.Star1.StarNo == ijEntry.Star2.StarNo || e.Star2.StarNo == ijEntry.Star2.StarNo) &&
							 e.DistanceArcSec > dikMin && e.DistanceArcSec < dikMax)
						.ToList();

                    if (m_ManualPairs != null && m_ManualPairs.Count == 3)
                        LimitIKtoManualPairs(ikCandidates);

					if (debug && (
							(debugiStarNo == ijEntry.Star1.StarNo && debugjStarNo == ijEntry.Star2.StarNo) ||
							(debugiStarNo == ijEntry.Star2.StarNo && debugjStarNo == ijEntry.Star1.StarNo)))
					{
						// The ikCandidates must contain the IK pair
						DistanceEntry rightikEntry = ikCandidates.FirstOrDefault(c =>
							(c.Star1.StarNo == debugkStarNo || c.Star2.StarNo == debugkStarNo));

						if (rightikEntry == null)
						{
							rightikEntry = m_DistancesByMagnitude.FirstOrDefault(c =>
								(c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugkStarNo) ||
								(c.Star1.StarNo == debugkStarNo && c.Star2.StarNo == debugiStarNo));

							if (rightikEntry != null)
								Trace.Assert(rightikEntry.DistanceArcSec > dikMin && rightikEntry.DistanceArcSec < dikMax);
							else
								Trace.Assert(false, string.Format("Cannot find the ik pair ({0}, {1}) in the area distances.", debugiStarNo, debugkStarNo));
						}

					}



					foreach (DistanceEntry ikEntry in ikCandidates)
					{
						bool debugTrippleFound = false;
						if (debug && 
							((debugiStarNo == ijEntry.Star1.StarNo && debugjStarNo == ijEntry.Star2.StarNo) ||
							(debugiStarNo == ijEntry.Star2.StarNo && debugjStarNo == ijEntry.Star1.StarNo)) &&
							(debugkStarNo == ikEntry.Star1.StarNo || debugkStarNo == ikEntry.Star2.StarNo))
						{
							debugTrippleFound = true;
						}
					
						// Ratios are preserved when changing the focal length (with linear fit) so check the ratios here
						double fittedFocalLength =
							m_PlateConfig.GetFocalLengthFromMatch(
								ijEntry.DistanceArcSec, ikEntry.DistanceArcSec,
								iCenter, jCenter, kCenter,
								toleranceInArcSec, m_Settings.PyramidFocalLengthAllowance);

						if (double.IsNaN(fittedFocalLength))
						{
							Trace.Assert(!debugTrippleFound);
							continue;
						}

						double djk = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength);

                        ulong iStarNo = uint.MaxValue;
                        ulong needIdx1 = uint.MaxValue;
                        ulong needIdx2 = uint.MaxValue;

						if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo)
						{
							// ik_1 = ij_1 = (i)
							iStarNo = ikEntry.Star1.StarNo;
							needIdx1 = ikEntry.Star2.StarNo;
							needIdx2 = ijEntry.Star2.StarNo;
						}
						else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo)
						{
							// ik_1 = ij_2 = (i)
							iStarNo = ikEntry.Star1.StarNo;
							needIdx1 = ikEntry.Star2.StarNo; // (k)
							needIdx2 = ijEntry.Star1.StarNo; // (j)
						}
						else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo)
						{
							// ik_2 = ij_1 = (i)
							iStarNo = ikEntry.Star2.StarNo;
							needIdx1 = ikEntry.Star1.StarNo; // (k)
							needIdx2 = ijEntry.Star2.StarNo; // (j)
						}
						else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo)
						{
							// ik_2 = ij_2 = (i)
							iStarNo = ikEntry.Star2.StarNo;
							needIdx1 = ikEntry.Star1.StarNo; // (k)
							needIdx2 = ijEntry.Star1.StarNo; // (j)
						}
						else
						{
							Trace.Assert(!debugTrippleFound);
							continue;
						}
							

						if (needIdx1 == needIdx2)
						{
							Trace.Assert(!debugTrippleFound);
							continue;
						}

						DistanceEntry jkEntry = m_DistancesByMagnitude.Where(e =>
							(e.Star1.StarNo == needIdx1 && e.Star2.StarNo == needIdx2) ||
							(e.Star1.StarNo == needIdx2 && e.Star2.StarNo == needIdx1)).FirstOrDefault();

						if (jkEntry != null)
						{
                            ulong jStarNo = uint.MaxValue;
                            ulong kStarNo = uint.MaxValue;
                        
							if (jkEntry.DistanceArcSec + toleranceInArcSec < djkMin)
							{
								Trace.Assert(!debugTrippleFound);
								continue;
							}
							if (jkEntry.DistanceArcSec - toleranceInArcSec > djkMax)
							{
								Trace.Assert(!debugTrippleFound);
								continue;
							}

							if (jkEntry.DistanceArcSec + toleranceInArcSec < djk)
							{
								Trace.Assert(!debugTrippleFound);
								continue;
							}
							if (jkEntry.DistanceArcSec - toleranceInArcSec > djk)
							{
								Trace.Assert(!debugTrippleFound);
								continue;
							}

							if (jkEntry.Star1.StarNo == needIdx1 &&
								jkEntry.Star2.StarNo == needIdx2)
							{

								m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry,
															   iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec);
							    if (m_Solution != null)
							    {
							        jStarNo = needIdx1;
							        kStarNo = needIdx2;
							        debugFieldIdentified = true;
							    }
							    else
							    {
                                    Trace.Assert(!debugTrippleFound);
                                    continue;
							    }
									
							}

							if (jkEntry.Star1.StarNo == needIdx2 &&
								jkEntry.Star2.StarNo == needIdx1)
							{
								m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry,
															   iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec);
							    if (m_Solution != null)
							    {
							        jStarNo = needIdx2;
							        kStarNo = needIdx1;
							        debugFieldIdentified = true;
							    }
							    else
							    {
                                    Trace.Assert(!debugTrippleFound);
							        continue;
							    }
							}

						    if (m_Solution != null)
						    {
						        if (TangraConfig.Settings.Astrometry.PyramidNumberOfPivots == 3)
                                    // Exist the initial alignment with only 3 candidate pivots
						            return true;

                                for (int l = 0; l < m_StarMap.Features.Count; l++)
                                {
                                    var piramid = m_StarMap.Features[l];
                                    if (piramid.FeatureId == i || piramid.FeatureId == j || piramid.FeatureId == k)
                                        continue;

                                    var lCenter = piramid.GetCenter();

                                    // NOTE: Continue until a set of distances is found in the cache for the 4-th pivot
                                    double dli = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, iCenter.XDouble, iCenter.YDouble, fittedFocalLength);
                                    double dlj = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, jCenter.XDouble, jCenter.YDouble, fittedFocalLength);
                                    double dlk = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength);

                                    List<DistanceEntry> ilCandidates = m_DistancesByMagnitude
						                .Where(e =>
							                (e.Star1.StarNo == iStarNo || e.Star2.StarNo == iStarNo) &&
                                            e.DistanceArcSec < dli + toleranceInArcSec && e.DistanceArcSec > dli - toleranceInArcSec)
						                .ToList();

                                    foreach (var cand_il in ilCandidates)
                                    {
                                        var lStar = cand_il.Star1.StarNo == iStarNo ? cand_il.Star2 : cand_il.Star1;

                                        List<DistanceEntry> jlCandidates = m_DistancesByMagnitude
                                        .Where(e =>
                                            ((e.Star1.StarNo == jStarNo && e.Star2.StarNo == lStar.StarNo) ||
                                             (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == jStarNo)) &&
                                            e.DistanceArcSec < dlj + toleranceInArcSec && e.DistanceArcSec > dlj - toleranceInArcSec)
                                        .ToList();

                                        List<DistanceEntry> klCandidates = m_DistancesByMagnitude
                                            .Where(e =>
                                                ((e.Star1.StarNo == kStarNo && e.Star2.StarNo == lStar.StarNo) ||
                                                 (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == kStarNo)) &&
                                                e.DistanceArcSec < dlk + toleranceInArcSec && e.DistanceArcSec > dlk - toleranceInArcSec)
                                            .ToList();

                                        if (jlCandidates.Count > 0 && klCandidates.Count > 0)
                                        {
                                            if (klCandidates.Count > 0)
                                                return true;        
                                        }
                                    }                                    
                                }
						    }
						}
					}
				}
			}
			finally
			{
				if (debug && !debugFieldIdentified)
				{
					DebugCheckUnidentifiedStars(
						dijMin, dijMax, dikMin, dikMax, djkMin, djkMax,
						debugiStarNo, debugjStarNo, debugkStarNo, i, j, k);
				}
					
			}

			return false;
		}
예제 #33
0
        internal void AddPixel(int x, int y, uint brightness)
        {
            uint idx = (uint)m_Width * (uint)y + (uint)x;

            if (m_Pixels.ContainsKey(idx))
            {
            #if ASTROMETRY_DEBUG
                Trace.Assert(m_Pixels[idx] == brightness);
            #endif
            }
            else
            {
                m_Pixels.Add(idx, brightness);

                if (brightness > m_MaxBrightness)
                {
                    m_MaxBrightness = brightness;
                    m_MaxBrightnessFirstKey = idx;
                    m_MaxBrightnessPixels = 1;
                }
                else if (brightness == m_MaxBrightness)
                    m_MaxBrightnessPixels++;
            }

            m_Center = null;
            m_Intencity = UInt32.MaxValue;
        }
예제 #34
0
		private bool RegisterRecognizedPair(ImagePixel starCenter, IStar celestialStar, int featureId)
		{
			if (m_MatchedPairs.ContainsKey(starCenter))
			{
				// The feature has been already matched with a different star (from a different triangle)
				// Probably the two stars are very close to each other. In this case we don't add the second match
				// and mark the first match as ambigous. Then later on if there is sufficient amount of pairs
				// the first match may be removed as well.
				if (m_AmbiguousMatches.IndexOf(starCenter) == -1)
					m_AmbiguousMatches.Add(starCenter);

				return false;
			}

			m_MatchedPairs.Add(starCenter, celestialStar);
			m_MatchedFeatureIdToStarIdIndexes.Add(featureId, celestialStar.StarNo);
			return true;
		}
예제 #35
0
        public static Dictionary<ImagePixel, double> LocateHotPixels(AstroImage image, uint[,] model, uint modelMedian)
        {
            var rv = new Dictionary<ImagePixel, double>();
            if (s_NumSamplesCombined > 0)
            {
                int width = image.Pixelmap.Width;
                int height = image.Pixelmap.Height;
                uint abv = model[3, 3] - modelMedian;
                uint minPeakLevel = (uint)(modelMedian + PEAK_PIXEL_LEVEL_REQUIRED * abv);
                EnumeratePeakPixels(image.Pixelmap.GetPixelsCopy(), width, height, minPeakLevel, Rectangle.Empty,
                    (x, y, z) =>
                    {
                        if (x >= 3 && x < width - 3 && y >= 3 && y < height - 3)
                        {
                            var newPix = new ImagePixel((int) z, x, y);
                            if (!rv.Keys.ToArray().Any(p => p.DistanceTo(newPix) < 5))
                                rv.Add(newPix, long.MinValue);
                        }

                    });

                foreach (ImagePixel center in rv.Keys.ToArray())
                {
                    uint[,] testArea = image.GetPixelsArea(center.X, center.Y, 7);
                    var score = ScoreArea(testArea);
                    rv[center] = score.Item1;
                }

                var positions = rv.Keys.ToArray();
                var scores = rv.Values.ToArray();
                Array.Sort(scores, positions);
                s_Candidates = positions;
                s_CandidateScores = scores;
            }

            return rv;
        }
예제 #36
0
 public ImagePixel(ImagePixel clone)
     : this(clone.Brightness, clone.XDouble, clone.YDouble)
 {
 }