private bool Overlaps(CraterInfo crater) { int intersectX1 = Math.Max(x1, crater.x1); int intersectX2 = Math.Min(x2, crater.x2); int intersectY1 = Math.Max(y1, crater.y1); int intersectY2 = Math.Min(y2, crater.y2); int intersectArea = 0; if (intersectX1 <= intersectX2 && intersectY1 <= intersectY2) intersectArea = (intersectX2 - intersectX1 + 1) * (intersectY2 - intersectY1 + 1); int unionArea = Area + crater.Area - intersectArea; return (10 * intersectArea > 3 * unionArea); }
{ return "MonoCircleDetect%" + angleTolerance.ToString() + "%" + arcSigmaTolerance.ToString(); } internal override bool IsNOOP() { return false; } internal override void LoadFromSerialization(string serializationBody) { string[] split = serializationBody.Split('%'); angleTolerance = float.Parse(split[0]); arcSigmaTolerance = float.Parse(split[1]); } protected override void InitializeOperations() { ImageSource.data.CopyTo(ImageResult.data, 0); ImageResult.Craters.craters.Clear(); foreach (Cluster c in ImageSource.Clusters) { if (c.Area < 300) { //ImageResult.Craters.craters.Add(new CraterInfo(c)); continue; } if (c.Center == 49447) { } ClusterAxis longAxis = c.GetLongAxis(); c.PostProcessing_LongAxis = longAxis; ClusterAxis shortAxis = longAxis.GetOtherAxis(); List<ClusterQuadrantArc> arcs = ClusterQuadrantArc.GetArcs(longAxis, shortAxis); arcs[0].GetEdgePointsQ1Q2(); arcs[1].GetEdgePointsQ1Q2(); arcs[2].GetEdgePointsQ3Q4(); arcs[3].GetEdgePointsQ3Q4(); foreach (ClusterQuadrantArc arc in arcs) { //Determine angle change for each point List<Angle> angleChanges = new List<Angle>(); Point lastPoint = new Point(); Angle lastAngle = new Angle(0f); for (int i = 0; i < arc.EdgePoints.Count; i++) { Point currentPoint = arc.EdgePoints[i]; Angle thisAngle = new Angle(0f); if (i <= 1) { angleChanges.Add(new Angle(0f)); } else { thisAngle = Cluster.GetAngle(ref lastPoint.x, ref lastPoint.y, ref currentPoint.x, ref currentPoint.y); } if (i > 1) { angleChanges.Add(thisAngle - lastAngle); } lastAngle = thisAngle; lastPoint = currentPoint; //currentPoint.Distance(c.Center); } Angle averageAngleChange = Cluster.GetAngleAverage(angleChanges); int numberOfIntolerantChanges = 0; double percentageOfIntolerantChanges; for (int i = 2; i < angleChanges.Count; i++) { Angle angleDifference = averageAngleChange - angleChanges[i]; float absAngleDifferenceDegrees = Math.Abs(angleDifference.angleDegrees); if (absAngleDifferenceDegrees > angleTolerance) numberOfIntolerantChanges++; } percentageOfIntolerantChanges = (double)numberOfIntolerantChanges / (angleChanges.Count - 1); arc.PostProcessing_AverageAngularChange = averageAngleChange.AbsoluteValue.angleDegrees; arc.PostProcessing_PercentIntolerantChanges = percentageOfIntolerantChanges; c.PostProcessing_ClusterArcs = arcs; } } //CALCULATE STANDARD DEVIATION OF ANGULAR INTOLERANCE PERCENTAGE double averagePercentIntolerantAngularChanges = 0; foreach (Cluster c in ImageSource.Clusters) { foreach (ClusterQuadrantArc arc in c.PostProcessing_ClusterArcs) { if (arc.EdgePoints.Count < 3) averagePercentIntolerantAngularChanges += 1.0; else averagePercentIntolerantAngularChanges += arc.PostProcessing_PercentIntolerantChanges; } } averagePercentIntolerantAngularChanges /= ImageSource.Clusters.Count * 4; double sumOfDerivation = 0; foreach (Cluster c in ImageSource.Clusters) { if (c.Center == 49447) { } foreach (ClusterQuadrantArc arc in c.PostProcessing_ClusterArcs) { if (arc.EdgePoints.Count < 3) sumOfDerivation++; else sumOfDerivation += arc.PostProcessing_PercentIntolerantChanges * arc.PostProcessing_PercentIntolerantChanges; } } double sumOfDerivationAverage = sumOfDerivation / (ImageSource.Clusters.Count * 4); double StdDev = Math.Sqrt(sumOfDerivationAverage - (averagePercentIntolerantAngularChanges * averagePercentIntolerantAngularChanges)); //FILTER THE CLUSTERS List<Cluster> clustersToRemove = new List<Cluster>(); foreach (Cluster c in ImageSource.Clusters) { if (c.Center == 49447) { } foreach (ClusterQuadrantArc arc in c.PostProcessing_ClusterArcs) { if (arc.EdgePoints.Count > 3 && arc.PostProcessing_PercentIntolerantChanges > (averagePercentIntolerantAngularChanges + (StdDev * (double)arcSigmaTolerance)) * .2) arc.PostProcessing_ExcludedArc = true; else { } } List<ClusterQuadrantArc> nonExcludedArcs = c.PostProcessing_NonExcludedArcs; if (nonExcludedArcs.Count <= 1) { clustersToRemove.Add(c); continue; } if (nonExcludedArcs.Count == 3) { //Exclude the arc which is alone in the groups of [1,2][3,4] if (c.PostProcessing_ClusterArcs[0].PostProcessing_ExcludedArc || c.PostProcessing_ClusterArcs[1].PostProcessing_ExcludedArc) { c.PostProcessing_ClusterArcs[0].PostProcessing_ExcludedArc = true; c.PostProcessing_ClusterArcs[1].PostProcessing_ExcludedArc = true; } else if (c.PostProcessing_ClusterArcs[2].PostProcessing_ExcludedArc || c.PostProcessing_ClusterArcs[3].PostProcessing_ExcludedArc) { c.PostProcessing_ClusterArcs[2].PostProcessing_ExcludedArc = true; c.PostProcessing_ClusterArcs[3].PostProcessing_ExcludedArc = true; } } if (nonExcludedArcs.Count == 4) { //Find the two arcs with the average angle change that are closest to each other, exclude the rest //This finds the most "circular" part of the circle int arc1Index = 0, arc2Index = 0; float angleDeltaMinChange = 9999f; for (int i = 0; i < c.PostProcessing_ClusterArcs.Count; i++) { for (int j = i; j < c.PostProcessing_ClusterArcs.Count; j++) { if (i == j) continue; if (Math.Abs(c.PostProcessing_ClusterArcs[i].PostProcessing_AverageAngularChange - c.PostProcessing_ClusterArcs[j].PostProcessing_AverageAngularChange) < angleDeltaMinChange) { angleDeltaMinChange = Math.Abs(c.PostProcessing_ClusterArcs[i].PostProcessing_AverageAngularChange - c.PostProcessing_ClusterArcs[j].PostProcessing_AverageAngularChange); arc1Index = i; arc2Index = j; } } } List<ClusterQuadrantArc> arcsToRemove = new List<ClusterQuadrantArc>(); for (int i = 0; i < c.PostProcessing_ClusterArcs.Count; i++) if (i != arc1Index && i != arc2Index) arcsToRemove.Add(c.PostProcessing_ClusterArcs[i]); foreach (ClusterQuadrantArc arc in arcsToRemove) c.PostProcessing_ClusterArcs[c.PostProcessing_ClusterArcs.IndexOf(arc)].PostProcessing_ExcludedArc = true; } List<ClusterQuadrantArc> finalArcs = c.PostProcessing_NonExcludedArcs; if (finalArcs.Count == 2) { //Remove cluster if arcs are not adjacent if (c.PostProcessing_ClusterArcs[0].PostProcessing_ExcludedArc ^ c.PostProcessing_ClusterArcs[1].PostProcessing_ExcludedArc) { clustersToRemove.Add(c); } else { ClusterQuadrantArc finalArc; if (Math.Abs(finalArcs[0].PostProcessing_AverageAngularChange) < Math.Abs(finalArcs[1].PostProcessing_AverageAngularChange)) finalArc = finalArcs[0]; else finalArc = finalArcs[1]; Point p1, p2; //Get radius finalArc.GetBoundingBoxOfReflectedEllipse(out p1, out p2); Line line = new Line(p1, p2); Point center = line.Center; float radius = (float)line.Length / 2; radius *= 1.2f; //compensation //Calculate new 'adjusted' center of circle //Get angle to center of 'circle' from bounding line Line boundCorner = new Line(finalArc.EdgePoints[0], finalArc.EdgePoints[finalArc.EdgePoints.Count - 1]); Point centerOfBound = boundCorner.Center; Angle angleToCenter = boundCorner.AngleFromP1toP2 - new Angle(270f); Point newCenter = centerOfBound.Move(radius, angleToCenter); Point xtl = new Point((int)Math.Round(newCenter.x - radius, 0), newCenter.y - (int)Math.Round(radius, 0));