最近在试图使用树莓派4B基于OpenCV做人脸识别门禁项目,发现树莓派的新版本系统对于摄像头驱动有不少改动(改用了libcamera),折腾了半天,记录一下遇到的问题和解决方案
注:在系统安装过程中发现最新版本系统是基于debian 12,代号为bookworm,并且相对于旧系统少了一小部分功能。暂不知晓换源是否需要考虑代号问题(因为换源链接中包含有代号,网络上的旧教程用的都是以前的代号)
刚开始我安装了最新的树莓派官方系统,在按照网络上各位前辈的教学进行配置时发现raspi-config内没有camera选项,加上一些对于新版本小功能缺失的不满故用官方烧录软件重新安装了烧录软件内最老的legacy系统(基于debian 11,也并没有特别老。虽然事实证明这个版本也已经删除了旧版本的摄像头相关驱动和库,改用libcamera作为官方的摄像头自带命令)
一、libcamera-hello命令出现“no cameras available”报错
在烧录了官方legacy系统后我在raspi-config内找到了类似的camera选项(enable camera (legacy)),并启用了它。(推测如果要使用libcamera则此选项不应该被启用,不过使用opencv需要启用他)使用以前教程的命令(如rpicam-hello)无法调用摄像头,发现官方已经改用libcamera驱动,应该使用libcamera-hello进行测试。然而出现了“error: XDG_RUNTIME_DIR not set in the environment.”“ERROR: *** no cameras available”等报错。(在最新系统使用此命令未出现报错)使用sudo vcgencmd get_camera指令能够得到:
supported=1 detected=1, libcamera interfaces=0
说明摄像头是成功连接的。经过寻找后找到树莓派论坛中一个英文帖子(原帖链接),提及boot/config.txt相关问题。使用指令打开文档比对
sudo nano /boot/config.txt
我原先的config.txt中有此内容:
# Automatically load overlays for detected cameras
start_x=1
似乎是因为这个命令会强制使用旧驱动,而非自动检测摄像头。于是将其改为:
# Automatically load overlays for detected cameras
#start_x=1
camera_auto_detect=1
再次执行libcamera-hello,摄像头正常运行。推测就是因为在config中开启了legacy camera相关内容导致的。有趣的是,现在执行sudo vcgencmd get_camera会得到结果
supported=0 detected=0, libcamera interfaces=0
不过libcamera-hello能正常使用。不知道是不是因为这条命令也是针对于旧驱动的。但是我当时没有想到,如果要使用opencv,则不能这样修改,反而需要原来那个start_x=1。后文会提及。
二、libcamera-jpeg命令出现“failed to allocate capture buffers”
在执行libcamera-jpeg命令(libcamera-jpeg -o test.jpg)进行拍照测试时,最后一行出现了以下报错
ERROR V4L2 v4l2_videodevice.cpp:1241 /dev/video14[18:cap]: Unable to request 1 buffers: Cannot allocate memory ERROR:
*** failed to allocate capture buffers ***
在网络上查询到帖子,称“您可能希望减少分配给 GPU 的内存。当您使用 libcamera 应用程序时,它们会使用 CPU 的内存,而不是 GPU,因此,如果为 GPU 提供过多内存,则会限制分配相机缓冲区的能力。”我想到之前我给GPU分配的内存是512MB,可能是因为大了,所以进入raspi-config修改GPU内存。(原帖链接)
第一种方法:图形化界面里点左下角logo打开菜单》首选项》Raspberry Pi Configuration,找到GPU Memory修改。
第二种方法:终端中进入raspi-config,找到GPM Memory(新系统在Interface Options里面,似乎与旧系统位置有差别)修改(记得重启树莓派)
我的树莓派4B为4G内存版本,想着给GPU内存多分配点应该还是够用,故我将GPU内存512MB修改为256,再次运行libcamera-jpeg命令,成功执行无报错。
三、在OpenCV中调用出错
之后在使用OpenCV时发现使用.read imshow等指令时发现会报错,返回的值为None。查阅资料发现OpenCV似乎需要旧的驱动,在重新去config开启摄像头的legacy后成功解决(原理同上文重新改为start_x=1)。树莓派官方真有你的......看来要想使用opencv就得抛弃libcamera。折腾了那么久最终还是绕回来了。
本文写于2023.11.26