首页 > 其他分享 >Android实现人脸识别检测(FaceDetector)

Android实现人脸识别检测(FaceDetector)

时间:2023-05-16 22:48:31浏览次数:67  
标签:人脸识别 FaceDetector 预览 mCamera bitmap new Android Bitmap

前言

目前网上常规解决这块问题的方案总结了一下有以下五种,当然有更多的暂时还未了解过~

1、OpenCV (API level 8 +)

2、Camera内部的 API (API level 14+)

3、android.media.FaceDetector 静态检测 (API level 1 +)

4、Google Play Service 的 Vision API (API 9,在 API 17 增加了一些功能)

5、Face++ Android SDK

正文

1、效果图

本文重点介绍FaceDetector基于静态人脸的检测实现,先上效果图~
image

2、检测说明

由于FaceDetector是只接收bitmap的静态图片的人脸检测方案,因此我们在做检测的时候需要将每一帧预览帧拿去做检验。

但是你以为这样就完了,太天真了,你每一帧是一个完整的手机屏幕里面的人脸可能检测的时候根本就没有出现在圆圈内。因此我们需要用前景遮挡图+背景预览帧画面组合合成一张待检测图片进行送检。

3、FaceDetector检测核心代码

FaceDetector face_detector = new FaceDetector(newBP.getWidth(), newBP.getHeight(), faceNum);
FaceDetector.Face[] faces = new FaceDetector.Face[faceNum];

image

image

4、注意事项

FaceDetector检测的bitmap要求为RGB_565格式(The bitmap must be in 565 format)

实例

1、相机实时预览

使用相机实时预览这边使用的是SurfaceView

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</layout>

2、定义圆形透明遮挡层

2.1 使用Canvas首先绘制整屏幕的白色遮挡层

canvas.drawARGB(255, 255, 255, 255);

2.2 使用Canvas在白色遮挡层上抠出一个透明的原型显示预览画面

mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAlpha(0);
// android.graphics.PorterDuff.Mode.CLEAR 显示挖空canvas为透明
mPaint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));

canvas.drawCircle(宽度, 高度, 大小, mPaint);

3、开始进行相机预览

使用SurfaceHolder对象增加回调监听,在监听中预览和处理响应识别业务

/**
     * 开始预览
     */
    private void startPreview() {
        SurfaceHolder holder = binding.surfaceView.getHolder();
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                mCamera = getCustomCamera();
                mCamera.setPreviewCallback((data, camera) -> {
                    // 是否已经检测成功,如果是则不继续检测
                    if (isIdentify) {
                        checkFaces(data, camera, surfaceHolder, this);
                    }
                });
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                if (mCamera != null) {
                    Camera.Parameters parameters = mCamera.getParameters();
                    // 选择合适的图片尺寸,必须是手机支持的尺寸
                    List<Camera.Size> sizeList = parameters.getSupportedPictureSizes();
                    // 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
                    if (sizeList.size() > 1) {
                        for (int j = 0; j < sizeList.size(); j++) {
                            Camera.Size size = sizeList.get(j);
                            previewWidth = size.width;
                            previewHeight = size.height;
                        }
                    }
                    //设置照片的大小
                    parameters.setPictureSize(previewWidth, previewHeight);
                    mCamera.setParameters(parameters);
                    try {
                        mCamera.setPreviewDisplay(holder);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    CameraUtils.takePicture((data, camera) -> {
                        CameraUtils.startPreview();
                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                        if (bitmap != null) {
                            bitmap = ImageUtils.getRotatedBitmap(bitmap, 180);
                        }
                        CameraUtils.startPreview();
                    });
                    //调用相机预览功能
                    mCamera.startPreview();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                if (null != mCamera) {
                    holder.removeCallback(this);
                    mCamera.setPreviewCallback(null);
                    //停止预览
                    mCamera.stopPreview();
                    mCamera.lock();
                    //释放相机资源
                    mCamera.release();
                    mCamera = null;
                }
            }
        });
    }

4、人脸识别检测

4.1 预览图片

通过回调方法我们可以实时获取相机预览的图片字节数据,但是需要注意的是这个图片的格式是Yuv格式的,如果要在Android中正常的显示和操作则需要进行常规的转换,这里Yuv转bitmap的方法如下:

  public Bitmap convertYUVtoRGB(byte[] yuvData, int width, int height) {
        if (yuvType == null) {
            yuvType = new Type.Builder(rs, Element.U8(rs)).setX(yuvData.length);
            in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

            rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
            out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
        }
        in.copyFrom(yuvData);
        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
        Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        out.copyTo(bmpout);
        return bmpout;
    }

4.2 构建检测图片

其中核心的如前面说的我们需要将整个画面截屏出来进行识别,但是SurfaceView由于他的缓存机制是无法通过常规的getDrawableCache获取其截图的,就算你获取了也是空白图片,所以这里需要获取非SurfaceView部分和相机预览部分进行人为的叠拼。

/**
     * 合并两张bitmap图片
     *
     * @param firstBitmap
     * @param secondBitmap
     * @return
     */
    private Bitmap mergeBitmap(Bitmap firstBitmap, Bitmap secondBitmap) {
        Bitmap bitmap = Bitmap.createBitmap(firstBitmap.getWidth(), firstBitmap.getHeight(), Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(firstBitmap, new Matrix(), null);
        canvas.drawBitmap(secondBitmap, new Matrix(), null);
        return bitmap;
    }

4.3 进行人脸检测

进行检测时直接调用上述的系统API即可完成操作,需要注意的是根据测试,当设置的检测数量大于人脸数量时,有时会直接返回最大数量而非实际数量。

Bitmap bitmap565 = bp.copy(Bitmap.Config.RGB_565, true);
Bitmap newBP = mergeBitmap(bitmap565, getViewBitmap());
FaceDetector face_detector = new FaceDetector(newBP.getWidth(), newBP.getHeight(), 1);
FaceDetector.Face[] faces = new FaceDetector.Face[1];
int face_count = face_detector.findFaces(newBP, faces);

标签:人脸识别,FaceDetector,预览,mCamera,bitmap,new,Android,Bitmap
From: https://www.cnblogs.com/java-six/p/17407082.html

相关文章

  • Android QQ登录界面
    布局loginpage.xml:<?xmlversion="1.0"encoding="UTF-8"?><LinearLayoutandroid:orientation="vertical"android:id="@+id/loginRoot" android:layout_width="fill_parent"android:lay......
  • Android 控件之Notification
    [quote]最近一直在研究android,并一边研究一边做应用。其中遇到了把程序通知常驻在Notification栏,并且不能被clear掉的问题。虽然notify()的第一个参数可以写死并clear掉,但这个值我并不想写死,但是这个值如果是随机生成一个数怎么传给Activity,用Intent当中的Bu......
  • Android Studio学习日志二,Toast用法
    首先,创建一个util,在ToastUtil里面调用方法在里面编写Toast类的代码,方便以后调用packagecom.example.appdemo.util;importandroid.content.Context;importandroid.widget.Toast;publicclassToastUtil{publicstaticToastmToast;publicstaticvoidsh......
  • 作为一个 Android 开发者,我为什么要在意深度学习?
    阅读本文大概需要5.20分钟。AlphaGo再次战胜人类,Google发布TensorFlow正式版,百度筹建深度学习实验室......人人都在谈论机器学习、深度学习,作为移动应用开发者,这些概念离你很远吗?其实不然,如果你不想被未来淘汰,想获得更好的工作,想在技术上变得更牛掰,机器学习和深度学习可能是......
  • Android Studio学习日志一,直接跳转和密码正确跳转
    记录一下我跟着手把手教你用AndroidStudio写一个APP_UP主Superior-Leo进行app开发小项目UP主的笔记首先,在资源文件创建一个文件夹,用来放APP背景图片,按钮图片一、直接跳转第一步、声明控件第二步,找到控件第三步骤,实现跳转代码packagecom.example.appdemo;importa......
  • Android Lottie动画库的导入与使用
    没想到又把安卓捡回来了,好长时间没碰这玩意但是大作业又不得不写......emmmm所以为了给大作业里的功能实现一个好看的UI界面还是得写个app出来。不少app在启动时或者干别的什么活动时会有一个动画效果,这时候可以用Lottie库实现。添加依赖在build.gradle(:app)的dependencies添......
  • Android消息机制——Handler、Looper、MessageQueue
    最近在做毕设,关于android的,其中觉得android的消息机制很有意思,这里就写下自己的想法和Windows一样android也是消息驱动的。Android通过Handler和looper实现消息循环机制。一、Handler的创建每个Handler都会和一个线程和线程的messagequeue关联起来,此时你可以传递messages和runna......
  • android开发mac系统搭建flutter开发环境
    安装xcodemac系统自带的AppStore里搜索xcode安装即可安装JDKJDK下载地址:https://www.oracle.com/java/technologies/downloads/需要登录Oracle账号才能下载下载dmg文件之后双击安装即可安装AndroidStudio开发工具AndroidStudio下载地址:https://developer.android.goog......
  • 【android】手机亮屏锁定(安卓亮屏解锁)
    1、Android屏幕常亮/点亮//保持屏幕常亮PowerManagerpm=(PowerManager)getSystemService(Context.POWER_SERVICE);mWakeLock=pm.newWakeLock(PowerManager.FULL_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP,LOCK_TAG);mWakeLock.acquire();//释放屏幕常亮锁if(nu......
  • Android AVD创建及设置中各参数详解
    设置AVD时有些参数比较模糊,特地找了篇文章,大家参考下!本文根据如下的模拟器安装做一些解释:[color=red][b]Name[/b][/color]:自定义虚拟的名称,不能有空格或者其他非法字符,否则不能创建,即CreatAVD不能高亮点击。[color=red][b]Target[/b][/color]:选择要运行的android版本(也可理解......