摄像头应用编程(一):使用v4l2-ctl、media-ctl采集摄像头数据

1、前言

本文将介绍如何使用v4l2-ctl、media-ctl工具采集UCV摄像头数据和MIPI摄像头数据。

2、v4l2-utils

v4l2-utils是一个用于 Linux 系统的工具包,包含一系列与 Video4Linux2 (V4L2) 框架相关的实用程序和库。它旨在帮助开发者、系统管理员和用户进行 V4L2 设备的管理、测试、配置和诊断。

2.1、主要组成部分

v4l2-ctl:

  • 用于操作和管理 V4L2 设备节点(如 /dev/videoX)。
  • 支持设置设备的格式(分辨率、像素格式等)、请求和管理缓冲区、控制视频流的启动和停止。

media-ctl:

  • 专注于管理媒体设备的拓扑结构,操作实体(entity)、接口(pad)和链接(link)。
  • 可以设置或查询设备之间的链接状态,定义数据流的路径。

开发库:

  • 包括 libv4l2 等库,提供对 V4L2 设备的编程支持。

3、采集UCV摄像头数据

UVC(USB Video Class)摄像头是一种遵循USB视频类标准的摄像头设备,广泛应用于多种场景,具有即插即用、高兼容性和无需额外驱动程序的特点。

对于USB摄像头来说,可以直接使用v4l2-ctl工具来采集数据。

3.1、查看USB摄像头节点

v4l2-ctl --list-devices

  • /dev/video*:视频捕获设备节点
  • /dev/media1:media子系统设备节点

3.2、查看摄像头支持的图像格式和分辨率

v4l2-ctl -d /dev/video10 --list-formats-ext

  • 支持MJPG和YUYV两种图像格式。

3.3、设置图像格式和分辨率

v4l2-ctl -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=MJPG
v4l2-ctl -d /dev/video0 --set-parm=30
  • width, height:分辨率
  • pixelformat:图像格式

3.4、确认图像格式和分辨率

v4l2-ctl -d /dev/video10 --get-fmt-video

3.5、采集一帧图像

# 采集一帧图像
v4l2-ctl --verbose -d /dev/video10 --stream-mmap=4 --stream-skip=3 --stream-count=1 --stream-to=./01.jpg --stream-poll

# 采集一帧图像,同时指定图像格式和分辨率
v4l2-ctl --verbose -d /dev/video10 --set-fmt-video=width=640,height=480,pixelformat=MJPG --stream-mmap=4 --stream-skip=3 --stream-count=1 --stream-to=./01.jpg --stream-poll

4、采集MIPI摄像头数据

在Linux中,MIPI摄像头的通路相对复杂,因为MIPI摄像头涉及到传感器Sensor、硬件接口、ISP等多个模块。

对于内核中的MIPI摄像头驱动框架来说,引入了media子系统来管理各个entity。在应用层,可以使用media-ctl工具来操作和查询媒体控制器的拓扑结构,包括实体(entities)、接口(pads)和链接(links)。

下面以RK3566和MIPI OV8858摄像头举例。

4.1、查看MIPI摄像头的media节点

v4l2-ctl --list-devices

4.2、查看媒体控制器的拓扑结构

4.2.1、命令行查看拓扑结构

media-ctl -p -d /dev/media0
  • -p:打印媒体控制器的拓扑结构,包括实体、接口和链接。
  • -d /dev/media0:指定媒体控制器的设备节点为 /dev/media0
Media controller API version 5.10.198

Media device information
------------------------
driver          rkisp-vir0
model           rkisp0
serial
bus info
hw revision     0x0
driver version  5.10.198

Device topology
- entity 1: rkisp-isp-subdev (4 pads, 8 links)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev0
        pad0: Sink
                [fmt:SBGGR10_1X10/3264x2448 field:none
                 crop.bounds:(0,0)/3264x2448
                 crop:(0,0)/3264x2448]
                <- "rkisp-csi-subdev":1 [ENABLED]
                <- "rkisp_rawrd0_m":0 []
                <- "rkisp_rawrd2_s":0 []
        pad1: Sink
                <- "rkisp-input-params":0 [ENABLED]
        pad2: Source
                [fmt:YUYV8_2X8/3264x2448 field:none colorspace:smpte170m quantization:full-range
                 crop.bounds:(0,0)/3264x2448
                 crop:(0,0)/3264x2448]
                -> "rkisp_mainpath":0 [ENABLED]
                -> "rkisp_selfpath":0 [ENABLED]
                -> "rkisp_iqtool":0 [ENABLED]
        pad3: Source
                -> "rkisp-statistics":0 [ENABLED]

- entity 6: rkisp-csi-subdev (6 pads, 5 links)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev1
        pad0: Sink
                [fmt:SBGGR10_1X10/3264x2448 field:none]
                <- "rockchip-csi2-dphy1":1 [ENABLED]
        pad1: Source
                [fmt:SBGGR10_1X10/3264x2448 field:none]
                -> "rkisp-isp-subdev":0 [ENABLED]
        pad2: Source
                -> "rkisp_rawwr0":0 [ENABLED]
        pad3: Source
        pad4: Source
                -> "rkisp_rawwr2":0 [ENABLED]
        pad5: Source
                -> "rkisp_rawwr3":0 [ENABLED]

- entity 13: rkisp_mainpath (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video0
        pad0: Sink
                <- "rkisp-isp-subdev":2 [ENABLED]

- entity 19: rkisp_selfpath (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video1
        pad0: Sink
                <- "rkisp-isp-subdev":2 [ENABLED]

- entity 25: rkisp_rawwr0 (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video2
        pad0: Sink
                <- "rkisp-csi-subdev":2 [ENABLED]

- entity 31: rkisp_rawwr2 (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video3
        pad0: Sink
                <- "rkisp-csi-subdev":4 [ENABLED]

- entity 37: rkisp_rawwr3 (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video4
        pad0: Sink
                <- "rkisp-csi-subdev":5 [ENABLED]

- entity 43: rkisp_iqtool (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video5
        pad0: Sink
                <- "rkisp-isp-subdev":2 [ENABLED]

- entity 49: rkisp_rawrd0_m (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video6
        pad0: Source
                -> "rkisp-isp-subdev":0 []

- entity 55: rkisp_rawrd2_s (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video7
        pad0: Source
                -> "rkisp-isp-subdev":0 []

- entity 61: rkisp-statistics (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video8
        pad0: Sink
                <- "rkisp-isp-subdev":3 [ENABLED]

- entity 67: rkisp-input-params (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video9
        pad0: Source
                -> "rkisp-isp-subdev":1 [ENABLED]

- entity 73: rockchip-csi2-dphy1 (2 pads, 2 links)
             type V4L2 subdev subtype Unknown flags 0
             device node name /dev/v4l-subdev2
        pad0: Sink
                [fmt:SBGGR10_1X10/3264x2448@10000/230000 field:none]
                <- "m00_b_ov8858 1-0036":0 [ENABLED]
        pad1: Source
                -> "rkisp-csi-subdev":0 [ENABLED]

- entity 76: m00_b_ov8858 1-0036 (1 pad, 1 link)
             type V4L2 subdev subtype Sensor flags 0
             device node name /dev/v4l-subdev3
        pad0: Source
                [fmt:SBGGR10_1X10/3264x2448@10000/230000 field:none]
                -> "rockchip-csi2-dphy1":0 [ENABLED]

以entity 76为例:

- entity 76: m00_b_ov8858 1-0036 (1 pad, 1 link)
             type V4L2 subdev subtype Sensor flags 0
             device node name /dev/v4l-subdev3
        pad0: Source
                [fmt:SBGGR10_1X10/3264x2448@10000/230000 field:none]
                -> "rockchip-csi2-dphy1":0 [ENABLED]
  • entity 76:代表一个实体,实体名为:m00_b_ov8858 1-0036。该实体有1个pad,1个link。
  • pad0: Source:pad代表端口,Source表明该端口为输出端口,如果是Sink则表明为输入端口。
  • -> "rockchip-csi2-dphy1":0:该端口连接至实体“rockchip-csi2-dphy1”的pad0。

4.2.2、生成拓扑图

将拓扑结构以Graphviz的.dot格式输出到文件media0.dot

media-ctl -d /dev/media0 --print-dot > media0.dot

安装Graphviz工具:

sudo apt install graphviz

使用Graphviz将.dot文件转换为PNG图片:

dot -Tpng media0.dot -o media0.png

4.3、配置链路

4.3.1、使能或关闭Sensor连接

关闭摄像头连接:

media-ctl -l '"m00_b_ov8858 1-0036":0 -> "rockchip-csi2-dphy1":0 [0]'
  • -l:启用或禁用链接。
  • [0]:0关闭,1使能。

使能摄像头连接:

media-ctl -l '"m00_b_ov8858 1-0036":0 -> "rockchip-csi2-dphy1":0 [1]'

4.3.2、设置路由

命令格式如下,这里暂不需要所以不演示:

media-ctl -r '"<source_entity>":<source_pad> -> "<sink_entity>":<sink_pad> [enable]'

4.4、video节点确认

MIPI摄像头对应的video节点为:video0、video1。

知道video节点后,剩下的操作都和操作UVC摄像头一样。

4.5、查看摄像头支持的图像格式和分辨率

v4l2-ctl -d /dev/video0 --list-formats-ext

4.6、采集一帧图像

v4l2-ctl --verbose -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=NV21 --stream-mmap=4 --stream-skip=3 --stream-count=1 --stream-to=./video0.yuv --stream-poll

windows下使用yuv player.exe软件查看图像:

5、总结

参考文章:

ArmSoM-W3开发板 (RK3588) 之 USB摄像头图像预览_rk3588 usb摄像头-优快云博客

RK3576——MIPI CSI之v4l2-ctl、media-ctl命令分析-优快云博客

### 在树莓派 Linux 系统中使用 V4L2 访问 MIPI 相机 要在树莓派的 Linux 系统中通过 V4L2 配置和访问 MIPI 相机,需要了解硬件接口与软件框架之间的交互方式。以下是关于此主题的关键点: #### 1. **MIPI 接口简介** MIPI(Mobile Industry Processor Interface)是种用于移动设备的标准接口协议,广泛应用于手机和其他嵌入式系统的摄像头模块通信。在树莓派上支持 MIPI 的硬件通常依赖于特定的 SoC 和驱动程序实现。 为了使 MIPI 摄像头正常工作,必须确保以下条件满足: - 树莓派主板具备 MIPI CSI-2 接口的支持。 - 使用兼容的 MIPI 摄像头模块,并确认其硬件规格匹配树莓派的 SoC 要求[^1]。 #### 2. **V4L2 设备节点配置** V4L2 是 Linux 内核中的视频捕获 API,提供了统的接口供应用程序访问各种类型的摄像设备。对于 MIPI 摄像头,在完成硬件连接后,需验证对应的设备节点 `/dev/videoX` 是否已注册到系统中。 可以通过以下命令检查是否存在有效的设备节点: ```bash ls /dev/video* ``` 如果未发现任何 `video` 类型的设备,则可能是因为驱动加载失败或者硬件初始化异常。此时可以尝试手动加载相关内核模块并重新启动服务: ```bash sudo modprobe bcm2835-v4l2 ``` 上述命令会激活 Raspberry Pi 上默认的 Video4Linux2 支持功能[^2]。 #### 3. **测试 V4L2 功能** 旦确认存在可用的设备节点,就可以利用工具如 `v4l2-ctl` 来查询和支持参数调整。例如显示当前选定摄像头的能力集: ```bash v4l2-ctl --all ``` 该指令能够提供分辨率选项、帧率范围以及其他属性的信息。另外还可以借助图形界面应用比如 Cheese 或者 FFmpeg 进步录制图像流文件作为后续分析用途。 #### 4. **高级定制化需求下的 FIMC 控制层引入** 当涉及到更复杂的场景处理时,某些高端 CMOS 图像传感器除了基本读数外还需要额外配合 ISP (Image Signal Processing) 单元才能获得最佳画质表现。正如 RV1126 & RV1109 平台所描述那样,实际操作过程中往往离不开专门设计用来管理这些外围组件行为模式的服务逻辑——即所谓的“FIMC”(Frame Image Memory Controller)。 尽管标准版 Raspbian OS 已经内置基础级别的多媒体管线架构,但对于那些追求极致性能优化的研发人员来说,深入研究官方文档资料库以及社区贡献项目将是不可或缺的学习途径之[^3]。 --- ### 示例代码片段:简单抓拍图片脚本 下面给出段基于 Python 结合 OpenCV 库快速捕捉静态照片的小例子: ```python import cv2 cap = cv2.VideoCapture('/dev/video0') # 替换为实际检测到的具体编号位置 if not cap.isOpened(): print("Cannot open camera") else: ret, frame = cap.read() if ret: cv2.imwrite('capture.jpg', frame) print("Image saved successfully.") else: print("Failed to capture image.") cap.release() cv2.destroyAllWindows() ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值