private void UpdateConvexityDefection( MatOfPoint contour, MatOfInt hullIndices, double defectMinY, RecordHandDetectResult resultSetter ) { var contourArray = contour.toArray(); var convexDefect = new MatOfInt4(); Imgproc.convexityDefects(contour, hullIndices, convexDefect); resultSetter.ConvexDefectVectors.Clear(); int convexDefectCount = convexDefect.rows(); if (convexDefectCount > 0) { for (int i = 0; i < convexDefectCount; i++) { convexDefect.get(i, 0, _convexityDefectSetValues); Point farPoint = contourArray[_convexityDefectSetValues[2]]; int depth = _convexityDefectSetValues[3]; if (depth > DefectThreasholdValue && farPoint.y < defectMinY) { var nearPoint1 = contourArray[_convexityDefectSetValues[0]]; var nearPoint2 = contourArray[_convexityDefectSetValues[1]]; resultSetter.ConvexDefectVectors.Add(new Vector2( (float)(nearPoint1.x * 0.5f + nearPoint2.x * 0.5 - farPoint.x), (float)(nearPoint1.y * 0.5f + nearPoint2.y * 0.5 - farPoint.y) )); } } } //ここまでやりきると全データが有効に更新されている。 resultSetter.HasValidHandArea = true; }
private void EstimateHand(Mat mat, List <MatOfPoint> contours, RecordHandDetectResult resultSetter) { //画像処理としてはcontourがあったが、今調べてる側については if (contours.Count == 0) { resultSetter.HasValidHandArea = false; return; } var contour = SelectLargestContour(contours); var boundRect = Imgproc.boundingRect(contour); //画像の下側で手首の凹み部分を検出することがあるのを、指の凹みと誤認識しないためのガードです。 double defectMinY = boundRect.y + boundRect.height * 0.7; var pointMat = new MatOfPoint2f(); Imgproc.approxPolyDP(new MatOfPoint2f(contour.toArray()), pointMat, 3, true); contour = new MatOfPoint(pointMat.toArray()); var handArea = Imgproc.minAreaRect(pointMat); var handAreaCenter = handArea.center; var handAreaSize = handArea.size; //方向固定のBoundを使うとこう。 resultSetter.HandAreaCenter = new Vector2(boundRect.x + boundRect.width / 2, boundRect.y + boundRect.height / 2); resultSetter.HandAreaSize = new Vector2(boundRect.width, boundRect.height); resultSetter.HandAreaRotation = (float)handArea.angle; //OBBを使うとこうなるが、これだけだとangleが45度超えてるときの挙動が直感に反する事があるので要注意 // resultSetter.HandAreaCenter = new Vector2((float)handAreaCenter.x, (float)handAreaCenter.y); // resultSetter.HandAreaSize = new Vector2((float)handAreaSize.width, (float)handAreaSize.height); // resultSetter.HandAreaRotation = (float)handArea.angle; Imgproc.convexHull(contour, _hullIndices); var hullIndicesArray = _hullIndices.toArray(); //通常ありえないが、凸包がちゃんと作れてないケース if (hullIndicesArray.Length < 3) { resultSetter.HasValidHandArea = false; return; } UpdateConvexityDefection(contour, _hullIndices, defectMinY, resultSetter); }