尝试 AI 人脸关键点算法实现一下 Android 人脸匿名功能
时间: 2020-08-18来源:V2EX
前景提要
什么是人脸匿名( Face Anonymization )
随着人脸识别技术的普及,人脸数据的隐私问题也得到越来越多关注,针对隐私保护的研究也陆续出现。目前大致有下面几个方向 篡改输入人脸识别系统的图像。 生成式对抗网络(GAN)来匿名某人的照片或视频。 直接模糊人脸识别到的人脸
本文主要讲第 3 点,讲讲怎么使用移动端人脸关键点算法实现人脸匿名功能。这种方法对设备要求低,代码简单易懂,修改后就可直接落地。
下图就是最终想实现的功能

什么是人脸关键点算法( Face Landmarks )
人脸关键点检测是人脸相关算法中的关键一环,它是人脸识别、表情分析、3D 人脸重建,表情驱动 3D 动画等一系列人脸相关问题的前提。

我们将使用 TengineKit 来实现人脸匿名功能
TengineKit
免费移动端实时人脸 212 关键点 SDK 。是一个易于集成的人脸检测和人脸关键点 SDK 。它可以在各种手机上以非常低的延迟运行。
https://github.com/OAID/TengineKit
TengineKit 效果图

实现
配置 Gradle
Project 中的 build.gradle 添加 repositories { ... mavenCentral() ... } allprojects { repositories { ... mavenCentral() ... } }
主 Module 中的 build.gradle 添加 dependencies { ... implementation 'com.tengine.android:tenginekit:1.0.3' ... }
配置 manifests <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.FLASHLIGHT" /> <uses-feature android:name = "android.hardware.camera" android:required="true"/> <uses-feature android:name = "android.hardware.camera.autofocus" />
初始化 Android Camera
为 App 创建自定义摄像头界面的步骤如下: 检测和访问 Camera 创建预览 TextureView 构建预览 TextureView 布局 将 Camera 和 TextureView 绑定 启动预览
我们先 new 一个 TextureView.SurfaceTextureListener,在里面完成 camera 的初始配置,当 TextureView 可用的时候,onSurfaceTextureAvailable 中的代码将被调用 private final TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(final SurfaceTexture texture, final int width, final int height) { int index = getCameraId(); camera = Camera.open(index); try { Camera.Parameters parameters = camera.getParameters(); List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } List<Camera.Size> cameraSizes = parameters.getSupportedPreviewSizes(); Size[] sizes = new Size[cameraSizes.size()]; int i = 0; for (Camera.Size size : cameraSizes) { sizes[i++] = new Size(size.width, size.height); } Size previewSize = CameraConnectionFragment.chooseOptimalSize(sizes, desiredSize.getWidth(), desiredSize.getHeight()); parameters.setPreviewSize(previewSize.getWidth(), previewSize.getHeight()); camera.setDisplayOrientation(90); camera.setParameters(parameters); camera.setPreviewTexture(texture); } catch (IOException exception) { camera.release(); } camera.setPreviewCallbackWithBuffer(imageListener); Camera.Size s = camera.getParameters().getPreviewSize(); camera.addCallbackBuffer(new byte[ImageUtils.getYUVByteSize(s.height, s.width)]); textureView.setAspectRatio(s.height, s.width); camera.startPreview(); } @Override public void onSurfaceTextureSizeChanged(final SurfaceTexture texture, final int width, final int height) { } @Override public boolean onSurfaceTextureDestroyed(final SurfaceTexture texture) { return true; } @Override public void onSurfaceTextureUpdated(final SurfaceTexture texture) { } };
此处将 textureView 和 camera 联系起来 textureView.setSurfaceTextureListener(surfaceTextureListener);
当 camera 启动预览,textureView 得到真实的 size 后。我们得到了 camera 的输出视频流的宽高和预览 textureView,将其保存起来,后续有用到。 textureView.setRealSizeListener(new AutoFitTextureView.RealSizeListener() { @Override public void onRealSizeMeasure(int w, int h) { if(!isReady){ isReady = true; Camera.Size s = camera.getParameters().getPreviewSize(); cameraReadyListener.onCameraReady( s.width, s.height,w, h ); } } });
处理 Camera 传过来的视频流
首先我们先初始化 TengineKit: 选用 camera 处理模式 打开人脸检测和人脸关键点功能 设置视频流格式为 YUV_NV21 ( Android camera 默认格式) 设置输入视频流的宽高,此处为 camera 的预览宽高 设置输出视频流的宽高,此处为 textrureView 的宽高 设置输入视频流来自前置摄像头 com.tenginekit.Face.init(getBaseContext(), AndroidConfig.create() .setCameraMode() .openFunc(AndroidConfig.Func.Detect) .openFunc(AndroidConfig.Func.Landmark) .setInputImageFormat(AndroidConfig.ImageFormat.YUV_NV21) .setInputImageSize(previewWidth, previewHeight) .setOutputImageSize(outputWidth, outputHeight) ); com.tenginekit.Face.Camera.switchCamera(false);
处理数据 得到手机旋转角度,将其设置到 TengineKit 开始检测,当检测到人脸数目大于 0 的时候,调用 faceDetect.landmark2d(),得到人脸关键点链表 int degree = CameraEngine.getInstance().getCameraOrientation(sensorEventUtil.orientation); com.tenginekit.Face.Camera.setRotation(degree - 90, false, outputWidth, outputHeight); com.tenginekit.Face.FaceDetect faceDetect = Face.detect(data); faceLandmarks = null; if(faceDetect.getFaceCount() > 0){ faceLandmarks = faceDetect.landmark2d(); }
高斯模糊和绘制
这里使用 Android 的 bitmap 来实现功能,这种做法比较粗糙,性能差,但是简单易懂,如果读者有兴趣可以使用 OpenGLES 来实现此功能。 将从摄像头中得到的 yuv 数据通过 TengineKit 的图片帮助函数转化为 Bitmap 通过人脸关键点的外接框,裁剪 bitmap 得到人脸的 bitmap 数组 将得到的人脸 bitmap 进行高斯模糊 if(testBitmap != null){ testBitmap.recycle(); } testBitmap = Face.Image.convertCameraYUVData( data, previewWidth, previewHeight, outputWidth, outputHeight, - 90, true); for(Bitmap bitmap : testFaceBitmaps){ bitmap.recycle(); } testFaceBitmaps.clear(); if(testBitmap != null && faceDetect.getFaceCount() > 0){ if(faceLandmarks != null){ for (int i = 0; i < faceLandmarks.size(); i++) { Bitmap face = BitmapUtils.getDstArea(testBitmap, faceLandmarks.get(i).getBoundingBox()); face = BitmapUtils.blurByGauss(face, 50); testFaceBitmaps.add(face); } } } runInBackground(new Runnable() { @Override public void run() { trackingOverlay.postInvalidate(); } });
trackingOverlay 为定制的 view,将 canvas 暴露出来用于画 bitmap trackingOverlay.addCallback(new OverlayView.DrawCallback() { @Override public void drawCallback(final Canvas canvas) { if(testBitmap != null){ canvas.drawBitmap(testBitmap, 0,0, circlePaint); } if(faceLandmarks != null){ for (int i = 0; i < faceLandmarks.size(); i++) { Rect r = faceLandmarks.get(i).getBoundingBox(); canvas.drawRect(r, circlePaint); canvas.drawBitmap(testFaceBitmaps.get(i), r.left, r.top, circlePaint); } } } });
效果

Demo

参考
https://github.com/OAID/TengineKit
源码
https://github.com/jiangzhongbo/TengineKit_Demo_Identity_Protection
知乎
https://zhuanlan.zhihu.com/p/161038093

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

热门排行