如何解决Mediapipe人体测量程序中的IndexError: tuple index out of range
错误日志
Traceback (most recent call last):
File "c:/Users/user/Desktop/Body detect/measurements4.py", line 23, in
results = pose.process(gray)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\mediapipe\python\solutions\pose.py", line 185, in process
results = super().process(input_data={'image': image})
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\mediapipe\python\solution_base.py", line 353, in process
if data.shape[2] != RGB_CHANNELS:
IndexError: tuple index out of range
用户原始代码
import cv2 import mediapipe as mp import math # Set up Mediapipe Pose model mp_pose = mp.solutions.pose pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, min_tracking_confidence=0.5) # Capture video from webcam cap = cv2.VideoCapture(0) while True: # Read a frame from the webcam ret, frame = cap.read() # Flip the frame horizontally frame = cv2.flip(frame, 1) # Convert the frame to grayscale gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Detect the pose landmarks in the frame results = pose.process(gray) # Check if any pose landmarks were detected if results.pose_landmarks: # Extract the coordinates of the shoulder, elbow, wrist, and chest landmarks landmarks = results.pose_landmarks.landmark shoulder_left = landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER].x, landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER].y shoulder_right = landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER].x, landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER].y elbow_left = landmarks[mp_pose.PoseLandmark.LEFT_ELBOW].x, landmarks[mp_pose.PoseLandmark.LEFT_ELBOW].y elbow_right = landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW].x, landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW].y wrist_left = landmarks[mp_pose.PoseLandmark.LEFT_WRIST].x, landmarks[mp_pose.PoseLandmark.LEFT_WRIST].y wrist_right = landmarks[mp_pose.PoseLandmark.RIGHT_WRIST].x, landmarks[mp_pose.PoseLandmark.RIGHT_WRIST].y chest = landmarks[mp_pose.PoseLandmark.MIDCHEST].x, landmarks[mp_pose.PoseLandmark.MIDCHEST].y # Calculate the distance between the shoulder joints to obtain the user's shoulder width in centimeters pixels_per_cm = 37 # adjust this value based on your camera and distance from camera to user shoulder_width = int(abs(shoulder_left[0] - shoulder_right[0]) * pixels_per_cm) # Calculate the distance between the elbow joints to obtain the user's arm length in centimeters arm_length_left = int(math.sqrt((elbow_left[0] - shoulder_left[0])**2 + (elbow_left[1] - shoulder_left[1])**2) * pixels_per_cm) arm_length_right = int(math.sqrt((elbow_right[0] - shoulder_right[0])**2 + (elbow_right[1] - shoulder_right[1])**2) * pixels_per_cm) # Measure the distance between the highest point of the shoulder joint to the bottom of the ribcage to obtain the user's upper body height in centimeters upper_body_height = int(abs(shoulder_left[1] - chest[1]) * pixels_per_cm) # Measure the distance between the chest points to obtain the user's chest size in centimeters chest_size = int(abs(chest[0] - chest[1]) * pixels_per_cm) # Display the measurements on the frame cv2.putText(frame, f"Shoulder width: {shoulder_width} cm", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Arm length (left): {arm_length_left} cm", (50, 80), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Arm length (right): {arm_length_right} cm", (50, 110), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Upper body height: {upper_body_height} cm", (50, 140), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Chest size: {chest_size} cm", (50, 170), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) # Show the frame cv2.imshow('Frame', frame) # Exit if the user presses the 'q' key if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the webcam and close the window cap.release() cv2.destroyAllWindows()
错误原因
Mediapipe Pose模型要求输入图像为RGB三通道格式,但代码中将帧转为了单通道灰度图,导致模型在读取通道维度(shape[2])时触发索引越界错误。此外代码缺少帧读取失败的判断,且胸部尺寸计算逻辑错误。
修复方案
1. 修正图像输入格式
移除灰度转换步骤,将OpenCV读取的BGR帧转为RGB格式后传入模型:
# 替换灰度转换代码为: rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = pose.process(rgb_frame)
2. 增加帧读取失败判断
在处理帧前检查ret值,避免空帧导致后续报错:
ret, frame = cap.read() if not ret: print("无法读取摄像头帧") break
3. 修正胸部尺寸计算逻辑
原代码取同一个胸部 landmark的x、y差值无意义,改为使用左右胸点的横向距离计算:
# 新增左右胸点提取 chest_left = landmarks[mp_pose.PoseLandmark.LEFT_PECTORAL].x, landmarks[mp_pose.PoseLandmark.LEFT_PECTORAL].y chest_right = landmarks[mp_pose.PoseLandmark.RIGHT_PECTORAL].x, landmarks[mp_pose.PoseLandmark.RIGHT_PECTORAL].y # 计算胸部宽度 chest_size = int(abs(chest_left[0] - chest_right[0]) * pixels_per_cm)
修复后的完整代码
import cv2 import mediapipe as mp import math # Set up Mediapipe Pose model mp_pose = mp.solutions.pose pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, min_tracking_confidence=0.5) # Capture video from webcam cap = cv2.VideoCapture(0) while True: # Read a frame from the webcam ret, frame = cap.read() if not ret: print("无法读取摄像头帧") break # Flip the frame horizontally frame = cv2.flip(frame, 1) # Convert BGR frame to RGB for Mediapipe rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Detect the pose landmarks in the frame results = pose.process(rgb_frame) # Check if any pose landmarks were detected if results.pose_landmarks: # Extract the coordinates of the shoulder, elbow, wrist, and chest landmarks landmarks = results.pose_landmarks.landmark shoulder_left = landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER].x, landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER].y shoulder_right = landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER].x, landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER].y elbow_left = landmarks[mp_pose.PoseLandmark.LEFT_ELBOW].x, landmarks[mp_pose.PoseLandmark.LEFT_ELBOW].y elbow_right = landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW].x, landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW].y wrist_left = landmarks[mp_pose.PoseLandmark.LEFT_WRIST].x, landmarks[mp_pose.PoseLandmark.LEFT_WRIST].y wrist_right = landmarks[mp_pose.PoseLandmark.RIGHT_WRIST].x, landmarks[mp_pose.PoseLandmark.RIGHT_WRIST].y chest_mid = landmarks[mp_pose.PoseLandmark.MIDCHEST].x, landmarks[mp_pose.PoseLandmark.MIDCHEST].y chest_left = landmarks[mp_pose.PoseLandmark.LEFT_PECTORAL].x, landmarks[mp_pose.PoseLandmark.LEFT_PECTORAL].y chest_right = landmarks[mp_pose.PoseLandmark.RIGHT_PECTORAL].x, landmarks[mp_pose.PoseLandmark.RIGHT_PECTORAL].y # Calculate the distance between the shoulder joints to obtain the user's shoulder width in centimeters pixels_per_cm = 37 # adjust this value based on your camera and distance from camera to user shoulder_width = int(abs(shoulder_left[0] - shoulder_right[0]) * pixels_per_cm) # Calculate the distance between the elbow joints to obtain the user's arm length in centimeters arm_length_left = int(math.sqrt((elbow_left[0] - shoulder_left[0])**2 + (elbow_left[1] - shoulder_left[1])**2) * pixels_per_cm) arm_length_right = int(math.sqrt((elbow_right[0] - shoulder_right[0])**2 + (elbow_right[1] - shoulder_right[1])**2) * pixels_per_cm) # Measure the distance between the highest point of the shoulder joint to the bottom of the ribcage to obtain the user's upper body height in centimeters upper_body_height = int(abs(shoulder_left[1] - chest_mid[1]) * pixels_per_cm) # Measure the distance between left and right chest points to obtain chest size chest_size = int(abs(chest_left[0] - chest_right[0]) * pixels_per_cm) # Display the measurements on the frame cv2.putText(frame, f"Shoulder width: {shoulder_width} cm", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Arm length (left): {arm_length_left} cm", (50, 80), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Arm length (right): {arm_length_right} cm", (50, 110), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Upper body height: {upper_body_height} cm", (50, 140), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"Chest size: {chest_size} cm", (50, 170), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) # Show the frame cv2.imshow('Frame', frame) # Exit if the user presses the 'q' key if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the webcam and close the window cap.release() cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者Anji_Ishu

