> For the complete documentation index, see [llms.txt](https://rpicn.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rpicn.bsdcn.org/shu-mei-pai/she-xiang-tou-ruan-jian.md).

# 摄像头软件

本文档介绍如何配合我们的软件工具使用受支持的摄像头模块。所有树莓派摄像头都可以使用我们的软件工具拍摄高分辨率照片、录制全高清 1080p（或更高）视频。

树莓派官方生产了多款摄像头模块，包括：

* 摄像头模块 1，搭载 500 万像素（初代产品，已停产）
* [摄像头模块 2](https://www.raspberrypi.com/products/camera-module-v2/)，搭载 800 万像素，红外滤镜可选
* [摄像头模块 3](https://raspberrypi.com/products/camera-module-3/)，搭载 1200 万像素，标准镜头、广角镜头可选，红外滤镜可选
* [高质量（High Quality）相机](https://www.raspberrypi.com/products/raspberry-pi-high-quality-camera/)，配有 CS 和 M12 卡口，搭载 1200 万像素，可同外部镜头搭配使用
* [全局快门（Global Shutter）相机](https://www.raspberrypi.com/products/raspberry-pi-global-shutter-camera/)，搭载 160 万像素，用于高速运动摄影
* [AI 相机](https://www.raspberrypi.com/products/ai-camera/)搭载 1200 万像素，使用索尼 IMX500 图像传感器，可为任何相机应用程序提供低延迟、高性能的 AI 能力

有关摄像头硬件的更多信息，请参阅[摄像头硬件文档](/pei-jian/she-xiang-tou.md)。

首先[安装你的摄像头模块](https://rpicn.bsdcn.org/shu-mei-pai/pages/erVW84ss4BKLJC469S2W#安装树莓派摄像头)，然后按照本节中的指南使用摄像头模块。

> **警告**
>
> 本指南不再涵盖 *Bullseye* 及更早版本树莓派系统中提供的旧版摄像头软件栈。旧版摄像头软件栈使用 `raspivid`、`raspistill` 等应用程序以及原始 `Picamera`（*不是* `Picamera2`）Python 库，已被弃用多年，目前不再受支持。如果你使用旧版摄像头软件栈，它仅支持摄像头模块 1、摄像头模块 2 和高质量摄像头，并且永远不会支持任何更新的摄像头模块。本文档中的任何内容均不适用于旧版摄像头软件栈。

## `rpicam-apps`

> **注意**
>
> 从树莓派系统 *Bookworm* 开始，相机捕获应用程序名为 `rpicam-*`。

树莓派提供了一小组示例 `rpicam-apps`。这些命令行应用程序基于 `libcamera`，从相机捕获图像和视频。这些应用程序包括：

* `rpicam-hello`：相机版“hello world”，将启动相机预览流并在屏幕上显示它。
* `rpicam-jpeg`：打开预览窗口，随后捕获高分辨率的静止图像。
* `rpicam-still`：模拟原 `raspistill` 应用程序的许多功能。
* `rpicam-vid`：捕获视频。
* `rpicam-raw`：直接从传感器捕获原始（未经处理的 Bayer）帧。
* `rpicam-detect`：默认不会构建，但如果你在自己的树莓派上安装了 TensorFlow Lite，可以自行构建。当检测到特定对象后，可捕获 JPEG 图像。

树莓派系统内置了五款基本的 `rpicam-apps`，因此即使在全新安装的树莓派系统上，你也可以使用摄像头记录图像和视频。

你可以创建基于 `rpicam` 的应用程序，并按自己的需求定制功能。[`rpicam-apps` 源代码](https://github.com/raspberrypi/rpicam-apps)在 BSD-2-Clause 许可下自由提供。

### `libcamera`

`libcamera` 是一款开源软件库，旨在让 Arm 处理器上的 Linux 操作系统直接支持摄像头系统。在博通 GPU 上运行的私有代码已降至最低。有关 `libcamera` 的更多信息，请参阅 [`libcamera` 网站](https://libcamera.org)。

`libcamera` 提供了 C++ API，用于配置相机，能让应用程序请求图像帧。这些图像缓冲区驻留在系统内存中，并可以直接传递给静态图像编码器（如 JPEG）或视频编码器（如 H.264）。`libcamera` 不会对图像进行编码和显示：要使用该功能，请使用 `rpicam-apps`。

你可以在 [`libcamera` 官方存储库](https://git.linuxtv.org/libcamera.git/)中找到源代码。树莓派系统发行版使用[分支](https://github.com/raspberrypi/libcamera.git)控制更新。

在 `libcamera` 核心之下，我们提供了一个自定义管道处理器。`libcamera` 使用这层来驱动树莓派上的传感器和图像信号处理器（ISP）。`libcamera` 包含了一系列图像处理算法（IPA），包括自动曝光/增益控制（AEC/AGC）、自动白平衡（AWB）和自动镜头阴影校正（ALSC）。

树莓派的 `libcamera` 实现可支持以下摄像头：

* 官方摄像头：
  * OV5647 (V1)
  * IMX219 (V2)
  * IMX708 (V3)
  * IMX477 (HQ)
  * IMX500 (AI)
  * IMX296 (GS)
* 第三方传感器：
  * IMX290
  * IMX327
  * IMX378
  * IMX519
  * OV9281
  * VD55G1
  * VD55G4
  * VD56G3
  * VD65G4
  * VD66GY

要增加对新传感器的支持，请[贡献至 `libcamera`](https://git.linuxtv.org/libcamera.git/)。

### `rpicam-hello`

`rpicam-hello` 会短暂显示一个预览窗口，其中包含来自所连接摄像头的视频流。要在终端中让 `rpicam-hello` 显示五秒钟的预览窗口，请运行以下命令：

```bash
$ rpicam-hello
```

你可以使用参数 `timeout` 指定可选的持续时间（毫秒）。值为 `0` 会无限期运行预览：

```bash
$ rpicam-hello --timeout 0
```

要结束 `rpicam-hello`，可在终端中按 **Ctrl** + **C**，或在预览窗口上点击关闭按钮。

#### 显示图像传感器预览

大多数 `rpicam-apps` 都在窗口中显示预览图像。如果没有活动的桌面环境，则使用 Linux 直接渲染管理器（DRM）直接把预览绘制到显示器。否则，`rpicam-apps` 会尝试使用桌面环境。这两种方式都使用零拷贝 GPU 缓冲区共享，因此不支持 X 转发。

如果你运行着 X 窗口服务器，想要使用 X 转发，请使用 `qt-preview` 参数，在 Qt 窗口中渲染预览。与其他方案相比，用 Qt 预览窗口将消耗更多资源。

> **注意**
>
> 使用 Gtk2 的旧版系统在与 OpenCV 链接时，可能会产生 `Glib-GObject` 报错，且无法显示 Qt 预览窗口。在这种情况下，请以 root 身份编辑文件 `/etc/xdg/qt5ct/qt5ct.conf`，把 `style=gtk2` 这行改成 `style=gtk3`。

要完全禁用预览窗口，请使用 `nopreview` 参数：

```bash
$ rpicam-hello -n
```

`info-text` 选项使用 `%` 指令在窗口标题栏上显示图像信息。例如，以下命令会显示当前的红色和蓝色增益值：

```bash
$ rpicam-hello --info-text "red gain %rg, blue gain %bg"
```

要查看指令的完整列表，请参阅 `info-text` 参考。

### `rpicam-jpeg`

`rpicam-jpeg` 可帮助你在树莓派设备上捕获图像。

要捕获全分辨率 JPEG 图像并将其保存成名为 `test.jpg` 的文件，请运行以下命令：

```bash
$ rpicam-jpeg --output test.jpg
```

你应该会看到预览窗口持续五秒钟。然后，`rpicam-jpeg` 会捕获并保存全分辨率 JPEG 图像。

可使用参数 `timeout` 来修改预览窗口的显示时间。参数 `width` 和 `height` 可更改保存图像的分辨率。例如，以下命令显示预览窗口 2 秒，然后捕获并保存分辨率为 640×480 像素的图像：

```bash
$ rpicam-jpeg --output test.jpg --timeout 2000 --width 640 --height 480
```

### `rpicam-still`

`rpicam-still`，同 `rpicam-jpeg` 一样，帮助你在树莓派设备上捕获图像。与 `rpicam-jpeg` 不同，`rpicam-still` 能兼容许多旧版应用程序中提供的参数。

要捕获全分辨率的 JPEG 图像并将其保存成名为 `test.jpg` 的文件，请运行以下命令：

```bash
$ rpicam-still --output test.jpg
```

#### 编码器

`rpicam-still` 可以多种格式保存图像，包括 `png`、`bmp`，以及 RGB 和 YUV 二进制像素转储。要读取这些二进制转储，处理文件的应用程序必须了解像素的排列方式。

使用参数 `encoding` 能指定输出格式。传递给 `output` 的文件名不会影响输出文件类型。

要捕获全分辨率的 PNG 图像并将其保存成名为 `test.png` 的文件，请运行以下命令：

```bash
$ rpicam-still --encoding png --output test.png
```

要了解有关指定图像格式的更多信息，请参阅 `encoding` 选项参考。

#### 捕获原始图像

原始图像直接由图像传感器生成，未经图像信号处理器（ISP）和 CPU 的处理。彩色图像传感器通常使用 Bayer 格式。使用 `raw` 参数来捕获原始图像。

要捕获图像，并将其保存成名为 `test.jpg` 的文件，再把图像的原始版本保存成名为 `test.dng` 的文件，请运行以下命令：

```bash
$ rpicam-still --raw --output test.jpg
```

`rpicam-still` 以 DNG（Adobe 数字负片）格式保存原始图像。要确定原始图像的文件名，`rpicam-still` 使用与输出文件相同的文件名，但将其扩展名更改为 `.dng`。要处理 DNG 图像，请使用类似于 Dcraw、RawTherapee 的应用程序。

DNG 文件包含了有关图像捕获的元数据，包括黑电平、白平衡信息以及 ISP 用于生成 JPEG 的色彩矩阵。使用 ExifTool 查看 DNG 元数据。以下输出显示了通过使用 HQ 相机捕获的原始图像中存储的典型元数据：

```json
File Name                       : test.dng
Directory                       : .
File Size                       : 24 MB
File Modification Date/Time     : 2021:08:17 16:36:18+01:00
File Access Date/Time           : 2021:08:17 16:36:18+01:00
File Inode Change Date/Time     : 2021:08:17 16:36:18+01:00
File Permissions                : rw-r--r--
File Type                       : DNG
File Type Extension             : dng
MIME Type                       : image/x-adobe-dng
Exif Byte Order                 : Little-endian (Intel, II)
Make                            : Raspberry Pi
Camera Model Name               : /base/soc/i2c0mux/i2c@1/imx477@1a
Orientation                     : Horizontal (normal)
Software                        : rpicam-still
Subfile Type                    : Full-resolution Image
Image Width                     : 4056
Image Height                    : 3040
Bits Per Sample                 : 16
Compression                     : Uncompressed
Photometric Interpretation      : Color Filter Array
Samples Per Pixel               : 1
Planar Configuration            : Chunky
CFA Repeat Pattern Dim          : 2 2
CFA Pattern 2                   : 2 1 1 0
Black Level Repeat Dim          : 2 2
Black Level                     : 256 256 256 256
White Level                     : 4095
DNG Version                     : 1.1.0.0
DNG Backward Version            : 1.0.0.0
Unique Camera Model             : /base/soc/i2c0mux/i2c@1/imx477@1a
Color Matrix 1                  : 0.8545269369 -0.2382823821 -0.09044229197 -0.1890484985 1.063961506 0.1062747385 -0.01334283455 0.1440163847 0.2593136724
As Shot Neutral                 : 0.4754476844 1 0.413686484
Calibration Illuminant 1        : D65
Strip Offsets                   : 0
Strip Byte Counts               : 0
Exposure Time                   : 1/20
ISO                             : 400
CFA Pattern                     : [Blue,Green][Green,Red]
Image Size                      : 4056x3040
Megapixels                      : 12.3
Shutter Speed                   : 1/20
```

要找到模拟增益，请将 ISO 数除以 100。自动白平衡（AWB）算法确定一个始终标记为 D65 的单个校准光源。

#### 拍摄长曝光照片

要拍摄非常长时间的曝光照片，请禁用自动曝光/增益控制（AEC/AGC）和自动白平衡（AWB）。否则，这些算法会迫使用户等待一定数量的帧，直到它们收敛。

要禁用这些算法，请为增益和 AWB 指定明确的值。因为长时间曝光本身就需要很多时间，通常最好使用 `immediate` 选项完全跳过预览阶段。

运行以下命令执行 100 秒曝光捕捉：

```bash
$ rpicam-still -o long_exposure.jpg --shutter 100000000 --gain 1 --awbgains 1,1 --immediate
```

要查找官方树莓派摄像头的最大曝光时间，请参阅[摄像头硬件规格](/pei-jian/she-xiang-tou.md)。

#### 创建延时摄影视频

要创建延时摄影视频，请定期拍摄静止图像，例如每分钟一次，然后使用应用程序将图片拼接成视频。

**通过 `rpicam-still` 延时模式**

要使用 `rpicam-still` 的内置延时模式，请使用 `timelapse` 选项。此选项需要一个值，代表你希望树莓派在捕获之间等待的时间间隔，单位为毫秒。

首先，创建一个目录，用于存储你的延时摄影照片：

```bash
$ mkdir timelapse
```

运行以下命令，将创建一段 30 秒的延时摄影，每两秒记录一张照片，将输出保存为 `image0000.jpg` 至 `image0013.jpg`：

```bash
$ rpicam-still --timeout 30000 --timelapse 2000 -o timelapse/image%04d.jpg
```

**通过 cron**

你还可以使用 cron 自动化延时摄影。首先，创建一个名为 `timelapse.sh` 的脚本，其中包含以下命令。把占位符 `<用户名>` 改成你树莓派上的用户账户名：

```bash
#!/bin/bash
DATE=$(date +"%Y-%m-%d_%H%M")
rpicam-still -o /home/<用户名>/timelapse/$DATE.jpg
```

然后，使脚本可执行：

```bash
$ chmod +x timelapse.sh
```

创建目录 `timelapse`，你将在其中保存延时摄影图片：

```bash
$ mkdir timelapse
```

打开你的 crontab 进行编辑：

```bash
$ crontab -e
```

在编辑器中打开文件后，添加以下行以安排每分钟捕获一次图像，把占位符 `<用户名>` 换成你主用户账户的用户名：

```bash
* * * * * /home/<用户名>/timelapse.sh 2>&1
```

保存退出，你应看到此信息：

```bash
crontab: installing new crontab
```

> **技巧**
>
> 要停止为延时摄影录制图像，请再次运行 `crontab -e`，并从你的 `crontab` 中删除上述行。

**拼接图像**

如果你拥有一系列延时摄影照片，你可能希望将它们合并成视频。在树莓派上使用 `ffmpeg` 来完成这个操作。

首先，安装 `ffmpeg`：

```bash
$ sudo apt install ffmpeg
```

在包含 `timelapse` 目录的目录中运行以下命令，将你的 JPEG 文件转换为 mp4 视频：

```bash
$ ffmpeg -r 10 -f image2 -pattern_type glob -i 'timelapse/*.jpg' -s 1280x720 -vcodec libx264 timelapse.mp4
```

上述命令使用以下参数：

* `-r 10`：将帧率（Hz）设置为每秒十帧的输出视频
* `-f image2`：设置 `ffmpeg` 从由模式指定的图像文件列表中读取
* `-pattern_type glob`：使用通配符模式（globbing）来解释带有 `-i` 的文件名输入
* `-i 'timelapse/*.jpg'`：指定输入文件，匹配 `timelapse` 目录中的 JPG 文件
* `-s 1280x720`：缩放至 720p
* `-vcodec libx264`：使用软件 x264 编码器
* `timelapse.mp4`：输出视频的文件名。

要了解有关 `ffmpeg` 参数的更多信息，请在终端中运行 `ffmpeg --help`。

### `rpicam-vid`

`rpicam-vid` 可帮助你在树莓派设备上捕获视频。`rpicam-vid` 会显示一个预览窗口，并将编码后的比特流写入指定的输出。这样得到的是未封装的视频比特流，没有包在任何容器（如 MP4 文件）格式中。

> **注意**
>
> 在可用时，`rpicam-vid` 使用硬件 H.264 编码。

例如，以下命令将十秒钟的视频写入名为 `test.h264` 的文件：

```bash
$ rpicam-vid -t 10s -o test.h264
```

你可以使用 ffplay 和其他视频播放器播放生成的文件：

```bash
$ ffplay test.h264
```

> **警告**
>
> 旧版 VLC 可以正确播放 H.264 文件，但较新的版本无法做到，只会显示少量帧，甚至可能显示乱码帧。请改用其他媒体播放器，或将文件保存为更广泛支持的容器格式，例如 MP4（见下文）。

在树莓派 5 上，你可以通过为输出文件指定 `mp4` 文件扩展名，直接输出到 MP4 容器格式：

```bash
$ rpicam-vid  -t 10s -o test.mp4
```

在树莓派 4 及更早的设备上，你可以使用以下命令保存 MP4 文件：

```bash
$ rpicam-vid -t 10s --codec libav -o test.mp4
```

#### 编码器

`rpicam-vid` 支持运动 JPEG 以及未压缩和未格式化的 YUV420：

```bash
$ rpicam-vid -t 10000 --codec mjpeg -o test.mjpeg
```

```bash
$ rpicam-vid -t 10000 --codec yuv420 -o test.data
```

`codec` 参数决定输出格式，而不是输出文件的扩展名。

`segment` 参数会按段大小（以毫秒为单位）将输出文件切分成多个块。这对于通过指定非常短的（1 毫秒）段来将运动 JPEG 流分解为单独的 JPEG 文件非常方便。例如，以下命令将 1 毫秒的段与输出文件名中的计数器结合起来，为每个段生成一个新的文件名：

```bash
$ rpicam-vid -t 10000 --codec mjpeg --segment 1 -o test%05d.jpeg
```

#### 捕获高帧率视频

为了减少高帧率（> 60fps）视频的帧丢失，请尝试以下配置调整：

* 使用 `--level 4.2` 将 H.264 目标级别设置为 `4.2`。
* 通过将参数 `denoise` 设置为 `cdn_off` 来禁用软件颜色去噪处理。
* 使用 `nopreview` 禁用显示窗口，以释放一些额外的 CPU 周期。
* 在 `/boot/firmware/config.txt` 中设置 `force_turbo=1` 以确保在视频捕获过程中 CPU 时钟不会降频。有关更多信息，请参阅 `force_turbo` 文档。
* 使用 `--width 1280 --height 720` 或更低的分辨率调整 ISP 输出，以实现你的帧率目标。
* 在树莓派 4 上，你可以在 `/boot/firmware/config.txt` 中添加 `gpu_freq=550` 及更高的值来超频 GPU，提高性能。有关更多详细信息，请参阅超频文档。

以下命令演示了如何实现 1280×720 120fps 视频：

```bash
$ rpicam-vid --level 4.2 --framerate 120 --width 1280 --height 720 --save-pts timestamp.pts -o video.264 -t 10000 --denoise cdn_off -n
```

#### `rpicam-vid` 与 libav 的集成

`rpicam-vid` 可以使用 `ffmpeg`/`libav` 编解码后端来对音频和视频流进行编码。你可以将这些流保存到文件，也可以通过网络进行流传输。当硬件可用时，`libav` 会使用硬件 H.264 视频编码。

要启用 `libav` 后端，请将 `libav` 传给 `codec` 参数：

```bash
$ rpicam-vid --codec libav --libav-format avi --libav-audio --output example.avi
```

#### 树莓派 5 上的低延迟视频

树莓派 5 使用软件视频编码器。与旧版硬件编码器相比，软件编码器输出的帧通常具有更长的延迟，这在实时流媒体应用中有时会成为问题。

在这种情况下，请在 `rpicam-vid` 命令中添加 `--low-latency` 选项。这会更改某些编码器选项，以便更快地输出编码帧。

代价是编码效率会（略微）降低，处理器的多个核心可能（略微）无法被充分利用。可编码的最大帧率也可能略有降低（但仍可轻松达到 1080p30）。

### `rpicam-raw`

`rpicam-raw` 直接从传感器以原始 Bayer 帧记录视频。它不显示预览窗口。要将两秒的原始剪辑记录到名为 `test.raw` 的文件中，请运行以下命令：

```bash
$ rpicam-raw -t 2000 -o test.raw
```

`rpicam-raw` 输出的原始帧不含任何格式信息，一帧紧接着一帧。应用程序会在终端窗口打印像素格式和图像尺寸，以帮助用户解释像素数据。

默认情况下，`rpicam-raw` 将原始帧输出到单个、可能非常大的文件中。使用 `segment` 参数将每个原始帧定向到单独的文件，并使用 `%05d` 指令使每个帧的文件名唯一：

```bash
$ rpicam-raw -t 2000 --segment 1 -o test%05d.raw
```

使用快速的存储设备，`rpicam-raw` 可以以 10fps 的速度将 18MB 1200 万像素 HQ 相机帧写入磁盘。`rpicam-raw` 无法将输出帧格式化为 DNG 文件；要使用该功能，请使用 `rpicam-still`。使用 `framerate` 选项指定低于 10 的值以避免丢帧：

```bash
$ rpicam-raw -t 5000 --width 4056 --height 3040 -o test.raw --framerate 8
```

有关原始格式的更多信息，请参阅 `mode` 文档。

### `rpicam-detect`

> **注意**
>
> 树莓派系统不包括 `rpicam-detect`。但是，如果你[安装了 TensorFlow Lite](#使用-tensorflow-lite-进行后处理)，可以自行编译 `rpicam-detect`。有关更多信息，请参阅 [`rpicam-apps` 编译说明](#构建-libcamera-和-rpicam-apps)。运行 `meson` 时，请不要忘记传入 `-Denable_tflite=enabled`。

`rpicam-detect` 显示一个预览窗口，并使用经过训练的 Google MobileNet v1 SSD（Single Shot Detector）神经网络监视画面，该网络使用 COCO 数据集训练，可识别约 80 类对象。`rpicam-detect` 可以识别人、汽车、猫和许多其他对象。

每当 `rpicam-detect` 检测到目标物体时，它会拍摄全分辨率的 JPEG。然后返回监视预览模式。

关于模型使用的一般信息，请参阅 [TensorFlow Lite 对象检测器](#object_detect_tf-阶段) 一节。例如，你可以在离开时秘密监视你的猫。

```bash
$ rpicam-detect -t 0 -o cat%04d.jpg --lores-width 400 --lores-height 300 --post-process-file object_detect_tf.json --object cat
```

### 配置

大多数用例无需更改摄像头配置即可自动工作。但是，某些常见用例确实需要进行配置调整，包括：

* 第三方摄像头（如有必要的配置更改，请参阅制造商的说明）
* 使用官方树莓派摄像头的非标准驱动程序或叠加层

树莓派系统在 `/boot/firmware/config.txt` 中识别以下叠加层。

|      摄像头模块      | `/boot/firmware/config.txt`                                                                                                         |
| :-------------: | ----------------------------------------------------------------------------------------------------------------------------------- |
|  V1 摄像头（OV5647） | `dtoverlay=ov5647`                                                                                                                  |
|  V2 摄像头（IMX219） | `dtoverlay=imx219`                                                                                                                  |
|  HQ 摄像头（IMX477） | `dtoverlay=imx477`                                                                                                                  |
|  GS 相机（IMX296）  | `dtoverlay=imx296`                                                                                                                  |
| 摄像头模块 3（IMX708） | `dtoverlay=imx708`                                                                                                                  |
|  IMX290、IMX327  | `dtoverlay=imx290,clock-frequency=74250000` 或 `dtoverlay=imx290,clock-frequency=37125000`（两个模块共享 imx290 内核驱动程序；请参考模块供应商的说明以获取正确的频率） |
|      IMX378     | `dtoverlay=imx378`                                                                                                                  |
|      OV9281     | `dtoverlay=ov9281`                                                                                                                  |

要使用这些叠加层，你必须禁用自动摄像头检测。要禁用自动检测，请在 `/boot/firmware/config.txt` 中设置 `camera_auto_detect=0`。如果 `config.txt` 已包含分配 `camera_auto_detect` 值的行，请将该值更改为 `0`。使用 `sudo reboot` 重启你的树莓派以加载更改。

如果你的树莓派有两个摄像头连接器（例如树莓派 5 或某个计算模块），你可以在上表中使用的 `dtoverlay` 后添加 `,cam0`，以指定使用摄像头连接器 0。如果不添加此项，则默认检查摄像头连接器 1。请注意，对于连接到单板计算机（而非计算模块）的官方树莓派摄像头模块，自动检测将正确识别连接到设备的所有摄像头。

#### 使用调整文件调整摄像头行为

树莓派的 `libcamera` 实现包括每个摄像头的调整文件。该文件控制算法和硬件，以产生最佳图像质量。`libcamera` 只能确定正在使用的传感器，而不能确定模块。因此，一些模块需要覆盖调整文件。使用 `tuning-file` 参数指定覆盖文件。你还可以复制和修改现有的调整文件，以定制摄像头行为。

例如，传感器的无红外滤光片（NoIR）版本使用与标准版本不同的自动白平衡（AWB）设置。在树莓派 5 及更高版本上，你可以使用以下命令为 IMX219 传感器指定 NoIR 调整文件：

```bash
$ rpicam-hello --tuning-file /usr/share/libcamera/ipa/rpi/pisp/imx219_noir.json
```

> **注意**
>
> 旧版树莓派型号使用其他的调整文件。在这些设备上，请改用 `/usr/share/libcamera/ipa/rpi/vc4/` 中存储的文件。

`libcamera` 维护着多种摄像头的调整文件，包括第三方型号。例如，你可以在 `se327m12.json` 找到 Soho Enterprises SE327M12 的调整文件。

### 使用多个摄像头

`rpicam-apps` 对多个摄像头有基本支持。你可以通过以下方式将多个摄像头连接到树莓派：

* 对于树莓派计算模块，你可以将两个摄像头直接连接到树莓派计算模块 IO 板。有关详细信息，请参阅计算模块文档。使用此方法时，你可以同时使用两个摄像头。
* 对于树莓派 5，你可以使用双 MIPI 连接器直接将两个摄像头连接到主板上。
* 对于带有摄像头接口的其他树莓派设备，你可以使用 Video Mux 板连接两个或更多摄像头，例如[这款第三方产品](https://www.arducam.com/multi-camera-v2-1-adapter-raspberry-pi.html)。由于两个摄像头连接到单个 Unicam 端口，因此一次只能使用一个摄像头。

要列出平台上所有可用的摄像头，请使用参数 `list-cameras`。要选择要使用的摄像头，请将摄像头索引传参给参数 `camera`。

> **注意**
>
> `libcamera` 尚不支持立体摄像头。当同时运行两个摄像头时，它们必须在单独的进程中运行，这意味着无法在它们之间同步 3A 操作。作为一种解决方法，你可以通过外部同步信号同步 HQ（IMX477）摄像头，或使用下文所述的软件摄像头同步支持；如有必要，将 3A 切换到手动模式。

#### 软件摄像头同步

树莓派 *libcamera* 实现能够仅使用软件同步不同摄像头的帧。这会使一台摄像头调整其帧时序，以便尽可能与另一台摄像头的帧重合。无需焊接或硬件连接，并且适用于所有树莓派摄像头模块，甚至第三方摄像头模块，只要其驱动程序正确实现了帧持续时间控制。

**工作原理**

该方案将一台摄像头指定为 *服务器*。服务器会定期（例如每秒一次）向网络广播时序消息。与此同时，其他摄像头（称为 *客户端*）可以监听这些消息，并据此略微延长或缩短帧时间，使其与服务器同步。此过程会持续进行，不过在第一次调整之后，后续调整通常很小。

客户端摄像头可以与服务器连接到同一树莓派设备，也可以连接到同一网络上的不同树莓派设备。客户端的摄像头型号可以与服务器相同，也可以不同。

客户端和服务器需要以相同的标称帧率运行（例如 30fps）。请注意，从客户端到服务器没有反向通道。客户端需要自行及时启动，以便与服务器匹配；服务器完全不知道客户端是否已成功同步，甚至不知道是否存在任何客户端。

在正常运行中，在同一树莓派上运行同一型号的摄像头时，我们预计摄像头图像的帧开始时间匹配误差在“几十微秒”之内。当摄像头型号不同时，这个误差可能会显著增大，因为摄像头可能无法精确匹配帧率，因此会不断漂移分开（并在每次收到时序消息时被拉回）。

当摄像头位于不同设备上时，应使用 NTP 同步系统时钟（树莓派系统通常默认如此）；如果精度不够，也可以使用 PTP 等其他协议。系统时钟之间的任何差异都会直接转化为帧开始时间的额外误差，即使帧上公布的时间戳不会告诉你这一点。

**服务器**

如前所述，服务器会向网络广播时序消息，默认每秒一次。服务器将运行固定的帧数，默认 100 帧，之后会通知设备上的摄像头应用程序已到达“同步点”。此时，应用程序将开始使用这些帧，因此对于 `rpicam-vid` 来说，它们将开始被编码和录制。请记住，客户端的行为甚至是否存在都不影响这一点。

如果需要，同一网络上可以有多个服务器，只要它们向不同的网络地址广播时序消息即可。当然，客户端必须配置为监听正确的地址。

**客户端**

客户端监听服务器的时序消息，收到消息后，会将摄像头帧持续时间缩短或延长所需的时间，以便后续帧尽可能与服务器的帧在同一时刻开始。

客户端从服务器的消息中获知正确的“同步点”，并像服务器一样，在同一时刻通知摄像头应用程序应开始使用这些帧。因此，对于 `rpicam-vid` 来说，这同样是帧开始被录制的时刻。

通常，在服务器 *之前* 启动客户端是合理的，因为客户端会一直等待（尚未到达“同步点”），直到看到服务器在网络上的广播。这显然可以避免服务器在所有客户端启动之前就到达“同步点”的时序问题！

**在 `rpicam-vid` 中使用**

我们可以将软件摄像头同步与 `rpicam-vid` 结合使用，录制逐帧同步的视频。我们假设连接了两台摄像头，并将摄像头 0 用作服务器，摄像头 1 用作客户端。`rpicam-vid` 默认固定为每秒 30 帧，这对我们来说没问题。

首先，我们应该启动客户端：

```bash
$ rpicam-vid -n -t 20s --camera 1 --codec libav -o client.mp4 --sync client
```

注意 `--sync client` 参数。这将在到达同步点 *之后* 才录制 20 秒。如有必要，它会无限期等待第一条服务器消息。

要启动服务器：

```bash
$ rpicam-vid -n -t 20s --camera 0 --codec libav -o server.mp4 --sync server
```

这也会从到达同步点并开始录制时起运行 20 秒。使用默认同步设置（30fps 下 100 帧）时，这意味着客户端有略多于 3 秒的时间来完成同步。

服务器的广播地址和端口、时序消息的频率以及等待客户端同步的帧数，都可以在摄像头调整文件中更改。客户端只关注这里的广播地址，该地址应与服务器匹配；其他信息将被忽略。有关更多信息，请参阅[树莓派摄像头调整指南](https://pip.raspberrypi.com/documents/RP-009070-TC)。

在实际操作中，还有最后几点需要注意：

* 固定帧率需要低于摄像头（在所使用的摄像头模式下）能够运行的最大帧率。这是因为同步算法可能需要 *缩短* 摄像头帧，以便客户端赶上服务器；如果摄像头已经以最快速度运行，这将失败。
* 虽然摄像头帧应该正确同步，但在较高帧率下或取决于系统负载，客户端或服务器上的帧可能会丢失。在这些情况下，帧时间戳可以帮助应用程序判断发生了什么，不过通常更简单的做法是尽量避免丢帧，例如降低帧率、增加分配给摄像头队列的缓冲区数量（参见 `--buffer-count` 选项），或降低系统负载。

### 安装 libcamera 和 rpicam-apps

树莓派提供了两种 `rpicam-apps` 包：

* `rpicam-apps` 包含完整的应用程序，支持使用桌面环境进行预览。此软件包已预装在树莓派系统中。
* `rpicam-apps-lite` 不支持桌面环境，仅提供 DRM 预览。此软件包已预装在精简版树莓派系统中。

#### 依赖关系

`rpicam-apps` 依赖于名为 `library-name<n>` 的库包，其中 `<n>` 是 ABI 版本。你的软件包管理器应会自动安装这些包。

#### 开发包

你可以重新构建 `rpicam-apps`，而无需从头开始构建 `libcamera` 和 `libepoxy`。有关更多信息，请参阅[在不重新构建 `libcamera` 的情况下构建 `rpicam-apps`](#构建-rpicam-apps-而不构建-libcamera)。

## 使用 `rpicam-apps` 在网络上进行视频流传输

本节介绍如何使用 `rpicam-vid` 通过网络流式传输视频。虽然不使用 `libav` 也可以传输非常简单的格式，但对于大多数应用，我们建议使用 `libav` 后端。

### UDP

使用以下命令在作为服务器的树莓派上通过 UDP 流式传输视频，把占位符 `<IP地址>` 换成客户端的 IP 地址（或组播地址），并把占位符 `<端口>` 换成你想要用于流式传输的端口：

```bash
$ rpicam-vid -t 0 -n --inline -o udp://<IP地址>:<端口>
```

使用以下命令在作为客户端的树莓派上查看通过 UDP 流式传输的视频，把占位符 `<端口>` 换成你想要从中流式传输的端口：

```bash
$ ffplay udp://@:<端口> -fflags nobuffer -flags low_delay -framedrop
```

如前所述，`vlc` 不再能处理未封装的 H.264 流。

事实上，对未封装 H.264 的支持通常很差，因此通常最好发送 MPEG-2 传输流。使用 `libav` 可以这样实现：

```bash
$ rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o udp://<IP地址>:<端口>
```

在这种情况下，我们也可以使用 `vlc` 成功播放该流：

```bash
$ vlc udp://@:<端口>
```

### TCP

你还可以通过 TCP 进行视频流传输。和之前一样，我们可以在网络上发送未封装的 H.264 流。要将树莓派用作服务器：

```bash
$ rpicam-vid -t 0 -n --inline --listen -o tcp://0.0.0.0:<端口>
```

使用以下命令在作为客户端的树莓派上查看通过 TCP 流式传输的视频，假设服务器以每秒 30 帧运行：

```bash
$ ffplay tcp://<服务器IP>:<端口> -vf "setpts=N/30" -fflags nobuffer -flags low_delay -framedrop
```

但与 UDP 示例一样，发送 MPEG-2 传输流往往更合适，因为它得到的支持更广泛。为此，请使用：

```bash
$ rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o tcp://0.0.0.0:<端口>?listen=1
```

现在，我们可以使用包括 `vlc` 在内的多种媒体播放器来播放：

```bash
$ vlc tcp://<服务器IP>:<端口>
```

### RTSP

我们可以将 VLC 用作 RTSP 服务器，但必须向它发送 MPEG-2 传输流，因为它不再能处理未封装的 H.264：

```bash
$ rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o - | cvlc stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/stream1}'
```

使用以下命令在作为客户端的树莓派上查看通过 RTSP 流式传输的视频：

```bash
$ ffplay rtsp://<服务器IP>:8554/stream1 -fflags nobuffer -flags low_delay -framedrop
```

或者，在客户端使用以下命令通过 VLC 播放：

```bash
$ vlc rtsp://<服务器IP>:8554/stream1
```

如果你想在服务器上看到预览窗口，只需去掉 `-n` 选项（参见 `nopreview`）。

### `libav` 和音频

我们已经在使用 `libav` 作为网络流传输的后端。`libav` 允许我们添加音频流，前提是使用的格式允许音频数据，例如 MPEG-2 传输流。

我们可以取用之前的某个命令，例如通过 TCP 流式传输 MPEG-2 传输流的命令，然后简单地添加 `--libav-audio` 选项：

```bash
$ rpicam-vid -t 0 --codec libav --libav-format mpegts --libav-audio -o "tcp://<IP地址>:<端口>?listen=1"
```

你可以使用类似的命令通过 UDP 进行流式传输：

```bash
$ rpicam-vid -t 0 --codec libav --libav-format mpegts --libav-audio  -o "udp://<IP地址>:<端口>"
```

### GStreamer

[GStreamer](https://gstreamer.freedesktop.org/) 是用于读取、处理和播放多媒体文件的 Linux 框架。我们还可以将其与 `rpicam-vid` 结合使用，进行网络流传输。

此设置使用 `rpicam-vid` 将 H.264 比特流输出到标准输出，不过正如我们之前所做的，我们会将其封装在 MPEG-2 传输流中，以获得更好的下游兼容性。

然后，我们使用 GStreamer `fdsrc` 元素接收比特流，并使用额外的 GStreamer 元素将其发送到网络上。在服务器上，运行以下命令以启动流，把占位符 `<IP地址>` 换成客户端的 IP 地址（或组播地址），并把占位符 `<端口>` 换成用于流式传输的端口：

```bash
$ rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o - | gst-launch-1.0 fdsrc fd=0 ! udpsink host=<IP地址> port=<端口>
```

你可以使用任何客户端（例如 VLC）；最适合播放的 GStreamer 客户端超出了本文档的范围。不过，以下管道（替换相应占位符）可在树莓派 4B 或更早的设备上运行：

```bash
$ gst-launch-1.0 udpsrc address=<IP地址> port=<端口> ! tsparse ! tsdemux ! h264parse ! queue ! v4l2h264dec ! autovideosink
```

对于树莓派 5 设备，请将 `v4l2h264dec` 替换为 `avdec_h264`。

> **技巧**
>
> 要测试此配置，请在同一设备的不同终端上运行服务器和客户端命令，使用 `localhost` 作为地址。

#### `libcamerasrc` GStreamer 元素

`libcamera` 提供了一个 `libcamerasrc` GStreamer 元素，可以直接替代 `rpicam-vid`。要使用此元素，请在服务器上运行以下命令，把占位符 `<IP地址>` 换成客户端的 IP 地址（或组播地址），并把占位符 `<端口>` 换为你希望用于流式传输的端口。在树莓派 4B 或更早的设备上，请使用：

```bash
$ gst-launch-1.0 libcamerasrc ! capsfilter caps=video/x-raw,width=640,height=360,format=NV12,interlace-mode=progressive ! v4l2h264enc extra-controls="controls,repeat_sequence_header=1" ! 'video/x-h264,level=(string)4' ! h264parse ! mpegtsmux ! udpsink host=<IP地址> port=<端口>
```

在树莓派 5 设备上，请将 `v4l2h264enc extra-controls="controls,repeat_sequence_header=1"` 替换为 `x264enc speed-preset=1 threads=1`。

在客户端上，我们可以使用上面相同的播放管道，或其他流媒体播放器。

### 第三方流媒体服务器

有许多可用的第三方流媒体服务器，虽然树莓派并不特别推荐其中某一个，但我们会为一些流行的服务器提供入门指导。

* [MediaMTX](#使用-mediamtx-流式传输)
* [MistServer](#使用-mistserver-流式传输)
* [go2rtc](#使用-go2rtc-流式传输)

所有这些流媒体服务器都可以接收由 `rpicam-vid` 创建的树莓派摄像头流，并将其重新传输给 RTSP 客户端、使用 WebRTC 的 Web 浏览器，或使用许多其他格式。MediaMTX 通过 `libcamera` 将树莓派摄像头作为原生选项支持，无需外部可执行文件（如 `rpicam-vid`）。

上面的列表并不详尽；不过，我们已经确认这些应用程序可以与树莓派摄像头系统正常配合工作。

#### 使用 MediaMTX 流式传输

[MediaMTX](https://github.com/bluenviron/mediamtx) 接受来自树莓派设备摄像头系统的输入流（例如由 `rpicam-vid` 创建的流），并将其重新传输给其他客户端。此外，它还支持将树莓派摄像头作为内置源。

**安装与配置**

要安装 MediaMTX：

1. 从[发布页面](https://github.com/bluenviron/mediamtx/releases)下载最新版本。
   * 如果你使用 64 位树莓派系统，请选择 `linux_arm64` 压缩 tar 文件（以 `.tar.gz` 结尾）。
   * 如果你使用 32 位树莓派系统，请选择 `armv7` 压缩 tar 文件。
2. 运行命令 `tar -xvzf <文件名.tar.gz>` 解压压缩 tar 文件。该文件包含一个 `mediamtx` 可执行文件和一个名为 `mediamtx.yml` 的配置文件。
3. 备份原始的 `mediamtx.yml` 文件（推荐）。例如，你可以运行 `cp mediamtx.yml mediamtx.yml.original`。我们推荐这样做，因为原始文件记录了许多树莓派摄像头选项，你可能以后想要探索，保留副本可供参考。

**添加摄像头流**

要流式传输摄像头，请将 `mediamtx.yml` 的内容替换为：

```yaml
paths:
  cam:
    source: rpiCamera
```

参数 `source: rpiCamera` 告诉 MediaMTX 自行启动和控制树莓派摄像头系统。

在命令提示符下输入 `mediamtx` 可执行文件的名称来启动它，必要时提供完整路径。

如果你希望 MediaMTX 仅在请求流时获取摄像头，请将以下行添加到更新后的 `mediamtx.yml` 中：

```yaml
    sourceOnDemand: yes
```

查阅原始的 `mediamtx.yml`，了解可用于选择图像尺寸、摄像头模式、比特率等的其他配置参数。在文件中搜索 `rpi` 可找到相关设置。

或者，你可以将 `mediamtx.yml` 按如下设置，在 MediaMTX 外部运行 `rpicam-vid`：

```yaml
paths:
  cam:
    source: udp://127.0.0.1:1234
```

你可以运行任何外部程序向此地址输出 MPEG-TS 流。对于 `rpicam-vid`，命令可能如下所示：

```bash
$ rpicam-vid -t 0 -n --codec libav --low-latency --libav-format mpegts -o udp://127.0.0.1:1234?pkt_size=1316
```

> **注意**
>
> 这提供了以某种方式修改图像的机会，例如使用 `rpicam-apps` 的后处理功能或 `Picamera2` Python 模块。`--low-latency` 选项会抑制 B 帧（在树莓派 5 及更高版本上；更早的树莓派设备不会生成 B 帧），这通常是明智的，因为客户端请求的某些流格式不支持 B 帧。

**使用客户端查看**

你可以在媒体播放器或 Web 浏览器中查看流。以下示例假设流名称为“cam”：

* 要使用支持 RTSP 协议的媒体播放器应用程序查看流，请使用地址 `rtsp://<MediaMTX服务器IP地址>:8554/cam`。
* 要在 Web 浏览器中查看流，请使用地址 `http://<MediaMTX服务器IP地址>:8889/cam`。

**故障排除**

视频流偶尔暂停可能是由于树莓派上的 UDP 接收缓冲区空间不足造成的。如果缓冲区太小，数据可能会被丢弃，导致可见的暂停。要永久增大这些缓冲区，请创建一个名为 `/etc/sysctl.d/99-network-tuning.conf` 的文件，其中包含以下行：

```bash
net.core.rmem_default=1000000
net.core.rmem_max=1000000
```

重启，或运行 `sudo sysctl -p /etc/sysctl.d/99-network-tuning.conf`。

在树莓派系统 Bookworm 上，你必须将这些行添加到 `/etc/sysctl.conf`（然后重启或运行 `sudo sysctl -p`）。

有关 MediaMTX 及其功能的更多信息，请参阅 [MediaMTX 文档](https://mediamtx.org/docs/kickoff/introduction)。

#### 使用 MistServer 流式传输

[MistServer](https://mistserver.org/) 是一款流行的免费媒体服务器，可以与树莓派摄像头系统结合使用。与 MediaMTX 不同，它没有内置的摄像头支持；不过，你可以配置 MistServer 接收来自 `rpicam-vid` 的流，并以多种格式将其提供给客户端。

**安装与配置**

你可以按照 MistServer 文档中的说明在树莓派上安装 MistServer：

* 对于 64 位操作系统，请遵循 [Armv8 64 位 Linux](https://docs.mistserver.org/mistserver/installation/linux#armv8-64-bits-linux) 中的说明。
* 对于 32 位操作系统，请遵循 [Armv7 Linux](https://docs.mistserver.org/mistserver/installation/linux/#armv7-linux) 中的说明。

确保以 root 身份运行命令。此过程会设置一个随系统自动运行的 MistServer 服务。

要配置 MistServer，请访问树莓派上的管理界面（MI）网页，地址为 `http://localhost:4242/`；如果你替换为树莓派的 IP 地址，也可以从另一台计算机访问该页面。首次使用管理界面时，它会要求你创建一个管理员账户。在后续步骤中，你可以接受默认值。

> **注意**
>
> 你也可以在与带有摄像头的树莓派不同的计算机上运行 MistServer。

**添加摄像头流**

要添加摄像头流，请转到 **管理界面** 网页并完成以下步骤：

1. 在左侧窗格中，选择 **Streams**。
2. 在右侧窗格中，选择 **Create Stream**。
3. 填写所需信息：

   * 流名称，例如“cam”。客户端通过此名称识别该流。
   * 源。要配置 MistServer 自动启动 `rpicam-vid`，请输入以下命令：

   ```bash
   $ ts-exec: rpicam-vid -n -t 0 --width 1920 --height 1080 --codec libav --libav-format mpegts -o -
   ```

   此命令中的参数配置如下：

   * `ts-exec` 将命令配置为向 `stdout` 输出 MPEG-TS 流。此外，该前缀要求 MistServer 运行在带有摄像头的树莓派上。
   * `rpicam-vid` 是视频命令。
   * `-n` 配置为不显示预览。
   * `-t` 将命令配置为无限期运行。
   * `--width` 和 `--height` 指定你选择的尺寸。

   或者，如果你在外部运行 `rpicam-vid` 并输出到 UDP 套接字，请使用 `tsudp` 代替 `ts-exec`，并在其后跟上传入流的 IP 地址。

**使用客户端查看**

你可以在媒体播放器或 Web 浏览器中查看流。以下示例假设流名称为“cam”：

* 要使用支持 RTSP 协议的媒体播放器应用程序查看流，请使用地址：`rtsp://<MistServer服务器IP地址>:8554/cam`。
* 要在网页中查看流，请使用 MistServer 内置的媒体播放器页面。在 Web 浏览器中，输入：`http://<MistServer服务器IP地址>:8080/cam.html`。

有关 MistServer 用例和选项的更多信息，请参阅 [MistServer 文档](https://docs.mistserver.org/)。

#### 使用 go2rtc 流式传输

[go2rtc](https://github.com/AlexxIT/go2rtc) 是一个媒体服务器平台，虽然不提供像 MediaMTX 那样的直接集成，但可以像 MistServer 一样进行互操作。

**安装与配置**

要安装 go2rtc：

1. 从[发布页面](https://github.com/AlexxIT/go2rtc/releases/)下载二进制文件：
   * 如果你运行 64 位操作系统，请选择 `go2rtc_linux_arm64` 二进制文件。
   * 如果你运行 32 位操作系统，请选择 `go2rtc_linux_arm` 二进制文件。
   * 如果你的设备是树莓派 1 或 Zero，请选择 `go2rtc_linux_armv6` 二进制文件。
2. 更改文件权限，使下载的二进制文件可执行。
3. 运行二进制文件。

你可以使用默认配置运行此应用程序。go2rtc 运行时，管理页面位于 `http://localhost:1984/`。

> **注意**
>
> 与 MediaMTX 一样，你可以在与带有摄像头的树莓派不同的系统上运行 go2rtc。

**添加摄像头流**

你可以通过创建一个 `go2rtc.yaml` 文件（放在运行可执行文件的文件夹中）来添加摄像头流。go2rtc 启动时，会向控制台输出一条消息，指示它期望在何处查找配置文件。

将以下文本添加到文件中，替换为你所需的宽度和高度：

```yaml
streams:
  cam:
    - exec:rpicam-vid -n -t 0 --width 1280 --height 720 --codec libav --libav-format mpegts --low-latency -o -
```

此配置会在任何客户端请求“cam”流时启动 `rpicam-vid`。参数 `--low-latency` 会在树莓派 5 或更高型号上抑制 B 帧。在这种情况下，go2rtc 必须运行在带有摄像头的树莓派上。

或者，你可以在外部运行 `rpicam-vid`，并让它向该地址输出 MPEG-TS 流，例如 `udp://127.0.0.1:1234`。要配置此方式，请确保 `go2rtc.yaml` 文件包含以下文本：

```yaml
  cam:
    - ffmpeg:udp://127.0.0.1:1234
```

如果 go2rtc 运行在与摄像头不同的计算机上，请调整 IP 地址。

**使用客户端查看**

要使用支持 RTSP 协议的媒体播放器应用程序查看流，并假设流名称为“cam”，请使用地址：`rtsp://<go2rtc服务器IP地址>:8554/cam`。

要在网页中查看流，请使用 go2rtc 的内置页面。输入 `http://<go2rtc服务器IP地址>:1984/stream.html?src=cam`。

有关 go2rtc 用例和选项的更多信息，请参阅 [go2rtc README 文档](https://github.com/AlexxIT/go2rtc/blob/master/README.md)。

## `rpicam-apps` 参数参考

### 常见参数

以下参数适用于所有语义相似或相同的 `rpicam-apps`，除非另有说明。

要将以下某个参数传给应用程序，请在参数名称前加上 `--`。如果参数需要一个值，请紧跟在参数名称后传入该值，并用单个空格分隔。如果值包含空格，请用引号括起来。

一些参数具有速记别名，例如 `-h` 可代替 `--help`。请使用这些速记别名代替完整的参数名称，以节省空间和时间，但可读性会有所降低。

#### `help`

别名： `-h`

打印完整的参数集，以及每个参数的简要概述。不接受值。

#### `version`

以字符串打印出 `libcamera` 和 `rpicam-apps` 的版本。不接受值。

示例输出：

```
rpicam-apps build: ca559f46a97a 27-09-2021 (14:10:24)
libcamera build: v0.0.0+3058-c29143f7
```

#### `list-cameras`

列出检测到的、连接到你的树莓派的摄像头及其可用的传感器模式。不接受值。

传感器模式标识符具有以下形式：`S<Bayer order><Bit-depth>_<Optional packing> : <Resolution list>`

即使在像素合并模式下，裁剪区域也以传感器原生像素为单位指定，格式为 `(<x>, <y>)/<宽>×<高>`。`(x, y)` 指定了传感器阵列中尺寸为宽 × 高的裁剪窗口的位置。

例如，以下输出显示有关索引为 0 处的 IMX219 传感器和索引为 1 处的 IMX477 传感器的信息：

```
Available cameras
-----------------
0 : imx219 [3280x2464] (/base/soc/i2c0mux/i2c@1/imx219@10)
    Modes: 'SRGGB10_CSI2P' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                             1640x1232 [41.85 fps - (0, 0)/3280x2464 crop]
                             1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                             3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]
           'SRGGB8' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                      1640x1232 [41.85 fps - (0, 0)/3280x2464 crop]
                      1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                      3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]
1 : imx477 [4056x3040] (/base/soc/i2c0mux/i2c@1/imx477@1a)
    Modes: 'SRGGB10_CSI2P' : 1332x990 [120.05 fps - (696, 528)/2664x1980 crop]
           'SRGGB12_CSI2P' : 2028x1080 [50.03 fps - (0, 440)/4056x2160 crop]
                             2028x1520 [40.01 fps - (0, 0)/4056x3040 crop]
                             4056x3040 [10.00 fps - (0, 0)/4056x3040 crop]
```

对于上述示例中的 IMX219 传感器：

* 所有模式都具有 RGGB Bayer 排序
* 所有模式在所列分辨率上提供 8 位或 10 位 CSI2 打包读出

#### `camera`

选择要使用的摄像头。请指定可用摄像头列表中的索引。

#### `config`

别名： `-c`

指定包含命令行参数和值的文件。设想一个名为 `example_configuration.txt` 的文件，其中包含以下文本，将参数和值指定为键值对，每行一个参数，只使用长（非别名）参数名称：

```sh
timeout=99000
verbose=
```

> **技巧**
>
> 省略通常会在命令行上传入的开头 `--`。对于缺少值的标志，例如上面示例中的 `verbose`，必须包含尾随 `=`。

然后，你可以运行以下命令来指定超时时间为 99000 毫秒并输出详细信息：

```bash
$ rpicam-hello --config example_configuration.txt
```

#### `timeout`

别名： `-t`

默认值：5000 毫秒（5 秒）

指定应用程序在关闭之前运行的时间长度。除非使用可选后缀更改单位，否则该值按毫秒解释。后缀可以是以下之一：

* `min`：分钟
* `s` 或 `sec`：秒
* `ms`：毫秒（未使用后缀时的默认值）
* `us`：微秒
* `ns`：纳秒。

此时间适用于视频录制和预览窗口。拍摄静态图像时，应用程序会先显示一段由 `timeout` 参数指定时长的预览窗口，然后再捕获输出图像。

要无限期运行应用程序，请指定值 `0`。也允许使用浮点值。

示例：`rpicam-hello -t 0.5min` 将运行 30 秒。

#### `preview`

别名： `-p`

设置桌面或 DRM 预览窗口的位置（x,y 坐标）和大小（w,h 尺寸）。不影响从摄像头请求的图像的分辨率或宽高比。会缩放图像大小，并对图像宽高比做加黑边或填充处理，使其适应预览窗口。

以以下逗号分隔的格式传入预览窗口尺寸：`x,y,w,h`

示例： `rpicam-hello --preview 100,100,500,500`

![Letterboxed 预览图像](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-331358d3855a18e59cf1489d9cc7166a6b25b028%2Fpreview_window.jpg?alt=media)

#### `fullscreen`

别名： `-f`

强制预览窗口使用整个屏幕，无边框或标题栏。会缩放图像大小，并对图像宽高比做加黑边或填充处理，使其适应整个屏幕。不接受值。

#### `qt-preview`

使用 Qt 预览窗口，消耗的资源比其他选项多，但支持 X 窗口转发。与 `fullscreen` 选项不兼容。不接受值。

#### `preview-backend`

强制使用特定的预览后端：`wayland-egl`、`egl`、`drm` 或 `qt`。如果未指定，应用程序会自动选择后端，在 Wayland 桌面会话中优先使用原生 Wayland（`wayland-egl`）预览。

示例：`rpicam-hello --preview-backend wayland-egl`

#### `nopreview`

别名： `-n`

使应用程序不显示预览窗口。不接受值。

#### `info-text`

默认值：`"#%frame (%fps fps) exp %exp ag %ag dg %dg"`

将提供的字符串设置为在桌面环境中运行时预览窗口的标题。支持以下图像元数据替换：

|     指令     | 替换内容                                              |
| :--------: | ------------------------------------------------- |
|  `%frame`  | 帧的序列号。                                            |
|   `%fps`   | 瞬时帧速率。                                            |
|   `%exp`   | 用于捕捉图像的快门速度，单位为微秒。                                |
|    `%ag`   | 在传感器中应用的模拟增益。                                     |
|    `%dg`   | 由 ISP 应用于图像的数字增益。                                 |
|    `%rg`   | 应用于每个像素的红色分量的增益。                                  |
|    `%bg`   | 应用于每个像素的蓝色分量的增益。                                  |
|  `%focus`  | 图像的焦点度量，较大的值表示图像更清晰。                              |
|    `%lp`   | 以屈光度表示的当前镜头位置（1 / 米数）。                            |
| `%afstate` | 自动对焦算法状态（`idle`、`scanning`、`focused` 或 `failed`）。 |

![Image showing focus measure](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-e00586047e446ca7d1c6f638d567da812ceb1a60%2Ffocus.jpg?alt=media)

#### `width` 和 `height`

每个都接受一个数字，用于定义所捕获图像的尺寸（单位为像素）。

对于 `rpicam-still`，`rpicam-jpeg` 和 `rpicam-vid`，指定输出分辨率。

对于 `rpicam-raw`，指定原始帧分辨率。对于具有 2×2 像素合并读出模式的摄像头，指定等于或小于合并模式的分辨率，将捕获 2×2 合并的原始帧。

对 `rpicam-hello` 无效。

示例：

* `rpicam-vid -o test.h264 --width 1920 --height 1080` 拍摄 1080p 视频。
* `rpicam-still -r -o test.jpg --width 2028 --height 1520` 拍摄 2028×1520 分辨率的 JPEG。如果与 HQ 摄像头一起使用，则使用 2×2 像素合并模式，因此原始文件（`test.dng`）包含 2028×1520 的原始 Bayer 图像。

#### `viewfinder-width` 和 `viewfinder-height`

每个都接受一个数字，用于定义预览窗口中显示图像的尺寸（单位为像素）。不影响预览窗口尺寸，因为图像会被调整大小以适应。不影响捕获的静止图像或视频。

#### `mode`

能让你用以下以冒号分隔的格式指定摄像头模式：`<宽>:<高>:<位深度>:<打包参数>`。如果提供的值没有完全匹配项，系统会为该传感器选择最接近的可用选项。你可以使用打包（`P`）或未打包（`U`）格式。影响存储的视频和静止图像的格式，但不影响传递给预览窗口的帧的格式。

位深度和打包是可选的。位深度默认为 `12`。打包默认为 `P`（打包）。

有关传感器可用的位深度、分辨率和打包参数的信息，请参阅 `list-cameras`。

示例：

* `4056:3040:12:P` - 4056×3040 分辨率，每像素 12 位，打包。
* `1632:1224:10` - 1632×1224 分辨率，每像素 10 位。
* `2592:1944:10:U` - 2592×1944 分辨率，每像素 10 位，未打包。
* `3264:2448` - 3264×2448 分辨率。

或者，按照 `list-cameras` 显示的模式列表中的索引指定相机模式，从 0 开始按列出顺序计数，格式为 `<索引>` 或 `<索引>:<打包参数>`。打包默认为 `P`（打包）。

示例：

* `1` - 列表中的第二个模式。
* `0:U` - 列表中的第一个模式，未打包。

**打包格式详细信息**

打包格式使用更少的存储空间来存储像素数据。

在树莓派 4 和早期设备上，打包格式使用 MIPI CSI-2 标准来打包像素。这意味着：

* 10 位相机模式将 4 个像素打包成 5 个字节。前 4 个字节包含每个像素的 8 个最高有效位（MSB），最后一个字节包含 4 对最低有效位（LSB）。
* 12 位相机模式将 2 个像素打包成 3 个字节。前 2 个字节包含每个像素的 8 个最高有效位（MSB），最后一个字节包含两个像素的 4 个最低有效位（LSB）。

在树莓派 5 及更高版本设备上，打包格式使用视觉无损压缩方案将像素值压缩为每像素 8 位（1 B）。

**未打包格式详细信息**

未打包格式提供的像素值更容易手动操作，但会以使用更多存储空间来存储像素数据为代价。

在所有设备上，未打包格式每像素使用 2 字节。

在树莓派 4 及旧款设备上，应用程序在最高有效端应用零填充。在未打包格式中，来自 10 位相机模式的像素不能超过值 `1023`。

在树莓派 5 和更新设备上，应用程序在最低有效端应用零填充，因此图像使用传感器提供的像素深度的完整 16 位动态范围。

#### `viewfinder-mode`

与 `mode` 参数相同，但它适用于传递给预览窗口的数据。有关更多信息，请参阅 `mode` 文档。

#### `lores-width` 和 `lores-height`

从摄像头传送第二个分辨率较低的图像流，并缩小到指定的尺寸。

每个都接受一个数字，用于定义低分辨率流的尺寸（单位为像素）。

可用于预览和视频模式。不适用于静态捕获。如果你指定与正常分辨率流不同的宽高比，则会生成非方形像素。

对于 `rpicam-vid`，可禁用额外的色彩去噪处理。

与图像后处理结合使用时，用于图像分析。

#### `hflip`

水平翻转图像。不接受值。

#### `vflip`

垂直翻转图像。不接受值。

#### `rotation`

旋转从传感器提取的图像。仅接受值 `0` 或 `180`。

#### `roi`

从传感器的整个视场中裁剪图像。接受四个小数值，范围为 0 到 1，格式如下：`<x>,<y>,<宽>,<高>`。每个值都是介于 `0` 和 `1` 之间的小数，表示可用宽度或高度的百分比。

这些值定义了以下比例：

* `<x>`：提取图像前要跳过的 X 坐标
* `<y>`：提取图像前要跳过的 Y 坐标
* `<宽>`：要提取的图像宽度
* `<高>`：要提取的图像高度

默认为 `0,0,1,1`（从第一个 X 坐标和第一个 Y 坐标开始，使用 100% 的图像宽度和 100% 的图像高度）。

示例：

* `rpicam-hello --roi 0.25,0.25,0.5,0.5` 从图像中心裁剪出总像素数量的一半（跳过前 25% 的 X 坐标，跳过前 25% 的 Y 坐标，使用总图像宽度的 50%，使用总图像高度的 50%）。
* `rpicam-hello --roi 0,0,0.25,0.25` 选择从图像左上角裁剪的像素总数的四分之一（跳过前 0% 的 X 坐标，跳过前 0% 的 Y 坐标，使用图像宽度的 25%，使用图像高度的 25%）。

#### `hdr`

默认值：`off`

以 HDR 模式运行摄像头。如果未传入值，则假定为 `auto`。接受以下值之一：

* `off` - 禁用 HDR。
* `auto` - 在支持的设备上启用 HDR。如果可用，使用传感器的内置 HDR 模式。如果传感器缺乏内置 HDR 模式，则使用板载 HDR 模式（如果可用）。
* `single-exp` - 使用板载 HDR 模式（如果可用），即使传感器具有内置 HDR 模式。如果板载 HDR 模式不可用，则禁用 HDR。

树莓派 5 及更高版本设备内置了 HDR 模式。

要检查传感器中的内置 HDR 模式，请在 `list-cameras` 之外一并传入此参数。

### 摄像头控制参数

以下参数控制图像处理以及影响摄像头图像质量的算法。

#### `sharpness`

设置图像锐度。接受以下范围内的数值：

* `0.0` 不应用锐化。
* 大于 `0.0` 但小于 `1.0` 的值，应用的锐化量少于默认值
* `1.0` 应用默认锐化量
* 大于 `1.0` 的值应用额外的锐化

#### `contrast`

指定图像对比度。接受以下范围内的数值。

* `0.0` 应用最小对比度
* 大于 `0.0` 但小于 `1.0` 的值，应用的对比度小于默认值。
* `1.0` 应用默认对比度
* 大于 `1.0` 的值会应用额外对比度

#### `brightness`

指定图像亮度，以偏移量的形式加到输出图像的所有像素上。接受以下范围内的数值。

* `-1.0` 应用最低亮度（黑色）
* `0.0` 应用标准亮度
* `1.0` 应用最大亮度（白色）

对于许多用例，建议改用 `ev`。

#### `saturation`

指定图像的颜色饱和度。接受以下范围内的数值：

* `0.0` 应用最小饱和度（灰度）
* 大于 `0.0` 但小于 `1.0` 的值，应用的饱和度小于默认值
* `1.0` 应用默认饱和度
* 大于 `1.0` 的值应用额外饱和度

#### `ev`

指定图像的曝光值（EV）补偿，以档为单位。接受一个数值，用于控制传递给自动曝光/增益控制（AEC/AGC）处理算法的目标值，范围为：

* `-10.0` 应用最小目标值
* `0.0` 应用标准目标值
* `10.0` 应用最大目标值

#### `shutter`

使用快门指定曝光时间（以微秒为单位）。使用此参数时，增益仍可能变化。如果摄像头运行的帧率过高，不允许指定的曝光时间（例如，帧率为 1fps，曝光时间为 10000 微秒），则传感器将使用帧率允许的最大曝光时间。

有关官方摄像头的最小和最大快门时间列表，请参阅[摄像头硬件文档](/pei-jian/she-xiang-tou.md)。超过最大值的数值会导致未定义行为。

#### `gain`

别名： `--analoggain`

设置组合的模拟和数字增益。当传感器驱动程序可以提供请求的增益时，仅使用模拟增益。当模拟增益达到最大值时，ISP 应用数字增益。接受数值。

对于官方摄像头的模拟增益限制列表，请参阅[摄像头硬件文档](/pei-jian/she-xiang-tou.md)。

有时，即使没有超过模拟增益限制，数字增益也可能超过 1.0。这可能发生在以下情况下：

* 任一颜色增益低于 1.0，这会使数字增益稳定为 `1.0/min(red_gain,blue_gain)`。这样可保持应用于所有颜色通道的总数字增益高于 1.0，以避免出现变色伪影。
* 在自动曝光/增益控制（AEC/AGC）变化期间出现轻微波动。

#### `metering`

默认值：`centre`

设置自动曝光/增益控制（AEC/AGC）算法的测光模式。接受以下数值：

* `centre` - 中央加权测光
* `spot` - 点测光
* `average` - 平均或整体测光
* `custom` - 摄像头调整文件中定义的自定义测光模式

有关定义自定义测光模式以及调整现有测光模式区域权重的更多信息，请参阅[树莓派摄像头和 libcamera 调整指南](https://pip.raspberrypi.com/documents/RP-009070-TC)。

#### `exposure`

设置曝光配置。更改曝光配置不应影响图像曝光。相反，不同模式会调整增益设置，以达到相同的整体效果。接受以下值：

* `sport`：短曝光，更大增益
* `normal`：正常曝光，正常增益
* `long`：长曝光，较小增益

你可以使用调整文件编辑曝光配置。有关更多信息，请参阅[树莓派摄像头和 libcamera 调整指南](https://pip.raspberrypi.com/documents/RP-009070-TC)。

#### `awb`

设置自动白平衡（AWB）模式。接受以下数值：

|      模式名称      |       色温范围      |
| :------------: | :-------------: |
|     `auto`     |  2500K 到 8000K  |
| `incandescent` |  2500K 到 3000K  |
|   `tungsten`   |  3000K 到 3500K  |
|  `fluorescent` |  4000K 到 4700K  |
|    `indoor`    |  3000K 到 5000K  |
|   `daylight`   |  5500K 到 6500K  |
|    `cloudy`    |  7000K 到 8500K  |
|    `custom`    | 在调整文件中定义的自定义范围。 |

这些值仅为近似值：具体数值可能因摄像头调整而异。

没有任何模式能完全禁用 AWB。相反，你可以使用 `awbgains` 来固定颜色增益。

有关 AWB 模式的更多信息，包括如何定义自定义模式，请参阅[树莓派摄像头和 libcamera 调整指南](https://pip.raspberrypi.com/documents/RP-009070-TC)。

#### `awbgains`

设置固定的红色和蓝色增益值，以替代自动白平衡（AWB）算法。设置非零值以禁用 AWB。接受以逗号分隔的数字输入，格式如下： `<red_gain>,<blue_gain>`

#### `denoise`

默认值： `auto`

设置去噪模式。接受以下数值：

* `auto`：启用标准空间去噪。视频使用超快速色彩去噪，图像使用高质量色彩去噪。在预览窗口中不启用额外的色彩去噪。
* `off`：禁用空间去噪和色彩去噪。
* `cdn_off`：禁用色彩去噪。
* `cdn_fast`：使用快速色彩去噪。
* `cdn_hq`：使用高质量色彩去噪。由于吞吐量降低，不适合视频或取景器使用。

即使快速色彩去噪也会降低帧率。高质量色彩去噪会显著降低帧率。

#### `tuning-file`

指定相机调整文件。调整文件允许你控制图像处理的许多方面，包括自动曝光/增益控制（AEC/AGC）、自动白平衡（AWB）、颜色阴影校正、颜色处理、降噪等。接受调整文件路径作为输入。

有关调整文件的更多信息，请参阅[使用调整文件调整摄像头行为](#使用调整文件调整摄像头行为)。

#### `autofocus-mode`

默认值： `default`

指定自动对焦模式。接受以下值：

* `default`：除非 `lens-position` 或 `autofocus-on-capture` 将模式覆盖为手动，否则将摄像头置于连续自动对焦模式
* `manual`：除非使用 `lens-position` 手动配置，否则根本不移动镜头
* `auto`：仅当摄像头启动时，或在拍摄前同时使用了 `autofocus-on-capture` 时，镜头才会进行自动对焦扫描
* `continuous`：随着场景变化自动调整镜头位置

该参数仅适用于某些摄像头模块。

#### `autofocus-range`

默认值：`normal`

指定自动对焦范围。接受以下数值：

* `normal`：从相当近的地方对焦到无限远
* `macro`：仅对近距离物体进行对焦，包括摄像头支持的最近对焦距离
* `full`：对整个范围对焦，从最接近的物体到无限远

该参数仅适用于某些摄像头模块。

#### `autofocus-speed`

默认值： `normal`

指定自动对焦速度。接受以下值：

* `normal`：以正常速度改变镜头位置
* `fast`：快速改变镜头位置

该参数仅适用于某些摄像头模块。

#### `autofocus-window`

指定传感器整个视场内的自动对焦窗口。接受四个小数值，范围为 0 到 1，格式如下：`<x>,<y>,<宽>,<高>`。每个值都是介于 0 和 1 之间的小数，表示可用宽度或高度的百分比。

这些值定义了以下比例：

* `<x>`：应用自动对焦前要跳过的 X 坐标
* `<y>`：应用自动对焦前要跳过的 Y 坐标
* `<宽>`：自动对焦区域宽度
* `<高>`：自动对焦区域高度

默认值在水平和垂直两个方向上都使用输出图像的中间三分之一（占总图像面积的 1/9）。

示例：

* `rpicam-hello --autofocus-window 0.25,0.25,0.5,0.5` 选择从图像中心裁剪的像素总数的一半（跳过 X 坐标的前 25%，跳过 Y 坐标的前 25%，使用总图像宽度的 50%，使用总图像高度的 50%）。
* `rpicam-hello --autofocus-window 0,0,0.25,0.25` 选择从图像左上角裁剪的像素总数的四分之一（跳过 X 坐标的前 0%，跳过 Y 坐标的前 0%，使用图像宽度的 25%，使用图像高度的 25%）。

该参数仅适用于某些摄像头模块。

#### `lens-position`

默认值：`default`

将镜头移动到固定的对焦距离，通常以屈光度（以米为单位的距离的倒数）表示。接受以下数值范围：

* `0.0`：将镜头移动到“无穷远”位置
* 其他 `数值`：将镜头移动到 1/`数值` 的位置。例如，数值 `2.0` 将对焦在大约 0.5 米处
* `default`：将镜头移动到与镜头的超焦点位置相对应的默认位置

镜头校准并不完美，因此同一型号的不同摄像头模块可能会有所差异。

#### `verbose`

别名： `-v`

默认值： `1`

设置详细级别。接受以下值：

* `0`：无输出
* `1`：正常输出
* `2`：详细输出

### 输出文件参数

#### `output`

别名: `-o`

设置用于记录图像或视频的文件的名称。除了纯文本文件名外，还接受以下特殊值：

* `-`：写入标准输出。
* `udp://` （前缀）：用于 UDP 流媒体的网络地址。
* `tcp://` （前缀）：用于 TCP 流媒体的网络地址。
* 在文件名中包含指令 `%d` ，以将指令替换为递增的计数，每打开一个文件计数递增。该指令支持标准 C 格式指令修饰符。

示例：

* `rpicam-vid -t 100000 --segment 10000 -o chunk%04d.h264` 记录一个 100 秒的文件，每 10 秒划分一个段，每个文件包含一个递增的四位数计数器，前面补零：例如 chunk0001.h264，chunk0002.h264 等。
* `rpicam-vid -t 0 --inline -o udp://192.168.1.13:5000` 使用 UDP 在端口 5000 上将 H.264 视频流传输到网络地址 192.168.1.13。

#### `wrap`

为 `output %d` 指令使用的计数器设置最大值。计数器在达到此值后将重置为零。接受数值。

#### `flush`

在帧完成写入后立即将输出文件刷新到磁盘，而不是等待系统处理。不接受数值。

#### `post-process-file`

指定配置图像管道应用的后处理的 JSON 文件。这适用于相机图像在到达应用程序之前。这类似于旧版 raspicam“图像效果”。接受文件名路径作为输入。

后处理是一个广泛的主题，允许使用第三方软件如 OpenCV 和 TensorFlowLite 来分析和操作图像。有关更多信息，请参阅后处理。

### 图像参数

本节中指定的命令行参数仅适用于静态图像输出。

要将以下参数之一传参给应用程序，请在参数名称前加上 `--`。如果参数需要一个值，请在参数名称后立即传参该值，用单个空格分隔。如果值包含空格，请用引号括起来。

一些参数具有速记别名，例如 `-h` 而不是 `--help`。使用这些速记别名而不是完整的参数名称，以节省空间和时间，但牺牲可读性。

#### `quality`

别名： `-q`

默认值： `93`

设置 JPEG 质量。接受介于 `1` 和 `100` 之间的值。

#### `exif`

在 JPEG 输出文件中保存额外的 EXIF 标签。仅适用于 JPEG 输出。由于 libexif 库的限制，许多标签当前（错误地）格式化为 ASCII 并在终端中打印警告。

此参数是添加与相机设置相关的某些 EXIF 标签所必需的。你可以在使用 ExifTool 录制后将与相机设置无关的标签添加到输出 JPEG 中。

示例： `rpicam-still -o test.jpg --exif IDO0.Artist=Someone`

#### `timelapse`

按指定间隔记录图像。接受以毫秒为单位的间隔。将此设置与 timeout 结合使用，以随时间捕获重复图像。

你可以使用字符串格式设置为每个输出文件指定单独的文件名，例如 `--output test%d.jpg`。

示例： `rpicam-still -t 100000 -o test%d.jpg --timelapse 10000` 每隔 10 秒捕获一次图像，持续 100 秒。

#### `framestart`

配置输出文件名中作为 %d 访问的帧计数的起始值。接受整数起始值。

#### `datetime`

在输出文件名中使用当前日期和时间，格式为 `MMDDhhmmss.jpg`：

* `MM` = 2 位数字月份编号
* `DD` = 2 位数字的日期
* `hh` = 2 位数字的 24 小时小时数
* `mm` = 2 位数字的分钟数
* `ss` = 2 位数的第二个数字

不接受值。

#### `timestamp`

使用当前系统 Unix 时间作为输出文件名。不接受值。

#### `restart`

默认值： `0`

配置 JPEG 输出的重启标记间隔。JPEG 重启标记有助于限制对 JPEG 图像的损坏影响，并且还可以启用多线程 JPEG 编码和解码。接受整数值。

#### `immediate`

当应用程序运行时立即捕获图像。

#### `keypress`

在超时或按下 **回车键** 时捕获图像，以先发生者为准。按 x 键，然后按 **回车键** 可以退出而不捕获图像。此选项不接受值。

#### `signal`

在超时或收到 `SIGUSR1` 信号时捕获图像。使用 `SIGUSR2` 信号可以退出而不捕获图像。此选项不接受值。

#### `thumb`

默认值: `320:240:70`

使用以下格式配置缩略图的尺寸和质量: `<w:h:q>` (或 `none`，省略缩略图)。

#### `encoding`

别名: `-e`

默认值： `jpg`

设置要用于图像输出的编码器。接受以下值：

* `jpg` - JPEG
* `png` - PNG
* `bmp` - BMP
* `rgb` - 未压缩的 RGB 像素的二进制转储
* `yuv420` - 未压缩 YUV420 像素的二进制转储

此参数始终确定编码，覆盖传参给 `output` 的扩展名。

在使用参数 `datetime` 和 `timestamp` 时，此参数确定输出文件扩展名。

#### `raw`

别名： `-r`

除了输出图像外，还以 DNG 格式保存原始 Bayer 文件。将输出文件名扩展名替换为 `.dng`。你可以使用 dcraw 或 RawTherapee 等工具处理这些标准 DNG 文件。不接受值。

原始文件中的图像数据完全是从传感器输出的，未经 ISP 或其他处理。文件中保存的 EXIF 数据包括：

* 曝光时间
* 模拟增益（ISO 标记是模拟增益的 100 倍）
* 白平衡增益（它们是“拍摄中性”值的倒数）
* ISP 使用的颜色矩阵

#### `latest`

创建指向最近保存文件的符号链接。接受符号链接名称作为输入。

#### `autofocus-on-capture`

如果设置，会在捕获图像之前运行自动对焦循环。与以下 `autofocus_mode` 值交互：

* `default` 或 `manual`：仅运行捕获时自动对焦循环。
* `auto`：在预览窗口加载时运行额外的自动对焦循环。
* `continuous`：忽略此参数，而是在整个预览过程中持续对焦。

不需要值，但你可以传参 `1` 以启用，传参 `0` 以禁用。不传参值相当于传参 `1`。

仅受某些摄像头模块支持（例如树莓派摄像头模块 3）。

### 视频参数

本节中指定的命令行参数仅适用于视频输出。

要将以下参数之一传参给应用程序，请在参数名称前加上 `--`。如果参数需要值，请在参数名称后立即传参值，用单个空格分隔。如果值包含空格，请用引号括起来。

一些参数具有速记别名，例如 `-h` 而不是 `--help`。使用这些速记别名而不是完整的参数名称，以节省空间和时间，但牺牲可读性。

#### `quality`

别名： `-q`

默认值： `50`

接受介于 `1` 和 `100` 之间的 MJPEG 质量级别。仅适用于以 MJPEG 格式编码的视频。

#### `bitrate`

别名： `-b`

控制 H.264 编码器使用的目标比特率，单位为每秒比特数。仅适用于以 H.264 格式编码的视频。影响输出视频的大小。

示例： `rpicam-vid -b 10000000 --width 1920 --height 1080 -o test.h264`

#### `intra`

别名： `-g`

默认值： `60`

设置 H.264 比特流中 I 帧（intra frames）的频率。接受帧数。仅适用于以 H.264 格式编码的视频。

#### `profile`

设置 H.264 配置文件。接受以下数值：

* `baseline`
* `main`
* `high`

仅适用于以 H.264 格式编码的视频。

#### `level`

设置 H.264 级别。接受以下数值：

* `4`
* `4.1`
* `4.2`

仅适用于以 H.264 格式编码的视频。

#### `codec`

设置用于视频输出的编码器。接受以下值：

* `h264` - 使用 H.264 编码器（默认值）
* `mjpeg` - 使用 MJPEG 编码器
* `yuv420` - 输出未压缩的 YUV420 帧。
* `libav` - 使用 libav 后端来编码音频和视频（有关更多信息，请参见 libav ）

#### `save-pts`

> **警告**
>
> 树莓派 5 不支持参数 `save-pts` 。请改用 libav 自动生成时间戳以替代。

启用帧时间戳输出，允许你使用类似 mkvmerge 的工具将比特流转换为容器格式。接受时间戳输出文件的纯文本文件名。

示例： `rpicam-vid -o test.h264 --save-pts timestamps.txt`

你可以使用以下命令从比特流和时间戳文件生成一个 MKV 容器文件：

```
$ mkvmerge -o test.mkv --timecodes 0:timestamps.txt test.h264
```

#### `keypress`

别名： `-k`

允许 CLI 使用回车键启用和禁用视频输出。始终以录制状态启动，除非使用 `initial` 另行指定。键入 **x 键** 并按 **回车键** 退出。不接受值。

#### `signal`

别名： -s

允许 CLI 使用 `SIGUSR1` 启用和禁用视频输出。使用 `SIGUSR2` 退出。除非使用 initial 指定，始终以录制状态启动。不接受值。

#### `initial`

默认值： `record`

指定是否启动应用程序时启用或禁用视频输出。接受以下值：

* `record`：启用视频输出启动。
* `pause`：禁用视频输出启动。

使用此参数与 `keypress`/`signal` 一起，以在两种状态之间切换。

#### `split`

当使用 `keypress`、`signal` 切换录制时，将来自单独录制会话的视频输出写入单独的文件中。不接受值。除非与 output 结合使用以为每个文件指定唯一名称，否则每次写入文件时都会覆盖。

#### `segment`

将视频输出剪切成传参持续时间的多个文件。接受以毫秒为单位的持续时间。如果传参一个非常小的持续时间（例如，1 ），则将每帧记录到单独的输出文件中以模拟突发捕获。

你可以使用字符串格式化为每个文件指定单独的文件名，例如 `--output test%04d.h264`。

#### `circular`

默认值： `4`

将视频录制写入内存中的循环缓冲区。当应用程序退出时，将循环缓冲区记录到磁盘。可接受以 MB 为单位的可选大小。

#### `inline`

在每个 I 帧（帧内）中写入序列头。这可以帮助客户端从视频的任何点解码视频序列，而不仅仅是从开头。建议与 `segment`，`split`，`circular` 和流媒体参数一起使用。

仅适用于以 H.264 格式编码的视频。不接受值。

#### `listen`

在对视频进行编码之前等待传入的客户端连接。用于通过 TCP/IP 进行网络流式传输。不接受值。

#### `frames`

记录完全指定数量的帧。任何非零值都会覆盖 `timeout`。接受非零整数。

#### `framerate`

记录完全指定的帧速率。接受非零整数。

#### `low-latency`

在树莓派 5 上，`--low-latency` 参数可降低编码延迟，这对实时流媒体应用可能有利，但代价是编码效率会（略微）降低（例如，不再使用 B 帧和算术编码）。

#### `sync`

以软件同步模式运行摄像头，在此模式下多台摄像头会将帧同步到同一时刻。`sync` 模式可以设置为 `client` 或 `server`。有关更多信息，请参阅[软件同步的工作原理](#软件摄像头同步)。

### `libav` 参数

本节中指定的命令行参数仅适用于 `libav` 视频后端。

要启用 `libav` 后端，请传参 `codec` 参数值为 `libav`。

要将以下参数之一传参给应用程序，请在参数名称前加上 `--`。如果参数需要值，请在参数名称后立即传参值，用单个空格分隔。如果值包含空格，请用引号括起来。

一些参数具有速记别名，例如 `-h` 而不是 `--help`。使用这些速记别名而不是完整的参数名称，以节省空间和时间，但牺牲可读性。

#### `libav-format`

设置 libav 输出格式。接受以下值：

* `mkv` 编码
* `mp4` 编码
* `avi` 编码
* `h264` 流式传输
* `mpegts` 流式传输

如果你未提供此参数，则传参给 `output` 参数的文件扩展名将确定文件格式。

#### `libav-audio`

启用音频录制。启用后，你还必须指定 `audio-codec`。不接受值。

#### `audio-codec`

默认值： `aac`

选择用于输出的音频编解码器。要查看可用编解码器的列表，请运行 `ffmpeg -codecs`。

#### `audio-bitrate`

设置音频编码的比特率，单位为每秒比特数。接受数字输入。

示例： `rpicam-vid --codec libav -o test.mp4 --audio_codec mp2 --audio-bitrate 16384` （以 mp2 编解码器以 16 千位/秒记录音频）

#### `audio-samplerate`

默认值： `0`

设置音频采样率（单位 Hz）。接受数字输入。`0` 使用输入采样率。

#### `audio-device`

为音频录制选择一个 ALSA 输入设备。要查看可用设备的列表，请运行以下命令：

```bash
$ pactl list | grep -A2 'Source #' | grep 'Name: '
```

你应该看到类似以下内容的输出：

```json
Name: alsa_output.platform-bcm2835_audio.analog-stereo.monitor
Name: alsa_output.platform-fef00700.hdmi.hdmi-stereo.monitor
Name: alsa_output.usb-GN_Netcom_A_S_Jabra_EVOLVE_LINK_000736B1214E0A-00.analog-stereo.monitor
Name: alsa_input.usb-GN_Netcom_A_S_Jabra_EVOLVE_LINK_000736B1214E0A-00.mono-fallback
```

#### `av-sync`

将音频样本时间戳按微秒值移动。接受正数和负数数值。

### 检测参数

本节中指定的命令行参数仅适用于使用 `rpicam-detect` 进行目标检测。

要将以下参数之一传参给 `rpicam-detect`，请在参数名称前加上 `--`。如果参数需要一个值，请在参数名称后立即传参该值，用单个空格分隔。如果值包含空格，请用引号括起来。

一些参数具有速记别名，例如 `-h` 而不是 `--help`。请使用这些速记别名，以节省空间和时间，但牺牲可读性。

#### `object`

从模型的标签文件中检测具有给定名称的对象。接受纯文本文件名作为输入。

#### `gap`

在捕获之间至少等待这么多帧。接受数值。

## 使用 `rpicam-apps` 进行后处理

`rpicam-apps` 共享一个通用的后处理框架。这使它们能够通过一系列自定义图像处理和图像分析例程，处理从相机系统接收到的图像。每个这样的例程被称为一个*阶段*。要运行后处理阶段，请提供一个 JSON 文件，指示应用程序应用哪些阶段和参数。你可以在 [`rpicam-apps` 存储库的 `assets` 文件夹](https://github.com/raspberrypi/rpicam-apps/tree/main/assets)中找到使用内置后处理阶段的示例 JSON 文件。

例如，否定阶段将亮像素变暗，暗像素变亮。由于否定阶段是基本的，不需要配置，negate.json 只是命名该阶段：

```json
{
    "negate": {}
}
```

要将否定阶段应用于图像，请将 `negate.json` 传参给 `post-process-file` 参数：

```bash
$ rpicam-hello --post-process-file negate.json
```

要运行多个后处理阶段，请创建一个包含多个阶段作为顶级键的 JSON 文件。例如，以下配置运行 Sobel 阶段，然后是否定阶段：

```json
{
    "sobel_cv":
    {
        "ksize": 5
    },
    "negate": {}
}
```

Sobel 阶段使用 OpenCV，因此具有 cv 后缀。它具有一个可由用户配置的参数，ksize，指定要使用的滤波器的内核大小。在这种情况下，Sobel 滤波器在黑色背景上产生明亮边缘，否定阶段将其转换为白色背景上的暗边缘。

![negated Sobel 滤波器](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-4ee31424f4510310ad2ecc15ead72ab6d5e9cd09%2Fsobel_negate.jpg?alt=media)

一个否定的 Sobel 滤波器。

一些阶段，如 negate，以某种方式改变图像。其他阶段分析图像以生成元数据。后处理阶段可以将此元数据传参给其他阶段甚至应用程序。

为了提高性能，图像分析通常使用降低的分辨率。`rpicam-apps` 直接从 ISP 提供专用的低分辨率馈送。

> **注意**
>
> 使用树莓派系统附带的 `rpicam-apps` 未包含 OpenCV 和 TensorFlow Lite。因此，依赖于它们的某些后处理阶段被禁用。要使用这些阶段，请重新编译 `rpicam-apps`。在运行 32 位内核的树莓派 3、4 上，使用参数 `-DENABLE_COMPILE_FLAGS_FOR_TARGET=armv8-neon` 进行编译能加快某些阶段的速度。

### 内置阶段

#### negate 阶段

此阶段将亮像素变暗，暗像素变亮。

negate 阶段没有用户可配置的参数。

默认的 `negate.json` 文件：

```json
{
    "negate" : {}
}
```

运行以下命令以在 `rpicam-hello` 中使用此阶段文件：

```json
$ rpicam-hello --post-process-file negate.json
```

示例输出：

![negated 图片](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-9820aaab5dff8bae8bade93f13e85fef18b31bad%2Fnegate.jpg?alt=media)

一个否定的图像。

#### hdr 阶段

本阶段强调使用高动态范围（HDR）和动态范围压缩（DRC）来突出图像中的细节。DRC 使用单个图像，而 HDR 结合多个图像以获得类似的结果。

参数分为三组：LP 滤波器、全局色调映射和局部对比度。

该阶段对完全处理过的输入图像应用平滑滤波器，生成低通（LP）图像。然后从原始图像和 LP 图像的差异中生成高通（HP）图像。然后，对 LP 图像应用全局色调映射，并将其添加回 HP 图像。该过程有助于保留局部对比度。

你可以使用以下参数配置此阶段：

|        `num_frames`       | 累积帧数；对于 DRC，请使用 `1`；对于 HDR，请尝试 `8`                                                                                                                                                                                          |
| :-----------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|    `lp_filter_strength`   | 低通 IIR 滤波器的系数。                                                                                                                                                                                                              |
|   `lp_filter_threshold`   | 将像素级别与有意义细节的阈值相关联的分段线性函数。                                                                                                                                                                                                   |
|  `global_tonemap_points`  | <p>输入图像直方图中的点映射到输出范围中的目标，我们希望将它们移动到那里。使用以下子配置：<br>一个在 <code>q</code> 和 <code>width</code> 之间的分位均值，作为完整输出范围的一部分（ <code>target</code> ），最大（ <code>max\_up</code> ）和最小（ <code>max\_down</code> ）增益，用于移动测量的分位均值，以防止图像变化过于剧烈</p> |
| `global_tonemap_strength` | 全局色调映射应用强度                                                                                                                                                                                                                  |
|    `local_pos_strength`   | 一个分段线性函数，定义了添加回色调映射 LP 图像时应用于局部对比度的增益，用于正（亮）细节                                                                                                                                                                              |
|    `local_neg_strength`   | 定义将应用于局部对比度的增益的分段线性函数，当添加回色调映射的 LP 图像时，用于负（暗）细节                                                                                                                                                                             |
|  `local_tonemap_strength` | 应用于所有局部对比度的整体增益，然后添加回去                                                                                                                                                                                                      |
|    `local_colour_scale`   | 一个因子，允许输出颜色受到更强烈或更弱的影响                                                                                                                                                                                                      |

控制处理强度，更改 `global_tonemap_strength` 和 `local_tonemap_strength` 参数。

在树莓派 4 上，处理单个图像需要 2 到 3 秒的时间。在累积多个帧时，此阶段仅将处理后的图像发送到应用程序。

DRC 的默认 `drc.json` 文件：

```json
{
    "hdr" : {
		"num_frames" : 1,
		"lp_filter_strength" : 0.2,
		"lp_filter_threshold" : [ 0, 10.0 , 2048, 205.0, 4095, 205.0 ],
		"global_tonemap_points" :
			[
			    { "q": 0.1, "width": 0.05, "target": 0.15, "max_up": 1.5, "max_down": 0.7 },
			    { "q": 0.5, "width": 0.05, "target": 0.5, "max_up": 1.5, "max_down": 0.7 },
			    { "q": 0.8, "width": 0.05, "target": 0.8, "max_up": 1.5, "max_down": 0.7 }
			],
		"global_tonemap_strength" : 1.0,
		"local_pos_strength" : [ 0, 6.0, 1024, 2.0, 4095, 2.0 ],
		"local_neg_strength" : [ 0, 4.0, 1024, 1.5, 4095, 1.5 ],
		"local_tonemap_strength" : 1.0,
		"local_colour_scale" : 0.9
    }
}
```

示例：

![没有 DRC 处理的图片](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-f0c4a5843a3458670ecc7c344aecc40c2c0d0418%2Fnodrc.jpg?alt=media)

没有 DRC 处理的图像

运行以下命令以在 `rpicam-still` 中使用此阶段文件

```bash
$ rpicam-still -o test.jpg --post-process-file drc.json
```

![DRC 处理的图片](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-cd65315f50376b78d83725cc830805ab4abe3050%2Fdrc.jpg?alt=media)

DRC 处理过的图像

HDR 的默认 `hdr.json` 文件：

```json
{
    "hdr" : {
		"num_frames" : 8,
		"lp_filter_strength" : 0.2,
		"lp_filter_threshold" : [ 0, 10.0 , 2048, 205.0, 4095, 205.0 ],
		"global_tonemap_points" :
			[
			    { "q": 0.1, "width": 0.05, "target": 0.15, "max_up": 5.0, "max_down": 0.5 },
			    { "q": 0.5, "width": 0.05, "target": 0.45, "max_up": 5.0, "max_down": 0.5 },
			    { "q": 0.8, "width": 0.05, "target": 0.7, "max_up": 5.0, "max_down": 0.5 }
			],
		"global_tonemap_strength" : 1.0,
		"local_pos_strength" : [ 0, 6.0, 1024, 2.0, 4095, 2.0 ],
		"local_neg_strength" : [ 0, 4.0, 1024, 1.5, 4095, 1.5 ],
		"local_tonemap_strength" : 1.0,
		"local_colour_scale" : 0.8
    }
}
```

示例：

![没有 HDR 处理的图像](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-6c2587fda9b350fdfaef73b8b577fdc1e9828fd2%2Fnohdr.jpg?alt=media)

没有 HDR 处理的图像

运行以下命令以在 rpicam-still 中使用此阶段文件：

```bash
$ rpicam-still -o test.jpg --ev -2 --denoise cdn_off --post-process-file hdr.json
```

![HDR 处理过的图像](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-c9ab3c918af23c04198e34f9938ec5039064cfdc%2Fhdr.jpg?alt=media)

带有 HDR 处理的图像

#### `motion_detect` 阶段

`motion_detect` 阶段分析来自低分辨率图像流的帧。你必须配置低分辨率流以使用此阶段。该阶段通过比较帧中感兴趣区域（ROI）与先前帧中相应部分来检测运动。如果帧之间的像素变化足够多，此阶段将在元数据下的 `motion_detect.result` 键中指示运动。

此阶段不依赖第三方库。

你可以使用以下参数配置此阶段，将尺寸传参为低分辨率图像尺寸的比例，介于 `0` 和 `1` 之间：

| `roi_x`            | 感兴趣区域的 x 偏移量用于比较（比例介于 `0` 和 `1` 之间）                                      |
| ------------------ | ------------------------------------------------------------------------ |
| `roi_y`            | 感兴趣区域的 y 偏移量用于比较（比例介于 `0` 和 `1` 之间）                                      |
| `roi_width`        | 用于比较的感兴趣区域的宽度（比例介于 `0` 和 `1` 之间）                                         |
| `roi_height`       | 用于比较的感兴趣区域的高度（比例介于 `0` 和 `1` 之间）                                         |
| `difference_m`     | 用于构建像素差异阈值的线性系数                                                          |
| `difference_c`     | 用于根据 `threshold = difference_m * pixel_value + difference_c` 构建像素阈值的恒定系数 |
| `frame_period`     | 运行此数量帧的运动检测器                                                             |
| `hskip`            | 像素水平下采样的数量                                                               |
| `vskip`            | 垂直方向按此比例进行像素子采样                                                          |
| `region_threshold` | 必须将多少比例的像素（区域）归类为不同，才能算作运动                                               |
| `verbose`          | 将消息打印到控制台，包括运动状态发生变化时                                                    |

默认 `motion_detect.json` 配置文件：

```json
{
    "motion_detect" : {
		"roi_x" : 0.1,
		"roi_y" : 0.1,
		"roi_width" : 0.8,
		"roi_height" : 0.8,
		"difference_m" : 0.1,
		"difference_c" : 10,
		"region_threshold" : 0.005,
		"frame_period" : 5,
		"hskip" : 2,
		"vskip" : 2,
		"verbose" : 0
    }
}
```

调整差异和阈值，使算法更加敏感或不那么敏感。为了提高性能，请使用参数 `hskip` 和 `vskip`。

运行以下命令以使用此阶段文件与 `rpicam-hello`：

```bash
$ rpicam-hello --lores-width 128 --lores-height 96 --post-process-file motion_detect.json
```

### 使用 OpenCV 进行后期处理

> **注意**
>
> 这些阶段需要安装 OpenCV。你可能需要重新构建带有 OpenCV 支持的 `rpicam-apps`。

#### sobel\_cv 阶段

该阶段将 Sobel 滤波器应用于图像，以突出边缘。

你可以使用以下参数配置此阶段：

| `ksize` | Sobel 滤波器的内核大小 |
| :-----: | :------------: |

默认 `sobel_cv.json` 文件：

```json
{
    "sobel_cv" : {
        "ksize": 5
    }
}
```

示例：

![使用 Sobel 滤波器来强调边缘](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-708f4413fef5dcea62b361385243e1ed0d09a8c7%2Fsobel.jpg?alt=media)

使用 Sobel 滤波器来强调边缘。

#### face\_detect\_cv 阶段

此阶段使用 OpenCV Haar 分类器来检测图像中的人脸。它返回人脸位置元数据，键为 `face_detect.results`，并可选择在图像上绘制位置。

你可以使用以下参数配置此阶段：

|  `cascade_name`  |   可找到 Haar 级联的文件名   |
| :--------------: | :-----------------: |
| `scaling_factor` |    确定搜索人脸图像的比例范围    |
|  `min_neighbors` |  需要重叠邻居的最小数量才能算作人脸  |
|    `min_size`    |        最小人脸尺寸       |
|    `max_size`    |        最大人脸尺寸       |
|  `refresh_rate`  | 在尝试重新运行人脸检测器之前等待多少帧 |
|  `draw_features` |   是否在返回的图像上绘制面部位置   |

`face_detect_cv` 阶段仅在预览和视频捕获期间运行。它会忽略静态图像捕获。它在分辨率为 320×240 和 640×480 像素之间的低分辨率流上运行。

默认 `face_detect_cv.json` 文件:

```json
{
    "face_detect_cv" : {
        "cascade_name" : "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml",
        "scaling_factor" : 1.1,
        "min_neighbors" : 2,
        "min_size" : 32,
        "max_size" : 256,
        "refresh_rate" : 1,
        "draw_features" : 1
    }
}
```

示例：

![在图像上检测到的面部绘制](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-9507813c1e2de07f1991d988dbb967099aba2794%2Fface_detect.jpg?alt=media)

在图像上检测到的面部绘制。

#### `annotate_cv` 阶段

该阶段使用与 `info-text` 参数相同的 `%` 替换，将文本写入图像的右上角。

首先解释指令 `info-text` ，然后将剩余的标记传参给 `strftime`。

例如，要在视频上实现日期时间戳，请传参 `%F %T %z`：

* `%F` 显示 ISO-8601 日期 (2023-03-07)
* `%T` 显示 24 小时本地时间（例如 “09:57:12”）
* `%z` 显示相对于 UTC 的时区（例如 “-0800”）

此阶段不会输出任何元数据，但会将在 JSON 配置文件中找到的元数据写入 `annotate.text` 的位置。这样，其他后处理阶段就可以将文本写入图像。

你可以使用以下参数配置此阶段：

|    `text`   |      要写入的文本字符串     |
| :---------: | :----------------: |
|     `fg`    |        前景颜色        |
|     `bg`    |        背景颜色        |
|   `scale`   |     与文本大小成比例的数字    |
| `thickness` |      决定文本厚度的数字     |
|   `alpha`   | 覆盖背景像素时应用的 alpha 量 |

默认 `annotate_cv.json` 文件:

```json
{
    "annotate_cv" : {
        "text" : "Frame %frame exp %exp ag %ag dg %dg",
        "fg" : 255,
        "bg" : 0,
        "scale" : 1.0,
        "thickness" : 2,
        "alpha" : 0.3
    }
}
```

示例：

![使用注释将相机和日期信息写入图像](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-6a0e20151588679ae943fe596fd5ebc2e38fe9ca%2Fannotate.jpg?alt=media)

使用注释将相机和日期信息写入图像。

### 使用 TensorFlow Lite 进行后处理

#### 先决条件

这些阶段需要导出 C++ API 的 TensorFlow Lite（TFLite）库。TFLite 不以这种形式分发库，但你可以从 lindevs.com 下载并安装一个导出 API 的版本。

安装后，你必须重新编译 `rpicam-apps` 以支持 TensorFlow Lite。

#### `object_classify_tf` 阶段

下载：<https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_224_quant.tgz>

`object_classify_tf` 使用 Google MobileNet v1 模型对摄像头图像中的对象进行分类。此阶段需要一个 `labels.txt` 文件。

你可以使用以下参数配置此阶段：

|  `top_n_results` | 要显示的结果数量                                                 |
| :--------------: | -------------------------------------------------------- |
|  `refresh_rate`  | 模型运行之间必须经过的帧数                                            |
| `threshold_high` | 对象被视为存在的置信度阈值（介于 0 和 1 之间）                               |
|  `threshold_low` | 对象必须下降到以下阈值以下才能被丢弃为匹配项                                   |
|   `model_file`   | TFLite 模型文件的文件路径                                         |
|   `labels_file`  | 包含对象标签的文件路径                                              |
| `display_labels` | 是否在图像上显示对象标签；为 `annotate_cv` 阶段插入 `annotate.text` 元数据以渲染 |
|     `verbose`    | 在控制台输出更多信息                                               |

示例 `object_classify_tf.json` 文件：

```json
{
    "object_classify_tf" : {
        "top_n_results" : 2,
        "refresh_rate" : 30,
        "threshold_high" : 0.6,
        "threshold_low" : 0.4,
        "model_file" : "/home/<用户名>/models/mobilenet_v1_1.0_224_quant.tflite",
        "labels_file" : "/home/<用户名>/models/labels.txt",
        "display_labels" : 1
    },
    "annotate_cv" : {
        "text" : "",
        "fg" : 255,
        "bg" : 0,
        "scale" : 1.0,
        "thickness" : 2,
        "alpha" : 0.3
    }
}
```

该阶段使用尺寸为 224×224 的低分辨率流图像。运行以下命令以使用此阶段文件与 `rpicam-hello`：

```bash
$ rpicam-hello --post-process-file object_classify_tf.json --lores-width 224 --lores-height 224
```

![桌面电脑和显示器的对象分类](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-ae9651da0a7a6d03e39dee32ef857c08b5ac5050%2Fclassify.jpg?alt=media)

桌面电脑和显示器的对象分类。

#### `pose_estimation_tf` 阶段

下载：<https://github.com/Qengineering/TensorFlow_Lite_Pose_RPi_32-bits>

`pose_estimation_tf` 使用 Google MobileNet v1 模型来检测姿势信息。

你可以使用以下参数配置此阶段：

| `refresh_rate` |   模型运行之间必须经过的帧数  |
| :------------: | :--------------: |
|  `model_file`  | TFLite 模型文件的文件路径 |
|    `verbose`   |    将额外信息输出到控制台   |

使用单独的 `plot_pose_cv` 阶段将检测到的姿势绘制到主图像上。

你可以使用以下参数配置 `plot_pose_cv` 阶段：

| `confidence_threshold` | 确定绘制程度的置信阈值；可以小于零 |
| :--------------------: | :---------------: |

示例 `pose_estimation_tf.json` 文件：

```json
{
    "pose_estimation_tf" : {
        "refresh_rate" : 5,
        "model_file" : "posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite"
    },
    "plot_pose_cv" : {
       "confidence_threshold" : -0.5
    }
}
```

该阶段在尺寸为 257×257 的低分辨率流图像上运行。因为 YUV420 图像必须具有偶数尺寸，所以对于 YUV420 图像，将尺寸四舍五入为 `258×258`。

运行以下命令以在 `rpicam-hello` 中使用此阶段文件：

```bash
$ rpicam-hello --post-process-file pose_estimation_tf.json --lores-width 258 --lores-height 258
```

![成年男性人体姿势检测](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-2b0ee4974b84685f23f5d56cf9c6eb5b2d50d297%2Fpose.jpg?alt=media)

成年男性人体姿势检测。

#### `object_detect_tf` 阶段

下载: <https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip>

`object_detect_tf` 使用 Google MobileNet v1 SSD（Single Shot Detector）模型来检测和标记对象。

你可以使用以下参数配置此阶段：

|     `refresh_rate`     |      必须在模型运行之间经过的帧数     |
| :--------------------: | :---------------------: |
|      `model_file`      |     TFLite 模型文件的文件路径    |
|      `labels_file`     |      包含标签列表的文件的文件路径     |
| `confidence_threshold` |       在接受匹配之前的置信阈值      |
|   `overlap_threshold`  | 确定匹配之间重叠的量，以便将它们合并为单个匹配 |
|        `verbose`       |       将额外信息输出到控制台       |

使用单独的 `object_detect_draw_cv` 阶段将检测到的对象绘制到主图像上。

你可以使用以下参数配置 `object_detect_draw_cv` 阶段：

| `line_thickness` |  边界框线条的粗细 |
| :--------------: | :-------: |
|    `font_size`   | 用于标签的字体大小 |

示例 `object_detect_tf.json` 文件：

```json
{
    "object_detect_tf" : {
        "number_of_threads" : 2,
        "refresh_rate" : 10,
        "confidence_threshold" : 0.5,
        "overlap_threshold" : 0.5,
        "model_file" : "/home/<用户名>/models/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29/detect.tflite",
        "labels_file" : "/home/<用户名>/models/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29/labelmap.txt",
        "verbose" : 1
    },
    "object_detect_draw_cv" : {
       "line_thickness" : 2
    }
}
```

该阶段在尺寸为 300×300 的低分辨率流图像上运行。运行以下命令，从尺寸为 400×300 的低分辨率图像中心将一个 300×300 的裁剪区域传给检测器，以使用此阶段文件与 `rpicam-hello`：

```bash
$ rpicam-hello --post-process-file object_detect_tf.json --lores-width 400 --lores-height 300
```

![检测对象为苹果和猫](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-7c650802dc5d63b2112cd6df763210b870c5dfab%2Fdetection.jpg?alt=media)

检测对象为苹果和猫。

#### `segmentation_tf` 阶段

下载：<https://tfhub.dev/tensorflow/lite-model/deeplabv3/1/metadata/2?lite-format=tflite>

`segmentation_tf` 使用 Google MobileNet v1 模型。此阶段需要一个标签文件，在 `assets/segmentation_labels.txt` 处找到。

此阶段在尺寸为 257×257 的图像上运行。因为 YUV420 图像必须具有偶数尺寸，所以低分辨率图像的宽度和高度至少应为 258 像素。该阶段向图像元数据添加一个包含 257×257 个值的向量，其中每个值表示像素所属的类别。你可以选择在图像的右下角绘制分割的表示。

你可以使用以下参数配置此阶段：

| `refresh_rate` |      必须在模型运行之间经过的帧数     |
| :------------: | :---------------------: |
|  `model_file`  |     TFLite 模型文件的文件路径    |
|  `labels_file` |      包含标签列表的文件的文件路径     |
|   `threshold`  | 当设置为详细时，打印当标签的像素数超过此数字时 |
|     `draw`     |      将分割地图绘制到图像的右下角     |
|    `verbose`   |       将额外信息输出到控制台       |

示例 `segmentation_tf.json` 文件：

```json
{
    "segmentation_tf" : {
        "number_of_threads" : 2,
        "refresh_rate" : 10,
        "model_file" : "/home/<用户名>/models/lite-model_deeplabv3_1_metadata_2.tflite",
        "labels_file" : "/home/<用户名>/models/segmentation_labels.txt",
        "draw" : 1,
        "verbose" : 1
    }
}
```

此示例将摄像头图像缩小至 258×258 像素。即使压缩非方形图像而无需裁剪，此阶段也能正常工作。此示例在右下角启用分割地图。

运行以下命令以使用此阶段文件与 `rpicam-hello`：

```bash
$ rpicam-hello --post-process-file segmentation_tf.json --lores-width 258 --lores-height 258 --viewfinder-width 1024 --viewfinder-height 1024
```

![在地图的右下角运行 segmentation 并显示结果](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-6790ef08cd2f4782d5bd92fb179b9e05a2992005%2Fsegmentation.jpg?alt=media)

在地图的右下角运行分割并显示结果。

### 编写自己的后处理阶段

使用 `rpicam-apps` 后处理框架，用户可以创建自己的自定义后处理阶段。甚至可以包括来自 OpenCV 和 TensorFlow Lite 的算法和例程。

#### 基本的后处理阶段

要创建自己的后处理阶段，请从 `PostProcessingStage` 类派生一个新类。所有后处理阶段必须实现以下成员函数：

`char const *Name() const` 返回阶段的名称。与 JSON 后处理配置文件中列出的阶段进行匹配。

`void Read(boost::property_tree::ptree const &params)` 从提供的 JSON 文件中读取阶段的配置参数。

`void AdjustConfig(std::string const &use_case, StreamConfiguration *config)` 为阶段提供影响相机配置的机会。对于不需要配置相机的阶段，通常为空。

`void Configure()` 在相机配置完成后调用，以分配资源并检查阶段是否可以访问必要的流。

`void Start()` 当摄像头启动时调用。对于不需要配置摄像头的阶段通常为空。

`bool Process(CompletedRequest &completed_request)` 展示已完成的摄像头请求以供后期处理。这是你将实现像素操作和图像分析的地方。如果后期处理框架不应将此请求传参给应用程序，则返回 `true`。

`void Stop()` 当摄像头停止时调用。用于关闭异步线程上的全部活动处理。

当相机配置被销毁时调用 `void Teardown()`。将其用作析构函数，在其中可以释放在 `Configure` 方法中设置的资源。

在所有阶段实现中，调用 `RegisterStage` 来向系统注册你的阶段。

不要忘记将你的阶段也添加到后处理文件夹的 `CMakeLists.txt` 中！

写自己的阶段时，请记住以下提示：

* `Process` 方法会阻塞成像管道。如果花费的时间太长，管道会出现卡顿。始终将耗时算法委托给异步线程。
* 将工作委托给另一个线程时，必须复制图像缓冲区。对于像图像分析这样不需要全分辨率的应用程序，尝试使用低分辨率图像流。
* 后处理框架使用并行处理每一帧。这提高了吞吐量。然而，一些 OpenCV 和 TensorFlow Lite 函数在每一帧内引入了另一层并行性。考虑在每一帧内序列化调用，因为后处理已经利用了多个线程。
* 大多数流，包括低分辨率流，使用 YUV420 格式。你可能需要将其转换为另一种格式以供某些 OpenCV 或 TFLite 函数使用。
* 为获得最佳性能，请始终就地修改图像。

对于一个基本示例，请参见 `negate_stage.cpp`。这个阶段通过将亮像素变暗和暗像素变亮来否定图像。这个阶段主要是派生类样板，仅用几行代码实现否定逻辑。

对于另一个示例，请参见 `sobel_cv_stage.cpp`，它仅使用几行 OpenCV 函数实现了 Sobel 滤波器。

#### TensorFlow Lite 阶段

对于使用 TensorFlow Lite (TFLite) 的阶段，请从 TfStage 类派生一个新类。该类将模型执行委托给单独的线程，以防止相机出现卡顿。

TfStage 类实现了所有后处理阶段通常必须实现的成员函数，除了 `Name`。所有派生自 `TfStage` 的阶段必须实现 `Name` 函数，并应实现以下一个或多个虚拟成员函数：

`void readExtras()` 基类读取命名模型和诸如 `refresh_rate` 之类的某些其他参数。使用此函数读取派生阶段的额外参数，并检查加载的模型是否正确（例如，具有正确的输入和输出维度）。

`void checkConfiguration()` 基类获取 TFLite 操作的低分辨率流和派生阶段需要的完整分辨率流。使用此函数检查你的阶段所需的流。如果你的阶段无法访问所需的流之一，则可能会跳过处理或引发错误。

`void interpretOutputs()` 使用此函数读取和解释模型输出。在模型完成时与模型在同一线程中运行。

`void applyResults()` 使用此函数将模型的结果（可能是几帧旧的）应用于当前帧。通常涉及附加元数据或绘图。在交付帧之前在主线程中运行。

有关示例实现，请参见 `object_classify_tf_stage.cpp` 和 `pose_estimation_tf_stage.cpp`。

## 高级 `rpicam-apps`

### 构建 `libcamera` 和 `rpicam-apps`

为自己构建 `libcamera` 和 `rpicam-apps` 以获得以下好处：

* 你可以获取最新的增强功能和特性。
* `rpicam-apps` 可以针对运行 32 位操作系统的树莓派 3 和树莓派 4 设备进行额外优化编译。
* 你可以包括可选的 OpenCV 和/或 TFLite 后处理阶段，或添加你自己的内容。
* 你可以定制或添加从 `rpicam-apps` 派生的应用程序。

#### 构建 `rpicam-apps` 而不构建 `libcamera`

要构建 `rpicam-apps` 而不必先重新构建 `libcamera` 和 `libepoxy`，请使用 `apt` 安装 `libcamera`、`libepoxy` 及其依赖项：

```bash
$ sudo apt install -y libcamera-dev libepoxy-dev libjpeg-dev libtiff5-dev libpng-dev libopencv-dev
```

> **技巧**
>
> 如果你不需要支持 GLES/EGL 预览窗口，请省略 `libepoxy-dev`。

要使用 Qt 预览窗口，请安装以下附加依赖项：

```bash
$ sudo apt install -y qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5
```

为了在 `rpicam-vid` 中支持 `libav`，请安装以下附加依赖项：

```bash
$ sudo apt install libavcodec-dev libavdevice-dev libavformat-dev libswresample-dev
```

如果你使用精简版树莓派系统，请安装 `git`：

```
$ sudo apt install -y git
```

接下来，构建 rpicam-apps。

#### 构建 libcamera

> **注意**
>
> 请仅在你需要定制行为或最新功能尚未进入 apt 存储库时，才从头开始构建 `libcamera`。

```bash
$ sudo apt install -y python3-pip git python3-jinja2
```

首先，安装以下 `libcamera` 依赖项：

```bash
$ sudo apt install -y libboost-dev
$ sudo apt install -y libgnutls28-dev openssl libtiff5-dev pybind11-dev
$ sudo apt install -y qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5
$ sudo apt install -y meson cmake
$ sudo apt install -y python3-yaml python3-ply
$ sudo apt install -y libglib2.0-dev libgstreamer-plugins-base1.0-dev
```

现在我们准备构建 libcamera 本身。

从 GitHub 下载树莓派的 libcamera 本地副本：

```bash
$ git clone https://github.com/raspberrypi/libcamera.git
```

切换到存储库的根目录：

```bash
$ cd libcamera
```

接下来，运行 `meson` 来配置构建环境：

```bash
$ meson setup build --buildtype=release -Dpipelines=rpi/vc4,rpi/pisp -Dipas=rpi/vc4,rpi/pisp -Dv4l2=true -Dgstreamer=enabled -Dtest=false -Dlc-compliance=disabled -Dcam=disabled -Dqcam=disabled -Ddocumentation=disabled -Dpycamera=enabled
```

> **注意**
>
> 在 meson 构建配置期间，你可以通过将 `-Dgstreamer=enabled` 替换为 `-Dgstreamer=disabled` 来禁用 `gstreamer` 插件。如果禁用 gstreamer，则无需安装 `libglib2.0-dev` 和 `libgstreamer-plugins-base1.0-dev` 依赖项。

现在，你可以使用 `ninja` 构建 `libcamera`：

```bash
$ ninja -C build
```

最后，运行以下命令安装你刚构建的 `libcamera` 二进制文件：

```bash
$ sudo ninja -C build install
```

> **技巧**
>
> 在内存小于 1GB 的设备上，构建过程可能超出可用内存。应在 `ninja` 命令中添加参数 `-j 1` 将构建限制为单个进程。这应该可以防止在树莓派 Zero 和树莓派 3 等设备上溢出可用内存。

`libcamera` 尚未具有稳定的二进制接口。始终在构建 `libcamera` 之后构建 `rpicam-apps`。

#### 构建 `rpicam-apps`

首先获取 `rpicam-apps` 的必要依赖项。

```bash
$ sudo apt install -y cmake libboost-program-options-dev libdrm-dev libexif-dev
$ sudo apt install -y meson ninja-build
```

下载树莓派的 `rpicam-apps` GitHub 存储库的本地副本：

```bash
$ git clone https://github.com/raspberrypi/rpicam-apps.git
```

切换到存储库的根目录：

```bash
$ cd rpicam-apps
```

对于像树莓派系统这样的基于桌面的操作系统，使用以下 `meson` 命令配置 `rpicam-apps` 构建：

```bash
$ meson setup build -Denable_libav=enabled -Denable_drm=enabled -Denable_egl=enabled -Denable_qt=enabled -Denable_opencv=disabled -Denable_tflite=disabled -Denable_hailo=disabled
```

对于像精简版树莓派系统这样的无头操作系统，使用以下 `meson` 命令配置 `rpicam-apps` 构建：

```bash
$ meson setup build -Denable_libav=disabled -Denable_drm=enabled -Denable_egl=disabled -Denable_qt=disabled -Denable_opencv=disabled -Denable_tflite=disabled -Denable_hailo=disabled
```

> **技巧**
>
> * 使用 `-Dneon_flags=armv8-neon` 来启用树莓派 3 或树莓派 4 上 32 位操作系统的优化。
> * 如果已安装 OpenCV 并希望使用基于 OpenCV 的后处理阶段，请使用 `-Denable_opencv=enabled`。
> * 如果已安装 TensorFlow Lite 并希望在后处理阶段中使用它，请使用 `-Denable_tflite=enabled`。
> * 如果已安装 HailoRT 并希望在后处理阶段中使用它，请使用 `-Denable_hailo=enabled`。

现在可以使用以下命令构建 `rpicam-apps`：

```bash
$ meson compile -C build
```

> **技巧**
>
> 在内存为 1GB 或更小的设备上，编译可能会溢出可用内存。请在 `meson` 命令中附加参数 `-j 1`，将构建限制为单个进程。这应该可以防止在树莓派 Zero 和树莓派 3 等设备上超出可用内存。

最后，运行以下命令安装你新构建的 `rpicam-apps` 二进制文件：

```bash
$ sudo meson install -C build
```

> **技巧**
>
> 前面的命令会自动更新 `ldconfig` 缓存。如果你无法访问新的 `rpicam-apps` 构建，请运行以下命令来更新缓存：
>
> ```bash
> $ sudo ldconfig
> ```

运行以下命令，检查你的设备是否使用了新的二进制文件：

```bash
$ rpicam-still --version
```

输出中会包含你本地 `rpicam-apps` 构建的日期和时间。

最后，请遵循[配置](#配置)一节中的 `dtoverlay` 和显示驱动程序说明。

#### rpicam-apps 墨森标志参考

meson 构建配置支持以下标志：

`-Dneon_flags=armv8-neon` 在运行 32 位操作系统的树莓派 3、4 设备上加快某些后处理功能。

`-Denable_libav=enabled` 启用/禁用 libav 编码器集成。

`-Denable_drm=enabled` 启用/禁用 DRM/KMS 预览渲染，这是在没有桌面环境的情况下使用的预览窗口。

`-Denable_egl=enabled` 启用/禁用非 Qt 桌面环境的预览。如果你的系统缺少桌面环境，请禁用。

`-Denable_qt=enabled` 启用/禁用对预览窗口的基于 Qt 的实现的支持。如果未安装桌面环境或者不打算使用基于 Qt 的预览窗口，则禁用它。通常不推荐使用基于 Qt 的预览，因为它在计算上非常昂贵，但它可以与 X 显示转发一起使用。

`-Denable_opencv=enabled` 强制 OpenCV 基于的后处理阶段链接或不链接。需要启用 OpenCV。默认为 `disabled`。

`-Denable_tflite=enabled` 启用或禁用 TensorFlow Lite 后处理阶段。默认情况下禁用。需要启用 TensorFlow Lite。根据你构建和/或安装 TFLite 的方式，你可能需要调整 `post_processing_stages` 目录中的文件 `meson.build` 。

`-Denable_hailo=enabled` 启用或禁用基于 HailoRT 的后处理阶段。需要启用 HailoRT。默认为 `auto`。

`-Ddownload_hailo_models=true` 为 HailoRT 后处理阶段下载并安装模型。需要安装 `wget`。默认为 `true`。

以上参数中的每个参数（ `neon_flags` 除外）支持以下值：

* `enabled`：启用该参数，如果依赖项不可用，则构建失败
* `disabled`：禁用该参数
* `auto`：如果有依赖项可用，则启用该参数

#### 构建 `libepoxy`

通常情况下不应重新构建 `libepoxy`，因为此库很少更改。但是，如果确实要从头构建它，请按照以下说明操作。

从安装必要的依赖项开始。

```bash
$ sudo apt install -y libegl1-mesa-dev
```

接下来，从 GitHub 下载 libepoxy 存储库的本地副本：

```bash
$ git clone https://github.com/anholt/libepoxy.git
```

切换到存储库的根目录：

```bash
$ cd libepoxy
```

在存储库的根目录创建一个构建目录，然后进入该目录：

```bash
$ mkdir _build
$ cd _build
```

接下来，运行 `meson` 以配置构建环境：

```bash
$ meson
```

现在，你可以使用 `ninja` 构建 libexpoxy ：

```bash
$ ninja
```

最后，运行以下命令安装你新构建的 libepoxy 二进制文件：

```bash
$ sudo ninja install
```

### 编写你自己的 rpicam 应用程序

`rpicam-apps` 并未提供所有摄像头相关功能，所有人都可能需要。相反，这些应用程序体积小巧灵活。需要不同行为的用户可以自行实现。

所有的 `rpicam-apps` 使用一个事件循环，当从摄像头系统接收到一组新的帧时会收到消息。这组帧被称为 `CompletedRequest`。这个 `CompletedRequest` 包含：

* 所有从单个摄像头帧派生的图像：通常是低分辨率图像和全尺寸输出
* 来自摄像头和后处理系统的元数据

#### `rpicam-hello`

`rpicam-hello` 是最小的应用程序，也是理解 `rpicam-apps` 设计的最佳起点。它从消息中提取 `CompletedRequestPtr`，一个指向 `CompletedRequest` 的共享指针，并将其转发到预览窗口：

```cpp
CompletedRequestPtr &completed_request = std::get<CompletedRequestPtr>(msg.payload);
app.ShowPreview(completed_request, app.ViewfinderStream());
```

每个 `CompletedRequest` 必须被回收到摄像头系统，以便缓冲区可以被重用。否则，摄像头会因为没有新的摄像头帧的缓冲区而耗尽。当不再有引用使用 C++ 的共享指针和自定义删除器机制时，这个回收过程会自动发生。

因此，`rpicam-hello` 必须完成以下操作以回收缓冲区空间：

* 事件循环必须完成一个周期，以便消息（代码中的 msg ），其中保存对 `CompletedRequest` 的引用，可以被下一条消息替换。这会丢弃对上一条消息的引用。
* 当事件线程调用 `ShowPreview` 时，它会向预览线程传参对 `CompletedRequest` 的引用。每次调用 `ShowPreview` 时，预览线程都会丢弃上一个 `CompletedRequest` 实例。

#### `rpicam-vid`

rpicam-vid 类似于 `rpicam-hello`，在事件循环中添加了编码。在事件循环开始之前，`rpicam-vid` 会使用回调函数配置编码器。回调函数处理包含编码图像数据的缓冲区。在下面的代码中，我们将缓冲区发送到 `Output` 对象。`Output` 可以根据指定的参数将其写入文件或流式传输。

```cpp
app.SetEncodeOutputReadyCallback(std::bind(&Output::OutputReady, output.get(), _1, _2, _3, _4));
```

因为此代码向编码器传参了对 `CompletedRequest` 的引用，所以 `rpicam-vid` 直到事件循环、预览窗口和编码器都丢弃它们的引用之前，无法回收缓冲区数据。

#### `rpicam-raw`

`rpicam-raw` 类似于 `rpicam-vid`。它也在事件循环中进行编码。然而，`rpicam-raw` 使用了一个名为 NullEncoder 的虚拟编码器。它将输入图像用作输出缓冲区，而不是使用编解码器对其进行编码。NullEncoder 仅在输出回调完成后丢弃对缓冲区的引用。这确保在回调处理图像之前不会回收缓冲区。

`rpicam-raw` 不会将任何内容转发到预览窗口。

在 `rpicam-raw` 中，`NullEncoder` 可能有些过度。我们也许可以直接将图像发送到 `Output` 对象，而不必经过它。但是，`rpicam-apps` 需要限制事件循环中的工作量。`NullEncoder` 演示了如何在其他线程中处理大多数流程（甚至是保持引用）。

#### `rpicam-jpeg`

`rpicam-jpeg` 以通常方式启动预览模式中的相机。计时器完成时，它会停止预览并切换到静态捕获：

```cpp
app.StopCamera();
app.Teardown();
app.ConfigureStill();
app.StartCamera();
```

事件循环从静态模式返回的第一帧并将其保存为 JPEG。

### 使用 `libcamera` 与 Qt

Qt 是一种流行的应用程序框架和 GUI 工具包。`rpicam-apps` 包括一个参数，可以在相机预览窗口中使用 Qt。

不幸的是，Qt 在全局命名空间中将某些符号（如 `slot` 和 `emit`）定义为宏。这会导致包含 `libcamera` 文件时出错。这个问题在所有同时使用 Qt 和 `libcamera` 的平台上都很常见。尝试以下解决方法以避免这些错误：

* 尽可能在全部情况下在 Qt 头文件之前列出 `libcamera` 包含文件，或包含 `libcamera` 文件的文件（如 `rpicam-apps` 文件）。
* 如果确实需要将 Qt 应用程序文件与 `libcamera` 包含混合在一起，请用 `Q_SIGNALS:` 替换 `signals:`，用 `Q_SLOTS:` 替换 `slots:`，用 `Q_EMIT` 替换 `emit`，用 `Q_FOREACH` 替换 `foreach`。
* 在所有 `libcamera` 包含文件的顶部添加以下内容：

  ```cpp
  #undef signals
  #undef slots
  #undef emit
  #undef foreach
  ```
* 如果你的项目使用 `qmake`，请将 `CONFIG += no_keywords` 添加到项目文件中。
* 如果你的项目使用 `cmake`，请添加 `SET(QT_NO_KEYWORDS ON)`。

### 使用 Python 与 Picamera2 一道使用 libcamera

[Picamera2 库](https://github.com/raspberrypi/picamera2)是基于 `rpicam` 的替代品，用于取代 Picamera——后者是树莓派旧版摄像头堆栈的 Python 接口。Picamera2 提供了易于使用的 Python API。

有关 Picamera2 的文档可在 [GitHub](https://github.com/raspberrypi/picamera2) 和 [Picamera2 手册](https://pip.raspberrypi.com/documents/RP-008156-DS)中找到。

#### 安装

最近的树莓派系统镜像包含了 Picamera2 以及所有 GUI（Qt 和 OpenGL）依赖项。最近的精简版树莓派系统镜像包含了 Picamera2 但不包含 GUI 依赖项，尽管可以使用 DRM/KMS 来显示预览图像。

如果你的镜像不包含 Picamera2，请运行以下命令安装包含所有 GUI 依赖项的 Picamera2：

```bash
$ sudo apt install -y python3-picamera2
```

如果你不想要 GUI 依赖项，可以运行以下命令安装 Picamera2 而不安装 GUI 依赖项：

```bash
$ sudo apt install -y python3-picamera2 --no-install-recommends
```

> **注意**
>
> 如果你之前使用 pip 安装了 Picamera2，请使用以下命令卸载： `pip3 uninstall picamera2`。

## 使用 USB 摄像头

大多数树莓派设备都有专用端口用于摄像头模块。摄像头模块是高质量、高度可配置的摄像头，深受树莓派用户喜爱。

然而，对于许多用途，USB 网络摄像头具备你从树莓派记录图片和视频所需的一切。本节将解释如何在树莓派上使用 USB 网络摄像头。

### 安装依赖项

首先，安装 fswebcam 软件包：

```bash
$ sudo apt install fswebcam
```

接下来，将你的用户名添加到 video 组，否则你可能会看到“权限被拒绝”错误：

```bash
$ sudo usermod -a -G video <用户名>
```

要检查用户是否已正确添加到组中，请使用命令 `groups` 。

### 拍照

运行以下命令使用网络摄像头拍照并将图像保存到名为 `image.jpg` 的文件中：

```bash
$ fswebcam image.jpg
```

你应该看到类似以下内容的输出：

```bash
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Adjusting resolution from 384x288 to 352x288.
--- Capturing frame...
Corrupt JPEG data: 2 extraneous bytes before marker 0xd4
Captured frame in 0.00 seconds.
--- Processing captured image...
Writing JPEG image to 'image.jpg'.
```

![默认状态](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-073f424357bd72902ff3c9bdca9012f6a00e06a4%2Fwebcam-image.jpg?alt=media)

默认情况下，fswebcam 使用低分辨率，并添加显示时间戳的横幅。

要为捕获的图像指定不同的分辨率，请使用参数 `-r`，传参宽度和高度作为两个由 `x` 分隔的数字：

```bash
$ fswebcam -r 1280x720 image2.jpg
```

你应该看到类似以下输出：

```bash
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
Captured frame in 0.00 seconds.
--- Processing captured image...
Writing JPEG image to 'image2.jpg'.
```

![Specify a resolution to capture a higher quality image](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-d66d1ac3ab4a332282c214009f3b8c86385ffb2a%2Fwebcam-image-high-resolution.jpg?alt=media)

指定分辨率以捕获更高质量的图像。

#### 删除横幅

要从捕获的图像中删除横幅，请使用参数 `--no-banner`：

```bash
$ fswebcam --no-banner image3.jpg
```

你应该看到类似以下内容的输出：

```bash
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
Corrupt JPEG data: 2 extraneous bytes before marker 0xd6
Captured frame in 0.00 seconds.
--- Processing captured image...
Disabling banner.
Writing JPEG image to 'image3.jpg'.
```

![横幅](https://3761843483-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvQpIJ2H9hr4SPLGQVGEh%2Fuploads%2Fgit-blob-c1711c2a72d838d3747b70ee75a3abbc06c465ce%2Fwebcam-image-no-banner.jpg?alt=media)

指定 `--no-banner` 以保存图像而不带有时间戳横幅。

### 自动化图像捕获

与 `rpicam-apps` 不同，fswebcam 没有内置什么功能来替换输出图像名称中的时间戳和数字。在捕获多个图像时，手动编辑文件名可能会很繁琐。相反，使用 Bash 脚本来实现这个功能。

在你的主文件夹中创建一个名为 `webcam.sh` 的新文件。添加以下示例代码，该代码使用 bash 编程语言将图像保存到文件中，文件名包含年、月、日、小时、分钟和秒：

```bash
#!/bin/bash

DATE=$(date +"%Y-%m-%d_%H-%M-%S")

fswebcam -r 1280x720 --no-banner $DATE.jpg
```

然后，通过运行以下命令使 bash 脚本可执行：

```bash
$ chmod +x webcam.sh
```

使用以下命令运行脚本，捕获图像并将其保存到带有时间戳名称的文件中，类似于 `2024-05-10_12-06-33.jpg`:

```bash
$ ./webcam.sh
```

你应该看到类似以下内容的输出:

```bash
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
Corrupt JPEG data: 2 extraneous bytes before marker 0xd6
Captured frame in 0.00 seconds.
--- Processing captured image...
Disabling banner.
Writing JPEG image to '2024-05-10_12-06-33.jpg'.
```

### 捕获时间间隔

使用 cron 来安排照片捕捉以给定间隔。通过正确的间隔，比如每分钟一次，你可以捕捉一个延时摄影。

首先，打开用于编辑的 cron 表：

```bash
$ crontab -e
```

请你在编辑器中打开文件，添加以下行到计划中，每分钟拍照一次，用你的用户名替换 `<用户名>`：

```bash
* * * * * /home/<用户名>/webcam.sh 2>&1
```

保存并退出，然后你应该看到以下消息：

```bash
crontab: installing new crontab
```

## V4L2 驱动程序

V4L2 驱动程序为访问摄像头和编解码器功能提供了标准的 Linux 接口。通常，Linux 在启动时会自动加载驱动程序。但在某些情况下，你可能需要[显式加载摄像头驱动程序](#配置)。

### 使用 libcamera 时的设备节点

| `/dev/videoX` | 默认操作                                                      |
| :-----------: | --------------------------------------------------------- |
|    `video0`   | 第一个 CSI-2 接收器的 Unicam 驱动程序                                |
|    `video1`   | 第二个 CSI-2 接收器的 Unicam 驱动程序                                |
|   `video10`   | 视频解码                                                      |
|   `video11`   | 视频编码                                                      |
|   `video12`   | 简单的 ISP，除了 Bayer 到 RGB/YUV 转换外，还可以在 RGB/YUV 格式之间执行转换和调整大小 |
|   `video13`   | 输入到完全可编程的 ISP                                             |
|   `video14`   | 来自完全可编程 ISP 的高分辨率输出                                       |
|   `video15`   | 完全可编程 ISP 的低结果输出                                          |
|   `video16`   | 完全可编程 ISP 的图像统计                                           |
|   `video19`   | HEVC 解码                                                   |

### 使用 V4L2 驱动程序

有关如何使用 V4L2 驱动程序的更多信息，请参阅 [V4L2 文档](https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/v4l2.html)。

## Unicam

树莓派 SoC 都有两个相机接口，支持 CSI-2 D-PHY 1.1 或紧凑相机端口 2（CCP2）源。该接口以代号 Unicam 而闻名。第一个 Unicam 实例支持两个 CSI-2 数据通道，而第二个支持四个。每个通道最高可运行速度为 1Gbit/s（DDR，因此最大链路频率为 500MHz）。

计算模块和树莓派 5 都将两个外设的所有通道路由出去。在树莓派 5 之前的其他型号只暴露第二个实例，只将两个数据通道路由到相机连接器。

### 软件接口

V4L2 软件接口是与 Unicam 外围设备通信的唯一方式。曾经还有固件和 MMAL rawcam 组件接口，但这些已不再受支持。

#### V4L2

> **注意**
>
> 仅在使用 libcamera 时，Unicam 的 V4L2 接口可用。

为 Unicam 块提供了一个完全开源的内核驱动程序；这个内核模块，称为 bcm2835-unicam，与 V4L2 子设备驱动程序进行交互，传参原始帧。这个 bcm2835-unicam 驱动程序控制传感器并配置摄像头串行接口 2（CSI-2）接收器。外围设备将原始帧（经过 Debayer 处理）写入 SDRAM，以便 V4L2 传参给应用程序。在摄像头传感器捕获图像和 bcm2835-unicam 驱动程序将图像数据放入 SDRAM 之间，除了 Bayer 解包到 16 位/像素之外，没有图像处理。

```sh
|------------------------|
|     bcm2835-unicam     |
|------------------------|
     ^             |
     |      |-------------|
 img |      |  Subdevice  |
     |      |-------------|
     v   -SW/HW-   |
|---------|   |-----------|
| Unicam  |   | I²C 或 SPI|
|---------|   |-----------|
csi2/ ^             |
ccp2  |             |
    |-----------------|
    |     sensor      |
    |-----------------|
```

主线 Linux 包含一系列现有驱动程序。树莓派内核树具有一些额外的驱动程序和设备树叠加，用于配置它们：

|         设备        |        类型        |      解释     |
| :---------------: | :--------------: | :---------: |
| Omnivision OV5647 |    500 万像素摄像头    |   原装树莓派摄像头  |
|     索尼 IMX219     |     800 万像素相机    |   旧版树莓派相机   |
|     索尼 IMX477     |    1200 万像素相机    |  树莓派 HQ 相机  |
|     索尼 IMX708     |    1200 万像素相机    |  树莓派相机模块 3  |
|     索尼 IMX296     |     160 万像素相机    | 树莓派全局快门相机模块 |
|  Toshiba TC358743 | HDMI 到 CSI-2 桥接器 |             |
|   模拟设备 ADV728x-M  |  模拟视频到 CSI-2 桥接器 |   不支持隔行扫描   |
|  Infineon IRS1125 |     飞行时间深度传感器    |    由第三方支持   |

由于子设备驱动程序也是具有标准化 API 的内核驱动程序，第三方可以自由地为他们选择的来源编写自己的驱动程序。

### 编写第三方驱动程序

这是通过 Unicam 进行接口的推荐方法。

当为打算与 `bcm2835-unicam` 模块一起使用的新设备开发驱动程序时，你需要驱动程序和相应的设备树叠加。理想情况下，应将驱动程序提交给 linux-media 邮件列表进行代码审查和合并到主线，然后移至内核树；但也可以对直接将驱动程序进行审查和合并到树莓派内核做出例外。

> **注意**
>
> 所有内核驱动程序均在 GPLv2 许可下授权，因此必须提供源代码。仅提供二进制模块的行为会违反 Linux 内核的 GPLv2 授权许可。

旧版 `bcm2835-unicam` 模块已经编写，以尝试适应当前在主线 Linux 内核中找到的所有类型的 CSI-2 源驱动程序。这些可以大致分为相机传感器和桥接芯片。桥接芯片允许在某些其他格式和 CSI-2 之间进行转换。

#### 相机传感器

相机传感器的传感器驱动程序负责设备的所有配置，通常通过 I²C/SPI。与从头开始编写驱动程序不同，通常更容易以现有驱动程序为基础并根据需要进行修改。

[IMX219 驱动程序](https://github.com/raspberrypi/linux/blob/rpi-6.1.y/drivers/media/i2c/imx219.c)是一个很好的起点。该驱动程序支持 8 位和 10 位 Bayer 读出，因此枚举帧格式和帧大小稍微复杂一些。

传感器通常支持 [V4L2 用户控件](https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/control.html)。并非所有这些控件都需要在驱动程序中实现。IMX219 驱动程序仅实现了一个小子集，如下所列，其实现由 `imx219_set_ctrl` 函数处理。

* `V4L2_CID_PIXEL_RATE` / `V4L2_CID_VBLANK` / `V4L2_CID_HBLANK`：允许应用程序设置帧速率
* `V4L2_CID_EXPOSURE`：设置曝光时间（以行为单位）；应用程序需要使用 `V4L2_CID_PIXEL_RATE`、`V4L2_CID_HBLANK` 和帧宽度来计算行时间
* `V4L2_CID_ANALOGUE_GAIN`：传感器特定单位中的模拟增益
* `V4L2_CID_DIGITAL_GAIN`：传感器特定单位中的可选数字增益
* `V4L2_CID_HFLIP` / `V4L2_CID_VFLIP`：将图像水平或垂直翻转；此操作可能会改变帧中数据的 Bayer 顺序，就像在 IMX219 上的情况一样。
* `V4L2_CID_TEST_PATTERN` / `V4L2_CID_TEST_PATTERN_*`：启用从传感器输出各种测试图案；用于调试

在 IMX219 的情况下，许多这些控件直接映射到对传感器本身的寄存器写入。

进一步的指导可在 `libcamera` 的 [传感器驱动要求](https://git.linuxtv.org/libcamera.git/tree/Documentation/sensor_driver_requirements.rst)中，以及[树莓派摄像头调整指南](https://pip.raspberrypi.com/documents/RP-009070-TC)第 3 章中找到。

**设备树**

设备树用于选择传感器驱动程序并配置参数，如 CSI-2 通道数量、连续时钟通道操作和链路频率（通常仅支持一个）。

6.1 内核的 [IMX219 设备树叠加层](https://github.com/raspberrypi/linux/blob/rpi-6.1.y/arch/arm/boot/dts/overlays/imx219-overlay.dts)可在 GitHub 上获得。

#### 桥接芯片

这些是将传入的视频流（例如 HDMI 或复合视频）转换为可以被树莓派 CSI-2 接收器接受的 CSI-2 流的设备。

处理桥接芯片更加复杂。与摄像头传感器不同，它们必须响应传入信号并将其报告给应用程序。

处理桥接芯片的机制可以分为两类：模拟或数字。

在下面的部分中使用 ioctls 时，名称中的 **S** 表示它是一个设置函数，而 **G** 是一个获取函数，**ENUM** 列举了一组允许的值。

**模拟视频源**

模拟视频源使用标准 `ioctls` 来检测和设置视频标准。`VIDIOC_G_STD`，`VIDIOC_S_STD`，`VIDIOC_ENUMSTD`，和 `VIDIOC_QUERYSTD` 可用。

选择错误的标准通常会导致图像损坏。设置标准通常也会在 V4L2 捕获队列上设置分辨率。无法通过 `VIDIOC_S_FMT` 设置。通常，在流媒体之前通过 `VIDIOC_QUERYSTD` 请求检测到的标准，然后用 `VIDIOC_S_STD` 设置是个好主意。

**数字视频源**

对于数字视频源，如 HDMI，有一组备用调用，允许指定所有数字定时参数： `VIDIOC_G_DV_TIMINGS`，`VIDIOC_S_DV_TIMINGS`，`VIDIOC_ENUM_DV_TIMINGS`，和 `VIDIOC_QUERY_DV_TIMINGS`。

与模拟桥一样，定时通常固定 V4L2 捕获队列分辨率，并在流之前使用 `VIDIOC_QUERY_DV_TIMINGS` 的结果调用 `VIDIOC_S_DV_TIMINGS` 应确保格式正确。

根据桥接芯片和驱动程序的不同，可能通过 `VIDIOC_SUBSCRIBE_EVENT` 和 `V4L2_EVENT_SOURCE_CHANGE` 向应用程序报告输入源的更改。

**目前支持的设备**

树莓派的 Linux 内核目前支持两种桥接芯片：用于模拟视频源的 Analog Devices ADV728x-M 和用于 HDMI 源的 Toshiba TC358743。

Analog Devices ADV728x(A)-M 模拟视频到 CSI2 桥接芯片将复合 S 视频(Y/C)或分量(YPrPb)视频转换为单通道 CSI-2 接口，并受 ADV7180 内核驱动程序支持。

有关该芯片各个版本的产品详细信息，请访问 Analog Devices 网站：ADV7280A，ADV7281A 和 ADV7282A。

由于当前核心 V4L2 实现中存在一些缺失的代码，选择源失败，因此树莓派内核版本添加了一个内核模块参数 dbg\_input 到 ADV7180 内核驱动程序，每次调用 VIDIOC\_S\_STD 时设置输入源。在某个时候，主流将修复底层问题（内核 API 调用 `s_routing` 和用户空间调用 `VIDIOC_S_INPUT` 之间的不一致），并将删除此修改。

不支持接收隔行视频，因此 ADV7281(A)-M 版本的芯片的用途有限，因为它没有必要的 I2P 去隔行块。在选择设备时，请确保指定-M 参数。如果没有，你将获得一个无法与树莓派接口的并行输出总线。

目前没有已知商用板使用这些芯片，但此驱动程序已通过模拟器件 EVAL-ADV7282-M 评估板进行了测试。

如果你使用的是基于 ADV7282-M 芯片的衍生，则可以使用 `config.txt` `dtoverlay adv7282m` 加载此驱动程序；或者如果你使用其他变体，则可以使用参数 `adv7280m=1`、`adv7281m=1` 或 `adv7281ma=1` 加载。

```bash
dtoverlay=adv728x-m,adv7280m=1
```

Toshiba TC358743 是一款 HDMI 到 CSI-2 桥接芯片，能够将视频数据转换为高达 1080p60。

可在 Toshiba 网站上找到有关此桥接芯片的信息。

TC358743 将 HDMI 接口转换为 CSI-2 和 I²S 输出。它受 TC358743 内核模块支持。

芯片支持将传入的 HDMI 信号作为 RGB888、YUV444 或 YUV422，最高支持 1080p60。它可以转发 RGB888，或将其转换为 YUV444 或 YUV422，并在 YUV444 和 YUV422 之间双向转换。仅已测试 RGB888 和 YUV422 支持。当使用两个 CSI-2 通道时，支持的最大速率为 1080p30 作为 RGB888，或 1080p50 作为 YUV422。在计算模块上使用四个通道时，1080p60 可以以任一格式接收。

HDMI 通过接收设备广告 EDID 来协商分辨率，其中包含其支持的所有模式。内核驱动程序不了解你希望接收的分辨率、帧率或格式，因此用户需要通过 `VIDIOC_S_EDID ioctl` 提供一个合适的文件，或者更容易地使用 `v4l2-ctl --fix-edid-checksums --set-edid=file=filename.txt` （添加参数 `--fix-edid-checksums` 意味着你不必在源文件中正确获取校验和值）。生成所需的 EDID 文件（二进制 EDID 文件的文本十六进制转储）并不太繁琐，有可用工具可用于生成它们，但这超出了本页面的范围。

如上所述，使用 `DV_TIMINGS ioctl` 配置驱动程序以匹配传入视频。这样做的最简单方法是使用命令 `v4l2-ctl --set-dv-bt-timings query`。驱动程序确实支持生成 `SOURCE_CHANGED` 事件，如果你希望编写一个处理变化源的应用程序。通过设置输出像素格式来实现更改像素格式，但只有像素格式字段将被更新，因为分辨率是由 DV 定时配置的。

有几块商用板可以将该芯片连接到树莓派。Auvidea B101 和 B102 是最常见的，但也有其他等效的板可用。

使用 `config.txt` `dtoverlay tc358743` 加载此驱动程序。

该芯片还支持通过 I²S 捕获立体声 HDMI 音频。Auvidea 板将相关信号引出到一个标头，可连接到树莓派的 40 引脚排针。所需的接线是：

|    信号    | B101 引脚 | 40 引脚 | BCM GPIO |
| :------: | :-----: | :---: | :------: |
| LRCK/WFS |    7    |   35  |    19    |
|  BCK/SCK |    6    |   12  |    18    |
|  DATA/SD |    5    |   38  |    20    |
|    GND   |    8    |   39  |    不适用   |

除了叠加层 `tc358743` 外，还需要叠加层 `tc358743-audio`。这应该为 HDMI 音频创建一个 ALSA 录音设备。

音频不进行重新采样。音频的存在反映在 V4L2 控制 `TC358743_CID_AUDIO_PRESENT` (音频存在) 中，传入音频的采样率反映在 V4L2 控制 `TC358743_CID_AUDIO_SAMPLING_RATE` (音频采样频率) 中。当没有音频存在或者采样率与报告的不同时录制会发出警告。

### `rpicam` 和 `raspicam` 之间的差异

`rpicam-apps` 模拟旧版 `raspicam` 应用程序的大多数功能。然而，用户可能会注意到以下差异：

* `Boost program_options` 不允许参数的多字符短版本，因此这些参数不得不被删除。长格式参数以相同的方式命名，并保留任意单字符短格式。
* `rpicam-still` 和 `rpicam-jpeg` 在预览窗口中不显示捕获的图像。
* `rpicam-apps` 移除了以下 `raspicam` 功能：
  * 不透明度 ( `--opacity` )
  * 图像效果 ( `--imxfx` )
  * 色彩效果 ( `--colfx` )
  * 注释（ `--annotate`，`--annotateex` ）
  * 动态范围压缩，或 DRC（ `--drc` ）
  * 立体声（ `--stereo`，`--decimate` 和 `--3dswap` ）
  * 图像稳定 ( `--vstab` )
  * 演示模式 ( `--demo` ) 后期处理替换了许多这些功能。
* rpicam-apps 移除了参数 `rotation` 支持 90° 和 270° 旋转。
* raspicam 混淆了计量和曝光；rpicam-apps 将这些参数分开。
* 要在 rpicam-apps 中禁用自动白平衡（AWB），请使用一对色彩增益设置 awbgains （例如 1.0,1.0 ）。
* rpicam-apps 无法将 NoIR 相机模块的自动白平衡（AWB）设置为灰世界模式。相反，将参数 `tuning-file` 传参给一个红外夜视特定的调整文件，如 `imx219_noir.json`。
* rpicam-apps 不提供对数字增益的显式控制。相反，参数 `gain` 隐式设置它。
* rpicam-apps 移除了参数 `--ISO` 参数。相反，计算所需 ISO 值对应的增益。供应商可以提供增益到 ISO 的映射。
* rpicam-apps 不支持设置闪烁周期。
* rpicam-still 不支持连拍。相反，考虑在 MJPEG 模式下使用 rpicam-vid，并使用 `--segment 1` 强制将每帧保存为单独的文件。
* rpicam-apps 使用开源驱动程序来驱动所有图像传感器，因此启用或禁用传感器上的瑕疵像素校正（DPC）的机制是不同的。树莓派 HQ 摄像头上的 imx477 驱动程序默认启用传感器上的 DPC。要在 HQ 摄像头上禁用传感器上的 DPC，请运行以下命令：

  ```bash
  $ sudo echo 0 > /sys/module/imx477/parameters/dpc_enable
  ```

## 故障排除

如果你的摄像头模块不像你期望的那样工作，请尝试以下一些修复方法：

* 在树莓派 3 及更早版本上，图形硬件只能支持最大尺寸为 2048×2048 像素的图像，这限制了可以调整大小以适应预览窗口的相机图像。因此，对大于 2048 像素宽的图像进行视频编码会产生损坏或缺失的预览图像。
* 在树莓派 4 上，图形硬件只能支持最大尺寸为 4096×4096 像素的图像，这限制了可以调整大小以适应预览窗口的相机图像。因此，对大于 4096 像素宽的图像进行视频编码会产生损坏或缺失的预览图像。
* 预览窗口可能在桌面环境中显示屏幕撕裂。这是一个已知的，无法修复的问题。
* 检查 FFC（平面柔性电缆）是否牢固插入，完全插入，并且接触面朝向正确方向。FFC 应该均匀插入，不应倾斜。
* 如果你在相机和你的树莓派之间使用连接器，请检查连接器上的端口是否牢固插入，完全插入，并且接触面朝向正确方向。
* 检查确保 FFC（平面柔性电缆）连接到 CSI（摄像头串行接口），而不是 DSI（显示串行接口）。连接器适配到任一端口，但只有 CSI 端口可以为摄像头供电和控制。在靠近端口的板上查找打印的 CSI 标签。
* [更新到最新软件。](https://rpicn.bsdcn.org/shu-mei-pai/pages/HvZgbtLcMP4kpmhvc4u2#更新当前的树莓派软件)
* 尝试不同的电源适配器。摄像头模块会给你的树莓派的电源需求增加约 200-250mA。如果你的电源适配器质量不高，你的树莓派可能无法为摄像头模块供电。
* 如果你已经检查了上述所有问题，但摄像头模块仍然无法按照你的期望工作，请尝试在[我们的论坛](https://forums.raspberrypi.com/)上发帖以获取更多帮助。

## 获取帮助

要获取有关 `libcamera` 和 `rpicam-apps` 的进一步帮助，请查看[树莓派摄像头论坛](https://forums.raspberrypi.com/viewforum.php?f=43)。在发帖之前：

* 记下你的操作系统版本（ `uname -a` ）。
* 记下你 libcamera 和 `rpicam-apps` 的版本（ `rpicam-hello --version` ）。
* 报告你正在使用的摄像头模块的制造商和型号。
* 报告你正在尝试使用的软件。我们不支持第三方摄像头模块供应商的软件。
* 报告你的树莓派型号，包括内存大小。
* 包括应用程序控制台输出中的所有相关摘录。

如果相机软件中存在特定问题（例如崩溃），请考虑在 [`rpicam-apps` GitHub 存储库中创建一个问题](https://github.com/raspberrypi/rpicam-apps)，并包括上面列出的相同细节。
