树莓派4B上OpenCV无法调用摄像头实现二维码扫描存CSV故障
问题分析
错误提示!img.empty()说明cv2.VideoCapture(-1)没有成功读取到摄像头帧。这是因为最新版Raspberry Pi OS(Bookworm及后续版本)默认采用libcamera作为相机堆栈,替代了传统的V4L2驱动,而原生OpenCV的VideoCapture无法直接适配libcamera设备,导致返回空帧。
解决方案
提供两种可行方案,优先推荐方案一(官方适配方案):
方案一:改用Picamera2配合OpenCV读取帧
Picamera2是树莓派官方适配libcamera的相机库,可直接获取帧并转换为OpenCV兼容格式。
步骤1:安装依赖
sudo apt install python3-picamera2
步骤2:修改后的代码
import cv2 import csv from datetime import date, datetime from picamera2 import Picamera2 # 初始化Picamera2并配置RGB格式(适配OpenCV) picam2 = Picamera2() config = picam2.create_preview_configuration(main={"format": "RGB888", "size": (640, 480)}) picam2.configure(config) picam2.start() detector = cv2.QRCodeDetector() while True: # 每次循环更新时间(避免所有记录都是程序启动时间) current_date = date.today().strftime("%d-%b-%Y") current_time = datetime.now().strftime("%H:%M:%S") # 从相机获取帧 img = picam2.capture_array() # 检测二维码 data, bbox, _ = detector.detectAndDecode(img) if bbox is not None: # 修复边框绘制的语法错误,绘制二维码边框 for i in range(len(bbox)): cv2.line(img, tuple(bbox[i][0].astype(int)), tuple(bbox[(i+1) % len(bbox)][0].astype(int)), color=(255, 0, 0), thickness=2) # 绘制识别到的文本 cv2.putText(img, data, (int(bbox[0][0][0]), int(bbox[0][0][1]) - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 250, 120), 2) if data: print("data found: ", data, current_date, current_time) # 写入CSV,添加newline=''避免空行 with open('Database.csv', mode='a', newline='') as csvfile: csvfileWriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL) csvfileWriter.writerow([data, current_date, current_time]) # 显示画面 cv2.imshow("code detector", img) # 按q退出 if cv2.waitKey(1) == ord("q"): break # 释放资源 picam2.stop() cv2.destroyAllWindows()
方案二:启用V4L2兼容层(临时方案)
如果坚持使用原生OpenCV的VideoCapture,可通过libcamera的V4L2兼容模块创建虚拟设备:
- 安装兼容模块:
sudo apt install libcamera-v4l2
- 加载虚拟设备驱动:
sudo modprobe v4l2loopback
- 启动libcamera转V4L2服务(保持终端窗口打开):
libcamera-vid -n -t 0 --width 640 --height 480 --codec yuv420 --inline -o /dev/video0
- 修改原代码中的
cap = cv2.VideoCapture(-1)为cap = cv2.VideoCapture(0),然后运行程序。
额外优化说明
- 原代码中
date和timeRN仅在启动时获取一次,会导致所有记录的时间都是程序启动时间,已调整为循环内实时更新。 - 修复了原代码中
bbox[(i, 1) % len(bbox)]的语法错误,改为(i+1) % len(bbox)。 - 写入CSV时添加
newline='',避免Windows/Linux下的空行问题。
内容的提问来源于stack exchange,提问作者sakulm1
相关产品推荐
相关产品推荐

