Face Detection in Android

Is there any Android API to detect face inside an image?

The Android framework has the FaceDetector API, although is only suitable for bitmaps (not real-time), and returns only the boundaries (rectangle) location.

For more advanced features, such as real-time detection or face features contour, there is the ML Kit library offered by Google. Although this library can also be used for very simple use cases, such as also getting the face location in a bitmap.

More about ML Kit in the next link:
https://developers.google.com/ml-kit/guides

enter image description here

Drawing a Box Around Face To Existed Photos with Google Face Detection ML Kit

-- While ML kit gives Rect of detected Faces. I think Google Developers make it more easier for us and draw rectangle automatically and provide faces as standalone bitmap objects.

For my solution :

I used the example project that @anonymous suggested to draw lines around the face.

  • First I got start, end, bottom and top points from provided face rect.
    ( This rect is created from original bitmap, not from the imageview. So the rect points are belong to the original bitmap I was using).

  • As Rect points are not belong to ImageView but the bitmap itself, We need to find related rect points on ImageView (or create a scaled bitmap and detect faces on it). We calculated this points as percentages in original Bitmap.

  • While we use original points as in the example project to draw lines. We implemented a view with Transparent Background with using calculated points to make face rectangles clickable.

-As the last thing we created bitmaps for each face.

    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)


}
}
}

Result :

enter image description here

Clicked Image



Related Topics



Leave a reply



Submit