4. V4L2 裁剪矩形结构体:struct v4l2_rect 的成员及坐标系统
在 V4L2 的裁剪(CROP)与合成(COMPOSE)操作中,所有窗口和区域的定义都依赖于一个核心数据结构——struct v4l2_rect。理解该结构体的成员含义及其背后的坐标系统,是正确配置裁剪与合成参数的前提。
4.1 struct v4l2_rect 结构体定义
该结构体定义在 Linux 内核头文件 linux/videodev2.h 中,用于描述一个二维矩形区域。其成员非常直观,包含矩形左上角坐标以及矩形的宽高。
struct v4l2_rect {
__s32 left; /* 矩形左上角 X 坐标 */
__s32 top; /* 矩形左上角 Y 坐标 */
__u32 width; /* 矩形宽度(像素) */
__u32 height; /* 矩形高度(像素) */
};
数据类型说明: 注意
left 和 top 是 __s32(有符号 32 位整数),允许负坐标值;而 width 和 height 是 __u32(无符号 32 位整数),表示尺寸必须为非负值。
4.2 成员详细解析
| 成员 | 类型 | 含义 | 取值范围说明 |
|---|---|---|---|
left |
__s32 |
矩形左上角顶点的 X 坐标(水平方向) | 可为负值,表示裁剪区域起始于图像有效数据边界之外 |
top |
__s32 |
矩形左上角顶点的 Y 坐标(垂直方向) | 可为负值,表示裁剪区域起始于图像有效数据边界之上 |
width |
__u32 |
矩形的宽度,单位为像素 | 必须 ≥ 1,且 left + width 不应超出源图像边界(硬件限制) |
height |
__u32 |
矩形的高度,单位为像素 | 必须 ≥ 1,且 top + height 不应超出源图像边界(硬件限制) |
4.3 V4L2 坐标系统
V4L2 的坐标系统遵循标准的计算机图形学惯例,与大多数图像处理库(如 OpenCV)保持一致。理解该坐标系统对于正确设置 left 和 top 至关重要。
- 原点位置: 坐标原点
(0, 0)位于图像帧的左上角。 - X 轴方向: 水平向右为正方向。
- Y 轴方向: 垂直向下为正方向。
- 像素寻址: 每个坐标点
(x, y)对应一个像素单元。矩形区域包含从left到left + width - 1,以及从top到top + height - 1的所有像素。
4.4 坐标系统与裁剪/合成的关系
在 CROP 和 COMPOSE 操作中,struct v4l2_rect 扮演着不同的角色,但其坐标系统始终遵循上述规则。
- CROP(裁剪):
v4l2_rect定义的是从源图像中选取的一个矩形窗口。该窗口的坐标是相对于源图像左上角(0, 0)的。例如,left=10, top=20, width=100, height=80表示从源图像的第 10 列、第 20 行开始,截取一个 100x80 像素的区域。 - COMPOSE(合成):
v4l2_rect定义的是在目标缓冲区中放置图像数据的矩形窗口。该窗口的坐标是相对于目标缓冲区左上角(0, 0)的。例如,left=0, top=0, width=640, height=480表示将图像数据填充到目标缓冲区的整个区域。
边界检查: 虽然
left 和 top 允许负值,但实际硬件驱动可能不支持负坐标或超出源图像边界的裁剪区域。在设置 v4l2_rect 时,应始终通过 VIDIOC_G/S_CROP 或 VIDIOC_G/S_SELECTION 查询设备的实际边界限制(V4L2_SEL_TGT_CROP_BOUNDS 或 V4L2_SEL_TGT_COMPOSE_BOUNDS),避免配置无效区域导致驱动报错或图像异常。
4.5 常见配置示例
以下示例展示了如何初始化一个 struct v4l2_rect 结构体,用于从 1920x1080 的源图像中心裁剪一个 1280x720 的区域。
struct v4l2_rect crop_rect;
/* 计算中心裁剪区域的偏移量 */
crop_rect.left = (1920 - 1280) / 2; /* 结果为 320 */
crop_rect.top = (1080 - 720) / 2; /* 结果为 180 */
crop_rect.width = 1280;
crop_rect.height = 720;
printf("Crop rect: left=%d, top=%d, width=%u, height=%u\n",
crop_rect.left, crop_rect.top,
crop_rect.width, crop_rect.height);
实战要点: 在编写应用程序时,建议始终使用
VIDIOC_G_SELECTION 查询当前设备的默认裁剪/合成区域,然后基于该默认值进行微调,而不是硬编码坐标值。这样可以提高代码对不同摄像头模组的兼容性。