本帖最后由 J.Xiao 于 2024-4-30 14:17 编辑
一、什么是人脸识别
人脸识别(Face Recognition)是一种依据人的面部特征(如统计或几何特征等),自动进行身份识别的一种生物识别技术,又称为面像识别、人像识别、相貌识别、面孔识别、面部识别等。通常我们所说的人脸识别是基于光学人脸图像的身份识别与验证的简称。
人脸识别利用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸图像进行一系列的相关应用操作。技术上包括图像采集、特征定位、身份确认和查找等等。简单来说,就是从照片中提取人脸中的特征,比如眉毛高度、嘴角等等,再通过特征的对比输出结果。
人脸识别算法主要包含三个模块,或者说需要经过这样三个步骤:
- 人脸检测(Face Detection)
- 人脸对齐(Face Alignment)
- 人脸识别(Face Recognition)
为了更直观地讲解这些模块,我们将使用InsightFace这个开源的2D和3D深度面部分析库。它能有效地实现了丰富多样的最先进的人脸识别、人脸检测和人脸对齐算法,并针对训练和部署进行了优化。
1、人脸检测
人脸检测用于确定人脸在图像中的大小和位置,即解决“人脸在哪里”的问题,把真正的人脸区域从图像中裁剪出来,便于后续的人脸特征分析和识别。
InsightFace支持 RetinaFace (CVPR'2020), SCRFD (Arxiv'2021)等多种检测算法:
RetinaFace是一款实用的单级面部检测器,已被CVPR 2020接受。InsightFace提供训练代码、训练数据集、预训练模型和评估脚本。
SCRFD是一种高效的高精度人脸检测方法,在Arxiv中进行了初步描述。InsightFace同样提供易于使用的管道来训练支持 NAS 的高效人脸检测器。
2、人脸对齐
同一个人在不同的图像序列中可能呈现出不同的姿态和表情,这种情况是不利于人脸识别的。所以有必要将人脸图像都变换到一个统一的角度和姿态,这就是人脸对齐。它的原理是找到人脸的若干个关键点(基准点,如眼角,鼻尖,嘴角等),然后利用这些对应的关键点通过相似变换(Similarity Transform,旋转、缩放和平移)将人脸尽可能变换到标准人脸。
对齐方法有SDUNets和SimpleRegression等。
SDUNets是一种基于热图的方法,被BMVC接受。
SimpleRegression 提供非常轻量级的面部特征点模型,具有快速坐标回归功能。这些模型的输入是松散裁剪的人脸图像,而输出是各关键点的坐标。
3、人脸识别
人脸识别算法,它接受的输入是标准化的人脸图像,通过特征建模得到向量化的人脸特征,最后通过分类器判别得到识别的结果。这里的关键是怎样得到对不同人脸有区分度的特征,通常我们在识别一个人时会看它的眉形、脸轮廓、鼻子形状、眼睛的类型等,人脸识别算法引擎要通过练习(训练)得到类似这样的有区分度的特征。
InsightFace主要使用一种加性角裕量损失(ArcFace)的模型来获得人脸识别的判别特征。
二、安装环境
1、安装依赖包
InsightFace主要基于PyTorch和MXNet。然后需要根据你的电脑是否带有GPU来安装ONNX运行库。
如果有GPU:
pip3 install onnxruntime-gpu
如果只有CPU:
pip3 install onnxruntime
2、安装InsightFace
安装方式也非常简单,在安装过程也会自动安装一些必要的依赖。
pip3 install -U insightface
3、测试
可以通过如下代码进行快速测试:
import cv2
import numpy as np
import insightface
from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image
app = FaceAnalysis(providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
app.prepare(ctx_id=0, det_size=(640, 640))
img = ins_get_image('t1')
faces = app.get(img)
rimg = app.draw_on(img, faces)
cv2.imwrite("./t1_output.jpg", rimg)
这个快速示例将从图像t1.jpg中检测人脸并在其上绘制检测结果。
4、模型库
在InsightFace中提供了如下规格的模型包,在首次调用程序时,会自动下载默认的buffalo_l模型。我们也可以下载其他模型到电脑的~/.insightface/models/ 目录。
Name | Detection Model | Recognition Model | Alignment | Attributes | Model-Size | Link | Auto |
antelopev2 | SCRFD-10GF | ResNet100@Glint360K | 2d106 & 3d68 | Gender&Age | 407MB | link | N | buffalo_l | SCRFD-10GF | ResNet50@WebFace600K | 2d106 & 3d68 | Gender&Age | 326MB | link | Y | buffalo_m | SCRFD-2.5GF | ResNet50@WebFace600K | 2d106 & 3d68 | Gender&Age | 313MB | link | N | buffalo_s | SCRFD-500MF | MBF@WebFace600K | 2d106 & 3d68 | Gender&Age | 159MB | link | N | buffalo_sc | SCRFD-500MF | MBF@WebFace600K | - | - | 16MB | link | N |
识别精度:
Name | MR-ALL | African | Caucasian | South Asian | East Asian | LFW | CFP-FP | AgeDB-30 | IJB-C(E4) |
buffalo_l | 91.25 | 90.29 | 94.70 | 93.16 | 74.96 | 99.83 | 99.33 | 98.23 | 97.25 | buffalo_s | 71.87 | 69.45 | 80.45 | 73.39 | 51.03 | 99.70 | 98.00 | 96.58 | 95.02 |
buffalo_m与buffalo_l具有相同的精度。
buffalo_sc与buffalo_s具有相同的精度。
三、编写ROS2节点
1、创建包
接下来,我们把InsightFace集成到ROS2中来,首先可以通过如下指令,创建一个ROS2的包。
cd ~/spark_ros2/src/spark_app
ros2 pkg create --build-type ament_python spark_face_recognition --dependencies rclpy sensor_msgs vision_msgs --node-name insightface
2、编写节点
然后,打开~/spark_ros2/src/spark_app/spark_face_recognition/spark_face_recognition/insightface.py并写入如下内容:
import rclpy
from rclpy.node import Node
import numpy as np
from sensor_msgs.msg import Image as ImageMsg
import insightface
from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image
def image_msg_to_image_np(image_msg):
n_channels = 3
dtype = 'uint8'
img_buf = np.asarray(image_msg.data, dtype=dtype)
image_np = np.ndarray(shape=(image_msg.height, image_msg.width, n_channels),
dtype=dtype, buffer=img_buf)
return image_np
def image_np_to_image_msg(image_np):
image_msg = ImageMsg()
image_msg.height = image_np.shape[0]
image_msg.width = image_np.shape[1]
image_msg.encoding = 'rgb8'
image_msg.data = image_np.tostring()
image_msg.step = len(image_msg.data) // image_msg.height
image_msg.header.frame_id = 'map'
return image_msg
class Insightface_node(Node):
def __init__(self):
super().__init__('Insightface_node')
self.get_logger().info('Insightface')
#self.app = FaceAnalysis(allowed_modules=['detection']) #指定只使用detection检测模型
#self.app = FaceAnalysis(name='buffalo_sc') #指定模型名称buffalo_sc为最小模型,适合算力不高的情况
self.app = FaceAnalysis() #默认为buffalo_l模型
self.app.prepare(ctx_id=0, det_size=(640, 640))
self.input_topic_p = self.declare_parameter('input_topic', '/camera/color/image_raw')
img_topic = self.input_topic_p.value
self.create_subscription(ImageMsg, img_topic, self.image_detection_callback, 1)
self.image_pub = self.create_publisher(ImageMsg, 'detections_image', 1)
def image_detection_callback(self, img_msg):
image_np = image_msg_to_image_np(img_msg)
image_np = image_np[:, :, ::-1] #RGB转BGR
faces = self.app.get(image_np)
#results.print()
rimg = self.app.draw_on(image_np, faces)
img_msg = image_np_to_image_msg(rimg[:, :, ::-1])
self.image_pub.publish(img_msg)
def main(args=None):
rclpy.init(args=args)
insightface_node = Insightface_node()
rclpy.spin(insightface_node)
insightface_node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
3、编译运行
紧接着我们编译包:
cd ~/spark_ros2
colcon build --packages-select spark_face_recognition
编译成功后,即可运行:
ros2 run spark_face_recognition insightface
打开另一个终端,并运行机器人摄像头节点:
ros2 launch spark_bringup driver_bringup.launch
此时,在打开的RViz中把图像显示节点的话题改为/detections_image:
即可实时显示识别出来的人脸结果:
|