代码部分
初级版
要实现我们的功能,第一步就是开启摄像头或读取目标视频,代码如下:
- cap = cv2.VideoCapture(0)
或:
- cap = cv2.VideoCapture('video.mp4')
第一行代码中0是摄像头序号,一般是笔记本电脑自带的摄像头的序号,若是外接的摄像头序号一般是1。而另一行代码的功能是读取视频,需要注意的是这种方式读取视频需要该视频为mp4格式且和main.py文件在同一目录下。
第二步是调用函数、简化并设置参数:
- mpPose = mp.solutions.pose
- pose = mpPose.Pose(min_detection_confidence=0.5,
- min_tracking_confidence=0.2)
第一行代码的目的在于简化对MediaPipe里姿态估计模块的调用,让代码看起来简洁直接。
第二行代码是在调用姿态估计模块里的类Pose后,根据函数的定义对参数min_detection_confidence和min_tracking_confidence进行的设置。
1)min_detection_confidence
这个参数用于控制姿态关键点被首次检测时的置信度阈值。具体来说,就是在MediaPipe 尝试于图像或视频帧中首次找到人体的姿态关键点时,它会给检测到的每个关键点分配一个置信度分数,只有当这个分数高于 min_detection_confidence 设定的值时,关键点才会被认为是有效的。在这行代码中,阈值被设置为 0.5,意味着只有置信度分数至少为0.5的关键点才会被检测到。如果增加这个值,会让姿态估计的标准更加严格,可以减少误检的可能,但也可能导致一些关键点的被遗漏。
2)min_tracking_confidence
这个参数用于控制姿态关键点在连续帧之间的跟踪置信度阈值。一旦 MediaPipe 在某一帧中检测到了姿态关键点,它会在后续的帧中尝试去跟踪这些关键点。对于每个跟踪的关键点,MediaPipe都会计算一个置信度分数。只有当这个分数高于 min_tracking_confidence 设定的值时,关键点才会被认为是有效且被跟踪的。在这行代码中,阈值被设置为 0.2,意味着跟踪的关键点需要至少有 20% 的置信度。这个值通常比 min_detection_confidence 低,因为在跟踪阶段,MediaPipe 已经有了先前帧的信息,所以可能更容易确认关键点的位置。降低这个值一定程度上会让跟踪更加稳定。
第三步也是简化调用,此函数的功能会在后面提及:
- mpDraw = mp.solutions.drawing_utils
此函数与效果的直观呈现有关。
第四步是函数的主体部分:
- while True:
- ret, img = cap.read()
- imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- results = pose.process(imgRGB)
- if results.pose_landmarks:
- mpDraw.draw_landmarks(img, results.pose_landmarks, mpPose.POSE_CONNECTIONS)
- for id, lm in enumerate(results.pose_landmarks.landmark):
- h, w, c = img.shape
- cx,cy = int(lm.x * w), int(lm.y * h)
- print(id, cx, cy)
- cv2.circle(img, (cx, cy), 5, (255,0,0), cv2.FILLED)
- cv2.imshow('img', img)
下面逐行解释代码:
- while True使得下方的代码无限循环
- ret, img = cap.read()是Python中OpenCV库里用于从视频捕获对象(如摄像头或视频文件)中读取帧的常用方式。
它返回两个值:
ret:一个布尔值,当成功读取帧,ret被赋值为True,否则为False。这可以用于检查视频是否已结束或是否出现了其他问题。
img:读取的帧,是一个NumPy数组,表示图像数据。如果ret为False, img则可能是一个空的NumPy数组或None。
3.imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
注:此处涉及颜色空间这一名词,简单来说,颜色空间是一种数学表示方法,用于描述和表示颜色。以我们代码里的RGB(红绿蓝)颜色空间为例,它是依据人眼识别的颜色定义出的空间,广泛应用于计算机图形学和显示设备中。在这个颜色空间中,红、绿和蓝是三种基本的加性颜色,可以通过不同比例的组合来形成所需的颜色。
这行代码的作用是将图像从BGR颜色空间转换到RGB颜色空间。这是因为许多计算机视觉库和深度学习模型使用RGB颜色空间作为输入,而OpenCV默认读取图像的颜色空间是BGR,因此,在使用OpenCV读取图像并将其输入到这些模型时,需要先将图像从BGR转换到RGB。
通过执行 cv2.cvtColor(img, cv2.COLOR_BGR2RGB),可以确保图像的颜色空间与模型期望的输入一致,从而避免任何由颜色空间不匹配引起的问题,如错误的姿态估计或降低的估计精度。
4.results = pose.process(imgRGB) 的功能是对输入的RGB图像进行姿态估计处理,识别图 像中人体的关键点(如关节位置),并将处理结果存储在 results 变量中。
本项目中运用了MediaPipe库里关于人体姿态识别的深度学习模型,对人体关键点的识别定义如下图:
此时计算机已经具备识别出视频画面中人物(只要人物完整出现在视频画面中)31个关键节点的能力,那么就来到下一步。
5.if results.pose_landmarks: 这一行是一个条件判断。results 是上句代码给出的处理结 果,而pose_landmarks 是这个对象的一个属性,包含了在图像中检测到的所有姿态关键 点。如果 pose_landmarks 存在(即不为空或None),那么条件为真,将执行接下来的代 码块。
6.mpDraw.draw_landmarks(img, results.pose_landmarks, mpPose.POSE_ CONNECTIONS)一行调用了第三步 mpDraw 模块中 draw_landmarks 函数来在图像上绘 制姿态关键点并连接。
7.
以上6行代码则是在上一步的代码的基础上读取了各个点位的x, y坐标值后打印出来, cv2.circle(img, (cx, cy), 5, (255,0,0), cv2.FILLED)这行代码的功能是对上一步的代码中绘制的关键点进行颜色形状的调整(准确来说是在关键点上绘制了实心的圆形图案,覆盖了原本绘制的关键点),并调用cv2.imshow()呈现摄像头获取到的视频画面。cv2.imshow()中第一个参数是窗口名称(Window Name),用于指定显示图像的窗口的名称。但要注意窗口名称在程序中应当是唯一的。第二个参数则是图像(Image),即我们想要呈现出来的画面,在本项目中我们将参数设为img就呈现了摄像头监测到的画面,方便观测。
第五步:
- if cv2.waitKey(1) == ord('q'):
- break
- cv2.destroyAllWindows()
以上是设置点击键盘的“q”结束读取视频画面(当然也可以设置别的按键)和确保所有的OpenCV窗口都被正确关闭避免程序结束时留下悬挂的窗口的代码,也就是写到这里初级版的代码就结束了。但初级版代码只是对人体姿态检查的使用,对于项目要求来说只是个基础,想要实现我们的项目功能,我们还需要为了简洁美观去除无关点位之间的连线、观测计算出所需三个点位形成的夹角、在画面上显示相关信息等,那么下篇就是实现我们所需功能的升级版代码。
(看到这里不妨点个关注收藏叭~ 找资料不迷路 你的支持也是我更新的动力!)