使用cv2读取VideoCapture帧时触发cv2.cvtColor断言失败错误
解决OpenCV cv2.VideoCapture读取摄像头帧时的!_src.empty()错误
错误原因分析
报错(-215:Assertion failed) !_src.empty()直接说明cv2.cvtColor的输入图像img是空的,根源是cap.read()没有成功获取到摄像头帧。你的代码存在两个关键问题:
cap.release()和cv2.destroyAllWindows()被放在while(True)循环内部,第一次循环就释放了摄像头资源,后续循环中cap已失效,无法读取帧。- 调用
cap.read()后未检查返回的ret值,未确认帧是否读取成功就直接处理。
修复步骤
- 将释放摄像头、销毁窗口的代码移到循环体外,确保循环结束后再执行资源清理。
- 在读取帧后,先判断
ret是否为True,若为False则跳出循环,避免处理空帧。 - 可选:添加摄像头是否成功打开的检查,提前排查设备连接问题。
修复后的完整代码
import cv2 import numpy as np import os from PIL import Image from Attendance import attendance from datetime import datetime from database import* def getProfile(Id): query="SELECT * FROM users WHERE id="+str(Id) mycursor.execute(query) profile = mycursor.fetchone() return profile detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("face-trainner.yml") cap = cv2.VideoCapture(0) # 获取摄像头视频流 # 检查摄像头是否成功打开 if not cap.isOpened(): print("无法打开摄像头") exit() cap.set(3, 640) cap.set(4, 480) font = cv2.FONT_HERSHEY_COMPLEX while(True): ret, img = cap.read() # 检查帧是否读取成功 if not ret: print("无法获取帧,退出循环") break gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: cv2.rectangle(img, (x,y), (x+w, y+h), (0,255,0), 2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] nbr_predicted, conf = recognizer.predict(gray[y:y+h, x:x+w]) print(nbr_predicted, conf) if(conf < 80): profile=getProfile(nbr_predicted) if profile != None: time_now=datetime.now() newdate=time_now.strftime('%Y-%m-%d') newtime=time_now.strftime('%H:%M:%S') attendance(nbr_predicted,newtime,newdate) cv2.putText(img, "Name: "+str(profile[4]), (x, y+h+30), font, 0.4, (0, 0, 255), 1) cv2.putText(img, "Gender: " + str(profile[7]), (x, y + h + 50), font, 0.4, (0, 0, 255), 1) else: cv2.putText(img, "Name: Unknown", (x, y + h + 30), font, 0.4, (0, 0, 255), 1) cv2.imshow('Preview',img) # 显示视频画面 # 按下ESC键退出循环 if cv2.waitKey(1) & 0xFF == 27: break # 循环结束后释放资源 cap.release() cv2.destroyAllWindows()
额外说明
- 修复后的代码新增了摄像头打开检查和帧读取成功判断,能提前排查设备连接问题。
- 增加了ESC键退出循环的逻辑,避免只能强制终止程序。
- 删除了原代码中
for循环内重复绘制人脸矩形的冗余代码。
内容的提问来源于stack exchange,提问作者Ashish Bula
相关产品推荐
相关产品推荐

