Пример #1
0
        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;
        }
Пример #2
0
        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);
        }