Android 集成百度人脸采集

app端使用活体检测,通过活体检测后,采集人像,base64格式,调接口后台判断人脸对比结果返回给app

1.官网地址:

人脸识别_人脸检测_人脸对比_人脸搜索_活体检测_百度智能云 (baidu.com)

里面有详细的集成步骤和说明

2.申请license

3.下载license拷贝到工程的assets目录

4.将faceplatform-ui以module方式集成项目

4.1在build.gradle 里添加

implementation project(':faceplatform-ui')

4.2在settings.gradle里添加

include ':faceplatform-ui'

faceplatform-ui里集成了faceplatform

5.混淆设置

-keep class com.baidu.vis.unified.license.** {*;}

-keep class com.baidu.liantian.** {*;}

-keep class com.baidu.baidusec.** {*;}

-keep class com.baidu.idl.main.facesdk.** {*;}

6.初始化sdk,前判断权限
if (EasyPermissions.hasPermissions(
        this,
        android.Manifest.permission.CAMERA
    )
) { //权限判断
    startBaiduFace() //初始化百度sdk
} else {
    
        AlertDialog.Builder(this).setTitle("提示信息")
            .setCancelable(false)
            .setMessage("因涉诈安全要求,我们需要您提供相机权限,用于人脸识别。如您拒绝授权,将无法正常登录,是否允许。")
            .setPositiveButton("开启权限") { _, _ ->
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(android.Manifest.permission.CAMERA),
                    0X12
                )
            }.setNegativeButton("取消", object : DialogInterface.OnClickListener {
                override fun onClick(p0: DialogInterface?, p1: Int) {
                    hideDialog()
                    finish()
                }

            }).create().show()
}
fun startBaiduFace() {
    //初始化SDK
    FaceSDKManager.getInstance()
        .initialize(this, "​​sunlightat0707-face-android",
            "idl-license.face-android", object : IInitCallback {
                override fun initSuccess() {
                    //初始化成功
                    //设置采集配置
                    if (!BaiDuFaceConfig.initLicenseSuccess()) {
                        return
                    }
                     //跳转到带活体检测的界面
                    startActivity(
                        Intent(
                            this,
                            FaceLivenessExpActivity::class.java
                        )
                    )
                }

                override fun initFailure(errCode: Int, errMsg: String) {
                    //初始化失败提示
                    CoroutineScope(Dispatchers.Main).launch(Dispatchers.Main) {
                        ToastUtils.showToast(
                            this,
                            "人脸功能初始化失败 = $errCode, $errMsg"
                        )
                    }
                    hideDialog()
                    finish()
                }
            })

}
百度人脸采集配置BaiDuFaceConfig类
class BaiDuFaceConfig {


    companion object {
        val sIntance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            BaiDuFaceConfig()
        }


        // 动作活体条目集合
        public var livenesssList: List<LivenessTypeEnum> = ArrayList()

        // 活体随机开关
        public var isLivenessRandom = false

        // 语音播报开关
        public var isOpenSound = true

        // 活体检测开关
        public var isActionLive = true

        // 质量等级(0:正常、1:宽松、2:严格、3:自定义)
        public var qualityLevel: Int = Constants.QUALITY_NORMAL

        public val destroyMap: MutableMap<String, Activity> = HashMap()


        /**
         * 参数配置方法
         */
        private fun setFaceConfig(): Boolean {
            val config = FaceSDKManager.getInstance().faceConfig
            // SDK初始化已经设置完默认参数(推荐参数),也可以根据实际需求进行数值调整
            // 质量等级(0:正常、1:宽松、2:严格、3:自定义)
            // 获取保存的质量等级
            val util = SharedPreferencesUtil(App.instance)
            var qualityLevel = util.getSharedPreference(Constants.KEY_QUALITY_LEVEL_SAVE, -1) as Int
            if (qualityLevel == -1) {
                qualityLevel = this.qualityLevel
            }
            // 根据质量等级获取相应的质量值(注:第二个参数要与质量等级的set方法参数一致)
            val manager: QualityConfigManager = QualityConfigManager.getInstance()
            manager.readQualityFile(App.instance, qualityLevel)
            val qualityConfig: QualityConfig = manager.getConfig() ?: return false
            // 设置模糊度阈值
            config.blurnessValue = qualityConfig.getBlur()
            // 设置最小光照阈值(范围0-255)
            config.brightnessValue = qualityConfig.getMinIllum()
            // 设置最大光照阈值(范围0-255)
            config.brightnessMaxValue = qualityConfig.getMaxIllum()
            // 设置左眼遮挡阈值
            config.occlusionLeftEyeValue = qualityConfig.getLeftEyeOcclusion()
            // 设置右眼遮挡阈值
            config.occlusionRightEyeValue = qualityConfig.getRightEyeOcclusion()
            // 设置鼻子遮挡阈值
            config.occlusionNoseValue = qualityConfig.getNoseOcclusion()
            // 设置嘴巴遮挡阈值
            config.occlusionMouthValue = qualityConfig.getMouseOcclusion()
            // 设置左脸颊遮挡阈值
            config.occlusionLeftContourValue = qualityConfig.getLeftContourOcclusion()
            // 设置右脸颊遮挡阈值
            config.occlusionRightContourValue = qualityConfig.getRightContourOcclusion()
            // 设置下巴遮挡阈值
            config.occlusionChinValue = qualityConfig.getChinOcclusion()
            // 设置人脸姿态角阈值
            config.headPitchValue = qualityConfig.getPitch()
            config.headYawValue = qualityConfig.getYaw()
            config.headRollValue = qualityConfig.getRoll()
            // 设置可检测的最小人脸阈值
            config.minFaceSize = FaceEnvironment.VALUE_MIN_FACE_SIZE
            // 设置可检测到人脸的阈值
            config.notFaceValue = FaceEnvironment.VALUE_NOT_FACE_THRESHOLD
            // 设置闭眼阈值
            config.eyeClosedValue = FaceEnvironment.VALUE_CLOSE_EYES
            // 设置图片缓存数量
            config.cacheImageNum = FaceEnvironment.VALUE_CACHE_IMAGE_NUM
            // 设置活体动作,通过设置list,LivenessTypeEunm.Eye, LivenessTypeEunm.Mouth,
            // LivenessTypeEunm.HeadUp, LivenessTypeEunm.HeadDown, LivenessTypeEunm.HeadLeft,
            // LivenessTypeEunm.HeadRight
            config.livenessTypeList = livenesssList
            // 设置动作活体是否随机
            config.isLivenessRandom = isLivenessRandom
            // 设置开启提示音
            config.isSound = isOpenSound
            // 原图缩放系数
            config.scale = FaceEnvironment.VALUE_SCALE
            // 抠图宽高的设定,为了保证好的抠图效果,建议高宽比是4:3
            config.cropHeight = FaceEnvironment.VALUE_CROP_HEIGHT
            config.cropWidth = FaceEnvironment.VALUE_CROP_WIDTH
            // 抠图人脸框与背景比例
            config.enlargeRatio = FaceEnvironment.VALUE_CROP_ENLARGERATIO
            // 检测超时设置
            config.timeDetectModule = FaceEnvironment.TIME_DETECT_MODULE
            // 检测框远近比率
            config.faceFarRatio = FaceEnvironment.VALUE_FAR_RATIO
            config.faceClosedRatio = FaceEnvironment.VALUE_CLOSED_RATIO
            (livenesssList as java.util.ArrayList).clear()
            //活体动作只用了眨眼
            (livenesssList as java.util.ArrayList).add(LivenessTypeEnum.Eye) 
            config.livenessTypeList = livenesssList
            FaceSDKManager.getInstance().faceConfig = config
            return true
        }

        /*
        * 初始化参数是否成功
        * */
        public fun initLicenseSuccess(): Boolean {
            if (!setFaceConfig()) {
                ToastUtils.showToast(App.instance, "百度人脸初始化失败,配置文件解析出错。")
                return false
            } else {
                return true;
            }
        }
    }


}

活体检测界面

public class FaceLivenessExpActivity extends FaceLivenessActivity {

    private DefaultDialog mDefaultDialog;


    @SuppressLint("CheckResult")
    @Override
    public void onLivenessCompletion(FaceStatusNewEnum status, String message,
                                     HashMap<String, ImageInfo> base64ImageCropMap,
                                     HashMap<String, ImageInfo> base64ImageSrcMap, int currentLivenessCount) {
        super.onLivenessCompletion(status, message, base64ImageCropMap, base64ImageSrcMap, currentLivenessCount);

        if (status == FaceStatusNewEnum.OK && mIsCompletion) {

            //获取到最优图片
            String firstImg = getBestImage(base64ImageCropMap, base64ImageSrcMap);
            if (!TextUtils.isEmpty(firstImg)) {
                //不为空,带图片回调,在回调地方,调接口上传,后台对BaiduFaceSDKManager.INSTANCE.getCallback().onCloseSDK(true, firstImg, null);
                finish()       
            }else{
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showToast(FaceLivenessExpActivity.this,"没有获取到人脸照片");
                    }
                });
            }
            //只有两个Timeout
        } else if (status == FaceStatusNewEnum.FaceLivenessActionCodeTimeout ||
                status == FaceStatusNewEnum.DetectRemindCodeTimeout) {
            showMessageDialog("活体检测", "采集超时");
        }
    }


    /**
     * 获取最优图片
     *
     * @param imageCropMap 抠图集合
     * @param imageSrcMap  原图集合
     */
    private String getBestImage(HashMap<String, ImageInfo> imageCropMap, HashMap<String, ImageInfo> imageSrcMap) {
        String bmpStr = null;
        // 将抠图集合中的图片按照质量降序排序,最终选取质量最优的一张抠图图片
        if (imageCropMap != null && imageCropMap.size() > 0) {
            List<Map.Entry<String, ImageInfo>> list1 = new ArrayList<>(imageCropMap.entrySet());
            Collections.sort(list1, new Comparator<Map.Entry<String, ImageInfo>>() {

                @Override
                public int compare(Map.Entry<String, ImageInfo> o1,
                                   Map.Entry<String, ImageInfo> o2) {
                    String[] key1 = o1.getKey().split("_");
                    String score1 = key1[2];
                    String[] key2 = o2.getKey().split("_");
                    String score2 = key2[2];
                    // 降序排序
                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
                }
            });

            // 获取抠图中的加密或非加密的base64
//            int secType = mFaceConfig.getSecType();
//            String base64;
//            if (secType == 0) {
//                base64 = list1.get(0).getValue().getBase64();
//            } else {
//                base64 = list1.get(0).getValue().getSecBase64();
//            }
        }

        // 将原图集合中的图片按照质量降序排序,最终选取质量最优的一张原图图片
        if (imageSrcMap != null && imageSrcMap.size() > 0) {
            List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
            Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {

                @Override
                public int compare(Map.Entry<String, ImageInfo> o1,
                                   Map.Entry<String, ImageInfo> o2) {
                    String[] key1 = o1.getKey().split("_");
                    String score1 = key1[2];
                    String[] key2 = o2.getKey().split("_");
                    String score2 = key2[2];
                    // 降序排序
                    return Float.valueOf(score2).compareTo(Float.valueOf(score1));
                }
            });
            bmpStr = list2.get(0).getValue().getBase64();

        }
        return bmpStr;
    }

    @Override
    public void onBackPressed() {
       //进界面就显示采集提示,采集成功,会回调,关闭当前界面;这里回调不成     BaiduFaceSDKManager.INSTANCE.getCallback().onCloseSDK(false, null, null); super.onBackPressed();

    }


    private void showMessageDialog(String title, String message) {
        if (mDefaultDialog == null) {
            DefaultDialog.Builder builder = new DefaultDialog.Builder(this);
            builder.setTitle(title).
                    setMessage(message).
                    setNegativeButton("确认",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    mDefaultDialog.dismiss();
                                    onBackPressed();
                                }
                            });
            mDefaultDialog = builder.create();
            mDefaultDialog.setCancelable(true);
        }
        mDefaultDialog.dismiss();
        mDefaultDialog.show();
    }


}

活体检测后的结果:

效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/341570.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

k8s-helm

Helm: 什么是helm,在没有这个heml之前&#xff0c;deployment service ingress的作用就是通过打包的方式&#xff0c;把deployment service ingress这些打包在一块&#xff0c;一键式的部署服务&#xff0c;类似于yum 官方提供的一个类似于安全仓库的功能&#xff0c;可以实现…

【ARMv8M Cortex-M33 系列 7 -- RA4M2 移植 RT-Thread 问题总结】

请阅读【嵌入式开发学习必备专栏 】 文章目录 问题小结栈未对齐 经过几天的调试&#xff0c;成功将rt-thead 移植到 RA4M2&#xff08;Cortex-M33 核&#xff09;上&#xff0c;thread 和 shell 命令已经都成功支持。 问题小结 在完成 rt-thread 代码 Makefile 编译系统搭建…

.NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

前言 在.NET 6之前我们一直是使用QRCoder来生成二维码&#xff08;QRCoder是一个非常强大的生成二维码的组件&#xff0c;用到了System.Drawing.Common 包&#xff09;&#xff0c;然后从.NET 6开始&#xff0c;当为非 Windows 操作系统编译引用代码时&#xff0c;平台分析器会…

TS学习笔记八:命名空间

本节介绍命名空间相关内容&#xff0c;包括命名空间的作用、实现方式、注意事项、命名空间和模块的区别等内容。 由于全局作用域下&#xff0c;有可能会导致命名冲突&#xff0c;使用命名空间之后就可以通过命名空间组织代码&#xff0c;将代码封装到不同的命名空间当中&#x…

GPTBots:利用FlowBot中的卡片和表单信息,提供丰富的客服体验

在当今的数字化时代&#xff0c;客户服务的形式和体验正在经历着前所未有的变革。传统的文字消息方式已经无法满足现代用户对于服务体验的多元化需求。那么&#xff0c;如何才能在这个信息爆炸的时代&#xff0c;让我们的服务方式更加个性化、多样化&#xff0c;从而提供更丰富…

MySQL-查询SQL语句

阅读目录 1.基础查询2.高级多表查询 回到顶部 1.基础查询 范围查询 在范围in select 字段 from 表名 where 字段 in (值,值); select id from stu where id in (2,3); 不在范围not in select 字段 from 表名 where 字段 in (值,值); select id from stu where id not in…

【RabbitMQ】RabbitMQ安装与使用详解以及Spring集成

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《RabbitMQ实战》。&#x1f3af;&#x1f3af; &am…

JVM实战篇:GC调优

目录 一.GC调优的核心指标 1.1吞吐量&#xff08;Throughput&#xff09; 1.2延迟&#xff08;Latency&#xff09; 1.3内存使用量 二.GC调优的方法 2.1监控工具 Jstat工具 VisualVm插件 Prometheus Grafana 2.2诊断原因 GC日志 GC Viewer GCeasy 2.3常见的GC模…

从零学算法78

78.给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3…

分布式websocket即时通信(IM)系统保证消息可靠性【第八期】

b站上面本期视频版本&#xff0c;观看视频食用更佳&#xff01;点击即可跳转,找不到视频可以直接搜索我 目前叫 呆呆呆呆梦 目前已经写的文章有。并且有对应视频版本。 git项目地址 【IM即时通信系统&#xff08;企聊聊&#xff09;】点击可跳转 sprinboot单体项目升级成sprin…

#GPU|LLM|AIGC#集成显卡与独立显卡|显卡在深度学习中的选择与LLM GPU推荐

区别 核心区别&#xff1a;显存&#xff0c;也被称作帧缓存。独立显卡拥有独立显存&#xff0c;而集成显卡通常是没有的&#xff0c;需要占用部分主内存来达到缓存的目的 集成显卡&#xff1a; 是集成在主板上的&#xff0c;与主处理器共享系统内存。 一般会在很多轻便薄型的…

Linux 网络传输学习笔记

这篇是混合《Linux性能优化实战》以及 《Wireshark网络分析就这么简单》的一些关于Linux 网络的学习概念和知识点笔记 &#xff0c;主要记录网络传输流程以及对于TCP和UDP传输的一些影响因素 Linux 网络传输流程 借用一张倪朋飞先生的《Linux性能优化实战》课程中的图片 接收流…

第二证券:新手也能搞定!新股申购流程攻略

由于参加打新的获利概率较大&#xff0c;也就有许多投资者参加到新股申购中。那么&#xff0c;新股申购流程是怎样的&#xff1f;对此&#xff0c;本文将借助有关知识来展开讨论&#xff0c;为我们供给一个参阅思路。 投资者在参加网上打新时&#xff0c;应首要了解新股的申购日…

测试不拘一格——掌握Pytest插件pytest-random-order

在测试领域,测试用例的执行顺序往往是一个重要的考虑因素。Pytest插件 pytest-random-order 提供了一种有趣且灵活的方式,让你的测试用例能够以随机顺序执行。本文将深入介绍 pytest-random-order 插件的基本用法和实际案例,助你摆脱固定的测试顺序,让测试更具变化和全面性…

yolov5 opencv dnn部署自己的模型

yolov5 opencv dnn部署自己的模型 github开源代码地址使用github源码结合自己导出的onnx模型推理自己的视频推理条件c部署c 推理结果 github开源代码地址 yolov5官网还提供的dnn、tensorrt推理链接本人使用的opencv c github代码,代码作者非本人&#xff0c;也是上面作者推荐的…

【Electron】Electron是什么

1. Electron是什么 Electron是使用JavaScript、HTML和CSS构建跨平台&#xff08;Windows、MacOs、Linux&#xff09;的桌面应用。Electron其实就是一个可以展示网页内容的壳子&#xff0c;相当于一个独立的浏览器&#xff0c;可以提供给你一些接口&#xff0c;去调用系统的资源…

验证码短信API:企业级安全验证的必备工具

引言 随着数字经济的蓬勃发展&#xff0c;企业对在线服务的安全性要求越来越高。在这种背景下&#xff0c;验证码短信API作为一种有效的安全验证工具&#xff0c;正逐渐成为企业级应用的标配。本文将探讨验证码短信API如何为企业级安全验证提供坚实保障。 验证码短信 API 的优…

MySQL-SQL-DQL

DQL-介绍 DQL-语法 基本查询 1、查询多个字段 2、设置别名 3、去除重复记录 条件查询 1、语法 2、条件 聚合函数 1、介绍 2、常见的聚合函数 3、语法 分组查询 1、语法 2、where与having区别 排序查询 1、语法 2、排序方式 分页查询 1、语法 DQL-执行顺序

关于在微信小程序中使用taro + react-hook后销毁函数无法执行的问题

问题&#xff1a; 在 taro中使用navigageTo() 跳转路由后hook中useEffect 的return函数没有执行 没有执行return函数 框架版本&#xff1a; tarojs: 3.6 react: 18.0 原因&#xff1a; 使用navigateTo() 跳转路由的话并不会销毁页面和组件&#xff0c;会加入一…