OpenCV中摄像头设置与视频捕获全解析
立即解锁
发布时间: 2025-08-21 00:15:08 阅读量: 1 订阅数: 4 


英特尔Galileo开发实战指南
### OpenCV 中摄像头设置与视频捕获全解析
#### 1. 摄像头属性的更改与读取
即使使用相同型号的网络摄像头,也可能会看到不同的设置。可以使用 `v4l2-ctl` 工具来更改和读取摄像头的属性。
- **更改属性**:使用 `--set-ctrl` 参数。例如,将对比度从 32 更改为 40,可在终端输入:
```bash
root@clanton:~# v4l2-ctl --set-ctrl=contrast=40
```
也可以使用分隔符 `=`:
```bash
root@clanton:~# v4l2-ctl --set-ctrl contrast=40
```
- **读取单个属性**:使用 `--get-ctrl` 而不是 `--all`(`--all` 会列出所有属性)。例如读取对比度:
```bash
root@clanton:~# v4l2-ctl --get-ctrl contrast
contrast: 40
```
- **获取控制列表**:使用 `-L` 参数,示例如下:
```bash
root@clanton:~# v4l2-ctl -L
brightness (int) : min=0 max=255 step=1 default=128
value=128
contrast (int) : min=0 max=255 step=1 default=32
value=40
saturation (int) : min=0 max=255 step=1 default=32
value=32
white_balance_temperature_auto (bool) : default=1 value=1
gain (int) : min=0 max=255 step=1 default=64
value=64
power_line_frequency (menu) : min=0 max=2 default=2 value=2
0 : Disabled
1 : 50 Hz
2 : 60 Hz
white_balance_temperature (int) : min=0 max=10000 step=10 default=4000
value=4000 flags=inactive
sharpness (int) : min=0 max=255 step=1 default=24
value=24
backlight_compensation (int) : min=0 max=1 step=1 default=0 value=0
exposure_auto (menu) : min=0 max=3 default=3 value=3
1 : Manual Mode
3 : Aperture Priority Mode
exposure_absolute (int) : min=1 max=10000 step=1 default=166
value=166 flags=inactive
exposure_auto_priority (bool) : default=0 value=1
```
#### 2. 像素格式与分辨率
- **检查支持的编码**:使用 `v4l2-ctl --list-formats` 命令,示例如下:
```bash
root@clanton:~# v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUV 4:2:2 (YUYV)
Index : 1
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : MJPEG
```
此摄像头支持两种编码:YUYV(索引 0)和 Motion JPEG(索引 1)。
- **更改分辨率**:以 C270 摄像头为例,将当前 640x480 分辨率更改为 1920x720,使用命令:
```bash
root@clanton:~# v4l2-ctl --set-fmt-video width=1920,height=780,pixelformat=0
```
这里索引 0 代表 YUYV 像素格式。
- **确定当前像素格式和分辨率**:使用 `v4l2-ctl --get-fmt-video` 命令,示例如下:
```bash
root@clanton:~# v4l2-ctl --get-fmt-video
Format Video Capture:
Width/Height : 1280/720
Pixel Format : 'YUYV'
Field : None
Bytes per Line: 2560
Size Image : 1843200
Colorspace : SRGB
```
- **检查支持的分辨率和帧率**:使用 `v4l2-ctl --list-formats-ext` 命令,该命令会列出每个像素格式支持的多种分辨率以及对应的帧率。例如:
```bash
root@clanton:~# v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUV 4:2:2 (YUYV)
Size: Discrete 640x480
Interval: Discrete 0.033 s (30.000 fps)
Interval: Discrete 0.040 s (25.000 fps)
Interval: Discrete 0.050 s (20.000 fps)
Interval: Discrete 0.067 s (15.000 fps)
Interval: Discrete 0.100 s (10.000 fps)
Interval: Discrete 0.200 s (5.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033 s (30.000 fps)
Interval: Discrete 0.040 s (25.000 fps)
Interval: Discrete 0.050 s (20.000 fps)
Interval: Discrete 0.067 s (15.000 fps)
Interval: Discrete 0.100 s (10.000 fps)
Interval: Discrete 0.200 s (5.000 fps)
...
```
不同像素格式下相同分辨率支持的帧率可能不同,若设置错误可能导致视频或图片捕获失败。
- **更改帧率**:使用 `--set-parm` 参数,例如设置为 30 fps:
```bash
root@clanton:~# v4l2-ctl --set-parm=30
Frame rate set to 30.000 fps
```
#### 3. 使用 libv4l2 捕获视频和图像
使用 V4L2 捕获视频和图像的过程相似,涉及相同的 IOCTL 调用和序列。摄像头有单平面和多平面之分,单平面意味着单个视频帧有一个起始的缓冲区地址,多平面则需要多个起始地址。捕获视频的序列基本相同,但软件保存帧的方式有所不同,可单独保存或作为整个流保存。
V4L2 API 支持三种 I/O 操作:
|操作类型|说明|
| ---- | ---- |
|Memory mapped buffers (mmap)|缓冲区在内核空间分配,设备决定可分配的缓冲区数量和大小。通常使用 `mmap()` 函数,应用程序在查询缓冲区前需使用 `V4L2_MEMORY_MMAP` 告知此方法。C270 摄像头使用此方法。|
|Userspace pointers|使用常规的 `malloc()` 或 `calloc()` 函数在用户空间分配缓冲区,使用 `V4L2_MEMORY_USERPTR` 查询缓冲区。|
|Direct Read/Write|应用程序可直接读写缓冲区,无需映射内存(`mmap`)或在用户空间分配内存(`malloc/calloc`)。|
在进行操作前,必须设置分辨率、像素格式和帧率。
#### 4. 视频捕获程序
以下是一个视频捕获程序的详细步骤及代码:
```mermaid
graph TD;
A[打开设备] --> B[初始化设备];
B --> C[重置图像裁剪设置];
C --> D[设置像素格式和分辨率];
D --> E[分配缓冲区];
E --> F[查询缓冲区状态并映射内存];
F --> G[入队缓冲区];
G --> H[开始捕获];
H --> I[出队缓冲区读取帧];
I --> J[停止流];
J --> K[释放缓冲区并取消内存映射];
K --> L[关闭设备];
```
- **封装 IOCTL 调用函数**:为方便多次使用 `ioctl()` 函数向内核发送 IOCTL,封装如下函数:
```c
static int xioctl(int fh, int request, void *arg)
{
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
```
- **打开设备**:使用文件描述符打开设备,示例代码如下:
```c
static void open_device(void)
{
fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exi
```
0
0
复制全文
相关推荐










