基于开源模型搭建实时人脸识别系统(四):人脸质量

续人脸识别实战之基于开源模型搭建实时人脸识别系统(三):人脸关键点、对齐模型概览与模型选型_CodingInCV的博客-CSDN博客
不论对于静态的人脸识别还是动态的人脸识别,我们都会面临一个问题,就是输入的人脸图像的质量可能会很差,比如人脸角度很大,人脸很模糊,人脸亮度很亮或很暗。这些质量低的图像不仅造成识别失败,还可能引起误识别。因此,对输入人脸识别进行一定的质量过滤是很必要的。这个领域的英文为Face Image Quality Assessment。
image.png

image.png

传统方法

传统的方法一般是将图像质量领域(Image Quality Assessment)的方法应用到人脸图像上,比如使用边缘检测来评测模糊、统计平均像素值来评测亮度。这些方法没有特别考虑人脸图像的特点,效果一般。

深度学习方法

普通深度学习方法

这类方法将人脸图像质量作为一个普通的深度学习问题,通过人工或预设算法对数据打标,然后设计一个网络,回归质量分数。这个方法的学习目标主要还是人眼感知上的质量,因为标签来源于人工打标,而并不是对于识别效果更好的质量。
这类方法的主要难题在于数据标签难获得,网络结构上只是简单的回归网络。

面向人脸识别的人脸质量评估

人脸质量的筛选目标是提高人脸识别的效果,因此越来越多的方法开始将人脸质量和人脸识别任务结合起来,结合的方式主要有2种:
一种是直接训一个特征能够用来衡量人脸质量的模型,代表是MagFace, 基本思想是用特征的模长来表征人脸质量。个人觉得这种方式实用起来存在一个问题就是要获得人脸质量就得进行人脸特征提取,开销太大。
另一种方式是通过人脸识别模型的特征关系来生成质量标签,代表方法:
SER-FIQ: 同一个人脸多次推理(开启dropout),统计多次推理特征的距离,对于质量好的图片,特征平均距离小,反之越大
SDD-FIQ: 统计计算人脸与同一ID和不同ID人脸的距离
FaceQnet, PCNet等

方法选择

理论上,面向人脸识别的人脸质量评估效果更好,不过这些方法与识别模型存在较大的耦合关系,根据笔者在私有数据上的实际测试,训练比较困难,开源出来的预训练模型也较大。KaenChan/lightqnet: Deployment of the Lightweight Face Image Quality Assessment (github.com) 这个比较轻量,但实测对于人脸区域比较敏感,没有区分度。
综合速度要求,选择 KS‐FQA: Keyframe selection based on face quality assessment for efficient face recognition in video - Bahroun - 2021 - IET Image Processing - Wiley Online Library
这个方法考虑了人脸角度、亮度、大小、模糊。速度较快,也有一定区分度,不过也还是有些缺陷,对于大侧脸的过滤效果一般。

import numpy as np
import cv2class FaceQualityOverall:def __init__(self, **kwargs) -> None:passdef pose_score(self, face_box: np.ndarray, landmarks: np.ndarray):center_x, center_y = (face_box[0] + face_box[2]) / 2, (face_box[1] + face_box[3]) / 2nose_x, nose_y = landmarks[2][0], landmarks[2][1]distance = np.sqrt((center_x - nose_x) ** 2 + (center_y - nose_y) ** 2)face_size = np.sqrt((face_box[2] - face_box[0]) ** 2 + (face_box[3] - face_box[1]) ** 2)pose_score = max(0, 1 - distance / face_size)return pose_scoredef sharpness_and_brightness_score(self, image: np.ndarray, face_box: np.ndarray):box = face_box[:]box = box.astype(np.int32)face_image = image[box[1] : box[3], box[0] : box[2], :]face_image_gray = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)# blur the face image with a 5x5 guassian kernelblur_face_image = cv2.GaussianBlur(face_image_gray, (5, 5), sigmaX=1, sigmaY=1)# calculate the sharpness scoresharpness_score = np.sum(np.abs(face_image_gray - blur_face_image)) / np.prod(face_image_gray.shape)sharpness_score = sharpness_score / 255.0sharpness_score = min(1, sharpness_score * 2)brightness_score = np.mean(face_image_gray)# normalize the brightness scoreif brightness_score < 20 or brightness_score > 230:brightness_score = 0else:brightness_score = 1 - abs(brightness_score - 127.5) / 127.5return sharpness_score, brightness_scoredef resolution_score(self, face_box: np.ndarray):face_width = face_box[2] - face_box[0]face_height = face_box[3] - face_box[1]resolution_score = min(1, min(face_width, face_height) / 224)if face_height/face_width > 2.5:resolution_score = 0if min(face_width, face_height) < 48:resolution_score = 0return resolution_scoredef run(self, image: np.ndarray, face_box: np.ndarray, landmarks: np.ndarray):pose_score = self.pose_score(face_box, landmarks)if pose_score < 0.3:return 0sharpness_score, brightness_score = self.sharpness_and_brightness_score(image, face_box)if sharpness_score<0.1:return 0resolution_score = self.resolution_score(face_box)if resolution_score < 48/224:return 0output = np.array([pose_score, sharpness_score, brightness_score, resolution_score])weight = np.array([0.3, 0.4, 0.1, 0.2])return np.sum(output * weight)if __name__ == "__main__":from face_recognition_modules.face_alignment.face_landmarks import FaceLandmarksfrom face_recognition_modules.face_detection.yolov8_face import Yolov8Faceimport cv2yolo8face = Yolov8Face(model_path="models/yolov8-lite-t.onnx", device="gpu")landmarks_det = FaceLandmarks(model_path="models/student_128.onnx", device="gpu")image = cv2.imread("test_images/1.jpg")if image is None:raise Exception("read image failed")face_box, _ = yolo8face.run(image)landmarks = landmarks_det.run(image, face_box[0])face_quality = FaceQualityOverall()quality = face_quality.run(image, face_box[0], landmarks)print(quality)

结语

这篇我们简要介绍了一下人脸质量评估,不过笔者在这方面涉猎也不深,只是做个简单的总结,需要深入做还是有不少工作。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 OpenTelemetry 构建可观测性 04 - 收集器

在之前的博文中&#xff0c;我们讨论了如何使用 SDK 和链路追踪生产者来导出进程中的遥测数据。尽管有多种类型的导出器可供选择&#xff0c;但其中一个常见的目标是将数据导出到 OpenTelemetry Collector。本篇文章将深入探讨收集器以及如何使用它。 选 OTel Collector 还是…

Spring中的依赖注入(Dependency Injection)有哪些不同的方式?可以举例说明吗?

Spring中的依赖注入&#xff08;Dependency Injection&#xff09;有哪些不同的方式&#xff1f;可以举例说明吗&#xff1f; 构造方法注入 使用构造函数进行DI注入 public class MyClass {private MyDependency myDependency;public MyClass(MyDependency myDependency) {t…

Eduma主题 - 线上教育WordPress主题/网站

Eduma主题 – 线上教育WordPress主题是为教育网站、LMS、培训中心、课程中心、学院、大学、学校、幼儿园而制作的。基于我们使用以前的主题eLearning WP构建WordPress LMS的经验&#xff0c;Education WP是下一代&#xff0c;也是围绕WordPress最好的教育主题之一&#xff0c;它…

C++编码规范解读

规范 C文件名和类名保持一致 好处&#xff1a;代码整体结构清晰、明了。java里强制如此。 类型命名采用大驼峰 比如&#xff1a;UrlEncoder FileParser 优先使用 头文件中的基本类型 如&#xff1a; 有符号类型 无符号类型 描述 int8_t uint8_t 宽度恰为8的有/无符号整…

C++并发多线程--std::async创建异步任务是否创建线程

1--std::async创建异步任务 std::async 创建一个异步任务&#xff0c;其不一定会创建一个新线程去执行该任务&#xff1b; 使用 std::launch::deferred 时&#xff0c;异步任务不会创建一个新线程&#xff1b; 使用 std::launch::async 时&#xff0c;操作系统会强制创建一个新…

一个炫酷的头像悬停效果 2

基于上次翻译的 &#x1f525;&#x1f525;一个炫酷的头像悬停效果 收获了不少同学的喜欢&#xff0c;原作者近期进行了优化升级。本文将升级后的核心实现过程进行梳理讲解&#xff0c;如果没看过第一期的推荐先看看第一期的实现过程。升级后的效果如下图所示。 gif动画效果如…

Baklib是比语雀、Notion、石墨文档更好用的在线知识库管理工具

在当今信息爆炸的时代&#xff0c;如何高效地管理和利用知识成为了每个人都面临的问题。在线知识库管理工具应运而生&#xff0c;帮助用户整理、存储和共享知识。在这篇文章中&#xff0c;我将介绍一个更好用的在线知识库管理工具——Baklib&#xff0c;并探讨它相对于其他知识…

变上限积分求导

y ∫ 0 x t f ( t 2 − x 2 ) d t y \int _0^x t f( t^2 - x^2)dt y∫0x​tf(t2−x2)dt 设 t 2 − x 2 u , 那么 t u x 2 , d t d u 2 u x 2 &#xff0c; 并且当 t x 时 u 0 , 当 t 0 时&#xff0c; u − x 2 设 t^2 - x^2 u,那么t \sqrt{ux^2},dt \frac{du}{2\s…

Spring系列篇--关于IOC【控制反转】的详解

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.什么是Spring 二.Spring的特点 三.什…

【O2O领域】Axure外卖订餐骑手端APP原型图,外卖众包配送原型设计图

作品概况 页面数量&#xff1a;共 110 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;外卖配送、生鲜配送 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为外卖订餐骑手端APP原型设计图&#x…

Datawhale Django 后端开发入门 Task05 DefaultRouter、自定义函数

一、DefaultRouter是Django REST framework中提供的一个路由器类&#xff0c;用于自动生成URL路由。路由器是将URL与视图函数或视图集关联起来的一种机制。Django REST framework的路由器通过简单的配置可以自动生成标准的URL路由&#xff0c;从而减少了手动编写URL路由的工作量…

Redis Lua脚本执行原理和语法示例

Redis Lua脚本语法示例 文章目录 Redis Lua脚本语法示例0. 前言参考资料 1. Redis 执行Lua脚本原理1.1. 对Redis源码中嵌入Lua解释器的简要解析&#xff1a;1.2. Redis Lua 脚本缓存机制 2. Redis Lua脚本示例1.1. 场景示例1. 请求限流2. 原子性地从一个list移动元素到另一个li…

基于郊狼算法优化的BP神经网络(预测应用) - 附代码

基于郊狼算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于郊狼算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.郊狼优化BP神经网络2.1 BP神经网络参数设置2.2 郊狼算法应用 4.测试结果&#xff1a;5.Matlab代码 摘要…

【深入解析:数据结构栈的魅力与应用】

本章重点 栈的概念及结构 栈的实现方式 数组实现栈接口 栈面试题目 概念选择题 一、栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数…

指针(一)【C语言进阶版】

大家好&#xff0c;我是深鱼~ 【前言】&#xff1a; 指针的主题&#xff0c;在初阶指针章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址的唯一标识一块内存空间&#xff08;指针变量&#xff09;&a…

【云原生|Docker系列第3篇】Docker镜像的入门实践

欢迎来到Docker入门系列的第三篇博客&#xff01;在前两篇博客中&#xff0c;我们已经了解了什么是Docker以及如何安装和配置它。本篇博客将重点介绍Docker镜像的概念&#xff0c;以及它们之间的关系。我们还将学习如何拉取、创建、管理和分享Docker镜像&#xff0c;这是使用Do…

jenkins同一jar包部署到多台服务器

文章目录 安装插件配置ssh服务构建完成后执行 没有部署过可以跟这个下面的步骤先部署一遍&#xff0c;我这篇主要讲jenkins同一jar包部署到多台服务器 【Jenkins】部署Springboot项目https://blog.csdn.net/qq_39017153/article/details/131901613 安装插件 Publish Over SSH 这…

stm32g070的PD0/PD2 PA8和PB15

目前在用STM32G070做项目&#xff0c;其中PD2TIMER3去模拟PWM&#xff0c;PD0用作按键检测&#xff0c;测试发现PD0低电平检测没有问题&#xff0c;高电平检测不到&#xff0c;电路图如下图所示&#xff1a; 用万用表测试电平&#xff0c;高电平1.0V左右&#xff0c;首先怀疑硬…

PyTorch安装教程:从头开始配置PyTorch环境

PyTorch是一个开源的机器学习框架&#xff0c;广泛用于深度学习任务。要开始使用PyTorch&#xff0c;您需要在计算机上正确配置PyTorch环境。本文将为您提供一步步的指南&#xff0c;帮助您成功安装和配置PyTorch。 第一部分&#xff1a;安装Python和相关工具 第一步&#xf…

rust踩雷笔记(4)——刷点Vec相关的题(持续更新)

俗话说&#xff0c;孰能生巧&#xff0c;今天是第六天接触Rust&#xff0c;感觉基础语法和特性没什么问题了&#xff08;当然如果你整天都学这个可能2天半就够了&#xff09;&#xff0c;但是想达到熟练使用&#xff0c;还需要刷点题。算法我相信能来看rust博客的人都是大牛&am…