/// <summary> /// Create a template /// </summary> private void TrainTemplate() { try { results.Clear(); using (Mat src = new Mat()) using (Mat output = new Mat()) using (Mat gx = new Mat()) using (Mat gy = new Mat()) using (Mat magnitude = new Mat()) using (Mat direction = new Mat()) { /// convert to gray image Cv2.CvtColor(template, src, ColorConversionCodes.RGB2GRAY); /// using the canny algorithm to get edges Cv2.Canny(src, output, TrainParame.Threshold1, TrainParame.Threshold2, TrainParame.ApertureSize, TrainParame.L2gradient); Cv2.FindContours(output, out var contours, out var hierarchy, TrainParame.Mode, TrainParame.Method); /// use the sobel filter on the template image which returns the gradients in the X (Gx) and Y (Gy) direction. Cv2.Sobel(src, gx, MatType.CV_64F, 1, 0, 3); Cv2.Sobel(src, gy, MatType.CV_64F, 0, 1, 3); /// compute the magnitude and direction(radians) Cv2.CartToPolar(gx, gy, magnitude, direction); /// save edge info var sum = new Point2d(0, 0); for (int i = 0, m = contours.Length; i < m; i++) { for (int j = 0, n = contours[i].Length; j < n; j++) { var cur = contours[i][j]; var fdx = gx.At <double>(cur.Y, cur.X, 0); // dx var fdy = gy.At <double>(cur.Y, cur.X, 0); // dy var der = new Point2d(fdx, fdy); // (dx,dy) var mag = magnitude.At <double>(cur.Y, cur.X, 0); // √(dx²+dy²) var dir = direction.At <double>(cur.Y, cur.X, 0); // atan2(dy,dx) results.Add(new PointInfo { Point = cur, Derivative = der, Direction = dir, Magnitude = mag == 0 ? 0 : 1 / mag, }); sum += cur; } } /// update Center and Offset in PointInfo var center = new Point2d(sum.X / results.Count, sum.Y / results.Count); foreach (var item in results) { item.Update(center); } /// overlay display origin image, edge(green) and center point(red) Cv2.DrawContours(template, new[] { results.Select(_ => _.Point) }, -1, Scalar.LightGreen, 2); //Cv2.DrawContours(template, contours, -1, Scalar.LightGreen, 2); Cv2.Circle(template, center.ToPoint(), 2, Scalar.Red, -1); } /// update UI RaisePropertyChanged(nameof(Template)); } catch (Exception ex) { Trace.TraceError(ex.Message); Trace.TraceError(ex.StackTrace); } }