Android实现人脸识别效果
龙旋
共 4460字,需浏览 9分钟
· 2021-12-17
作者 | itfitness 地址 | https://www.jianshu.com/p/9383ce973d6a
效果展示:
实现步骤
1、绘制圆圈遮罩
这里我们是用了混合模式来实现圆圈部分的扣除,这里我们用到了PorterDuff.Mode.CLEAR
/**
* 绘制圆圈遮罩
* @param canvas
*/
private void drawCircleMask(Canvas canvas) {
canvas.save();
//目标图Dst
canvas.drawRect(new Rect(0,0,getWidth(),getHeight()), mPaint);
//设置混合模式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//源图Src,重叠区域右下角部分
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 3, mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restore();
}
这时效果如下:
2、绘制两个动画效果的圆圈
咱们绘制的两个图片如下:
我们要做的就是通过计算将Bitmap缩放成与之前遮罩效果的圆圈一样大,因为我们这里用的两张图片是一样大的,因此我们只需要计算出内圆圈图片与遮罩圆圈的缩放比例即可,由于之前咱们给遮罩圆圈设置的半径为:控件宽度 / 3
因此我们缩放后的圆圈Bitmap宽高应当是如下图所示的中间红线部分加两边蓝色部分的总长
其中中间红线部分就是:控件宽度 / 3 ,而蓝线部分可以通过PhotoShop等工具测量,然后根据与红线部分的比例求出,代码如下,其中mInnerCircleBitmap是内圆,mOutCircleBitmap是外圆
/**
* 画圆圈外部的圆圈图片
*/
private void drawBitmapCircle(Canvas canvas) {
if(mInnerCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mInnerCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_innercircle);
mInnerCircleBitmap = Bitmap.createScaledBitmap(mInnerCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
if(mOutCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mOutCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_outcircle);
mOutCircleBitmap = Bitmap.createScaledBitmap(mOutCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
int left = (getWidth() - mInnerCircleBitmap.getWidth()) / 2;
int top = (int) (getWidth() / 2 - getWidth() / 3 - getWidth() / 1.5f / 8);
canvas.drawBitmap(mInnerCircleBitmap,left,top,mPaint);
canvas.drawBitmap(mOutCircleBitmap,left,top,mPaint);
}
这时效果如下:
3、实现旋转动画效果
接下来我们就可以通过ValueAnimator来实现圆圈的旋转效果了,从文章开头的效果我们可以看出两个圆圈的旋转方向是不一样的,因此我们逻辑上也要注意一个是顺时针旋转另一个是逆时针旋转,代码如下
private float mDegress = 0;//旋转角度
private void init() {
//定义动画
valueAnimator = ValueAnimator.ofFloat(0f, 360f);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(6000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mDegress = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
/**
* 画圆圈外部的圆圈图片
*/
private void drawBitmapCircle(Canvas canvas) {
if(mInnerCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mInnerCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_innercircle);
mInnerCircleBitmap = Bitmap.createScaledBitmap(mInnerCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
if(mOutCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mOutCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_outcircle);
mOutCircleBitmap = Bitmap.createScaledBitmap(mOutCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
int left = (getWidth() - mInnerCircleBitmap.getWidth()) / 2;
int top = (int) (getWidth() / 2 - getWidth() / 3 - getWidth() / 1.5f / 8);
//顺时针旋转
canvas.save();
canvas.rotate(mDegress,getWidth() / 2, getWidth() / 2);
canvas.drawBitmap(mInnerCircleBitmap,left,top,mPaint);
canvas.restore();
//逆时针旋转
canvas.save();
canvas.rotate(-mDegress,getWidth() / 2, getWidth() / 2);
canvas.drawBitmap(mOutCircleBitmap,left,top,mPaint);
canvas.restore();
}
这时效果如下:
4、增加提示文字
绘制文字就比较简单了,主要是用于提示用户需要进行的操作,代码如下:
canvas.drawText("请把脸移入圈内",getWidth() / 2, (float) (getWidth() * 1.2),mTextPaint);
最终效果如下:
案例源码:
以上实现步骤中的源码我都是拆分开讲的,详细完整的代码大家可以通过如下地址获取:
https://gitee.com/itfitness/face-check-view
到这里就结束啦。
评论
15种时间序列预测方法总结(包含多种方法代码实现)
向AI转型的程序员都关注了这个号👇👇👇在这篇文章中,我们将深入探讨时间序列预测的基本概念和方法。我们将首先介绍单元预测和多元预测的概念,然后详细介绍各种深度学习和传统机器学习方法如何应用于时间序列预测,包括循环神经网络(RNN)、一维卷积神经网络(1D-CNN)、Transformer、自回归模型(
机器学习AI算法工程
0
SpringBoot 实现图片防盗链功能
程序员的成长之路互联网/程序员/技术/资料共享 关注阅读本文大概需要 4 分钟。来自:blog.csdn.net/weixin_46157208/article/details/138051737前言出于安全考虑,我们需要后端返回的图片只允许在某个网站内展示,不想被爬虫拿到图片地
程序员的成长之路
0
一站式解决方案:基于 Arthas 实现服务发现和权限控制
来源:juejin.cn/post/7281849496983994383👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接
小哈学Java
0
用 Shader 实现旗帜飘扬动画效果
我觉得对于刚入门 3D 编程的朋友来说,如果能够完成代码创建模型数据->创建材质->编写Shader动画这一系列,想必会有满满的成就感。今天就用 Cocos Creator 的 utils.MeshUtils.createMesh 接口,带大家感受一下这个流程。这个流程不仅可以用于新手学
COCOS
2
盘点一个使用超级鹰识别验证码并自动登录的案例
点击上方“Python共享之家”,进行关注回复“资源”即可获赠Python学习资料今日鸡汤江上几人在,天涯孤棹还。大家好,我是皮皮。一、前言前几天在Python钻石交流群【静惜】问了一个Python实现识别验证码并自动登录的问题,提问截图如下:验证码的截图如下所示:二、实现过程这里大家激烈的探讨,【
IT共享之家
0
SpringBoot+Minio实现上传凭证、分片上传、秒传和断点续传
关注我们,设为星标,每天7:40不见不散,架构路上与您共享回复架构师获取资源大家好,我是你们的朋友架构君,一个会写代码吟诗的架构师。Spring Boot整合Minio后,前端的文件上传有两种方式:1、文件上传到后端,由后端保存到Minio这种方式好处是完全由后端集中管理,可以很好的做到、身份验证、
Java架构师社区
0
超越原生,散点图实现华夫饼图
之前我们介绍过了如何使用新卡片图实现华夫饼图。参考:超越原生,PowerBI 华夫饼图实现但是利用卡片图实现的华夫饼图有一些缺点,形状之间的大小跟间距不太好把握,而且有时形状大一点的话显示就会不正常,需要做出二次调整。今天给大家介绍一种原生视觉对象生成华夫饼图的更佳方案,既简单又美观。上图是利用散点
PowerBI战友联盟
2
全新 SOTA backbone | 2024年了,再见ViT系列Backbone,实数难得,不知道效果如何?
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达在构建用于精确匹配的深度固定长度表示时,确定指纹上的密集特征点,特别是在像素 Level 上,具有重大意义。为了探索指纹匹配的可解释性,作者提出了一种多阶段可解释的指纹匹配网络,名为通过视觉 Transformer 进行指纹匹配的
小白学视觉
10