实验:Blazeface人脸检测
2024-10-22 14:52:45

Blazeface人脸检测

第一章 Blazeface

第一节 介绍

BlazeFace是Google开发的一种机器学习模型,用于快速检测人脸的位置和关键点。最初该模型是针对Google 提供的MediaPipe。

BlazeFace 是为了在移动 GPU 上执行非常快速的推理。具体来说,它的运行速度比MobileNetV2-SSD快近 2.3 倍。

img

BlazeFace使用基于MobileNet 的改进网络。考虑到 56x56x128 张量的 3x3 深度卷积在 iPhoneX 上需要 0.07ms,而随后从 128 到 128 通道的 1x1 卷积速度慢了 4.3 倍,为 0.3ms,这表明增加深度部分的内核大小相对便宜。因此,作者建议用 5x5 深度卷积替换 3x3 深度卷积,使模型更浅以加快处理速度。

img

此外,为 GPU 上的着色器调度特定层计算存在固定成本。例如,对于MobileNetV1,在 4.9 毫秒的推理时间中,只有 3.9 毫秒用于实际 GPU 着色器计算。为了减少锚点计算的调度成本,作者采用了另一种锚点方案来减少层数。

img

第二节 代码实验

本代码是基于PaddleDetection进行,在进行实验之前需要准备PaddleDetection的环境。

环境搭建可参考:实验:PaddleDetection目标检测

另存为下载:

字体文件:SimHei.ttf
Blazeface权重文件:blazeface_1000e.pdparams
Blazeface权重文件:blazeface_fpn_ssh_1000e.pdparams

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import sys
sys.path.append("./PaddleDetection")

import cv2
import paddle
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from ppdet.core.workspace import load_config
from ppdet.engine import Trainer
from ppdet.metrics import get_infer_results
from ppdet.data.transform.operators import NormalizeImage, Permute

if __name__ == '__main__':
# 准备基础的参数
config_path = './PaddleDetection/configs/face_detection/blazeface_1000e.yml'
cfg = load_config(config_path)
weight_path = 'blazeface_1000e.pdparams'

# infer_img_path = 'PaddleDetection/demo/hrnet_demo.jpg'
# cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture('/Xian.mp4')
# cap.set(cv2.CAP_PROP_POS_FRAMES, 21 * 60 * 60)
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

if not cap.isOpened():
print('无法打开摄像头')
exit()

cfg.weights = weight_path
bbox_thre = 0.8
paddle.set_device('gpu')

# 创建所需的类
trainer = Trainer(cfg, mode='test')
trainer.load_weights(cfg.weights)
trainer.model.eval()
normaler = NormalizeImage(mean=[123, 117, 104], std=[127.502231, 127.502231, 127.502231], is_scale=False)
permuter = Permute()

while True:
ret, frame = cap.read()

if not ret:
print("无法接受帧,请退出")
break

# cropped_image = center_crop(frame, (640, 640))

im = frame
# 进行图片读取
# im = cv2.imread(frame)
# im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

# 准备数据字典
data_dict = {'image': im}
data_dict = normaler(data_dict)
data_dict = permuter(data_dict)
h, w, c = im.shape
data_dict['im_id'] = paddle.Tensor(np.array([[0]]))
data_dict['im_shape'] = paddle.Tensor(np.array([[h, w]], dtype=np.float32))
data_dict['scale_factor'] = paddle.Tensor(np.array([[1., 1.]], dtype=np.float32))
data_dict['image'] = paddle.Tensor(data_dict['image'].reshape((1, c, h, w)))
data_dict['curr_iter'] = paddle.Tensor(np.array([0]))


# 进行预测
outs = trainer.model(data_dict)

# 对预测的数据进行后处理得到最终的bbox信息
for key in ['im_shape', 'scale_factor', 'im_id']:
outs[key] = data_dict[key]

for key, value in outs.items():
outs[key] = value.numpy()

clsid2catid, catid2name = {0: 'face'}, {0: 0}
batch_res = get_infer_results(outs, clsid2catid)
bbox = [sub_dict for sub_dict in batch_res['bbox'] if sub_dict['score'] > bbox_thre]

for box in bbox:
# print(box['bbox'])
x1, y1, w, h = box['bbox']

im = Image.fromarray(im)
draw = ImageDraw.Draw(im)

# simhei.ttf 是字体,你如果没有字体,需要下载
font = ImageFont.truetype("SimHei.ttf", 15, encoding="utf-8")
string = '概率:{}%'.format(round(box['score'] * 100, 2))
draw.text((int(x1), int(y1) - 15), string, (0, 255, 0), font=font)
# im = cv2.cvtColor(np.array(im), cv2.COLOR_RGB2BGR)
im = np.array(im).copy()

# cv2.putText(im, string, (int(x1), int(y1) - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.6, color=(0, 255, 0))
cv2.rectangle(im, (int(x1), int(y1)), (int(x1 + w), int(y1 + h)), (0, 255, 0), 2) # 绘制矩形框,颜色为绿色,线宽为 2

cv2.imshow('Camera', im)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destoryALLWindows()