DEV Community

Cover image for Face Detection com Android e Kotlin
Danilo Barreto
Danilo Barreto

Posted on

2 1

Face Detection com Android e Kotlin

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)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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)
        }
Enter fullscreen mode Exit fullscreen mode

O código completo está aqui no repo.

Aqui também está um vídeo da implementação:
Face Detection com Android e Kotlin

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs