在 Android 中使用 FaceOnLive SDK 构建人脸识别应用
haoteby 2025-01-09 13:00 1 浏览
照片由 安托万·博维利亚 on Unsplash
作为一名使用人脸识别技术的 Android 开发人员,我尝试了多种方法和库,例如将 FaceNet 与 MLKit 的人脸检测、CameraX 和 dlib-android 一起使用。使用服务器端推理,将人脸图像发送到远程 API 以验证其相似性,也是一个很好的策略,但需要额外的后端服务,并且由于网络调用而在应用程序中引入延迟。此外,人脸识别技术还需要处理实时摄像头,这完全排除了服务器端推理。
我有机会尝试了 FaceOnLive 的人脸和活体检测 Android SDK,我想分享我对 SDK 及其在现有 Android 应用程序中的集成的经验。
我们在哪里使用人脸识别技术?
人脸识别可以通过将图片与存储在数据库中的现有图像进行匹配来验证一个人的身份。有几个用例,其中包括:
- 校园和办公室的考勤监控:可靠的人脸识别应用程序可以取代指纹或身份证扫描机制,以标记工厂工人、办公室员工或教育校园学生的日常出勤情况。结合实时检测,代理出勤的机会大大降低。此外,还消除了包括特殊硬件设备(传感器或指纹扫描仪)的需要。
- eKYC(e了解您的客户):这是授权组织和代理对特定可用服务验证和验证客户个人数据的过程。使用人脸识别技术,可以在众多文档中轻松匹配eKYC流程中的客户面孔与官方文件中给出的图片进行匹配。
- 客户分析:通过识别进入购物中心或商店的客户,可以通过分析他们的购物历史和在商店中的存在来定制许多服务。由于人脸识别系统也可以用作身份验证手段,因此免结账解决方案也是可能的,因为它们可以通过面部图片验证人的身份,从而直接确定人的付款方式。店主可以分析常客并定制特定服务,以最大限度地保留和满足客户。
- 具有面部识别功能的视频监控:它涉及使用安全摄像头和软件通过分析视频源及其面部特征来识别人员。它可以帮助识别刑事调查中的嫌疑人或监控商店中的顾客行为。
FaceOnLive SDK的功能
- 设备端推理,无需对每个人脸检测请求进行服务器调用。它还确保了最少的延迟并改善了整体用户体验。
- 使用内置的人脸活体检测,我们不需要编写单独的逻辑来确定相机帧中检测到的人脸的活体。这也消除了在关键应用程序中使用人脸代理。
Android 设置
在本节中,我们将讨论将 FaceOnLive 人脸识别和活体检测 SDK 集成到 Android 应用程序中所需的步骤。
SDK 入门
一旦我们收到 API 密钥,就应该将其添加到 license 文件中 app/src/main/assets ,
BsTr9o4f4R/rM3TxbCWVb/hrOJuOIdz8ArQ/t2IgQFFUQzGHOLNNaMJiK/fUfr5zo005zoTA/cm6
VoZ6iGl+/hZGA3R5T/VWwhxekbw8JVz9sNesU6rMG5+1cNSN75trH2tpzdCPZ28ZDnZlttmiuUoC
9QazRe1xKi5tUXa+xgIxzL0vE6UW2dLKWaEXjn3fSJfLxXWw0q+UZP0hQAXb5Y9Yl/NVi7y3d0xT
Vq6/weuMQkgLcNdLqFRvQXup0M9W/pvuhaubySAxHCKVY8wToygN2iM78cOkyyAbGVwZeGQP0Jfd
46VZo+w+KCNw355j3osVVMghrOcVZnfbp1dNyg==
然后,我们可以通过通过传递从 assets 目录 license 中的文件中读取的 API 密钥来调用 FaceSDK.setActivation 我们 onCreate MainActivity 的方法中的 SDK,
val license_str = application.assets.open("license").bufferedReader().use{
it.readText()
}
var ret = FaceSDK.setActivation(license_str)
if (ret == FaceSDK.SDK_SUCCESS) {
ret = FaceSDK.init(assets)
}
ret 表示来自 SDK 的激活响应。它可以根据 SDK 激活过程的结果假设多个值,并应相应地进行处理,
if (ret != FaceSDK.SDK_SUCCESS) {(
var message = "SDK initialization failed"
if (ret == FaceSDK.SDK_LICENSE_KEY_ERROR) {
message = "License key error!"
} else if (ret == FaceSDK.SDK_LICENSE_APPID_ERROR) {
message = "App ID error!"
} else if (ret == FaceSDK.SDK_LICENSE_EXPIRED) {
message = "License key expired!"
} else if (ret == FaceSDK.SDK_NO_ACTIVATED) {
message = "Activation failed!"
} else if (ret == FaceSDK.SDK_INIT_ERROR) {
message = "Engine init error!"
}
}
SDK 现在已准备好用于人脸识别。在下一步中,我们将注册必须被 SDK 识别的人脸(主题)。
注册人脸以进行识别
向 SDK 注册用户(来源:作者)
人脸识别器需要图像,必须从实时摄像头馈送中识别出人的基本事实。此映像使用应用程序用户提供的用户名或 ID 进行注释,并存储在本地设备数据库中。
在实时检测来自摄像头源的人脸时,将检测到的人脸与已注册或作为基本事实提供给 SDK 的人脸进行比较。如果检测到的人脸与数据集中存在的图像匹配,并且在给定特定阈值的情况下具有相似性,则 SDK 会得出结论,检测到的人脸属于图像匹配度最高的人。
// (1) Initialize face detection API
val faceDetectionParam = FaceDetectionParam()
faceDetectionParam.check_liveness = true
// liveness_level determines the model used for liveness detection
// 0 -> model v0
// 1 -> model v2-fast
faceDetectionParam.check_liveness_level = 0
// (2) Perform face detection
// bitmap -> input image containing faces
var faceBoxes: List<FaceBox>? = FaceSDK.faceDetection(bitmap, faceDetectionPar
// (3) Interpret the face detection results
if(faceBoxes.isNullOrEmpty()) {
// No faces found in the image
}
else if (faceBoxes.size > 1) {
// Multiple faces found in the image
}
else {
// (4) Extract face templates (Features) from the input image
val templates = FaceSDK.templateExtraction(bitmap, faceBoxes[0])
// (5) Save `templates` locally, for instance in an SQLite database
// The cropped face can also be obtained with Utils.cropFace
// From the image, crop the region which bounds the face
val faceImage = Utils.cropFace(bitmap, faceBoxes[0])
}
在下一步中,我们将探讨如何将人脸识别 SDK 与 CameraX 集成以显示实时摄像头源(预览版)。
使用人脸检测创建实时预览
使用 SDK 进行人脸检测和活体检测(来源:作者)
我们通过向 Fotoapparat 提供必要的相机参数和 CameraView 对象来创建实时相机预览,
val PREVIEW_WIDTH = 720
val PREVIEW_HEIGHT = 1280
private lateinit var cameraView: CameraView
private lateinit var faceView: FaceView
private lateinit var fotoapparat: Fotoapparat
private var activeCamera: Camera = Camera.FrontCamera
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera_kt)
cameraView = findViewById(R.id.preview)
faceView = findViewById(R.id.faceView)
fotoapparat = Fotoapparat.with(this)
.into(cameraView)
.lensPosition(activeCamera.lensPosition)
.frameProcessor(FaceFrameProcessor())
.previewResolution { Resolution(PREVIEW_HEIGHT,PREVIEW_WIDTH) }
.build()
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED
) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1)
} else {
fotoapparat.start()
}
...
}
我们还需要编写一个实现 FaceFrameProcessor ,其中包含对相机产生的每一帧调用 process( frame: Frame ) 的方法,我们执行以下任务,
使用 SDK 识别人脸的示意图(来源:作者)
- 使用 FaceSDK.yuv2Bitmap 将 YUV 图像转换为对象中包含的 Bitmap RGB 图像。让我们 inputImage 称之为我们的理解。
- 执行人脸检测, inputImage 使用 FaceSDK.faceDetection 时返回 FaceBox
人脸活体检测(来源:作者)
- 检查是否 faceBox.liveness 超过某个阈值,如果没有,则从 process 该方法返回,因为该脸可能不属于物理人。
- 从 inputImage 和 FaceBox 使用 FaceSDK.templateExtraction 中 subjectTemplates 提取人脸模板
- 读取存储在数据库中的模板,并将它们中的每一个与 subjectTemplates 返回表示 Float 相似性的 using FaceSDK.similarityCalculation 进行比较。如果相似性大于给定的阈值,请将其与我们在早期迭代中发现的最大相似性进行比较。
inner class FaceFrameProcessor : FrameProcessor {
override fun process(frame: Frame) {
// (1) Convert the YUV frame received from the camera to a
// RGB bitmap
val bitmap = FaceSDK.yuv2Bitmap(frame.image, frame.size.width, frame.size.height, cameraOrientation)
// (2) Initiate face detection
val faceDetectionParam = FaceDetectionParam()
faceDetectionParam.check_liveness = true
// liveness_level determines the model used for liveness detection
// 0 -> model v0
// 1 -> model v2-fast
faceDetectionParam.check_liveness_level = 1
val faceBoxes = FaceSDK.faceDetection(bitmap, faceDetectionParam)
// (3) Provide faceBoxes to the faceView
// for rendering them on the screen
runOnUiThread {
faceView.setFaceBoxes(faceBoxes)
}
if(faceBoxes.size > 0) {
val faceBox = faceBoxes[0]
// Check if liveness score is above a given threshold
if (faceBox.liveness > 0.7) {
// (4) Compare faces stored in database
// and determine the greatest match
val templates = FaceSDK.templateExtraction(bitmap, faceBox)
var maxSimiarlity = 0f
var maximiarlityPerson: Person? = null
for (person in DBManager.personList) {
val similarity = FaceSDK.similarityCalculation(templates, person.templates)
if (similarity > maxSimiarlity) {
maxSimiarlity = similarity
maximiarlityPerson = person
}
}
if (maxSimiarlity > SettingsActivity.getMatchThreshold(context)) {
recognized = true
val identifiedPerson = maximiarlityPerson
val identifiedSimilarity = maxSimiarlity
// (5) Navigate the user to the next screen where the
// similarity score can be displayed along with the
// detected face parameters
}
}
}
}
}
查看人脸参数
除了人脸及其活度分数的边界框外,SDK 还返回检测到的人脸的偏航、俯仰和滚动。让我们讨论一下这些参数中的每一个:
偏航、俯仰和横滚的图示。源
- 偏航:它表示从头部直向上的轴的旋转程度。将头部向侧面转动将改变, yaw 如果头部向左转动,则为正,如果头部向右转,则为负数(假设脸在观众面前)。对于直视,为 yaw 0。
- 俯仰:与偏航类似,它测量绕穿过双耳的轴的旋转程度。向上看如果使 pitch 它为负,而向下看将使它为正。
- 滚动:它测量围绕穿过鼻子和后脑勺的轴的旋转程度。它测量脸部的侧向倾斜度。
对于每个 FaceBox 返回的 FaceSDK.faceDetection 参数,这些参数可以通过属性访问轻松检索,
val faceDetectionParam = FaceDetectionParam()
faceDetectionParam.check_liveness = true
faceDetectionParam.check_liveness_level = 1
val faceBoxes = FaceSDK.faceDetection(bitmap, faceDetectionParam)
val faceBox = faceBoxes[0]
val yaw = faceBox.yaw
val pitch = faceBox.pitch
val roll = faceBox.roll
结论
我希望博客内容丰富,读者会考虑在他们的 Android 应用程序中使用 FaceOnLive SDK 进行人脸识别。如有疑问和建议,可以在 Medium 上写下评论,或直接与我联系。祝你有美好的一天!
相关推荐
- 用户界面干货盘点
-
为了解决大家找资源难的问题,EVGET特别开辟每周盘点用户界面干货的专栏,一网打尽热门的界面资讯、Demo示例、版本升级及下载、移动Web开发,以及各种UI神器推荐。更多资源及工具也可以在用户界面专题...
- 不仅仅是创意,26款科技小玩意
-
新科技不断在卖场出现,总是吸引着消费者的眼球。许多很棒的科技小玩意儿被发明,手机、平板、手提电脑、游戏主机、甚至是3D打印都适用。现在的初创公司已经发正在让21世纪打破各种科技壁垒障碍。本文收集26...
- FastReport.Net报表设计器如何连接到SQLCe
-
MicrosoftSQLServerCompactEdition是一个简单的本地关系数据库,不需要安装,并且已与数据库文件建立连接。您不需要管理员权限即可使用基础功能。您也只能“密码”基础功能...
- 2015年最值得关注的8款用户界面新品
-
软件界面开发解决方案这一块一直以来是慧都控件(EVGET)的强项,我们有400多款用户界面产品,250多款图表报表产品,此外还提供专业的软件界面定制开发服务,其中DevExpress定制开发、甘特图定...
- 小贴士:安装TBarCode office的注意事项和相关资源
-
TBarCodeoffice是一款适用于MicrosoftWord2007、2010等版本,具有强大功能的条码插件。在这里我们介绍一下安装TBarCodeoffice的注意事项和相关资源。安装...
- 初学者不容错过的修复Bug小技巧
-
Bug的发生,我想这是每个开发人员几乎每天都要面对的问题,包括历史上非常有名的编程人员,他们依旧要面对Bug。成为一个熟练的程序员并不意味着永远不会犯错误,而是擅于发现错误并能很好地修正错误。当你刚开...
- 【推荐】一款基于 .NET 开源的支持多厂区、多项目级的MOM/MES系统
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍tmom是一款基于.NET开源、通用的生产制造系统,支持多厂区/多项目级的MOM/MES系统,计划排程...
- 你不可不知的10个Github功能
-
Github让全世界的开发人员、设计人员可以在一起工作交流。Github不仅提供大量开源项目、编程语言代码,他也发布过Windows和OSX桌面应用,可以让我们在工作中无缝集成Github。...
- Fastreport.Net用户手册(十四):文本编辑
-
编辑对象的文本,只需双击文本内容,然后会弹出一个文本编辑器。在编辑器右方有一个可以添加至文本中的数据树组件。可以通过鼠标拖拽该组件到需要的地方。在文本中嵌入该组件的另一个方法是双击该组件,然后该组件将...
- 火狐浏览器开发者专版上手体验
-
当Mozilla宣布FirefoxDeveloperEdition,我想不少开发者都很高兴,因为第一个大型开发者专用浏览器诞生了。既然是开发者专用版,那么和普通版本肯定是不一样的。早已经迫不及待...
- FastReport.Net 2015.3.3 优化了报表解析器
-
FastReport.Net2015.3.3于近日正式发布。点击FastReport.Net2015.3.3下载试用FastReport.Net最新版本。[Core][Exports]重写保存在...
- 改变上网体验:10个超赞的Google Chrome扩展
-
你使用谷歌浏览器浏览网页吗?其实,全世界数以百万的用户都喜欢使用GoogleChrome浏览网页,这也促使其成为全球使用量第二大的Web浏览器。GoogleChrome浏览器具有快速、干净的页面,...
- 如何在 FastReport Online Designer 中处理报表的 5 个函数
-
FastReports产品的时代并没有停滞不前。每个月都会添加新的函数和对象,并改进和优化当前的代码。FastReportOnlineDesigner...
- Winform应用界面开发技术特点图解
-
整理一下自己之前的Winform开发要点,以图文的方式展示一些关键性的技术特点,总结一下。...
- 跨平台的可视化Web报表设计器-FastReport Online Designer
-
好消息!FastReportOnlineDesigner现在作为一个独立的应用程序发布啦!此前作为FastReport.Net的专业版的一部分的在线设计测试版,现在可以单独或作为FastRepor...