【问题标题】:Drawing a Box Around Face To Existed Photos with Google Face Detection ML Kit使用 Google Face Detection ML Kit 在现有照片周围绘制一个框
【发布时间】:2021-07-12 06:25:20
【问题描述】:

我们在 Android 中实现了用于人脸检测的 Android ML Kit。它的作用就像魅力一样,可以检测人脸。

问题:当检测到多个人脸时,我们想在检测到的人脸周围绘制矩形

我们做了什么:

已实现

 implementation 'com.google.android.gms:play-services-mlkit-face-detection:16.1.5'

创建了一个自定义视图:

class FaceView(val theContext : Context, val bounds : Rect) : View(theContext) {

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        val myPaint = Paint()

        myPaint.color = Color.BLACK
        myPaint.style = Paint.Style.STROKE
        myPaint.strokeWidth = 10f

        canvas?.drawRect(bounds, myPaint)
    }
}

试图在我们从人脸对象 ML 套件创建的边界上绘制一个矩形

val result = detector.process(image).addOnSuccessListener { faces ->

for (face in faces) {
val bounds = face.boundingBox

val view = FaceView(requireContext(), bounds)
binding.actionRoot.addView(view)

val lp : ConstraintLayout.LayoutParams =
 ConstraintLayout.LayoutParams(bounds.width(),bounds.height())

lp.startToStart = binding.actionPhoto.id
lp.topToTop = binding.actionPhoto.id

lp.marginStart = bounds.right
lp.topMargin = bounds.bottom
        
view.layoutParams = lp
}}

结果:

我们如何为我们从 URI(不是从 CameraX)生成的每个人脸绘制一个矩形并使其可点击?

【问题讨论】:

    标签: android android-canvas face-detection firebase-mlkit google-mlkit


    【解决方案1】:

    这里可以参考项目,不过是java代码

    https://github.com/kkdroidgit/FaceDetect

    【讨论】:

    • 感谢您的回复。我检查了它,我可以用这种方法在脸部周围画一个矩形。但我也需要是可点击的(选择要改变的脸),并且项目中提供的功能不包括它。我的目的不是创建绘制的位图,而是创建图像视图。
    【解决方案2】:

    -- 虽然 ML 套件提供检测到的人脸的矩形。我认为 Google Developers 让我们更轻松,自动绘制矩形并将人脸作为独立的位图对象提供。

    对于我的解决方案:

    我使用@anonymous 建议的示例项目在脸部周围画线。

    • 首先,我从提供的面部矩形中获得了起点、终点、底部和顶部。 (这个矩形是从原始位图创建的,而不是从图像视图中创建的。所以矩形点属于我使用的原始位图)。

    • 由于 Rect 点不属于 ImageView 而属于位图本身,我们需要在 ImageView 上找到相关的 rect 点(或者创建一个缩放的位图并在其上检测人脸)。我们将这些点计算为原始位图中的百分比。

    • 虽然我们在示例项目中使用原始点来绘制线条。我们实现了一个带有透明背景的视图,使用计算点来使面部矩形可点击。

    -作为最后一件事,我们为每个面创建了位图。

        detector.process(theImage)
                        .addOnSuccessListener { faces ->
        
               val bounds = face.boundingBox
                val screenWidth = GetScreenWidth().execute()
        
                // val theImage = InputImage.fromBitmap(tempBitmap,0)
        
                val paint = Paint()
                paint.strokeWidth = 1f
                paint.color = Color.RED
                paint.style = Paint.Style.STROKE
        
                val theStartPoint = if(bounds.left < 0) 0 else{ bounds.left}
                val theEndPoint = if(bounds.right > tempBitmap.width) tempBitmap.width else { bounds.right}
                val theTopPoint = if(bounds.top < 0) 0 else { bounds.top }
                val theBottomPoint = if(bounds.bottom > tempBitmap.height) tempBitmap.height else { bounds.bottom }
        
                val faceWidth = theEndPoint - theStartPoint
                val faceHeight = theBottomPoint - theTopPoint
        
                Log.d(Statics.LOG_TAG, "Face width : ${faceWidth} Face Height $faceHeight")
        
                val startPointPercent = theStartPoint.toFloat() / tempBitmap.width.toFloat()
                val topPointPercent = theTopPoint.toFloat() / tempBitmap.height.toFloat()
        
                Log.d(Statics.LOG_TAG, "Face start point percent : ${startPointPercent} Face top percent $topPointPercent")
        
                val faceWidthPercent = faceWidth / tempBitmap.width.toFloat()
                val faceHeightPercent = faceHeight / tempBitmap.height.toFloat()
        
                Log.d(Statics.LOG_TAG, "Face width  percent: ${faceWidthPercent} Face Height Percent $faceHeightPercent")
        
                val faceImage = ConstraintLayout(requireContext())
                faceImage.setBackgroundColor(Color.TRANSPARENT)
                binding.actionRoot.addView(faceImage)
        
                val boxWidth = screenWidth.toFloat()*faceWidthPercent
                val boxHeight = screenWidth.toFloat()*faceHeightPercent
        
                Log.d(Statics.LOG_TAG, "Box width : ${boxWidth} Box Height $boxHeight")
        
                val lp : ConstraintLayout.LayoutParams =
                    ConstraintLayout.LayoutParams(
                        boxWidth.toInt(),
                        boxHeight.toInt()
                    )
        
        
                lp.startToStart = binding.actionPhoto.id
                lp.topToTop = binding.actionPhoto.id
        
                lp.marginStart = (screenWidth * startPointPercent).toInt()
                lp.topMargin = (screenWidth * topPointPercent).toInt()
        
                faceImage.layoutParams = lp
        
                val theFaceBitmap = Bitmap.createBitmap(
                    tempBitmap,
                    theStartPoint,
                    theTopPoint,
                    faceWidth,
                    faceHeight)
        
        
                if (face.trackingId != null) {
                    val id = face.trackingId
        
                    faceImage.setOnClickListener {
                        
                    
                        binding.actionPhoto.setImageBitmap(theFaceBitmap)
                        
                     
                    }
                }
    }
    

    结果:

    【讨论】:

      猜你喜欢
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多