public static List <Point[]> SelectMarkers(List <Point[]> candidateCorners, Bitmap undistoredImage) { return(candidateCorners.Where(corners => { int minX = int.MaxValue; int maxX = int.MinValue; int minY = int.MaxValue; int maxY = int.MinValue; double perimeter = 0; for (int i = 0; i < corners.Length; i++) { perimeter += Math.Sqrt(Math.Pow(corners[i].X - corners[(i + 1) % corners.Length].X, 2) + Math.Pow(corners[i].Y - corners[(i + 1) % corners.Length].Y, 2)); minX = Math.Min(minX, corners[i].X); maxX = Math.Max(maxX, corners[i].X); minY = Math.Min(minY, corners[i].Y); maxY = Math.Max(maxY, corners[i].Y); } var side = perimeter / 4; var total_cnt = 0; var border_cnt = 0; double border_sum = 0; for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { if (CornerDetector.checkPointInPolygon(new Point(x, y), corners.ToList())) { total_cnt++; var dist = Douglas_Peucker.CalcDistFromPointToPolygon(new Point(x, y), corners); var pixel = undistoredImage.GetPixel(x, y); var res = 0.21 * pixel.R + 0.72 * pixel.G + 0.07 * pixel.B; if (dist < side * borderRate) { border_cnt++; border_sum += res; } } } } var average = border_sum / border_cnt; return average <= blackThreshold; }).ToList()); }
public static List <Point[]> FindCorners(MyImage source) { var dx = new int[] { 1, -1, 0, 0 }; var dy = new int[] { 0, 0, 1, -1 }; var minMarkerPerimeterRate = 0.05; var minDimension = Math.Min(source.Height, source.Width); var minPerimeter = minDimension * minMarkerPerimeterRate; Console.WriteLine("MinPerimeter = " + minPerimeter); var candidateCorners = new List <List <Point> >(); var visited = new bool[source.Height, source.Width]; for (int x = 1; x < source.Height - 1; x++) { for (int y = 1; y < source.Width - 1; y++) { if (!visited[x, y] && source.red[x, y] >= whiteThreshold) { var points = new List <Point>(); var queue = new Queue <Point>(); var startPixel = new Point(x, y); queue.Enqueue(startPixel); visited[x, y] = true; while (queue.Count > 0) { var currentPixel = queue.Dequeue(); points.Add(currentPixel); for (int direction = 0; direction < dx.Length; direction++) { var nextPoint = new Point(currentPixel.X + dx[direction], currentPixel.Y + dy[direction]); if (!visited[nextPoint.X, nextPoint.Y] && source.red[nextPoint.X, nextPoint.Y] >= whiteThreshold) { queue.Enqueue(nextPoint); visited[nextPoint.X, nextPoint.Y] = true; } } } points = SortPoints(points); var corners = new List <Point>(); Douglas_Peucker.DouglasPeucker(points, 0, points.Count - 1, ref corners, true); double perimeter = 0; var minSide = double.MaxValue; var maxSide = double.MinValue; for (int i = 0; i < corners.Count; i++) { var side = Math.Sqrt(Math.Pow(corners[i].X - corners[(i + 1) % corners.Count].X, 2) + Math.Pow(corners[i].Y - corners[(i + 1) % corners.Count].Y, 2)); perimeter += side; minSide = Math.Min(minSide, side); maxSide = Math.Max(maxSide, side); } if (corners.Count == 4 && minSide / maxSide > 0.6 && perimeter >= minPerimeter) { Console.WriteLine("corner 1: " + corners[0]); Console.WriteLine(minSide + " " + maxSide + " " + minSide / maxSide + " " + perimeter); candidateCorners.Add(corners); } } ; } } ; return(candidateCorners.Select(c => c.Select(p => new Point(p.Y, p.X)).ToArray()).ToList()); }