摄像头的使用

这份资料是嵌入式Linux多媒体开发的核心实战篇章,从输入子系统平滑过渡到了摄像头视频采集。内容非常扎实,涵盖了从驱动接口到图像算法,再到库移植的完整链路。

我来为你梳理一个去粗取精、直击要害的总结,帮你把这一长串内容内化为自己的知识体系。


一、核心主线:视频采集全流程(V4L2)

这是本次课的骨架,必须像背流程一样熟悉:

  1. 打开设备open("/dev/video0", O_RDWR)
  2. 查询能力ioctl(VIDIOC_QUERYCAP) —— 确认支持“视频捕获”和“流式传输”。
  3. 设置格式ioctl(VIDIOC_S_FMT) —— 关键:设置V4L2_PIX_FMT_YUYV(YUV422)及分辨率。注意:驱动可能不支持你设的分辨率,务必用VIDIOC_G_FMT回读确认!
  4. 申请缓冲区ioctl(VIDIOC_REQBUFS) —— 申请若干帧缓冲区(如4个),类型为MMAP
  5. 内存映射mmap() —— 将内核空间的缓冲区映射到用户空间,实现零拷贝。
  6. 缓冲区入队ioctl(VIDIOC_QBUF) —— 将所有申请的缓冲区加入驱动队列,等待填充数据。
  7. 开启流ioctl(VIDIOC_STREAMON) —— 告诉驱动开始采集。
  8. 循环处理(核心)
    • select() 监听fd是否可读(有数据了再读,避免忙等)。
    • ioctl(VIDIOC_DQBUF) 出队 —— 取出一个装满数据的缓冲区。
    • 处理数据 —— 对这个缓冲区里的YUV数据进行转换(见下文)。
    • ioctl(VIDIOC_QBUF) 入队 —— 处理完后,把这个缓冲区放回队列,循环利用。
  9. 停止与清理ioctl(VIDIOC_STREAMOFF) -> munmap() -> close()

💡 李明轩老师点拨select监听的是可读状态!摄像头是“写数据给我们”,我们等它“写完”(可读)再读。超时(返回0)说明设备可能出问题了。


二、核心难点:YUV(YUYV)转RGB

这是算法重点,也是面试常考点。

1. 理解YUYV(YUV422)存储格式

  • 核心规则两个Y分量(像素)共享一组U、V分量
  • 内存排列Y0 U0 Y1 V0 | Y2 U2 Y3 V2 ...
  • 含义
    • (Y0, U0, V0) 构成第一个像素。
    • (Y1, U0, V0) 构成第二个像素。
    • 4个字节存储2个像素

2. 转换公式(必须掌握)

R = Y + 1.402 * (V - 128)
G = Y - 0.344 * (U - 128) - 0.714 * (V - 128)
B = Y + 1.772 * (U - 128)

注意:公式中的U就是CbV就是Cr

3. 代码实现关键点(来自博客与讲解)

  • 循环单位:每次循环处理4个字节(2个像素),地址索引i += 4
  • 边界钳制:计算出的R/G/B是浮点数,且可能超出[0, 255]范围。必须if判断并钳制到0-255,否则颜色会炸裂。
  • 效率:用整数运算或查表法可以优化速度,但初学先保证正确性。
  • 常见坑:你的摄像头数据可能是BGR顺序,而非RGB,调试时要留意。

三、实战技巧与工程经验

1. 坐标/图像缩放

  • 触摸屏:原始坐标(如1024x600)需通过等比例缩放映射到LCD分辨率(如800x480)。
  • 摄像头:若摄像头输出分辨率(如176x144)与LCD不符,需进行缩放。博客中使用最邻近插值法(速度快,实现简单),比双线性插值更适合嵌入式场景。

2. 图像格式转换链

在完整项目中,数据流通常如下:
YUYV (Camera) -> RGB (Processing) -> RGB565 (LCD Display) -> JPEG (Storage/Network)

3. libjpeg库移植与使用(重磅)

这是实现网络传输和存储的关键。

  • 移植三步configure(指定交叉编译工具链和--host=arm-linux)-> make -> make install
  • 内存压缩:新版libjpeg(如v8b)支持jpeg_mem_dest()函数,可将RGB数据直接压缩到内存缓冲区,避免了耗时的文件I/O,完美契合网络发送(send())的需求。
  • 编译命令arm-linux-gnueabihf-gcc your_app.c -ljpeg -I/path/to/include -L/path/to/lib

四、课后作业与进阶思考

  1. 状态机(State Machine):在复杂的UI或协议处理中,用switch-case管理不同状态(如:空闲、采集、暂停、传输),是嵌入式必备设计模式。
  2. V4L2文档:重点查阅ioctl请求码(如VIDIOC_*)和v4l2_buffer结构体。官方文档是最好的参考书。
  3. 性能优化:思考如何用多线程分离“采集”、“转换”、“显示/发送”任务,避免一帧处理慢导致丢帧。

一句话总结本课

打通了摄像头(V4L2采集YUYV)→ 算法(YUYV转RGB)→ 处理(缩放/压缩)→ 输出(LCD显示/网络发送)的全栈数据通路,是嵌入式Linux多媒体应用的基石。

posted @ 2026-07-15 18:35  南质冰清  阅读(3)  评论(0)    收藏  举报