Python代码中已定义label,为何仍触发NameError未定义报错?
问题原因与修复方案
为什么会触发NameError?
你的label变量是在for (x,y,w,h) in faces_rect:循环内部定义的——只有当faces_rect不为空(也就是检测到人脸)时,循环才会执行,label才会被赋值。如果某一帧没检测到人脸(比如人脸移出画面、光线不足、分类器加载失败),faces_rect是空列表,循环根本跑不起来,label就从未被定义过,后面执行file.write(people[label])自然会报错。
另外你的代码还有几个隐性问题,会加剧这个情况:
- 循环里重复初始化
haar_cascade,而且路径和开头不一致(开头是绝对路径,循环里用相对路径),如果当前工作目录不对,faces.xml加载失败,直接导致faces_rect为空。 - 代码里漏了关键的人脸检测步骤:没有将帧转灰度图(
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)),也没有调用detectMultiScale生成faces_rect,这会直接导致faces_rect未定义或为空。 - 就算检测到多张人脸,最后写入文件的也只是最后一张的信息,逻辑可能不符合你的预期。
为什么之前运行正常?
之前能正常跑是因为每一次循环都成功检测到了人脸,for循环正常执行,label被正确赋值。但只要某次摄像头没捕捉到人脸,或者分类器没识别出来,就会触发这个错误。
修复代码的关键点
- 提前初始化变量:在循环开头给
label和confidence设默认值,避免未定义的情况:
haar_cascade = cv.CascadeClassifier(r'C:\Users\User\Desktop\Project-III\faces.xml') people = ['ABC', 'XYZ','PQR'] file = open(r'C:\Users\User\Desktop\face.txt', 'a') capture = cv.VideoCapture(1) while True: isTrue, frame = capture.read() if not isTrue: break # 读取帧失败直接退出 # 补全灰度转换和人脸检测步骤 gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) faces_rect = haar_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4) # 初始化默认值 label = -1 confidence = 0.0 for (x,y,w,h) in faces_rect: # 修正ROI截取错误:x:x+w而不是x:x+h faces_roi = gray[y:y+h, x:x+w] label, confidence = face_recognizer.predict(faces_roi) print(f'Label={people[label]} with a confidence of {confidence}') # 如果要每检测到一张人脸就写入,把write放在循环内 # file.write(f"{people[label]} {confidence} {datetime.datetime.now()}\n") # 只有检测到人脸时才写入文件 if label != -1: file.write(f"{people[label]} {confidence} {datetime.datetime.now()}\n") # 把显示窗口放在循环内,实时更新画面 cv.imshow('Detected faces', frame) if cv.waitKey(20) & 0xFF == ord('d'): break file.close() cv.destroyAllWindows() # 加上销毁窗口的代码
- 补全缺失的检测步骤:必须包含灰度转换和
detectMultiScale调用,否则根本检测不到人脸。 - 修正ROI错误:之前的
x:x+h会导致截取的人脸区域变形,改成x:x+w才是正确的矩形区域。 - 避免重复加载分类器:把
haar_cascade初始化放在循环外,没必要每次循环都重新加载一次文件。
内容的提问来源于stack exchange,提问作者Parth Parlikar
相关产品推荐
相关产品推荐

