/// <summary> /// The segment detector function. It calls the RLHT scorer and if line segments are sensed, it calls the LineAnalyzer to find the source blobs. /// </summary> /// <param name="Input">Input data.</param> /// <param name="Position">Position of the input data array in the image.</param> /// <param name="Data">Bag of algorithm parameters and data.</param> static void LTD_RLHT(double[,] Input, SchedCore.ImageSegmentPosition Position, LongTrailData Data) { /* Extracts the size of the input data */ int Height = Input.GetLength(0), Width = Input.GetLength(1); double Diagonal = Math.Sqrt(Width * Width + Height * Height); /* Initialize VPool */ lock (Data.AgData.VPool) if (Data.AgData.VPool.Constructor == null) { Data.AgData.VPool.Constructor = () => new List <Vector>(); } /* Applies the RLHT algorithm */ Data.AgData.StrongValueFunction = (x) => ThresholdComputer(x, Data, Diagonal); var Result = RLHT.SmartSkipRLHT(Input, Data.ImageParameters, Data.AgData); /* Prepare common data for the LineAnalyzer */ bool[,] Mask = new bool[Height, Width]; double SST = Data.SegmentSelectThreshold * Data.Sigma, SDT = Data.SegmentDropThreshold * Data.Sigma; int MIB = Data.MaxInterblobDistance, SW = Data.ScanWidth, pX = (int)Position.Alignment.X, pY = (int)Position.Alignment.Y; if (Data.DropCrowdedRegion) /* If the region is too crowded, it's very likely to be some luminous residue - for example star halos */ { if (Result.StrongPoints.Count > Diagonal) /* There is no deep meaning between this comparison; a reasonable Diagonal seems to correspond to a reasonable number of lines */ { goto clear_end; } } /* Analyze each possible trail line and store the detections */ foreach (Vector vx in Result.StrongPoints) { var z = LineAnalyzer.AnalyzeLine(Input, Mask, Height, Width, vx.X, vx.Y, SST, SDT, MIB, SW, pX, pY); lock (Data.Results) Data.Results.AddRange(z.Select((x) => StandardDetectionFactory.CreateDetection(Data.RunningImage, x.Points, x.PointValues))); } clear_end: /* Release resources */ Result.StrongPoints.Clear(); Data.AgData.HTPool.Release(); Data.AgData.VPool.Release(); }
/// <summary> /// Performs a median filter between multiple data sets. /// </summary> /// <param name="Inputs">Input data.</param> /// <param name="Output">Output data.</param> /// <param name="InputPositions">Input alignments.</param> /// <param name="OutputPosition">Output alignment.</param> /// <param name="empty">Dummy argument.</param> static void MultiImageMedianFilter(double[][,] Inputs, double[,] Output, SchedCore.ImageSegmentPosition[] InputPositions, SchedCore.ImageSegmentPosition OutputPosition, object empty) { PixelPoint[] InputAlignments = InputPositions.Select((x) => x.Alignment).ToArray(); PixelPoint OutputAlignment = OutputPosition.Alignment; IWCSProjection[] InputImagesTransforms = InputPositions.Select((x) => x.WCS).ToArray(); IWCSProjection OutputImageTransform = OutputPosition.WCS; int OW = Output.GetLength(1); int OH = Output.GetLength(0); int i, j, k, c; double[] MedValues = new double[Inputs.Length]; PixelPoint pxp = new PixelPoint(); for (i = 0; i < OH; i++) { for (j = 0; j < OW; j++) { pxp.X = j + OutputAlignment.X; pxp.Y = i + OutputAlignment.Y; EquatorialPoint eqp = OutputImageTransform.GetEquatorialPoint(pxp); c = 0; for (k = 0; k < Inputs.Length; k++) { PixelPoint pyp = InputImagesTransforms[k].GetPixelPoint(eqp); pyp.X = Math.Round(pyp.X - InputAlignments[k].X); pyp.Y = Math.Round(pyp.Y - InputAlignments[k].Y); if (pyp.X < 0 || pyp.X >= Inputs[k].GetLength(1)) { continue; } if (pyp.Y < 0 || pyp.Y >= Inputs[k].GetLength(0)) { continue; } double dex = Inputs[k][(int)pyp.Y, (int)pyp.X]; MedValues[c] = dex; c++; } if (c == 0) { continue; } Array.Sort(MedValues); if (c % 2 == 1) { Output[i, j] = MedValues[c / 2]; } else { Output[i, j] = MedValues[c / 2 - 1]; } } } }