mediapipe.solutions.face_mesh # 人脸网状检测
mediapipe.solutions.face_detection # 人脸识别
mediapipe.solutions.hands # 手部关键点检测
mediapipe.solutions.pose # 人体姿态检测
mediapipe.solutions.face_detection.FaceDetection() 人脸检测函数
参数:min_detection_confidence: 默认为 0.5。人脸检测模型的最小置信值 (0-1之间),高于该置信度则将检测视为成功。
返回值:
detections:检测到的人脸的集合,其中每个人脸都表示为一个检测原始消息,其中包含 人脸的概率、1 个边界框、6 个关键点(右眼、左眼、鼻尖、嘴巴中心、右耳、左耳)。边界框由 xmin 和 width (由图像宽度归一化为 [0, 1])以及 ymin 和 height (由图像高度归一化为 [0, 1])组成。每个关键点由 x 和 y 组成,分别通过图像宽度和高度归一化为 [0, 1]。
detections.score: 获取图像是人脸的概率
detections.location_data: 获取识别框的 x, y, w, h 和 6个关键点的 x, y
detections.location_data.relative_bounding_box: 获取识别框的 x, y, w, h
detections.location_data.relative_keypoints: 6个关键点的 x, y 组成的列表
mediapipe.solutions.hands.Hands() 手部关键点检测方法
参数:static_image_mode: 默认为 False,将输入图像视为视频流。它将尝试在第一个输入图像中检测手,并在成功检测后进一步定位手的坐标。在随后的图像中,一旦检测到所有 max_num_hands 手并定位了相应的手的坐标,它就会跟踪这些坐标,而不会调用另一个检测,直到它失去对任何一只手的跟踪。这减少了延迟,非常适合处理视频帧。如果设置为 True,则在每个输入图像上运行手部检测,用于处理一批静态的、可能不相关的图像。
max_num_hands: 最多检测几只手,默认为2
min_detection_confidence: 手部检测模型的最小置信值(0-1之间),超过阈值则检测成功。默认为 0.5
min_tracking_confidence: 坐标跟踪模型的最小置信值 (0-1之间),用于将手部坐标视为成功跟踪,不成功则在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 static_image_mode 为真,则忽略这个参数,手部检测将在每个图像上运行。默认为 0.5
返回值:
MULTI_HAND_LANDMARKS: 被检测/跟踪的手的集合,其中每只手被表示为21个手部地标的列表,每个地标由x, y, z组成。x和y分别由图像的宽度和高度归一化为[0,1]。Z表示地标深度。
MULTI_HANDEDNESS: 被检测/追踪的手是左手还是右手的集合。每只手由label(标签)和score(分数)组成。 label 是 'Left' 或 'Right' 值的字符串。 score 是预测左右手的估计概率。
mediapipe.solutions.pose.Pose() 姿态关键点检测函数
参数:static_image_mode: 默认为 False,将输入图像视为视频流。它将尝试在第一张图像中检测最突出的人,并在成功检测后进一步定位姿势地标。在随后的图像中,它只是简单地跟踪那些地标,而不会调用另一个检测,直到失去对目标的跟踪,可以减少计算和延迟。若为 True,则会对每张输入图像执行人体检测方法,非常适合处理一批静态的、可能不相关的图像。
model_complexity: 默认为 1,姿势地标模型的复杂度:0、1 、2。地标准确度和推理延迟通常随着模型复杂度的增加而增加。
smooth_landmarks: 默认为 True,平滑图像,过滤不同的输入图像上的姿势地标以减少抖动,但如果static_image_mode也设置为 True 则忽略。
upper_body_only: 默认为 False,是否只检测上半身的地标。人体姿势共有33个地标,上半身的姿势地标有25个。
enable_segmentation: 默认为False。如果设置为 true,除了姿势地标之外,该解决方案还会生成分割掩码。
smooth_segmentation:默认为 True,过滤不同的输入图像上的分割掩码以减少抖动,但如果 enable_segmentation 设置为 False,或者 static_image_mode 设置为 True 则忽略。
min_detection_confidence: 默认为 0.5,来自人员检测模型的最小置信值 (0-1之间),高于该阈值则认为检测视为成功。
min_tracking_confidence:默认为 0.5。来自地标跟踪模型的最小置信值 (0-1之间),用于将被视为成功跟踪的姿势地标,否则将在下一个输入图像上自动调用人物检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 static_image_mode 为 True,则人员检测将在每帧图像上运行。
返回值:
具有 "pose_landmarks" 字段的 NamedTuple 对象,其中包含检测到的最突出人物的姿势坐标。
mediapipe.solutions.drawing_utils.draw_landmarks() # 可视化函数
image: 需要画图的原始图片
landmark_list: 检测到的关键点坐标
connections: 连接线,需要把那些坐标连接起来
landmark_drawing_spec: 坐标的颜色,粗细
connection_drawing_spec: 连接线的粗细,颜色等
import time
import cv2
import mediapipe as mp
# (1)视频捕获
cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头
# (2)创建检测关键点的方法
Models = mp.solutions.hands # 检测方法
Model = Models.Hands(static_image_mode=False, # 静态追踪,低于0.5置信度会再一次跟踪
max_num_hands=2, # 最多有2只手
min_detection_confidence=0.5, # 最小检测置信度
min_tracking_confidence=0.5) # 最小跟踪置信度
# 创建检测手部关键点和关键点之间连线的方法
mpDraw = mp.solutions.drawing_utils
# 查看时间
pTime = 0 # 处理一张图像前的时间
cTime = 0 # 一张图处理完的时间
# (3)处理视频图像
while True: # 对每一帧视频图像处理
# 返回是否读取成功和读取的图像
success, img = cap.read()
# 在循环中发送rgb图像到hands中,opencv中图像默认是BGR格式
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 把图像传入检测模型,提取信息
results = Model.process(imgRGB)
# 检查是否检测到什么东西了,没有检测到手就返回None
# print(results.multi_hand_landmarks)
# 检查每帧图像是否有多只手,一一提取它们
if results.multi_hand_landmarks: # 如果没有手就是None
for handlms in results.multi_hand_landmarks:
# (4)获取每个关键点的索引和坐标
for index, lm in enumerate(handlms.landmark):
# 索引为0代表手底部中间部位,为4代表手指关键或指尖
# 输出21个手部关键点的xyz坐标(0-1之间),是相对于图像的长宽比例
# print(index, lm)
# 只需使用x和y查找位置信息
# 将xy的比例坐标转换成像素坐标
h, w, c = img.shape # 分别存放图像长\宽\通道数
# 中心坐标(小数),必须转换成整数(像素坐标)
cx ,cy = int(lm.x * w), int(lm.y * h) #比例坐标x乘以宽度得像素坐标
# 打印显示21个关键点的像素坐标
print(index, cx, cy)
# 存储坐标信息
lmList.append([index, cx, cy])
# 在21个关键点上换个圈,img画板,坐标(cx,cy),半径5,蓝色填充
cv2.circle(img, (cx,cy), 12, (0,0,255), cv2.FILLED)
# 绘制每只手的关键点
mpDraw.draw_landmarks(img, handlms, Models.HAND_CONNECTIONS)
# 传入想要绘图画板img,单只手的信息handlms
# mpHands.HAND_CONNECTIONS绘制手部关键点之间的连线
# 记录执行时间
cTime = time.time()
# 计算fps
fps = 1 / (cTime - pTime)
# 重置起始时间
pTime = cTime
# 把fps显示在窗口上;img画板;取整的fps值;显示位置的坐标;设置字体;字体比例;颜色;厚度
cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)
# 显示图像
cv2.imshow('Image', img) # 窗口名,图像变量
if cv2.waitKey(1) & 0xFF == 27: # 每帧滞留1毫秒后消失;ESC键退出
break
# 释放视频资源
cap.release()
cv2.destroyAllWindows()