internal SpectraReader(AstroImage image, float angleDegrees) { m_Image = image; m_Mapper = new RotationMapper(image.Width, image.Height, angleDegrees); m_SourceVideoFrame = new RectangleF(0, 0, image.Width, image.Height); }
internal float LocateSpectraAngle(PSFFit selectedStar, AstroImage image) { float x0 = (float)selectedStar.XCenter; float y0 = (float)selectedStar.YCenter; uint brigthness10 = (uint)(0.1 * selectedStar.Brightness); uint brigthness20 = (uint)(0.2 * selectedStar.Brightness); uint brigthness40 = (uint)(0.4 * selectedStar.Brightness); uint bgFromPsf = (uint)(selectedStar.I0); int minDistance = (int)(10 * selectedStar.FWHM); int clearDist = (int)(2 * selectedStar.FWHM); float width = image.Width; float height = image.Height; uint[] angles = new uint[360]; uint[] sums = new uint[360]; uint[] pixAbove10Perc = new uint[360]; uint[] pixAbove20Perc = new uint[360]; uint[] pixAbove40Perc = new uint[360]; int diagonnalPixels = (int)Math.Ceiling(Math.Sqrt(image.Width * image.Width + image.Height * image.Height)); int iFrom = 0; int iTo = 360; bool peakFound = false; for (int i = iFrom; i < iTo; i++) { var mapper = new RotationMapper(image.Width, image.Height, i); PointF p1 = mapper.GetDestCoords(x0, y0); float x1 = p1.X; float y1 = p1.Y; uint rowSum = 0; uint pixAbove10 = 0; uint pixAbove10Max = 0; bool prevPixAbove10 = false; uint pixAbove20 = 0; uint pixAbove20Max = 0; bool prevPixAbove20 = false; uint pixAbove40 = 0; uint pixAbove40Max = 0; bool prevPixAbove40 = false; for (int d = minDistance; d < diagonnalPixels; d++) { PointF p = mapper.GetSourceCoords(x1 + d, y1); if (p.X >= 0 && p.X < width && p.Y >= 0 && p.Y < height) { uint value = (uint)image.GetPixel((int)p.X, (int)p.Y); rowSum += value; PointF pu = mapper.GetSourceCoords(x1 + d, y1 + clearDist); PointF pd = mapper.GetSourceCoords(x1 + d, y1 - clearDist); if (pu.X >= 0 && pu.X < width && pu.Y >= 0 && pu.Y < height && pd.X >= 0 && pd.X < width && pd.Y >= 0 && pd.Y < height) { uint value_u = (uint)image.GetPixel((int)pu.X, (int)pu.Y); uint value_d = (uint)image.GetPixel((int)pd.X, (int)pd.Y); if ((value - bgFromPsf) > brigthness10 && value > value_u && value > value_d) { if (prevPixAbove10) pixAbove10++; prevPixAbove10 = true; } else { prevPixAbove10 = false; if (pixAbove10Max < pixAbove10) pixAbove10Max = pixAbove10; pixAbove10 = 0; peakFound = true; } if ((value - bgFromPsf) > brigthness20 && value > value_u && value > value_d) { if (prevPixAbove20) pixAbove20++; prevPixAbove20 = true; } else { prevPixAbove20 = false; if (pixAbove20Max < pixAbove20) pixAbove20Max = pixAbove20; pixAbove20 = 0; peakFound = true; } if ((value - bgFromPsf) > brigthness40 && value > value_u && value > value_d) { if (prevPixAbove40) pixAbove40++; prevPixAbove40 = true; } else { prevPixAbove40 = false; if (pixAbove40Max < pixAbove40) pixAbove40Max = pixAbove40; pixAbove40 = 0; peakFound = true; } } else { prevPixAbove10 = false; if (pixAbove10Max < pixAbove10) pixAbove10Max = pixAbove10; pixAbove10 = 0; prevPixAbove20 = false; if (pixAbove20Max < pixAbove20) pixAbove20Max = pixAbove20; pixAbove20 = 0; prevPixAbove40 = false; if (pixAbove40Max < pixAbove40) pixAbove40Max = pixAbove40; pixAbove40 = 0; peakFound = true; } } } angles[i] = (uint)i; sums[i] = rowSum; pixAbove10Perc[i] = pixAbove10Max; pixAbove20Perc[i] = pixAbove20Max; pixAbove40Perc[i] = pixAbove40Max; } if (!peakFound) return float.NaN; var angles10 = new List<uint>(angles).ToArray(); var angles20 = new List<uint>(angles).ToArray(); var angles40 = new List<uint>(angles).ToArray(); Array.Sort(sums, angles); Array.Sort(pixAbove10Perc, angles10); Array.Sort(pixAbove20Perc, angles20); Array.Sort(pixAbove40Perc, angles40); uint roughAngle = angles[359]; if (pixAbove10Perc[358]*2 < pixAbove10Perc[359]) { // If second best at 10% id a lot smaller score than the top 10% scopem then this is it roughAngle = angles10[359]; } else { if (Math.Abs((int)angles[358] - (int)angles[359]) > 3)// or for large stars the two best can be sequential angles return float.NaN; } uint bestSum = 0; float bestAngle = 0f; for (float a = roughAngle - 1; a < roughAngle + 1; a += 0.02f) { var mapper = new RotationMapper(image.Width, image.Height, a); PointF p1 = mapper.GetDestCoords(x0, y0); float x1 = p1.X; float y1 = p1.Y; uint rowSum = 0; for (int d = minDistance; d < diagonnalPixels; d++) { PointF p = mapper.GetSourceCoords(x1 + d, y1); if (p.X >= 0 && p.X < width && p.Y >= 0 && p.Y < height) { uint pixVal = (uint)image.GetPixel((int)p.X, (int)p.Y); rowSum += pixVal; } } if (rowSum > bestSum) { bestSum = rowSum; bestAngle = a; } } return bestAngle; }
private bool SelectingStarSpectra(Point location, bool shiftHeld, bool controlHeld) { IVideoFrame currentVideoFrame = m_VideoRenderingController.GetCurrentFrame(); if (currentVideoFrame != null) { var astroImg = new AstroImage(currentVideoFrame, m_VideoRenderingController.Width, m_VideoRenderingController.Height, currentVideoFrame.MaxSignalValue); uint[,] areaPixels = astroImg.GetMeasurableAreaPixels(location.X, location.Y); PSFFit psfFit = new PSFFit(location.X, location.Y); psfFit.Fit(areaPixels); if (psfFit.IsSolved && psfFit.Certainty > Settings.Default.TrackingMinGuidingCertainty) { float angle = LocateSpectraAngle(psfFit, astroImg); if (!float.IsNaN(angle)) { TrackingContext.Current.GuidingStar = new LastTrackedPosition(m_Bpp) { FWHM = (float)psfFit.FWHM, X = (float)psfFit.XCenter, Y = (float)psfFit.YCenter, IsFixed = false }; TrackingContext.Current.ReConfigureNativeTracking(m_VideoRenderingController.Width, m_VideoRenderingController.Height); TrackingContext.Current.SpectraAngleDeg = angle; return true; } } } return false; }
private bool SelectingTargetStar(Point location, bool shiftHeld, bool controlHeld) { IVideoFrame currentVideoFrame = m_VideoRenderingController.GetCurrentFrame(); if (currentVideoFrame != null) { var astroImg = new AstroImage(currentVideoFrame, m_VideoRenderingController.Width, m_VideoRenderingController.Height); uint[,] areaPixels = astroImg.GetMeasurableAreaPixels(location.X, location.Y); PSFFit psfFit = new PSFFit(location.X, location.Y); psfFit.Fit(areaPixels); TrackingContext.Current.TargetStar = new LastTrackedPosition(m_Bpp) { FWHM = (float)psfFit.FWHM, X = (float)psfFit.XCenter, Y = (float)psfFit.YCenter }; TrackingContext.Current.TargetStar.IsFixed = !psfFit.IsSolved || psfFit.Certainty < Settings.Default.TrackingMinForcedFixedObjCertainty || controlHeld; TrackingContext.Current.TargetStar.IsFullDisapearance = shiftHeld; TrackingContext.Current.ReConfigureNativeTracking(m_VideoRenderingController.Width, m_VideoRenderingController.Height); return true; } return false; }
private bool SelectGuidingStar(Point location, bool shiftHeld, bool controlHeld) { IVideoFrame currentVideoFrame = m_VideoRenderingController.GetCurrentFrame(); if (currentVideoFrame != null) { // Find the object at the location and set it as a guiding star var astroImg = new AstroImage(currentVideoFrame, m_VideoRenderingController.Width, m_VideoRenderingController.Height); uint[,] areaPixels = astroImg.GetMeasurableAreaPixels(location.X, location.Y); PSFFit psfFit = new PSFFit(location.X, location.Y); psfFit.Fit(areaPixels); if (psfFit.IsSolved && psfFit.Certainty > Settings.Default.TrackingMinGuidingCertainty) { TrackingContext.Current.GuidingStar = new LastTrackedPosition(m_Bpp) { FWHM = (float)psfFit.FWHM, X = (float)psfFit.XCenter, Y = (float)psfFit.YCenter, IsFixed = false }; TrackingContext.Current.ReConfigureNativeTracking(m_VideoRenderingController.Width, m_VideoRenderingController.Height); TrackingContext.Current.SpectraAngleDeg = float.NaN; return true; } else { // NOTE: Too faint to be used as a guiding star MessageBox.Show(m_MainForm, "This object is not bright enought for a Guiding star.", "OccuRec", MessageBoxButtons.OK, MessageBoxIcon.Error); } } return false; }