前言
使用YOLOv8-m对图像进行手部检测,然后扩大检测框区域,并对该区域使用YOLOv8-s-pose使用关键点检测,实现实时的手部关键点检测。
1.扩大检测框区域
参考:基于YOLOv8-pose的手部关键点检测(2)- 模型训练、结果分析和超参数优化
需要将手部区域放大:2/3 。放大框的函数如下,scale=2/3:
def expand_bbox(xyxy, img_width, img_height, scale=0.1):
# 计算宽度和高度,和中心点
width = xyxy[2] - xyxy[0]
height = xyxy[3] - xyxy[1]
center_x = xyxy[0] + width / 2
center_y = xyxy[1] + height / 2
# 增加10%的宽度和高度
new_width = width * (1 + scale)
new_height = height * (1 + scale)
# 计算新的边界框坐标,并确保新的边界框坐标不超过图片的边界
new_x1 = max(2, int(center_x - new_width / 2))
new_y1 = max(2, int(center_y - new_height / 2))
new_x2 = min(int(img_width) - 2, int(center_x + new_width / 2))
new_y2 = min(int(img_height), int(center_y + new_height / 2))
return new_x1, new_y1, new_x2, new_y2
2.先检测手部,后检测手部关键点
关键代码如下,下面结果开始展示容错,因为我把scale错写成了1/3:
frame, _ = resize_image(frame, 720)
img_height, img_width, _ = frame.shape
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
hand_all = det_shou(img)[0]
for i, bbox in enumerate(hand_all.boxes.xyxy):
x1, y1, x2, y2 = list(map(int, bbox))
x11, y11, x22, y22 = expand_bbox(bbox, img_width, img_height, scale=1 / 3)
conf = hand_all.boxes.conf[i]
cls = hand_all.boxes.cls[i]
label = f'{hand_all.names[int(cls)]} {float(conf):.2f}'
# 绘制边界框和标签
cv2.rectangle(frame, (x11, y11), (x22, y22), (0, 255, 0), 2)
cv2.putText(frame, label, (x11, y11 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
image_shou = frame[y11:y22, x11:x22]
shou_all = pose_shou(image_shou)[0].cpu().numpy()
if len(shou_all.boxes.conf) > 0:
kpts = [list(map(int, shou_all.keypoints.xy[0].reshape(1, 42)[0].tolist()))]
image_shou = draw_bboxes_and_keypoints(image_shou, shou_all.boxes.xyxy, shou_all.boxes.conf,
shou_all.boxes.cls,
kpts=kpts, cat_order=_connections, line_color=line_color)
frame[y11:y22, x11:x22] = image_shou
cv2.imshow('Frame', frame)
以下绿色框表示:YOLOv8的bbox扩大得到的检测框;
以下红色框表示:YOLOv8-pose的bbox。
3.正面视角检测
不遮挡,基本都能检测正确。
啥 卵平台把视频禁了
4.侧面视角检测
开了二倍速,也可以完美检测,不过在手交叉时候略有检测错误。
video_plot_2024-08-16-21-05
5.摄像头视角检测
慢速下关键点都可以识别准确。
video_plot_2024-08-16-21-17
6.遮挡视角检测
存在遮挡情况下,检测准确度骤降。一方面,一只手被手部检测后,会得到两个检测框(数据集里有两只手交叉的情况,会有两个框重叠)。另一方面,手部关键点数据集没有点的分类,被遮挡点当做不可见点处理。这样无法预测不可见的位置。
video_plot_2024-08-16-20-58
7.结论
非遮挡情况,不存在手部相交,基本都可以识别正确。存在手部相交时,准确率会骤降。
遮挡情况,可能导致模型几乎不可用,需要加入前处理和后处理。合并最接近相邻手部检测框(即使是两只手也当做一只手来做)。如果一个检测框检测出多只手,只取置信度最大的那只。增加局部区域物品检测,判断是否存在遮挡。