赞
踩
#继之前安装树莓派3.7python+mediapipe之后,实现了一种通过cvzone(封装了mediapipe)
1使用cvzone里的cvzone.FaceDetectionModule.FaceDetector找到人脸位置获取人脸边框坐标
2通过cvzone里的cvzone.HandTrackingModule.HandDetector找到人手关键点坐标位置
3通过人脸位置的x,y,w,h和手指关键坐标的一点,我使用了小拇指第二关节,一旦检测到小拇指进入了人脸检测区域就可以得到捂眼睛的状态,实测cvzone的人脸检测可以做到半张脸检测到人脸信息,同时两种检测同时进行在i7 笔记本电脑cpu上不会卡顿,移植在树莓派4B上可以通过480p流畅运行,720p略有卡顿,1080p严重卡顿延迟拖影,可能是树莓派本身的视频流处理的原因,我使用过树莓派的两种视频解码模式都效果不是很好,正在持续寻找解决方法。
4在输入参量中cover_mode = 1只检测捂左眼反之 = 2只检测捂右眼。代码可以直接运行
检测过程如下图一,手的关键点坐标如图二:
完整实例代码如下:
- # -*- coding: utf-8 -*-
- import cv2
- import time
- import numpy as np
- import cvzone.HandTrackingModule
- import cvzone.FaceDetectionModule
- face_detector = cvzone.FaceDetectionModule.FaceDetector(minDetectionCon=0.5)
- hand_direction_detector = cvzone.HandTrackingModule.HandDetector(mode=False, # 视频流图像
- maxHands=4, # 最多检测两只手
- detectionCon=0.5, # 最小检测置信度
- minTrackCon=0.7) # 最小跟踪置信度
-
-
- def is_coverings_eye(cap_hand_direction, cover_mode=1, test_time=5):
- print("捂眼检测")
- atime = time.time()
- while True:
- success, frame = cap_hand_direction.read()
- if success is not True:
- break
- # frame = cv2.flip(frame, flipCode=1) # 这里是否反转 下面是否反转还得测试
- _, face_boxs = face_detector.findFaces(frame, draw=False)
- hands = hand_direction_detector.findHands(frame, draw=False, flipType=False)
- # 获取人脸边框范围 与人手比较
- if face_boxs: # 如果检测到了人脸 在此判断条件下再去检测人手 三种情况 没手 一只手 两只手
- max_area = 0 # 初始化最大面积为0
- max_index = -1 # 初始化最大面积对应的遍历序号为-1
- for index, facebox in enumerate(face_boxs): # 先全部遍历求出面积最大的人脸序号
- _, _, w, h = facebox["bbox"]
- area = w * h # 计算人脸面积
- if area > max_area:
- max_area = area
- max_index = index
- face_x, face_y, face_w, face_h = face_boxs[max_index]['bbox'] # 求出人脸范围
- if hands: # 如果有手存在 找到面积最大的左手和右手的序号
- left_hand_max_area = 0 # 初始化最大面积为0
- right_hand_max_area = 0 # 初始化最大面积为0
- left_hand_max_index = -1 # 初始化最大面积对应的遍历序号为-1
- right_hand_max_index = -1 # 初始化最大面积对应的遍历序号为-1
- left_region_status = 0 # 初始化左手是否在范围内
- right_region_status = 0 # 初始化右手是否在范围内
- for index, hand in enumerate(hands):
- if hand["type"] == "Left" and cover_mode == 1: # 左手
- _, _, w_left, h_left = hand["bbox"]
- left_hand_area = w_left * h_left # 计算面积
- if left_hand_area > left_hand_max_area:
- left_hand_max_area = left_hand_area
- left_hand_max_index = index
- if hand["type"] == "Right" and cover_mode == 2: # 右手
- _, _, w_right, h_right = hand["bbox"]
- right_hand_area = w_right * h_right # 计算面积
- if right_hand_area > right_hand_max_index:
- right_hand_max_index = right_hand_area
- right_hand_max_index = index
- # 这里已经知道人脸范围 同时若index不等于-1 的时候就是有这只手
- if left_hand_max_index != -1: # 如果检测到了左手
- left_hand_x, left_hand_y = hands[left_hand_max_index]["lmList"][20][:2] # 用小拇指头代表左手
- if face_x <= left_hand_x <= face_x + face_w and face_y <= left_hand_y <= face_y + face_h:
- left_region_status = 1 # 左手在这个范围里
- else:
- pass
- if right_hand_max_index != -1: # 如果检测到了左手
- right_hand_x, right_hand_y = hands[right_hand_max_index]["lmList"][20][:2] # 用小拇指头代表左手
- if face_x <= right_hand_x <= face_x + face_w and face_y <= right_hand_y <= face_y + face_h:
- right_region_status = 1 # 左手在这个范围里
- else:
- pass
- if left_region_status == 1: # 左手在范围里 就需要检测右手指向
- print("左手在范围内")
- return 1
- if right_region_status == 1:
- print("右手在范围内")
- return 2
- if time.time() - atime > test_time:
- return 0
- cv2.imshow("test", frame)
- if cv2.waitKey(1) & 0xFF == 27: # 每帧滞留20毫秒后消失,ESC键退出
- break
-
-
- if __name__ == '__main__':
- print("开始载入视频")
- cap = cv2.VideoCapture(0)
- cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
- cap.set(3, 640) # 设置摄像头宽度
- cap.set(4, 480) # 设置摄像头高度
- print("载入视频完成")
- cover_eys_model = is_coverings_eye(cap, cover_mode=1, test_time=40) # cover_mode = 1是检测捂左眼
- print(cover_eys_model)
- cover_eys_model = is_coverings_eye(cap, cover_mode=2, test_time=40) # cover_mode = 1是检测捂右眼
- print(cover_eys_model)

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。