OpenCV 3.4.1-dev在Ubuntu调用USB相机报libv4l2 set_fmt错误求助
解决Ubuntu下OpenCV调用USB相机报错
libv4l2: error set_fmt gave us a different result then try_fmt! 我之前也碰到过这个问题,这本质是OpenCV与USB相机通过libv4l2进行格式协商时,相机返回的格式与OpenCV尝试设置的格式不匹配,导致初始化失败或运行崩溃。下面是一步步的解决方案:
1. 先确认相机支持的格式和分辨率
首先用Linux下的v4l2-ctl工具查看相机的所有支持参数,这是解决问题的关键前提:
sudo apt-get install v4l-utils # 没安装的话先执行这条 v4l2-ctl --list-formats-ext
这个命令会输出相机支持的所有像素格式(比如YUYV、MJPG),以及每个格式对应的分辨率、帧率列表。你可能会看到类似这样的输出:
Size: Discrete 640x480 Interval: Discrete 0.033s (30.000 fps) Size: Discrete 1280x720 Interval: Discrete 0.033s (30.000 fps)Size: Discrete 640x480 Interval: Discrete 0.017s (60.000 fps)
2. 在代码中显式指定相机支持的参数
不要依赖OpenCV的默认设置,手动指定相机支持的格式、分辨率和帧率,避免协商失败。
Python3 示例代码
import cv2 # 初始化相机,设备号0对应第一个USB相机,多相机时可能是1、2等 cap = cv2.VideoCapture(0) # 根据v4l2-ctl的结果,设置相机支持的格式(比如YUYV) cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y','U','Y','V')) # 设置支持的分辨率 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置帧率(可选,根据支持的列表选择) cap.set(cv2.CAP_PROP_FPS, 30) # 检查相机是否成功打开 if not cap.isOpened(): print("无法打开相机,请检查设备连接或权限") exit() # 验证实际生效的参数(可选,确认设置是否成功) print(f"实际分辨率: {cap.get(cv2.CAP_PROP_FRAME_WIDTH)}x{cap.get(cv2.CAP_PROP_FRAME_HEIGHT)}") print(f"实际格式FourCC: {int(cap.get(cv2.CAP_PROP_FOURCC))}") # 后续的视频读取、导出逻辑 while True: ret, frame = cap.read() if not ret: print("无法获取帧,可能是流中断") break cv2.imshow('Camera Feed', frame) # 按需导出PNG或AVI的逻辑示例 key = cv2.waitKey(1) if key == ord('q'): break elif key == ord('s'): cv2.imwrite('captured_frame.png', frame) print("已导出PNG图片") # AVI导出可以参考OpenCV的VideoWriter类实现 cap.release() cv2.destroyAllWindows()
C++ 示例代码
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // 初始化相机 VideoCapture cap(0); if (!cap.isOpened()) { cerr << "无法打开相机,请检查设备连接或权限" << endl; return -1; } // 设置相机支持的格式(比如YUYV) cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y','U','Y','V')); // 设置支持的分辨率 cap.set(CAP_PROP_FRAME_WIDTH, 640); cap.set(CAP_PROP_FRAME_HEIGHT, 480); // 设置帧率 cap.set(CAP_PROP_FPS, 30); // 验证实际参数 cout << "实际分辨率: " << cap.get(CAP_PROP_FRAME_WIDTH) << "x" << cap.get(CAP_PROP_FRAME_HEIGHT) << endl; cout << "实际格式FourCC: " << (int)cap.get(CAP_PROP_FOURCC) << endl; Mat frame; while (true) { cap >> frame; if (frame.empty()) { cerr << "无法获取帧,流中断" << endl; break; } imshow("Camera Feed", frame); char key = waitKey(1); if (key == 'q') { break; } else if (key == 's') { imwrite("captured_frame.png", frame); cout << "已导出PNG图片" << endl; } // AVI导出逻辑可通过VideoWriter实现 } cap.release(); destroyAllWindows(); return 0; }
3. 尝试切换到V4L1后端(兼容老相机)
如果上面的方法还是不行,可能你的相机对v4l2支持不好,可以强制OpenCV使用更老的v4l1后端:
Python中修改初始化代码
cap = cv2.VideoCapture(0, cv2.CAP_V4L)
C++中修改初始化代码
VideoCapture cap(0, CAP_V4L);
4. 其他可能的修复手段
- 检查相机权限:确保当前用户有权限访问/dev/video0设备,可以用
sudo chmod 666 /dev/video0临时解决,或者将用户加入video组:sudo usermod -aG video $USER(重启后生效)。 - 更新libv4l库:执行
sudo apt-get update && sudo apt-get install --reinstall libv4l-0 libv4l-dev,修复可能的库损坏或版本不兼容问题。
内容的提问来源于stack exchange,提问作者Jeremy Higgins
相关产品推荐
相关产品推荐

