来源介绍
人脸检测项目libfacedetection是2015年创建的开源项目,算法模型为YuNet,已经持续维护8年至今,在GitHub上已经获得11.7K星。链接
2022-2023年作者对训练部分进行了大幅改进。更加大胆地对算法进行优化迭代,放弃了第二版的Anchor-based机制而采用Anchor-free机制,并对损失函数、正负样本标签匹配等部分进行改进,得到了第三版YuNet。第三版YuNet有两个版本:追求高速度的YuNet-s和追求高精度的YuNet-n。
- YuNet-s:该版本将参数量降低到54K,降幅约40%。精度略有下降,达到了0.887/0.871/0.768(比上一版85K参数版本好)。在C++库上,作者采用YuNet-s重新编写了新模型的执行代码,推理速度提升约20%。
- YuNet-n:将参数量降低到76K,在WIDER Face验证集上,Easy/Medium/Hard三个难度分别达到了0.892/0.883/0.811,达到了人脸检测领域内的高水平。
如何使用
如果你想在你的程序中使用YuNet进行人脸检测,有以下几种简单的方式:
- 通过OpenCV库使用。目前OpenCV库已经集成了最新版的YuNet作为人脸检测模块,只要你的环境中安装了OpenCV库,就可以直接调用人脸检测的API。
- 通过pip安装yuface包。我们团队使用pybind11对C++的人脸检测库进行了封装,并且将其上传到pypi,现在你只需要执行pip install yuface,就可以直接在Python中使用YuNet进行人脸检测。
- 直接从我们的开源库libfacedetection中克隆代码,然后根据你的需求修改相关的函数调用。我们已经在开源库中提供了预训练好的模型权重文件。
- 使用onnx推理引擎进行推理。我们已经将YuNet导出为onnx格式,并且使用Numpy库对输入和输出进行了高效的处理。
代码实现
单张图片
import yuface
import cv2
def plt_pic(image, confs, bboxes, landmarks):
# 定义边界框和关键点的颜色
bbox_color = (0, 255, 0) # BGR 格式的颜色,这里是绿色
landmark_color = (255, 0, 0) # BGR 格式的颜色,这里是蓝色
# 绘制边界框和关键点
for conf, bbox, landmark in zip(confs, bboxes, landmarks):
# 绘制边界框
x, y, w, h = bbox
cv2.rectangle(image, (x, y), (x + w, y + h), bbox_color, 2)
# 绘制关键点
for i in range(0, len(landmark), 2):
x, y = landmark[i], landmark[i + 1]
cv2.circle(image, (x, y), 3, landmark_color, -1)
# 绘制置信度文本
cv2.putText(image, f"Confidence: {conf.item():.2f}", (bbox[0], bbox[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9,
(0, 255, 0), 2)
if __name__ == '__main__':
path=(r'1.jpg')
img=cv2.imread(path)
confs, bboxes, landmarks =yuface.detect(img)
print(confs, bboxes, landmarks)
plt_pic(img, confs, bboxes, landmarks)
cv2.imshow("img", img)
cv2.waitKey(0)
摄像头
import yuface
import cv2
def plt_pic(image, confs, bboxes, landmarks):
# 定义边界框和关键点的颜色
bbox_color = (0, 255, 0) # BGR 格式的颜色,这里是绿色
landmark_color = (255, 0, 0) # BGR 格式的颜色,这里是蓝色
# 绘制边界框和关键点
for conf, bbox, landmark in zip(confs, bboxes, landmarks):
# 绘制边界框
x, y, w, h = bbox
cv2.rectangle(image, (x, y), (x + w, y + h), bbox_color, 2)
# 绘制关键点
for i in range(0, len(landmark), 2):
x, y = landmark[i], landmark[i + 1]
cv2.circle(image, (x, y), 3, landmark_color, -1)
# 绘制置信度文本
cv2.putText(image, f"Confidence: {conf.item():.2f}", (bbox[0], bbox[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9,
(0, 255, 0), 2)
if __name__ == '__main__':
Capture = cv2.VideoCapture(0)
while True:
ret, frame = Capture.read()
if not ret:
print("无法打开摄像头")
confs, bboxes, landmarks = yuface.detect(frame)
plt_pic(frame, confs, bboxes, landmarks)
cv2.imshow("img", frame)
if cv2.waitKey(1) == 27:
break
Capture.release()
限制区域摄像头
import cv2
import yuface
from test import plt_pic
cap = cv2.VideoCapture(0)
while True:
# 读取一帧图像
ret, frame = cap.read()
if not ret:
print("无法读取摄像头图像")
break
# 获取帧的宽度和高度
frame_height, frame_width, _ = frame.shape
# 定义ROI的左上角和右下角坐标
roi_top_left = (0, int(frame_height / 4)) # 左上角坐标
roi_bottom_right = (frame_width, int(frame_height / 4 * 3)) # 右下角坐标
# 提取ROI
roi = frame[roi_top_left[1]:roi_bottom_right[1], roi_top_left[0]:roi_bottom_right[0]]
# 在帧上绘制ROI区域
cv2.rectangle(frame, roi_top_left, roi_bottom_right, (0, 255, 0), 2)
# 将感兴趣区域转换为灰度图像
confs, bboxes, landmarks = yuface.detect(roi)
plt_pic(roi, confs, bboxes, landmarks)
# 在窗口中显示图像
cv2.imshow("Camera", frame)
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()