private void FindDefects(Mat maskImage, ref int cx, ref int cy, int min_defects_count, int max_defects_count) { int erosion_size = 1; Mat element = Imgproc.getStructuringElement( Imgproc.MORPH_ELLIPSE, new Size(2 * erosion_size + 1, 2 * erosion_size + 1), new Point(erosion_size, erosion_size)); // dilate and erode Imgproc.dilate(maskImage, maskImage, element); Imgproc.erode(maskImage, maskImage, element); element.Dispose(); //Find Contours in image List <MatOfPoint> contours = new List <MatOfPoint>(); Imgproc.findContours(maskImage, contours, new MatOfPoint(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); //Loop to find the biggest contour; If no contour is found index=-1 int index = -1; double area = 2000; for (int i = 0; i < contours.Count; i++) { var tempsize = Imgproc.contourArea(contours[i]); if (tempsize > area) { area = tempsize; index = i; } } if (index == -1) { return; } else { var points = new MatOfPoint(contours[index].toArray()); var hull = new MatOfInt(); Imgproc.convexHull(points, hull, false); var defects = new MatOfInt4(); Imgproc.convexityDefects(points, hull, defects); var start_points = new MatOfPoint2f(); var far_points = new MatOfPoint2f(); for (int i = 0; i < defects.size().height; i++) { int ind_start = (int)defects.get(i, 0)[0]; int ind_end = (int)defects.get(i, 0)[1]; int ind_far = (int)defects.get(i, 0)[2]; double depth = defects.get(i, 0)[3] / 256; double a = Core.norm(contours[index].row(ind_start) - contours[index].row(ind_end)); double b = Core.norm(contours[index].row(ind_far) - contours[index].row(ind_start)); double c = Core.norm(contours[index].row(ind_far) - contours[index].row(ind_end)); double angle = Math.Acos((b * b + c * c - a * a) / (2 * b * c)) * 180.0 / Math.PI; double threshFingerLength = ((double)maskImage.height()) / 8.0; double threshAngle = 80; if (angle < threshAngle && depth > threshFingerLength) { //start point var aa = contours[index].row(ind_start); start_points.push_back(contours[index].row(ind_start)); far_points.push_back(contours[index].row(ind_far)); } } points.Dispose(); hull.Dispose(); defects.Dispose(); // when no finger found if (far_points.size().height < min_defects_count || far_points.size().height > max_defects_count) { return; } var cnts = new List <MatOfPoint>(); cnts.Add(contours[index]); Mat mm = new Mat(); Imgproc.cvtColor(maskImage, mm, Imgproc.COLOR_GRAY2BGR); Imgproc.drawContours(mm, cnts, 0, new Scalar(0, 0, 255)); // OpenCVForUnity.ImgcodecsModule.Imgcodecs.imwrite("D:/tempImg.jpg", mm) //var rotatedRect = Imgproc.minAreaRect(far_points); var boundingRect = Imgproc.boundingRect(far_points); cx = (int)(boundingRect.x + boundingRect.width / 2); cy = (int)(boundingRect.y + boundingRect.height / 2); } }