一、demo03姿态检测.py
1.1 导入所需库
先导入要用的库:
python
import cv2
import mediapipe as mp
1.2 进入主入口
然后进主入口:
python
if __name__ == '__main__':
1.3 初始化姿态检测模型
里面先是一段注释,讲 mp_pose.Pose() 的参数:
python
'''
mp_pose.Pose()其参数:
1)static_image_mode:静态图像还是连续帧视频;
2)model_complexity:人体姿态估计模型,0表示速度最快,精度最低(三者之中),1表示速度中间,精度中间(三者之中),2表示速度最慢,精度最高(三者之中);
3)smooth_landmarks:是否平滑关键点;
4)enable_segmentation:是否对人体进行抠图;
5)min_detection_confidence:检测置信度阈值;
6)min_tracking_confidence:各帧之间跟踪置信度阈值;
'''
这一段是在说,static_image_mode 决定处理静态图还是视频,model_complexity 是模型复杂度,0 最快但精度最低,2 最慢但精度最高,1 居中。smooth_landmarks 是平滑关键点,enable_segmentation 是抠图,后面两个是检测和追踪的可信度阈值。
接着拿姿态模块,初始化 Pose:
python
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(static_image_mode=True,
model_complexity=1,
smooth_landmarks=True,
# enable_segmentation=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
drawing = mp.solutions.drawing_utils
这里 static_image_mode=True,说明是处理静态图片。模型复杂度用 1,中间档。平滑关键点开着。抠图那行注释掉了,没启用。检测和追踪可信度都是 0.5。drawing 是画图工具。
1.4 读取并预处理图片
然后读图片:
python
# read img BGR to RGB
img = cv2.imread("1.jpg")
cv2.imshow("input", img)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = pose.process(img)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
先用 imread 读 1.jpg,弹窗显示原图。OpenCV 读进来是 BGR,MediaPipe 要 RGB,所以先转 RGB。丢给 pose.process 检测。检测完再转回 BGR,方便后面画图显示。
1.5 输出关键点坐标
看检测出来多少个关键点,再把每个点的坐标打出来:
python
print(len(results.pose_landmarks.landmark))
for i in range(len(results.pose_landmarks.landmark)):
x=results.pose_landmarks.landmark[i].x
y=results.pose_landmarks.landmark[i].y
z=results.pose_landmarks.landmark[i].z
print(x,y,z)
results.pose_landmarks.landmark 里装的就是每个姿态关键点,打印长度能看出检测到多少个点,然后循环把每个点的 x、y、z 打出来。
画关键点和骨架:
python
drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
cv2.imshow("keypoint", img)
draw_landmarks 把关键点画到 img 上,POSE_CONNECTIONS 决定哪些点连起来。画完显示在 keypoint 窗口。
再画一份世界坐标的关键点:
python
drawing.plot_landmarks(results.pose_world_landmarks, mp_pose.POSE_CONNECTIONS)
pose_world_landmarks 是三维世界坐标下的关键点,plot_landmarks 会单独弹一个窗口把它画出来。
最后等按键、关窗口:
python
cv2.waitKey(0)
cv2.destroyAllWindows()
waitKey(0) 是一直等,按任意键才继续。然后关掉所有窗口。
二、demo04脸部关键点检测.py
2.1 导入库并初始化模块
先导入库,初始化 Mediapipe 模块:
python
import cv2
import mediapipe as mp
# 初始化 Mediapipe 模块
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_face_mesh 是脸部网格模块,mp_drawing 是画图工具,mp_drawing_styles 是画图风格。
2.2 设置 Face Mesh 参数
设置 Face Mesh 参数:
python
# 设置 Face Mesh 参数
face_mesh = mp_face_mesh.FaceMesh(
static_image_mode=False,
max_num_faces=2,
refine_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
static_image_mode=False,适合视频。最多检测 2 张脸。refine_landmarks=True,会把眼睛和嘴唇周围的点细化。检测和追踪可信度都是 0.5。
2.3 打开摄像头
打开摄像头:
python
# 打开摄像头
cap = cv2.VideoCapture(0)
2.4 循环读取视频帧
进循环,只要摄像头开着就一直读:
python
while cap.isOpened():
success, frame = cap.read()
h, w = frame.shape[:2]
if not success:
print("无法读取摄像头画面")
break
success 表示有没有读到画面,frame 是这一帧。h, w 取高和宽。读不到就打印提示,跳出循环。
2.5 转换颜色空间并检测
转颜色空间,送进去检测:
python
# 转换颜色空间
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_mesh.process(frame_rgb)
OpenCV 是 BGR,MediaPipe 要 RGB,所以转一下再 process。
如果检测到脸,就遍历每张脸:
python
# 绘制关键点
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# print(len(face_landmarks.landmark)) # 478
for i in range(len(face_landmarks.landmark)):
x = face_landmarks.landmark[i].x
y = face_landmarks.landmark[i].y
# z = face_landmarks.landmark[i].z
# print(x,y,z)
cv2.putText(frame, str(i), (int(x * w), int(y * h)), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 255, 0), 2)
脸部关键点一共 478 个。循环每个点,取 x、y,z 那行注释掉了,没打印。然后在画面上用绿色小字把点的编号写出来,字号 0.3,粗细 2。
接着画网格:
python
mp_drawing.draw_landmarks(
image=frame,
landmark_list=face_landmarks,
connections=mp_face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_tesselation_style()
)
FACEMESH_TESSELATION 是脸部网格连线。landmark_drawing_spec=None 表示不单独画点,connection_drawing_spec 用默认的网格风格,这样画出来是细密的网格。
显示结果,按 ESC 退出:
python
# 显示结果
cv2.imshow('Face Mesh', frame)
if cv2.waitKey(1)==27:
break
cap.release()
cv2.destroyAllWindows()