Android 集成百度人脸采集

发布时间:2024年01月23日

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();
    }


}

活体检测后的结果:

效果:

文章来源:https://blog.csdn.net/sunshine_0707/article/details/134249463
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。