You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python+OpenCV姿态检测代码报TypeError错误,求解决方案

解决cvzone PoseModule中TypeError: unsupported operand type(s) for -: 'int' and 'list'错误

问题重现

使用OpenCV和cvzone.PoseModule编写姿态关键点位置记录代码,运行时触发类型错误。代码如下:

import cv2
from cvzone.PoseModule import PoseDetector 

cap=cv2.VideoCapture('Video (1).mp4') 

detector=PoseDetector() 

posList = []
while True: # This line starts an infinite loop. The code inside this loop will continue to run until it encounters a break statement or the program is terminated manually.

    success, img = cap.read() 

    img = detector.findPose(img) 

    lmList,bboxInfo = detector.findPosition(img) 
    
    
    if bboxInfo:
        lmString = ''
        for lm in lmList:
            # print(lm)
            lmString += f'{lm[1]},{img.shape[0]-lm[2]},{lm[3]}'
        posList.append(lmString)
    
    print(posList)
            # num_points = len(lmList)
            # print("Number of Points Detected:", num_points)


    cv2.imshow("Image",img)
    cv2.waitKey(1)   

报错信息:

INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
Traceback (most recent call last):
  File "d:\py_projects\motionDetector\motionCap.py", line 22, in <module>
    lmString += f'{lm[1]},{img.shape[0]-lm[2]},{lm[3]}'
TypeError: unsupported operand type(s) for -: 'int' and 'list'

错误原因

报错显示整数类型的img.shape[0]无法与列表类型的lm[2]执行减法运算,说明lmList中每个关键点元素的结构不符合预期——你假设lm[2]是y坐标的整数值,但实际它是一个列表。这种情况通常由cvzone版本差异或findPosition方法返回的数据结构与预期不一致导致。

解决方案

步骤1:确认关键点数据结构

先在循环中打印单个关键点的内容,明确其具体结构:

if bboxInfo:
    lmString = ''
    for lm in lmList:
        print(lm)  # 打印单个关键点结构,确认坐标位置
        lmString += f'{lm[1]},{img.shape[0]-lm[2]},{lm[3]}'
    posList.append(lmString)

步骤2:调整坐标提取方式

根据打印结果修改代码:

  • 如果打印结果为[0, 150, 300, 0](结构为[id, x, y, z]),则说明是版本问题,执行以下命令更新依赖:
    pip install --upgrade cvzone opencv-python
    
  • 如果打印结果为[0, 150, [300], 0](y坐标嵌套在列表中),则修改减法部分为:
    lmString += f'{lm[1]},{img.shape[0]-lm[2][0]},{lm[3]}'
    

步骤3:修复视频循环终止逻辑

原代码未处理视频播放结束的情况,需添加退出判断:

while True:
    success, img = cap.read() 
    if not success:  # 视频读取失败或播放完毕时退出循环
        break
    # 后续代码...

修正后的完整代码

import cv2
from cvzone.PoseModule import PoseDetector 

cap=cv2.VideoCapture('Video (1).mp4') 
detector=PoseDetector() 
posList = []

while True:
    success, img = cap.read() 
    if not success:
        break

    img = detector.findPose(img) 
    lmList,bboxInfo = detector.findPosition(img) 
    
    if bboxInfo:
        lmString = ''
        for lm in lmList:
            # 根据实际结构调整索引,此处假设结构为[id, x, y, z]
            # 如果y坐标是嵌套列表,改为lm[2][0]
            lmString += f'{lm[1]},{img.shape[0]-lm[2]},{lm[3]},'
        posList.append(lmString.rstrip(','))  # 移除末尾多余的逗号
    
    cv2.imshow("Image",img)
    if cv2.waitKey(1) & 0xFF == ord('q'):  # 按q键可手动退出
        break

cap.release()
cv2.destroyAllWindows()

内容的提问来源于stack exchange,提问作者Dipanwita Biswas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:40:13