安卓人脸识别笔记

news/2024/10/18 22:29:48/

人脸识别的SDK来自虹软的人脸识别SDK,开源免费
虹软的官网 http://www.arcsoft.com.cn/ai/arcface.html
faceDemo实现效果:
这里写图片描述
在项目实现过程中遇到的一些问题,记一下。

一、调用系统相机方法

这里使用FileProvider.getUriForFile();获取Uri 而不使用Uri.fromFile()android7.0对于系统权限做了一些更爱,为了提高私有文件的安全性。当我们在访问文件的时候,安卓禁止你的应用外部公开file://uri 会报错:android.os.FileUriExposedException:
由于我的手机是Android7.1故使用以下,Android7.0以下的可以直接使用Uri.fromFile(),为了保持兼容性可以在程序中加一个判断当前系统版本进行调用

// 获取SD卡状态
String state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){            photoPath = Environment.getExternalStorageDirectory() + "/face.png";File imageDir = new File(photoPath);if(!imageDir.exists()){// 根据地址生成新的文件try {imageDir.createNewFile();} catch (IOException e) {e.printStackTrace();}
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//Uri uri = Uri.fromFile(imageDir);
Uri uri =  FileProvider.getUriForFile(MainActivity.this, "com.demo.cjh.facedemo.fileprovider", imageDir);
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
startActivityForResult(intent,11);
}else {Toast.makeText(MainActivity.this,"SD卡未插入",Toast.LENGTH_SHORT).show();
}

关于FileProvider.getUriForFile()调用的设置

第一步 在清单文件下注册
<provider  android:name="android.support.v4.content.FileProvider"  //此处的provider需要和代码中的provider保持一致  android:authorities="你的包名.provider"  android:exported="false"  android:grantUriPermissions="true">  <meta-data  android:name="android.support.FILE_PROVIDER_PATHS"  android:resource="@xml/provider_paths" />  
</provider>  
第二步 res/xml/provider_paths类
<?xml version="1.0" encoding="utf-8"?>  
<paths>  <external-path  name="external_files"  path="." />  
</paths>  

注意你的代码里面的provider名字需要和清单的provider名字一致,否则会报空

二、activity回调接收相机的图片

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// requestCode 回调代码,用来识别是哪个activity回调回来的,和startActivityForResult();第二个参数比较// resultCode 系统确认代码,有Activity.RESULT_OK |Activity.RESULT_CANCELED  前者表示成功回调,后者表示取消}

三、虹软SDK的使用

    // 把图形格式转化为软虹SDK使用的图像格式NV21byte[] data = new byte[bp.getWidth() * bp.getHeight() * 3 / 2];ImageConverter convert = new ImageConverter();convert.initial(bp.getWidth(), bp.getHeight(), ImageConverter.CP_PAF_NV21);if (convert.convert(bp, data)) {Log.d(TAG, "convert ok!");}convert.destroy();// 人脸信息检测 检测的结果包括人脸矩形框的位置AFD_FSDKEngine FD_engine = new AFD_FSDKEngine();AFD_FSDKVersion FD_version = new AFD_FSDKVersion();// 用来存放检测到的人脸信息列表List<AFD_FSDKFace> FD_result = new ArrayList<AFD_FSDKFace>();// 首先初始化人脸检测引擎AFD_FSDKError FD_error = FD_engine.AFD_FSDK_InitialFaceEngine(FaceDB.appid,FaceDB.fd_key,AFD_FSDKEngine.AFD_OPF_0_HIGHER_EXT, 16, 5);if(FD_error.getCode() != AFD_FSDKError.MOK ){Toast.makeText(Register.this, "FD初始化失败,错误码:" + FD_error.getCode(), Toast.LENGTH_SHORT).show();}// 输入的data数据为NV21格式,人脸检测返回结果保存在FD_result中FD_error = FD_engine.AFD_FSDK_StillImageFaceDetection(data,bp.getWidth(), bp.getHeight(), AFD_FSDKEngine.CP_PAF_NV21, FD_result);// 画box框Bitmap bitmap = Bitmap.createBitmap(bp.getWidth(), bp.getHeight(), bp.getConfig());Canvas canvas = new Canvas(bitmap);canvas.drawBitmap(bp, 0, 0, null);Paint mPaint = new Paint();for (AFD_FSDKFace face : FD_result) {mPaint.setColor(Color.RED);mPaint.setStrokeWidth(10.0f);mPaint.setStyle(Paint.Style.STROKE);canvas.drawRect(face.getRect(), mPaint);}//  canvas.restore();bp = bitmap;imageView.setImageBitmap(bp);if(!FD_result.isEmpty()) {// 检测人脸特征信息AFR_FSDKVersion FR_version1 = new AFR_FSDKVersion();AFR_FSDKEngine FR_engine1 = new AFR_FSDKEngine();// 存放人脸特征信息AFR_FSDKFace FR_result1 = new AFR_FSDKFace();// 初始化AFR_FSDKError FR_error1 = FR_engine1.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);if(FR_error1.getCode() != AFR_FSDKError.MOK ){Toast.makeText(Register.this, "FR初始化失败,错误码:" + FD_error.getCode(), Toast.LENGTH_SHORT).show();}// 检测人脸特征FR_error1 = FR_engine1.AFR_FSDK_ExtractFRFeature(data,bp.getWidth(),bp.getHeight(), AFR_FSDKEngine.CP_PAF_NV21, new Rect(FD_result.get(0).getRect()), FD_result.get(0).getDegree(), FR_result1);if(FR_error1.getCode() != AFR_FSDKError.MOK){Toast.makeText(Register.this, "人脸特征无法检测,请换一张图片", Toast.LENGTH_SHORT).show();}else{mAFR_FSDKFace = FR_result1.clone(); // 复制//  裁剪int width = FD_result.get(0).getRect().width();int height = FD_result.get(0).getRect().height();Bitmap face_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);Canvas face_canvas = new Canvas(face_bitmap);face_canvas.drawBitmap(bp, FD_result.get(0).getRect(), new Rect(0, 0, width, height), null);// 显示imageView2.setImageBitmap(face_bitmap);// 添加人脸特征信息到脸库// App.mFaceDB.addFace("name",mAFR_FSDKFace);}// 销毁FR_error1 = FR_engine1.AFR_FSDK_UninitialEngine();}else{Toast.makeText(Register.this, "未检测到人脸", Toast.LENGTH_SHORT).show();}FD_error = FD_engine.AFD_FSDK_UninitialFaceEngine();

人脸检测布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.demo.cjh.facedemo.Detecter"><com.guo.android_extend.widget.CameraSurfaceView
        android:id="@+id/surfaceView"android:layout_width="1dp"android:layout_height="1dp"/><com.guo.android_extend.widget.CameraGLSurfaceView
        android:id="@+id/glsurfaceView"android:layout_width="144dp"android:layout_height="176dp"android:layout_marginTop="80dp"android:layout_centerHorizontal="true"/><TextView
        android:id="@+id/text1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="faceDemo"android:layout_below="@id/glsurfaceView"android:layout_centerHorizontal="true"android:paddingTop="10dp"/></RelativeLayout>

人脸检测代码

public class Detecter extends AppCompatActivity implements View.OnTouchListener, CameraSurfaceView.OnCameraListener, Camera.AutoFocusCallback {private final String TAG = this.getClass().getSimpleName();private CameraSurfaceView mSurfaceView;private CameraGLSurfaceView mGLSurfaceView;private Camera mCamera;private TextView textView1 ;int mCameraID;int mCameraRotate;boolean mCameraMirror;private int mWidth, mHeight, mFormat;List<AFT_FSDKFace> result = new ArrayList<>();AFT_FSDKVersion version = new AFT_FSDKVersion();AFT_FSDKEngine engine = new AFT_FSDKEngine();byte[] mImageNV21 = null;FRAbsLoop mFRAbsLoop = null;AFT_FSDKFace mAFT_FSDKFace = null;boolean isOK = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mCameraID = getIntent().getIntExtra("Camera", 0) == 0 ? Camera.CameraInfo.CAMERA_FACING_BACK : Camera.CameraInfo.CAMERA_FACING_FRONT;mCameraRotate = getIntent().getIntExtra("Camera", 0) == 0 ? 90 : 270;mCameraMirror = getIntent().getIntExtra("Camera", 0) == 0 ? false : true;mWidth = 1280;mHeight = 960;mFormat = ImageFormat.NV21;setContentView(R.layout.activity_detecter);mGLSurfaceView = (CameraGLSurfaceView) findViewById(R.id.glsurfaceView);mGLSurfaceView.setOnTouchListener(this);mSurfaceView = (CameraSurfaceView) findViewById(R.id.surfaceView);mSurfaceView.setOnCameraListener(this);mSurfaceView.setupGLSurafceView(mGLSurfaceView, true, mCameraMirror, mCameraRotate);mSurfaceView.debug_print_fps(true, false);textView1 = (TextView) findViewById(R.id.text1);// 初始化人脸跟踪程序AFT_FSDKError err = engine.AFT_FSDK_InitialFaceEngine(FaceDB.appid, FaceDB.ft_key, AFT_FSDKEngine.AFT_OPF_0_HIGHER_EXT, 16, 5);Log.d(TAG, "AFT_FSDK_InitialFaceEngine =" + err.getCode());err = engine.AFT_FSDK_GetVersion(version);Log.d(TAG, "AFT_FSDK_GetVersion:" + version.toString() + "," + err.getCode());mFRAbsLoop = new FRAbsLoop(); // 识别线程mFRAbsLoop.start();}class FRAbsLoop extends AbsLoop {AFR_FSDKVersion version = new AFR_FSDKVersion();AFR_FSDKEngine engine = new AFR_FSDKEngine();AFR_FSDKFace result = new AFR_FSDKFace();List<FaceDB.FaceRegist> mResgist = App.mFaceDB.mRegister;List<ASAE_FSDKFace> face1 = new ArrayList<>();List<ASGE_FSDKFace> face2 = new ArrayList<>();@Overridepublic void setup() {AFR_FSDKError error = engine.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);Log.d(TAG, "AFR_FSDK_InitialEngine = " + error.getCode());error = engine.AFR_FSDK_GetVersion(version);Log.d(TAG, "FR=" + version.toString() + "," + error.getCode()); //(210, 178 - 478, 446), degree = 1 780, 2208 - 1942, 3370}@Overridepublic void loop() {if(isOK){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}mFRAbsLoop.shutdown();Detecter.this.finish();}// 进行人脸识别检测if (mImageNV21 != null) {long time = System.currentTimeMillis();AFR_FSDKError error = engine.AFR_FSDK_ExtractFRFeature(mImageNV21, mWidth, mHeight, AFR_FSDKEngine.CP_PAF_NV21, mAFT_FSDKFace.getRect(), mAFT_FSDKFace.getDegree(), result);Log.d(TAG, "AFR_FSDK_ExtractFRFeature cost :" + (System.currentTimeMillis() - time) + "ms");Log.d(TAG, "Face=" + result.getFeatureData()[0] + "," + result.getFeatureData()[1] + "," + result.getFeatureData()[2] + "," + error.getCode());AFR_FSDKMatching score = new AFR_FSDKMatching();float max = 0.0f;String name = null;for (FaceDB.FaceRegist fr : mResgist) {for (AFR_FSDKFace face : fr.mFaceList) {error = engine.AFR_FSDK_FacePairMatching(result, face, score);Log.d(TAG,  "Score:" + score.getScore() + ", AFR_FSDK_FacePairMatching=" + error.getCode());if (max < score.getScore()) {max = score.getScore();name = fr.mName;}}}//age & genderface1.clear();face2.clear();//crop byte[] data = mImageNV21;YuvImage yuv = new YuvImage(data, ImageFormat.NV21, mWidth, mHeight, null);ExtByteArrayOutputStream ops = new ExtByteArrayOutputStream();yuv.compressToJpeg(mAFT_FSDKFace.getRect(), 80, ops);final Bitmap bmp = BitmapFactory.decodeByteArray(ops.getByteArray(), 0, ops.getByteArray().length);try {ops.close();} catch (IOException e) {e.printStackTrace();}if (max > 0.6f) {// 分数大于6.0识别成功//fr success.final float max_score = max;Log.d(TAG, "fit Score:" + max + ", NAME:" + name);final String mNameShow = name;runOnUiThread(new Runnable() {@Overridepublic void run() {textView1.setText("识别成功!");textView1.setTextColor(Color.BLACK);isOK = true;}});} else {final String mNameShow = "未识别";Log.d(TAG,  "识别:" + name);runOnUiThread(new Runnable() {@Overridepublic void run() {textView1.setText("识别失败!");textView1.setTextColor(Color.RED);}});}mImageNV21 = null;}}@Overridepublic void over() {AFR_FSDKError error = engine.AFR_FSDK_UninitialEngine();Log.d(TAG, "AFR_FSDK_UninitialEngine : " + error.getCode());}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();// 销毁mFRAbsLoop.shutdown();AFT_FSDKError err = engine.AFT_FSDK_UninitialFaceEngine();Log.d(TAG, "AFT_FSDK_UninitialFaceEngine =" + err.getCode());}@Overridepublic boolean onTouch(View v, MotionEvent event) {CameraHelper.touchFocus(mCamera, event, v, this); // 点击聚焦return false;}@Overridepublic Camera setupCamera() {// 在相机启动前设置一些属性,设置数据的格式为NV21,图像的宽高mCamera = Camera.open(mCameraID);try {Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewSize(mWidth, mHeight);parameters.setPreviewFormat(mFormat);for( Camera.Size size : parameters.getSupportedPreviewSizes()) {Log.d(TAG, "SIZE:" + size.width + "x" + size.height);}for( Integer format : parameters.getSupportedPreviewFormats()) {Log.d(TAG, "FORMAT:" + format);}List<int[]> fps = parameters.getSupportedPreviewFpsRange();for(int[] count : fps) {Log.d(TAG, "T:");for (int data : count) {Log.d(TAG, "V=" + data);}}//parameters.setPreviewFpsRange(15000, 30000);//parameters.setExposureCompensation(parameters.getMaxExposureCompensation());//parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);//parameters.setAntibanding(Camera.Parameters.ANTIBANDING_AUTO);//parmeters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);//parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);//parameters.setColorEffect(Camera.Parameters.EFFECT_NONE);mCamera.setParameters(parameters);} catch (Exception e) {e.printStackTrace();}if (mCamera != null) {mWidth = mCamera.getParameters().getPreviewSize().width;mHeight = mCamera.getParameters().getPreviewSize().height;}return mCamera;}@Overridepublic void setupChanged(int format, int width, int height) {}@Overridepublic boolean startPreviewLater() {return false;}@Overridepublic Object onPreview(byte[] data, int width, int height, int format, long timestamp) {// 获取数据流 检测人脸信息框AFT_FSDKError err = engine.AFT_FSDK_FaceFeatureDetect(data, width, height, AFT_FSDKEngine.CP_PAF_NV21, result);Log.d(TAG, "AFT_FSDK_FaceFeatureDetect =" + err.getCode());Log.d(TAG, "Face=" + result.size());for (AFT_FSDKFace face : result) {Log.d(TAG, "Face:" + face.toString());}if (mImageNV21 == null) {if (!result.isEmpty()) {mAFT_FSDKFace = result.get(0).clone();mImageNV21 = data.clone();} else {//mHandler.postDelayed(hide, 3000);}}//copy rectsRect[] rects = new Rect[result.size()];for (int i = 0; i < result.size(); i++) {rects[i] = new Rect(result.get(i).getRect());}//clear result.result.clear();//return the rects for render.return rects;}@Overridepublic void onBeforeRender(CameraFrameData data) {}@Overridepublic void onAfterRender(CameraFrameData data) {//  绘制人脸框mGLSurfaceView.getGLES2Render().draw_rect((Rect[])data.getParams(), Color.GREEN, 2);}@Overridepublic void onAutoFocus(boolean success, Camera camera) {}
}

http://www.ppmy.cn/news/836834.html

相关文章

Android人脸识别

文章目录 Android自带的人脸识别API第三方提供大牛们的封装 Android自带的人脸识别API Android实现人脸识别可以通过google原生自带API实现&#xff0c;只能识别静态图片&#xff0c;缺点是精度不高&#xff0c;识别信息很少&#xff0c;只有眼睛的识别 栗子 在页面上放一个…

Android 人脸识别了解一下 (上)

转载请注明作者及出处&#xff1a;https://www.jianshu.com/p/ca3a12bc4911 引言 人脸识别这件事想来早已经不新鲜&#xff0c;在 Android 中的应用也并不广泛&#xff0c;所以网上相关资料乏善可陈。但是在面对特殊的应用场景时&#xff0c;人脸识别的功能还是有一定的用处的…

Android在线人脸识别登录系统

Android在线人脸识别登录系统 前言 最近需要做一个Android的在线人脸识别项目&#xff0c;需求是能够在线人脸识别登录&#xff0c;找了很多资料都是价格很高或者是离线保存样本的&#xff0c;最后选择免费的虹软人脸识别&#xff0c;经过查询很多资料&#xff0c;最终完结了…

安卓SDK——人脸识别

引 还是讯飞&#xff0c;前两篇文章 语音识别 https://blog.csdn.net/nishigesb123/article/details/90478104 语音合成 https://blog.csdn.net/nishigesb123/article/details/90478584 参考链接 官网&#xff1a;https://www.xfyun.cn/ 人脸识别说明文档&#xff1a;ht…

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

title: Android实现人脸识别&#xff08;人脸检测&#xff09;初识 categories: Android tags:人脸识别人脸检测相机处理 date: 2020-05-21 11:35:51 介绍 本篇文章主要介绍一下移动端Android的人脸识别大致逻辑&#xff0c;后续文章会陆续放出干货&#xff0c;首先我们要明确…

人脸识别考勤系统安卓APP(手把手教学-手动滑稽)

由于百度API开始收费&#xff0c;所以这个应用暂时无法使用了&#xff0c;代码部分仍然有参考价值&#xff0c;建议大家自行更换token去验证。个人博客的下载验证码bug&#xff0c;已经fix。可以继续下载了。 更新于2022.02.13 ————————————————————我是分…

Android 人脸识别 活体检测 人脸对比

人脸识别技术应用于支付、门禁、以及手机解锁在当下已经非常成熟&#xff0c;作为一个Android 开发者&#xff0c;掌握人脸识别技术已经是必须做的事情了&#xff0c;市面上比较流行的人脸识别API主要有阿里云&#xff08;5000条以内免费&#xff09;、腾讯云&#xff08;收费&…

Android开发实现人脸识别

之前看到有人在博客写用face做人脸识别app&#xff0c;后来我也照着教程去试了一遍&#xff0c;发现根本行不通&#xff0c;原因在于他调用的库是旧版本&#xff0c;face已经全面更新了版本.后来我照着face官网新版本的API文档打了一遍代码&#xff0c;发现识别的结果还算差强人…