public static Mat Extract(Mat src, FaceCorners corners, Guid jobId) { var widthA = Math.Sqrt(Math.Pow(corners.BottomRight.X - corners.BottomLeft.X, 2) + Math.Pow(corners.BottomRight.Y - corners.BottomLeft.Y, 2)); var widthB = Math.Sqrt(Math.Pow(corners.TopRight.X - corners.TopLeft.X, 2) + Math.Pow(corners.TopRight.Y - corners.TopLeft.Y, 2)); var maxWidth = Math.Max(widthA, widthB); var heightA = Math.Sqrt(Math.Pow(corners.TopRight.X - corners.BottomRight.X, 2) + Math.Pow(corners.TopRight.Y - corners.BottomRight.Y, 2)); var heightB = Math.Sqrt(Math.Pow(corners.TopLeft.X - corners.BottomLeft.X, 2) + Math.Pow(corners.TopLeft.Y - corners.BottomLeft.Y, 2)); var maxHeight = Math.Max(heightA, heightB); var perspectiveTransformationMatrix = Cv2.GetPerspectiveTransform(new List <Point2f> { corners.TopLeft, corners.TopRight, corners.BottomRight, corners.BottomLeft }, new List <Point2f> { new Point2f(0, 0), new Point2f((float)maxWidth - 1, 0), new Point2f((float)maxWidth - 1, (float)maxHeight - 1), new Point2f(0, (float)maxHeight - 1), }); Mat warped = new Mat(new Size((float)maxWidth, (float)maxHeight), MatType.CV_16S); Cv2.WarpPerspective(src, warped, perspectiveTransformationMatrix, new Size((float)maxWidth, (float)maxHeight)); var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(warped); bitmap.Save($"Results\\{jobId}\\Extracted\\face-corners-" + Guid.NewGuid() + ".jpg", ImageFormat.Jpeg); return(warped); }
public static FaceCorners GetFaceCorners(Mat src, Mat tresh, Guid jobId, Window w = null) { FaceCorners result = null; var dst = ImageUtil.GetCopy(src); var copy = ImageUtil.GetCopy(tresh); var matched_countours = ContourUtil.FindContours(copy); matched_countours = matched_countours.Distinct(new LambdaComparer <Point[]>((x, y) => { var mx = GetMassCenter(x); var my = GetMassCenter(y); var dx = Math.Abs(mx.X - my.X); var dy = Math.Abs(mx.Y - my.Y); double distance = Math.Sqrt(dx * dx + dy * dy); return(mx == my || distance < 5 && distance > 0); })).ToList(); //Cv2.DrawContours(dst, matched_countours, -1, Scalar.Purple, 2); foreach (var c in matched_countours) { var angle = ContourUtil.GetAngle(c, dst); } var cts = matched_countours.GroupBy(c => ContourUtil.GetAngle(c)); int i = 1; foreach (var group in cts) { var count = group.Count(); //foreach (var c in group) //{ // Cv2.PutText(dst, "g" + ((int)i).ToString() + " " + group.Key, new Point2f(c[0].X + 20, c[0].Y + 20), HersheyFonts.HersheyPlain, 1, Scalar.SpringGreen); //} //i++; var all = group.SelectMany(g => g).ToList(); if (count == 9) { //tl var p1 = all.FirstOrDefault(pt => pt.X + pt.Y == all.Min(p => p.X + p.Y)); //br var p2 = all.FirstOrDefault(pt => pt.X + pt.Y == all.Max(p => p.X + p.Y)); //tr var p3 = all.FirstOrDefault(pt => pt.X - pt.Y == all.Min(p => p.X - p.Y)); //bl var p4 = all.FirstOrDefault(pt => pt.X - pt.Y == all.Max(p => p.X - p.Y)); var points = new List <Point>() { p1, p2, p3, p4 }; points = points.Distinct(new LambdaComparer <Point>((a, b) => { var dx = Math.Abs(a.X - b.X); var dy = Math.Abs(a.Y - b.Y); double distance = Math.Sqrt(dx * dx + dy * dy); return(distance < 20 && distance > 0); })).ToList(); // if two of the points from [tl,br,tr,bl] are ~ equal then we need to find alternatives // like the most left or the most top element if (points.Count < 4) { // top most p1 = all.FirstOrDefault(pt => pt.Y == all.Min(p => p.Y)); // left most p2 = all.FirstOrDefault(pt => pt.X == all.Min(p => p.X)); // right most p3 = all.FirstOrDefault(pt => pt.X == all.Max(p => p.X)); // bottom most p4 = all.FirstOrDefault(pt => pt.Y == all.Max(p => p.Y)); result = new FaceCorners { Rotated = true, TopMost = p1, LeftMost = p2, RightMost = p3, BottomMost = p4 }; } else { result = new FaceCorners { TopLeft = p1, BottomRight = p2, TopRight = p3, BottomLeft = p4 }; } Cv2.Circle(dst, p1, 10, Scalar.Red); Cv2.Circle(dst, p2, 10, Scalar.Red); Cv2.Circle(dst, p3, 10, Scalar.Red); Cv2.Circle(dst, p4, 10, Scalar.Red); var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst); bitmap.Save($"Results\\{jobId}\\Detected\\face-corners-" + Guid.NewGuid() + ".jpg", ImageFormat.Jpeg); } if (count >= 5 && count < 9) { result = FindFaceCornersForContour(group.FirstOrDefault(), all.ToArray()); if (result != null) { Cv2.Circle(dst, result.TopLeft, 10, Scalar.Red); Cv2.Circle(dst, result.BottomLeft, 10, Scalar.Red); Cv2.Circle(dst, result.TopRight, 10, Scalar.Red); Cv2.Circle(dst, result.BottomRight, 10, Scalar.Red); var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst); bitmap.Save($"Results\\{jobId}\\Detected\\face-corners-" + Guid.NewGuid() + ".jpg", ImageFormat.Jpeg); } } } if (w == null) { Cv2.ImShow("src", dst); } else { w.ShowImage(dst); } return(result); }