O Google disponibiliza uma API que permite realizar detecção de rostos de maneira offline, sem depender de nenhum serviço na nuvem. Essa API é a Google Vision e foi introduzida no Play Services na versão 8.1. Fazer uma implementação básica é bem simples:
Inclua a referência no build.gradle:
implementation 'com.google.android.gms:play-services-vision:8.1.0'
Em seguida vem a implementação do controle
package com.avanade.myfacedetection
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.SparseArray
import android.view.View
import androidx.core.util.valueIterator
import com.google.android.gms.vision.Frame
import com.google.android.gms.vision.face.Face
import com.google.android.gms.vision.face.FaceDetector
public class FaceOverlayView(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int) : View(context, attrs, defStyleAttr) {
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
private lateinit var mBitmap: Bitmap
private var mFaces: SparseArray<Face> = SparseArray<Face>()
fun setBitmap(bitmap: Bitmap){
mBitmap = bitmap
val faceDetector : FaceDetector = FaceDetector.Builder(context)
.setTrackingEnabled(true)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.ACCURATE_MODE)
.build()
if(!faceDetector.isOperational()){
//TODO: Colocar verificação
}
else{
val frame : Frame = Frame.Builder()
.setBitmap(mBitmap)
.build()
mFaces = faceDetector.detect(frame)
faceDetector.release()
}
invalidate()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if(mBitmap != null && mFaces != null){
var scale : Int? = canvas?.let { drawBitmap(it) }
if(canvas != null && scale != null){
drawFaceBox(canvas, scale)
}
}
}
fun drawBitmap(canvas: Canvas) : Int{
val viewWidth : Int = canvas?.width ?: 0
val viewHeight : Int = canvas?.height ?: 0
val imageWidth : Int = mBitmap.width
val imageHeight : Int = mBitmap.height
val scale : Int = Math.min(viewWidth / imageWidth, viewHeight / imageHeight)
val bounds : Rect = Rect(0, 0, imageWidth * scale, imageHeight * scale)
canvas.drawBitmap(mBitmap, null, bounds, null)
return scale
}
fun drawFaceBox(canvas: Canvas, scale: Int){
var paint: Paint = Paint()
paint.setColor(Color.BLUE)
paint.style = Paint.Style.STROKE
paint.strokeWidth = 5F
var left : Float = 0F
var top : Float = 0F
var right : Float = 0F
var bottom : Float = 0F
for(face in mFaces.valueIterator()){
left = face.position.x * scale
top = face.position.y * scale
right = scale * (face.position.x + face.width)
bottom = scale * (face.position.y + face.height)
canvas.drawRect(left, top, right, bottom, paint)
}
}
}
Aqui fazemos a criação do objeto que faz a detecção dos rostos na foto
val faceDetector : FaceDetector = FaceDetector.Builder(context)
.setTrackingEnabled(true)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.ACCURATE_MODE)
.build()
Logo abaixo temos if(!faceDetector.isOperational())
que é uma verificação importante. Caso o usuário nunca tenha usado em nenhuma aplicação a API do Google Vision o device vai baixar essa lib e, pode ser que nesse momento a API ainda não esteja disponível. Então é importante fazer essa verificação para evitar um erro de NullPointerException.
val frame : Frame = Frame.Builder()
.setBitmap(mBitmap)
.build()
mFaces = faceDetector.detect(frame)
faceDetector.release()
Aqui é onde o código irá efetivamente analisar a imagem e verificar os rostos das pessoas. As informações dos rostos encontrados é armazenado em um array de Faces usado aqui para desenhar os quadrados sobre o frame:
for(face in mFaces.valueIterator()){
left = face.position.x * scale
top = face.position.y * scale
right = scale * (face.position.x + face.width)
bottom = scale * (face.position.y + face.height)
canvas.drawRect(left, top, right, bottom, paint)
}
O código completo está aqui no repo.
Top comments (0)