2

我正在探索精彩的移动视觉 api,我正在研究Face Tracker示例并寻找一个解决方案,我可以在其中找出嘴巴是否张开。例如,人在打哈欠。没有直接的方式face.getIsLeftEyeOpenProbability();

所以我想我需要找出左右嘴的x,y坐标找出差异并弄清楚鼠标是否打开。我不确定这是否可行。

但是有没有其他方法可以确定嘴是张开还是闭合?

4

5 回答 5

2

Mobile Vision API 不直接支持嘴巴开/关检测。但是这段代码可能会对你有所帮助。我已经在我的设备上测试和工作的魅力。

 @Override
    public void draw(Canvas canvas) {

        Face face = mFace;

        if (face == null) {
            return;
        }

        if ((contains(face.getLandmarks(), 11) != 99)
                && (contains(face.getLandmarks(), 5) != 99)
                && (contains(face.getLandmarks(), 6) != 99)
                ) {

            Log.i(TAG, "draw: Mouth Open >> found all the points");

            /**
             * for bottom mouth
             */
            int cBottomMouthX;
            int cBottomMouthY;
            if (FaceTrackerActivity.mIsFrontFacing) {
                cBottomMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().x);
                cBottomMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().y);

                Log.i(TAG, "draw: Condition Bottom mouth >> cBottomMouthX >> " + cBottomMouthX + "    cBottomMouthY >> " + cBottomMouthY);


            } else {
                cBottomMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().x);
                cBottomMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().y);
            }
            canvas.drawCircle(cBottomMouthX, cBottomMouthY, 10, mPaint);

            /**
             * for left mouth
             */
            int cLeftMouthX;
            int cLeftMouthY;
            if (FaceTrackerActivity.mIsFrontFacing) {
                cLeftMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().x);
                cLeftMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().y);

                Log.i(TAG, "draw: Condition LEft mouth >> cLeftMouthX >> " + cLeftMouthX + "    cLeftMouthY >> " + cLeftMouthY);


            } else {
                cLeftMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().x);
                cLeftMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().y);
            }
            canvas.drawCircle(cLeftMouthX, cLeftMouthY, 10, mPaint);

            /**
             * for Right mouth
             */
            int cRightMouthX;
            int cRightMouthY;
            if (FaceTrackerActivity.mIsFrontFacing) {
                cRightMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().x);
                cRightMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().y);

                Log.i(TAG, "draw: Condition Right mouth >> cRightMouthX >> " + cRightMouthX + "    cRightMouthY >> " + cRightMouthY);


            } else {
                cRightMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().x);
                cRightMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().y);
            }
            canvas.drawCircle(cRightMouthX, cRightMouthY, 10, mPaint);

            float centerPointX = (cLeftMouthX + cRightMouthX) / 2;
            float centerPointY = ((cLeftMouthY + cRightMouthY) / 2) - 20;

            canvas.drawCircle(centerPointX, centerPointY, 10, mPaint);

            float differenceX = centerPointX - cBottomMouthX;
            float differenceY = centerPointY - cBottomMouthY;

            Log.i(TAG, "draw: difference X >> " + differenceX + "     Y >> " + differenceY);

            if (differenceY < (-60)) {
                Log.i(TAG, "draw: difference - Mouth is OPENED ");
            } else {
                Log.i(TAG, "draw: difference - Mouth is CLOSED ");
            }
         }
     }

这是另一种方法。

int contains(List<Landmark> list, int name) {
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).getType() == name) {
            return i;
        }
    }
    return 99;
}

PS - 此代码将找到左嘴和右嘴的中心点坐标,并找到下嘴坐标和中心点坐标之间的差异。

于 2017-03-30T11:20:24.943 回答
2

我们可以使用mouthLeftPosition、mouthRightPosition 和mouthBottomPosition 之间的角度来检测嘴巴是否张开。

使用以下方法计算角度:

双倍浮动比率 = (AB * AB + AC * AC - BC * BC) /( 2 * AC * AB); 度 = Math.acos(ratio)*(180/Math.PI);

if (degree < (110)) {
  System.out.println("Mouth is open");
}else {
  System.out.println("Mouth is close");
}
于 2019-04-10T13:48:41.893 回答
1

不幸的是,Mobile Vision API 不支持张嘴检测。

于 2017-02-09T15:12:45.987 回答
1

该 API 确实允许跟踪嘴巴左、右和底部的面部标志:

https://developers.google.com/android/reference/com/google/android/gms/vision/face/Landmark

但是不,API 中没有明确的张嘴检测。

于 2017-02-09T16:00:58.430 回答
0

计算左右嘴点之间的距离并非在每种情况下都适用,因为当用户远离相机时,这个距离会比用户靠近相机时更短,因此没有标准来获得一个恒定的阈值检测嘴巴何时张开。我认为,更好的方法是计算左-> 下和右-> 嘴线之间的角度。当角度减小时,它将描绘张嘴事件。

我一直在尝试实现相同的目标,但无法使用简单的方法找到它。所以,我考虑了这个解决方案,并将在我的最终实施它。

于 2019-04-10T12:57:45.310 回答