Exemplo n.º 1
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();
            });
        }