Пример #1
0
        /// <summary>
        /// Calls the algorithm code (depending on its type).
        /// </summary>
        static void CallAlgorithm(RunDetails Details, ImageData[] Inputs, ImageData Output)
        {
            switch (Details.Type)
            {
            case AlgorithmType.SimpleMap_T: Details.Algorithm.DynamicInvoke(Inputs[0].Data, Output.Data, Details.Parameters[0]); break;

            case AlgorithmType.SimpleMap_TU: Details.Algorithm.DynamicInvoke(Inputs[0].Data, Output.Data, Details.Parameters[0], Details.Parameters[1]); break;

            case AlgorithmType.SimpleMap_TUV: Details.Algorithm.DynamicInvoke(Inputs[0].Data, Output.Data, Details.Parameters[0], Details.Parameters[1], Details.Parameters[2]); break;

            case AlgorithmType.PositionMap:
                ImageSegmentPosition pmIP = GetPosition(Inputs[0]);
                ImageSegmentPosition pmOP = GetPosition(Output);
                Details.Algorithm.DynamicInvoke(Inputs[0].Data, Output.Data, pmIP, pmOP, Details.Parameters[0]);
                break;

            case AlgorithmType.Combiner:
                ImageSegmentPosition[] cIP = Inputs.Select(GetPosition).ToArray();
                ImageSegmentPosition   cOP = GetPosition(Output);
                Details.Algorithm.DynamicInvoke(Inputs.Select((x) => x.Data).ToArray(), Output.Data, cIP, cOP, Details.Parameters[0]); break;

            case AlgorithmType.Extractor: Details.Algorithm.DynamicInvoke(Inputs[0].Data, Details.Parameters[0]); break;

            case AlgorithmType.PositionExtractor: Details.Algorithm.DynamicInvoke(Inputs[0].Data, GetPosition(Inputs[0]), Details.Parameters[0]); break;
            }
        }
Пример #2
0
 static void DetectSources(double[,] Input, ImageSegmentPosition Position, BitArray[] Mask)
 {
     for (int i = 0; i < Input.GetLength(0); i++)
     {
         for (int j = 0; j < Input.GetLength(1); j++)
         {
             int Y = i + (int)System.Math.Round(Position.Alignment.Y);
             int X = j + (int)System.Math.Round(Position.Alignment.X);
             Mask[Y][X] = (Input[i, j] != 0);
         }
     }
 }
Пример #3
0
        /// <summary>
        /// Actual detection function for trailless light sources.
        /// </summary>
        /// <param name="Input">Input image data.</param>
        /// <param name="Position">Data position in the image.</param>
        /// <param name="Instance">DotDetector instance in which this is called.</param>
        static void DetectSources(double[,] Input, ImageSegmentPosition Position, DotDetector Instance)
        {
            int OW = Input.GetLength(1);
            int OH = Input.GetLength(0);
            int i, j;

            bool[,] Mask = new bool[OH, OW];
            List <DotDetection> ldot = new List <DotDetection>();

            /* Local mean & variance computation */
            double Mean = 0, Var = 0;
            double NThSq = Instance.NonrepresentativeThreshold * Instance.NonrepresentativeThreshold;
            int    cnt   = 0;

            for (i = 0; i < OH; i++)
            {
                for (j = 0; j < OW; j++)
                {
                    if (Input[i, j] * Input[i, j] < NThSq)
                    {
                        Mean += Input[i, j]; Var += Input[i, j] * Input[i, j]; cnt++;
                    }
                }
            }
            Mean /= cnt;
            Var  /= cnt;
            Var  -= Mean * Mean;
            double StDev         = Sqrt(Var);
            double HighThreshold = Instance.HighThresholdMultiplier * StDev + Mean;
            double LowThreshold  = Instance.LowThresholdMultiplier * StDev + Mean;

            /* Hysteresis-based detection */
            for (i = 0; i < OH; i++)
            {
                for (j = 0; j < OW; j++)
                {
                    if (Mask[i, j])
                    {
                        continue;
                    }
                    if (Input[i, j] > HighThreshold)
                    {
                        ldot.Add(BitmapFill(Input, new IntPoint()
                        {
                            X = j, Y = i
                        }, Mask, LowThreshold, (int)Position.Alignment.X, (int)Position.Alignment.Y));
                    }
                }
            }
            ldot.RemoveAll((x) => x.Pixels.Count < Instance.MinPix);
            lock (Instance.Detections)
                Instance.Detections.AddRange(ldot);
        }
Пример #4
0
        static void CoreFilterAlgorithm(double[,] Input, double[,] Output, ImageSegmentPosition InputPosition, ImageSegmentPosition OutPos, CoreFilterParameters FilterParameters)
        {
            int OW = Output.GetLength(1);
            int OH = Output.GetLength(0);
            int i, j, k, l;
            int Size = (int)Math.Round(Math.Sqrt(FilterParameters.PSF.Length));
            int XSz  = Size / 2;

            double[] MedValues = new double[FilterParameters.PSF.Length];
            double[] DPSF      = new double[FilterParameters.PSF.Length];
            int      cnt;
            double   s;
            int      SzD = Size / 2;

            for (i = 0; i < OH; i++)
            {
                for (j = 0; j < OW; j++)
                {
                    cnt = 0;
                    for (k = 0; k < Size; k++)
                    {
                        for (l = 0; l < Size; l++)
                        {
                            int Y = i + k + ((int)Math.Round(InputPosition.Alignment.Y));
                            int X = j + l + ((int)Math.Round(InputPosition.Alignment.X));
                            if (X < 0 || X >= FilterParameters.Mask[0].Length || Y < 0 || Y >= FilterParameters.Mask.Length)
                            {
                                continue;
                            }
                            DPSF[cnt] = FilterParameters.PSF[k * Size + l];
                            if (!FilterParameters.Mask[Y][X])
                            {
                                MedValues[cnt] = Input[i + k, j + l]; cnt++;
                            }
                        }
                    }
                    if (cnt <= 2 * Size + 1)
                    {
                        Output[i, j] = 0;
                    }
                    else
                    {
                        Array.Sort(MedValues, DPSF, 0, cnt);
                        double w;
                        for (s = 0, w = 0, k = Size; k <= cnt - Size; k++)
                        {
                            s += MedValues[k] * DPSF[k]; w += DPSF[k];
                        }
                        Output[i, j] = s / w;
                    }
                }
            }
        }
Пример #5
0
 /// <summary>Mesh generation function.</summary>
 static void RunMesh(double[,] Input, ImageSegmentPosition Position, Point4Distance Mesh)
 {
     /* Find median of input block */
     double[] V = new double[Input.Length];
     Buffer.BlockCopy(Input, 0, V, 0, V.Length * sizeof(double));
     Array.Sort(V);
     /* In very bright regions, keep image's zero level as the median, thus avoiding background stretching by stars */
     if (Abs(V[V.Length / 2] - Mesh.InputStat.ZeroLevel) > 10 * Mesh.InputStat.StDev)
     {
         V[V.Length / 2] = Mesh.InputStat.ZeroLevel;
     }
     /* Load the median as a mesh point */
     Mesh.MedianPoints[(int)Round(Position.Alignment.Y) / Mesh.MeshSize, (int)Round(Position.Alignment.X) / Mesh.MeshSize] = V[V.Length / 2];
 }
Пример #6
0
        static void MaskBadpixel(double[,] Input, double[,] Output, ImageSegmentPosition InputPosition, ImageSegmentPosition OutputPosition, BitArray[] Mask)
        {
            System.Diagnostics.Debug.Assert(InputPosition.Alignment.X == OutputPosition.Alignment.X);
            System.Diagnostics.Debug.Assert(InputPosition.Alignment.Y == OutputPosition.Alignment.Y);

            for (int i = 0; i < Input.GetLength(0); i++)
            {
                for (int j = 0; j < Input.GetLength(1); j++)
                {
                    int Y = i + (int)System.Math.Round(InputPosition.Alignment.Y);
                    int X = j + (int)System.Math.Round(InputPosition.Alignment.X);
                    Output[i, j] = (Mask[Y][X] ? 0.0 : Input[i, j]);
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Creates a mask from an image. All light sources are detected via a hysteresis algorithm and flagged in the mask.
        /// </summary>
        /// <param name="Input">Input image data.</param>
        /// <param name="Position">Data position in the image.</param>
        /// <param name="Properties">Bag of mask data.</param>
        static void GenerateMask(double[,] Input, ImageSegmentPosition Position, MaskProperties Properties)
        {
            int        Width = Input.GetLength(1);
            int        Height = Input.GetLength(0);
            int        i, j;
            PixelPoint pxp = new PixelPoint();

            /* Compute masking thresholds */
            double UpperThreshold = Properties.UTM * Properties.StDev + Properties.Mean;
            double LowerThreshold = Properties.LTM * Properties.StDev + Properties.Mean;

            for (i = 0; i < Height; i++)
            {
                for (j = 0; j < Width; j++)
                {
                    pxp.X = j + Position.Alignment.X;
                    pxp.Y = i + Position.Alignment.Y;

                    if (pxp.Y >= Properties.MaskData.Length)
                    {
                        break;
                    }
                    if (pxp.X >= Properties.MaskData[(int)pxp.Y].Length)
                    {
                        break;
                    }

                    if (Properties.MaskData[(int)pxp.Y][(int)pxp.X])
                    {
                        continue;
                    }

                    if (Input[i, j] > UpperThreshold)
                    {
                        BitmapFill(Properties.MaskData, Input, Position.Alignment, pxp, LowerThreshold, Properties.MaskRadiusMultiplier, Properties.ExtraMaskRadius, out Filtering.Star? Star);
                        if (Star != null)
                        {
                            Filtering.Star S = Star.Value; S.EqCenter = Position.WCS.GetEquatorialPoint(S.PixCenter); lock (Properties.StarList) Properties.StarList.FixedStarList.Add(S);
                        }
                    }
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Masks the input image with a given mask. Masked pixels are set to -1 standard deviation.
        /// </summary>
        /// <param name="Input">Input image data.</param>
        /// <param name="Output">Output image data.</param>
        /// <param name="InputPosition">Input data position.</param>
        /// <param name="OutputPosition">Output data position.</param>
        /// <param name="Properties">Mask data.</param>
        static void MaskImage(double[,] Input, double[,] Output, ImageSegmentPosition InputPosition, ImageSegmentPosition OutputPosition, MaskProperties Properties)
        {
            int Width = Output.GetLength(1);
            int Height = Output.GetLength(0);
            int i, j;

            PixelPoint pxp = new PixelPoint();

            for (i = 0; i < Height; i++)
            {
                for (j = 0; j < Width; j++)
                {
                    pxp.X = j + OutputPosition.Alignment.X; pxp.Y = i + OutputPosition.Alignment.Y;
                    EquatorialPoint ep  = OutputPosition.WCS.GetEquatorialPoint(pxp);
                    PixelPoint      mpt = Properties.MaskTransform.GetPixelPoint(ep);
                    mpt.X = Math.Round(mpt.X); mpt.Y = Math.Round(mpt.Y);
                    if (mpt.X < 0 || mpt.X >= Properties.MaskData[0].Length)
                    {
                        continue;
                    }
                    if (mpt.Y < 0 || mpt.Y >= Properties.MaskData.Length)
                    {
                        continue;
                    }
                    PixelPoint ipt = InputPosition.WCS.GetPixelPoint(ep);
                    ipt.X = Math.Round(ipt.X - InputPosition.Alignment.X); ipt.Y = Math.Round(ipt.Y - InputPosition.Alignment.Y);

                    if (Properties.MaskData[(int)mpt.Y][(int)mpt.X])
                    {
                        Output[i, j] = -Properties.StDev;
                    }
                    else
                    {
                        Output[i, j] = Input[(int)ipt.Y, (int)ipt.X] - Properties.Mean;
                    }
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Output normalization function.
        /// </summary>
        static void Normalize(double[,] Input, double[,] Output, ImageSegmentPosition InputPosition, ImageSegmentPosition OutputPosition, Point4Distance Mesh)
        {
            int OH = Input.GetLength(0), OW = Input.GetLength(1);
            int i, j;

            /* Deal with image edges */
            if (InputPosition.Alignment.Y <= Mesh.MeshSize)
            {
                for (i = 0; i < OH; i++)
                {
                    for (j = 0; j < Mesh.MeshSize; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[2, 2];
                    }
                    for (; j < OW - Mesh.MeshSize; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[2, j / Mesh.MeshSize];
                    }
                    for (; j < OW; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[2, Mesh.MedianPoints.GetLength(1) - 3];
                    }
                }
                return;
            }
            if (InputPosition.Alignment.Y + 2 * Mesh.MeshSize >= Mesh.Input.Height)
            {
                for (i = 0; i < OH; i++)
                {
                    for (j = 0; j < Mesh.MeshSize; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[Mesh.MedianPoints.GetLength(0) - 2, 2];
                    }
                    for (; j < OW - Mesh.MeshSize; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[Mesh.MedianPoints.GetLength(0) - 2, j / Mesh.MeshSize];
                    }
                    for (j = 0; j < Mesh.MeshSize; j++)
                    {
                        Output[i, j] = Input[i, j] - Mesh.MedianPoints[Mesh.MedianPoints.GetLength(0) - 2, Mesh.MedianPoints.GetLength(1) - 3];
                    }
                }
                return;
            }

            for (i = 0; i < OH; i++)
            {
                for (j = 0; j < 3 * Mesh.MeshSize / 2; j++)
                {
                    Output[i, j] = Input[i, j] - Mesh.MedianPoints[(i + (int)InputPosition.Alignment.Y) / Mesh.MeshSize, 2];
                }
                /* Perform main loop */
                for (; j < OW - 3 * Mesh.MeshSize / 2; j++)
                {
                    int      PX = (int)InputPosition.Alignment.X + j;
                    int      PY = (int)InputPosition.Alignment.Y + i;
                    double[] Distances = new double[4];
                    double   DistSum, ValSum;

                    /* Find nearest mesh points and the distances to them */
                    int dPX = PX % Mesh.MeshSize;
                    int dPY = PY % Mesh.MeshSize;
                    int kPX = PX / Mesh.MeshSize;
                    int kPY = PY / Mesh.MeshSize;
                    Distances[0] = Sqrt(dPX * dPX + dPY * dPY);
                    Distances[1] = Sqrt((Mesh.MeshSize - dPX) * (Mesh.MeshSize - dPX) + dPY * dPY);
                    Distances[2] = Sqrt((Mesh.MeshSize - dPY) * (Mesh.MeshSize - dPY) + dPX * dPX);
                    Distances[3] = Sqrt((Mesh.MeshSize - dPX) * (Mesh.MeshSize - dPX) + (Mesh.MeshSize - dPY) * (Mesh.MeshSize - dPY));
                    DistSum      = Distances[0] + Distances[1] + Distances[2] + Distances[3];
                    /* Interpolate based on the distance to each mesh point */
                    ValSum  = (DistSum - Distances[0]) * Mesh.MedianPoints[kPY, kPX] + (DistSum - Distances[1]) * Mesh.MedianPoints[kPY, kPX + 1];
                    ValSum += (DistSum - Distances[2]) * Mesh.MedianPoints[kPY + 1, kPX] + (DistSum - Distances[3]) * Mesh.MedianPoints[kPY + 1, kPX + 1];
                    double Interpolated = ValSum / DistSum / 3;
                    /* Remove background */
                    Output[i, j] = Input[i, j] - Interpolated;
                }
                for (; j < OW; j++)
                {
                    Output[i, j] = Input[i, j] - Mesh.MedianPoints[(i + (int)InputPosition.Alignment.Y) / Mesh.MeshSize, Mesh.MedianPoints.GetLength(1) - 3];
                }
            }
        }