android - 使用 CameraView 在 Android 上使用 ML Kit 检测人脸

标签 android android-camera face-detection firebase-mlkit google-mlkit

我正在尝试运行这个 example of face detection with the firebase MLkit在安卓系统上。我没有使用内置的 CameraView,而是使用库 CameraView . 运行日志中显示的代码:人脸:[],因此未从相机中找到人脸。

您可以结帐the project here on github .

代码:

import android.os.Bundle
import android.util.Log
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import android.widget.TextView
import androidx.annotation.WorkerThread
import com.otaliastudios.cameraview.CameraView
import com.otaliastudios.cameraview.Frame
import com.otaliastudios.cameraview.FrameProcessor
import com.otaliastudios.cameraview.Size
import androidx.core.view.ViewCompat.getRotation
import com.google.android.gms.tasks.OnFailureListener
import com.google.firebase.FirebaseApp
import com.google.firebase.ml.vision.FirebaseVision
import com.google.firebase.ml.vision.common.FirebaseVisionImage
import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata
import com.google.firebase.ml.vision.face.FirebaseVisionFace
import com.google.firebase.ml.vision.face.FirebaseVisionFaceContour
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions
import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark


class MainActivity : AppCompatActivity() {

    private lateinit var textMessage: TextView
    private lateinit var camera:CameraView
    private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_home -> {
                textMessage.setText(R.string.title_home)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_dashboard -> {
                textMessage.setText(R.string.title_dashboard)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_notifications -> {
                textMessage.setText(R.string.title_notifications)
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        textMessage = findViewById(R.id.message)
        navView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)

        camera = findViewById<CameraView>(R.id.camera)
        camera.setLifecycleOwner(this)

        val realTimeOpts1 = FirebaseVisionFaceDetectorOptions.Builder()
            .setContourMode(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
            .build()
        val realTimeOpts = FirebaseVisionFaceDetectorOptions.Builder()
            .setPerformanceMode(FirebaseVisionFaceDetectorOptions.ACCURATE)
            .setLandmarkMode(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
            .build()

        FirebaseApp.initializeApp(this);


        camera.addFrameProcessor { frame ->
            val data = frame.data
            val rotation = frame.rotation
            val time = frame.time
            val size = frame.size
            val format = frame.format
            val metadata = FirebaseVisionImageMetadata.Builder()
                .setWidth(480) // 480x360 is typically sufficient for
                .setHeight(360) // image recognition
                .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
                .setRotation(3)
                .build()
            val image = FirebaseVisionImage.fromByteArray(data, metadata)
            val detector = FirebaseVision.getInstance()
                .getVisionFaceDetector(realTimeOpts)

            val result = detector.detectInImage(image)
                .addOnSuccessListener { faces ->
                    // Task completed successfully
                    // ...
                    Log.e("FACE", faces.toString())

                    for (face in faces) {
                        val bounds = face.boundingBox
                        val rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees
                        val rotZ = face.headEulerAngleZ // Head is tilted sideways rotZ degrees

                        // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
                        // nose available):
                        val leftEar = face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR)
                        leftEar?.let {
                            val leftEarPos = leftEar.position
                        }

                        // If contour detection was enabled:
                        val leftEyeContour = face.getContour(FirebaseVisionFaceContour.LEFT_EYE).points
                        val upperLipBottomContour = face.getContour(FirebaseVisionFaceContour.UPPER_LIP_BOTTOM).points

                        // If classification was enabled:
                        if (face.smilingProbability != FirebaseVisionFace.UNCOMPUTED_PROBABILITY) {
                            val smileProb = face.smilingProbability
                        }
                        if (face.rightEyeOpenProbability != FirebaseVisionFace.UNCOMPUTED_PROBABILITY) {
                            val rightEyeOpenProb = face.rightEyeOpenProbability
                        }

                        // If face tracking was enabled:
                        if (face.trackingId != FirebaseVisionFace.INVALID_ID) {
                            val id = face.trackingId
                        }
                    }
        }.addOnFailureListener(
                    object : OnFailureListener {
                        override fun onFailure(e: Exception) {
                            // Task failed with an exception
                            // ...
                            Log.e("M", e.toString())
                        }
                    })
    }}

}

在 activity_main.xml 中:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/activity_horizontal_margin"
        android:layout_marginLeft="@dimen/activity_horizontal_margin"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:text="@string/title_home"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <androidx.cardview.widget.CardView
            xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:layout_gravity="center"
            android:layout_width="280dp"
            card_view:cardCornerRadius="280dp"
            android:layout_height="280dp">
        <com.otaliastudios.cameraview.CameraView
                android:id="@+id/camera"
                app:cameraFacing="front"
                android:keepScreenOn="true"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    </androidx.cardview.widget.CardView>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

也对 Fotoapparat 进行了同样的尝试,相同的结果:找不到人脸。我在这里缺少什么?

最佳答案

尝试以编程方式从 frame 获取高度和宽度,而不是对它们进行硬编码。

关于android - 使用 CameraView 在 Android 上使用 ML Kit 检测人脸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56315457/

相关文章:

java - 为什么 Epoxy 不生成模型类?

android - 在显示在 surfacetexture 上之前获取每个 android.hardware.camera2 帧的数据

android - 有没有什么方法可以简单地在 android studio 中使用 google mediapipe 框架进行手动跟踪?

Android 无法打开文件,FileNotFoundException(权限被拒绝),但 PermissionRead 被授予

java - 从android日历获取假期

java - 正在寻找适用于 android/java 的 CoAP api/库?

java - 如何使用适用于 Android 的 WebRTC Native Code 实现 3 路电话 session 视频聊天?

java - 照片由相机上传异常(Firebase 存储)

swift - VNDetectFaceRectanglesRequest 没有调用 completionHandler

opencv - OpenCV 中的人脸检测