Beispiel #1
0
        void SetStar(CaptureView capture, RegionView region)
        {
            var xSize = region.VisibleWidth;
            var ySize = region.VisibleHeight;

            var sub = Photometry.GetSubImage(2,
                                             capture.ImageArray,
                                             capture.YSize,
                                             capture.XSize,
                                             region.VisibleY,
                                             region.VisibleX,
                                             region.VisibleY + ySize,
                                             region.VisibleX + xSize);

            var unclipped = Photometry.KappaSigmaClip(sub[0], 1.0, 3);

            var signal  = new ushort[sub[0].Length - unclipped.Count];
            var signals = 0;

            var background  = new ushort[unclipped.Count];
            var backgrounds = 0;

            for (var i = 0; i < sub[0].Length; i++)
            {
                if (unclipped.Contains(i))
                {
                    background[backgrounds++] = sub[0][i];
                }
                else
                {
                    signal[signals++] = sub[0][i];
                }
            }

            var regionMean      = Photometry.FindMean(sub[0]);
            var backgroundSigma = Photometry.FindStandardDeviation(background);
            var backgroundMean  = Photometry.FindMean(background);

            Focus.Star.SetStats(signals, backgrounds, regionMean, backgroundSigma, backgroundMean);

            var snr = regionMean / backgroundSigma;

            var bg = Focus.UsePhdBackgroundFormula ? regionMean + backgroundSigma * 2.0 : regionMean;

            Photometry.Subtract(sub[0], (ushort)bg);

            if (Focus.UseMedianFilter)
            {
                sub[0] = Photometry.MedianBoxFilter(sub[0], xSize, ySize);
            }

            Focus.Region.Capture = new CaptureView
            {
                XSize      = xSize,
                YSize      = ySize,
                ImageArray = sub[0],
                Image      = new Mat(ySize, xSize, MatType.CV_16UC1, sub[0])
            };

            Focus.RegionChanged();

            if (signals < 5)
            {
                Focus.Star.SetStarNotFound();
            }
            else
            {
                var brightestX = 0;
                var brightestY = 0;
                var br         = 0;

                for (var y = 0; y < ySize; y++)
                {
                    for (var x = 0; x < xSize; x++)
                    {
                        var brightest = brightestY * xSize + brightestX;

                        if (sub[0][brightest] < sub[0][y * xSize + x])
                        {
                            brightestX = x;
                            brightestY = y;
                            br         = sub[0][brightest];
                        }
                    }
                }

                var center = Photometry.FindCenterOfMass(sub[0], xSize, ySize);

                ushort peak = 0;

                for (var i = 0; i < sub[0].Length; i++)
                {
                    if (sub[0][i] > peak)
                    {
                        peak = sub[0][i];
                    }
                }

                var weightedCenterX = (center.X / (double)xSize) * 100.0;
                var weightedCenterY = (center.Y / (double)ySize) * 100.0;
                var brightestPixelX = (brightestX / (double)xSize) * 100.0;
                var brightestPixelY = (brightestY / (double)ySize) * 100.0;

                Focus.Star.SetMeasurements(
                    snr,
                    peak,
                    weightedCenterX,
                    weightedCenterY,
                    brightestPixelX,
                    brightestPixelY);

                var samples = new ushort[40];
                var max     = 0.0;

                for (var x = 0; x < 40; x++)
                {
                    samples[x] = sub[0][(int)center.Y * 40 + x];
                    max        = samples[x] > max ? samples[x] : max;
                }

                Focus.SetProfileSamples(samples);
            }
        }
Beispiel #2
0
        unsafe void ProcessImage()
        {
            var width       = _camera.CameraXSize;
            var height      = _camera.CameraYSize;
            var max         = 0;
            var starPeakAdu = 0;
            var pixels      = GetCameraAs16Bits(width, height, out max);
            var scale       = (double)ushort.MaxValue / max;
            var maxAdu      = _camera.MaxADU;
            var peakAdu     = maxAdu; // maxAdu * scale;

            var mat = new Mat(height, width, MatType.CV_16UC1, pixels);

            var mat2 = mat.GaussianBlur(new OpenCvSharp.Size(5, 5), 0, 0, BorderTypes.Default);

            if (backgroundLevel == 0)
            {
                backgroundLevel = Math.Round(Photometry.FindSkyBackgroundIntensity(pixels) * 1.5);

                Dispatcher.Invoke(() =>
                {
                    blackLevel.Text = backgroundLevel.ToString();
                });
            }

            mat2 = mat2.Threshold(backgroundLevel, ushort.MaxValue, ThresholdTypes.Binary);

            var mat3 = new Mat();

            mat2.ConvertTo(mat3, MatType.CV_8UC1);

            var contours = mat3.FindContoursAsMat(RetrievalModes.List, ContourApproximationModes.ApproxSimple);

            //mat.DrawContours(contours, -1, new Scalar(ushort.MaxValue), thickness: 2);

            var                found      = contours.Length;
            var                sat        = 0;
            var                w          = 0.0;
            var                error      = 0.0;
            StarInfo           star       = null;
            GaussianFitOptions fitOptions = GaussianFitOptions.Default;

            var graph = new Mat(256, 256, MatType.CV_8UC1);

            foreach (var contour in contours)
            {
                Point2f center;
                float   radius;

                contour.MinEnclosingCircle(out center, out radius);

                graph.SetTo(new Scalar(0));

                if (_clicked != null)
                {
                    var clickDistance = (center.X - _clicked.Value.X) * (center.X - _clicked.Value.X) + (center.Y - _clicked.Value.Y) * (center.Y - _clicked.Value.Y);

                    if (clickDistance < radius * radius)
                    {
                        var mass  = 0;
                        var peakX = 0;
                        var peakY = 0;

                        Photometry.FindStarMassAndPeak(pixels, width, height, center.X, center.Y, radius, peakAdu, out mass, out starPeakAdu, out peakX, out peakY);

                        fitOptions.Radius = (int)radius * 2;

                        peakX = (int)center.X;
                        peakY = (int)center.Y;

                        if (starPeakAdu == peakAdu)
                        {
                            sat++;
                        }

                        star = new StarInfo {
                            Peak = starPeakAdu, X = peakX, Y = peakY
                        };
                        var fit = Photometry.FindStarGaussianPSF(pixels, width, height, star, -1, GaussianFitOptions.Default);
                        w     = Photometry.GetFullWidthHalfMaximum(fit.Width);
                        error = Photometry.GaussianFitError(star.Peak, fit.Width, pixels, width, height, star, GaussianFitOptions.Default);

                        var samples = new List <Tuple <double, double> >();

                        for (var x = star.X - fitOptions.Radius; x < star.X + fitOptions.Radius; x++)
                        {
                            for (var y = star.Y - fitOptions.Radius; y < star.Y + fitOptions.Radius; y++)
                            {
                                var distance = (double)((x - star.X) * (x - star.X) + (y - star.Y) * (y - star.Y));
                                var r        = fitOptions.Radius / 2 * fitOptions.Radius / 2;

                                if (distance < r)
                                {
                                    distance = Math.Sqrt(distance);

                                    if (x < star.X)
                                    {
                                        distance *= -1;
                                    }

                                    samples.Add(new Tuple <double, double>(distance, pixels[y * width + x]));
                                }
                            }
                        }

                        var distances = samples.Select(x => x.Item1);
                        var minX      = distances.Min();
                        var maxX      = distances.Max();

                        var amplitudes = samples.Select(x => x.Item2);
                        var minY       = amplitudes.Min();
                        var maxY       = amplitudes.Max();

                        var scaleX = 160.0 / (maxX - minX);
                        var scaleY = 200.0 / (maxY - minY);

                        foreach (var sample in samples)
                        {
                            var x = 49 + (sample.Item1 - minX) * scaleX;
                            var y = 29 + (sample.Item2 - minY) * scaleY;

                            graph.Set <byte>(256 - (int)y, (int)x, byte.MaxValue);
                        }

                        var lastY = -1;

                        for (var x2 = minX; x2 < maxX; x2 += .01)
                        {
                            var distance = x2;
                            var y2       = Photometry.GaussianAmplitudeFromPSF(distance * distance, starPeakAdu, fit.Width);

                            //if (lastY == -1)
                            //{
                            lastY = (int)y2;
                            //}

                            var x  = 49 + (x2 - minX) * scaleX;
                            var y  = 29 + (y2 - minY) * scaleY;
                            var y3 = 29 + (lastY - minY) * scaleY;

                            if (lastY > y)
                            {
                                for (var yi = (int)y; yi < y3; yi++)
                                {
                                    graph.Set(256 - yi, (int)x, byte.MaxValue);
                                }
                            }
                            else
                            {
                                for (var yi = (int)y3; yi < y; yi++)
                                {
                                    graph.Set(256 - yi, (int)x, byte.MaxValue);
                                }
                            }

                            lastY = (int)y2;
                        }

                        break;
                    }
                }

                // draw saturated pixels only
                //mat = mat.Threshold(peakAdu-1, peakAdu, ThresholdTypes.Binary);
                //mat.Circle(center, (int)radius, new Scalar(ushort.MaxValue), thickness: 2);
            }

            Dispatcher.Invoke(() =>
            {
                stars.Content    = found;
                fwhm.Content     = Math.Round(w, 2);
                starPeak.Content = starPeakAdu;
                fitError.Content = error;
                mat *= scale;

                if (star != null)
                {
                    var rect = new OpenCvSharp.Rect(star.X - fitOptions.Radius, star.Y - fitOptions.Radius, fitOptions.Radius * 2, fitOptions.Radius * 2);
                    var sub2 = new Mat(fitOptions.Radius, fitOptions.Radius, MatType.CV_16SC1);
                    var sub  = new Mat(mat, rect);
                    sub.CopyTo(sub2);
                    sub2  = sub2.Resize(new OpenCvSharp.Size(256, 256), 0, 0, InterpolationFlags.Area);
                    sub2 -= backgroundLevel * scale;
                    saturated.Content = sat > 0 ? "Yes" : "No";
                    focus.Source      = sub2.ToWriteableBitmap();
                    plot.Source       = graph.ToWriteableBitmap();
                }

                preview.Source = mat.ToWriteableBitmap();
            });
        }