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

基于手部追踪的手指计数出现IndexError:元组索引越界问题排查

错误原因分析

1. 核心问题:返回值结构不匹配

你使用的cvzone.HandTrackingModule.HandDetector的findPosition方法,返回的手部关键点列表仅包含[x, y]坐标,每个元素只有2个值(索引0对应x,1对应y),但你的代码试图访问索引2,直接触发IndexError。

而视频中Murtaza使用的是自定义HandTrackingModule,其findPosition方法返回的是包含[id, x, y](或带z轴深度)的结构,因此可以通过索引2访问对应坐标,这是两者的核心差异。

2. 次要问题:手部检测不稳定

当摄像头未检测到手、检测置信度不足时,lmList会为空列表;或偶尔检测到的关键点数量不完整,也会导致索引越界。


解决方法

提供两种方案,根据需求选择:

方案一:换回视频中的自定义HandTrackingModule

取消代码中自定义模块的注释,替换cvzone的Detector:

import cv2
import time
import HandTrackingModule as htm  # 取消注释

wcam, hcam = 640 ,480
cap = cv2.VideoCapture(0)
cap.set(3, wcam)
cap.set(4, hcam)
pTime = 0
detector = htm.HandDetector(detectionCon=0.7, maxHands=5)  # 使用自定义模块
tipIds = [4,8,12,16,20]

while True:
    success, img = cap.read()
    img = detector.findHands(img)
    lmList = detector.findPosition(img, draw=False)
    
    fingers = [0,0,0,0,0]
    if len(lmList) != 0:
        # 大拇指单独判断(x坐标对比)
        if lmList[tipIds[0]][1] < lmList[tipIds[0]-2][1]:
            fingers[0] = 1
        # 其他手指判断(y坐标对比)
        for id in range(1,5):
            if lmList[tipIds[id]][2] < lmList[tipIds[id]-2][2]:
                fingers[id] = 1

    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img,f'fps: {int(fps)}',(70,40), cv2.FONT_HERSHEY_PLAIN,3,(255,255,0),3)
    cv2.imshow("image",img)
    cv2.waitKey(1)

方案二:适配cvzone的返回结构

修改代码,使用cvzone返回的[x,y]坐标(索引0对应x,1对应y),同时修正大拇指的判断逻辑:

import cv2
import time
from cvzone.HandTrackingModule import HandDetector

wcam, hcam = 640 ,480
cap = cv2.VideoCapture(0)
cap.set(3, wcam)
cap.set(4, hcam)
pTime = 0
detector = HandDetector(detectionCon=0.7, maxHands=5)
tipIds = [4,8,12,16,20]

while True:
    success, img = cap.read()
    img = detector.findHands(img)
    lmList = detector.findPosition(img, draw=False)
    
    fingers = [0,0,0,0,0]
    # 确保关键点数量足够(至少21个,对应完整手部)
    if len(lmList) >= 21:
        # 大拇指判断:对比x坐标(默认适配右手,如需左手可调整判断方向)
        if lmList[tipIds[0]][0] < lmList[tipIds[0]-2][0]:
            fingers[0] = 1
        # 其他手指判断:对比y坐标(y值越小越靠上,指尖在上则表示伸直)
        for id in range(1,5):
            if lmList[tipIds[id]][1] < lmList[tipIds[id]-2][1]:
                fingers[id] = 1

    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img,f'fps: {int(fps)}',(70,40), cv2.FONT_HERSHEY_PLAIN,3,(255,255,0),3)
    cv2.imshow("image",img)
    cv2.waitKey(1)

额外注意事项
  • 确保手部完整出现在摄像头画面中,避免部分关键点无法检测
  • 可调整detectionCon参数(如设置为0.8)提升检测稳定性,减少误判
  • 如果需要支持左右手,可通过cvzone的findHands返回的手部信息添加方向判断逻辑

内容的提问来源于stack exchange,提问作者Yash Rakesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:32:44