一、摄像头基础

1.摄像头整体成像与信号处理流程

在这里插入图片描述

光学投射:景物的光学图像通过镜头(LENS)投射到图像传感器(Sensor)表面;
电信号转换:Sensor 将接收到的光学图像转化为模拟电信号;
模数转换:通过 A/D(模数转换器)把模拟电信号转换为数字图像信号;
数字处理:数字图像信号送入数字信号处理芯片(DSP)中进行加工处理;
传输显示:处理后的信号通过 I/O 接口传输到 CPU 中进一步处理,最终通过显示设备(display)呈现出图像。

2.Sensor(感光传感器)核心工作原理

1.镜头前置配合:镜头(Lens)滤去不可见光,仅让可见光进入并精准投射到 Sensor 上;
2.Sensor 信号转化链:光照→产生电荷→形成弱电流→转化为 RGB 数字信号波形→进一步转化为 YUV 数字信号;
3.信号后续处理:Sensor 输出的信号会经过性能补偿、信号放大后,再送入 A/D 转换器进行模数转换。

3.核心技术指标

指标维度 核心影响 工程选型关键
分辨率 画面清晰度、数据量 平衡带宽 / 算力,嵌入式常用 VGA/720P
色深 色彩还原度 主流 24 位真彩色,低功耗场景用 16 位
变焦 拍摄灵活性 光学变焦优先,数码变焦仅作辅助
压缩算法 传输 / 存储效率 嵌入式优先 H.264,低带宽用 H.265
降噪 / AWB/AF/AE 画面质量 决定摄像头的实际成像效果,是 Sensor 调校的核心

二、摄像头测试

1.ubuntu抢占摄像头

虚拟机(VM) → 可移动设备(Removable Devices) → 找到你的摄像头设备(如Logitech HD Pro Webcam C920) → 选择「连接(断开与主机的连接)」
在这里插入图片描述
验证命令

ls /dev/video0 -l
crw-rw----+ 1 root video 81, 0 Apr 30 21:28 /dev/video0

2.Cheese 测试摄像头

  1. 工具作用
    Cheese 是 Ubuntu 下的图形化摄像头测试工具,用于快速验证摄像头硬件、驱动、V4L2 子系统是否正常工作,是嵌入式摄像头开发的前置验证步骤。

  2. 安装与使用

# 更新软件源
sudo apt-get update
# 安装 Cheese
sudo apt-get install cheese

然后启动测试

cheese

正常现象:窗口实时显示摄像头采集的画面,支持拍照、录像、特效等功能;
异常排查:若无法启动 / 无画面,需检查:
摄像头是否正确挂载到虚拟机(而非物理机占用)
/dev/video0 设备文件是否存在、权限是否正常
V4L2 驱动是否加载、用户是否在 video 用户组

三、mjpg-streamer移植

1.常用嵌入式视频图像开源库

  • luvcview:
    基于 V4L2、SDL 的程序,支持拍照录像,参数调节,代码精简实用,适合学习 V4L2 编程
  • cheese:
    基于 V4L2、GTK 的程序,支持拍照录像,特殊视频效果
  • motion:
    移动侦测拍照程序
  • mjpg-streamer:
    网络摄像机程序
  • ffmpeg

mjpg-streamer简介
MJPG-streamer是一个优秀的开源project,它可以通过HTTP的方式访问linux上面的兼容摄像头,从而做到远程视频传输的效果。它就是一个把摄像头画面变成 “网络视频” 的小工具,让你在浏览器里直接看监控。
流程:摄像头硬件 → V4L2 驱动 → /dev/video0 设备节点 → MJPG-streamer 程序 → HTTP 服务器 → 网络 → 浏览器/播放器

2.mjpg-streamer移植

  1. 安装前准备(安装编译依赖)
# 安装基础依赖
sudo apt-get install libsdl1.2-dev subversion
# 安装JPEG编解码库(核心依赖,用于MJPEG编码)
sudo apt-get install libjpeg62-dev
# 安装图像处理工具
sudo apt-get install imagemagick
# 若未安装git,先执行此命令安装
sudo apt-get install git
  1. 下载 MJPG-streamer 源码
# 进入指定工作目录(提前创建好该目录)
cd /home/peng/work/camera
# 从GitHub克隆源码
git clone https://github.com/shrkey/mjpg-streamer
  1. 编译安装
# 进入源码根目录
cd mjpg-streamer/mjpg-streamer
# 执行编译(Makefile会自动编译主程序和插件)
make
# 执行安装(将程序、插件、网页文件安装到系统目录)
sudo make install

3.编译结果
在这里插入图片描述
在这里插入图片描述
执行脚本

export LD_LIBRARY_PATH="$(pwd)"
./mjpg_streamer -i "./input_uvc.so -y" -o "./output_http.so -w ./www" -o "./output_file.so -f /www/pice -d 15000"
  1. export LD_LIBRARY_PATH=“$(pwd)”
    让系统能找到插件文件(.so)
  2. ./mjpg_streamer
    启动流媒体服务
  3. 后面一大串参数(最核心)
    -i “./input_uvc.so -y”
    读取 USB 摄像头画面(YUV 格式)
    -o “./output_http.so -w ./www”
    开启网页服务
    浏览器输入 IP:8080 就能看实时监控
    -o “./output_file.so -f /www/pice -d 15000”
    每 15 秒拍一张照片
    保存到 /www/pice 文件夹

这些是写在start.sh里的
特就是运行

.sudo ./start.sh

在这里插入图片描述
本机测试:直接在 Ubuntu 浏览器输入http://127.0.0.1:8080,打开自带监控页
手机远程:用ifconfig查到 Ubuntu 的 IP(比如192.168.3.100),手机浏览器输入http://192.168.3.100:8080就能看
直接抓图:输入http://192.168.3.100:8080/?action=snapshot,直接下载当前帧图片

四、mjpg-streamer支持单拍、连拍

mjpg_stream 中output-file.so 只实现了连续拍照的 功能,没有实现单拍或连拍几张的功能
我们要修改以下文件:
work/camera/mjpg-streamer/mjpg-streamer/plugins/output_file/output_file.c

添加代码
步骤 1:在 worker_thread 函数(196 行)初始化管道

char buf[10];    // 存从管道读取的命令
int flags = 0;   // 拍照标志:1=拍11张,2=拍1张
int fd_com = 0;  // 管道的文件描述符
int stop_num = 0;// 拍照计数

// 1. 检查管道是否存在,不存在则创建
if ( access("/tmp/webcom",F_OK) < 0 )
{
    if ( mkfifo("/tmp/webcom",0666) < 0 )
    {
        printf("photo fifo create failed\n");
    }
}

// 2. 以只读方式打开管道
fd_com = open ("/tmp/webcom",O_RDONLY,0666);
if (fd_com < 0)
{
    perror ("open the file webcom error");
}

步骤 2:在视频采集循环(229 行 while 内)监听管道命令

if (flags == 0)
{
    while(1)
    {
        // 从管道读取命令
        read(fd_com,buf,sizeof(buf));

        // 收到 "danger" → 标记拍11张
        if (strncmp(buf,"danger",6) == 0)
        {
            flags = 1;
            bzero(buf,sizeof(buf));
            break;
        }

        // 收到 "one" → 标记拍1张
        if (strncmp(buf,"one",3) == 0)
        {
            flags = 2;
            bzero(buf,sizeof(buf));
            break;
        }
    }
}

步骤 3:在拍照逻辑(355 行)执行拍照计数与复位

stop_num++;

// 拍11张的逻辑
if (flags == 1)
{
    if ( stop_num > 9 ) // 计数到10(共11张:0-10)
    {
        stop_num = 0;
        flags = 0; // 复位标志,回到监听状态
    }
}
// 拍1张的逻辑
else if (flags == 2)
{
    stop_num = 0;
    flags = 0; // 拍1张后直接复位
}

这里

if (strncmp(buf,"danger",6) == 0)
if (strncmp(buf,"one",3) == 0)

意思是:
收到 danger → 拍 11 张
收到 one → 拍 1 张

所以完整工作流程就是
1.启动 mjpg-streamer → worker_thread 初始化管道 /tmp/webcom,打开管道等待命令
2.外部发命令(比如终端执行 echo “one” > /tmp/webcom)
3.管道读取命令 → flags 被设为 2,退出监听,回到视频采集
4.执行拍照 → 采集 1 帧后,flags 复位,回到等待命令状态
5.发 danger 命令 → flags=1,连续采集 11 帧,计数满后复位

五、总结

  1. 先进入目录(必须做)
cd /home/peng/work/camera/mjpg-streamer/mjpg-streamer
  1. 一键启动监控(核心命令)
./start.sh

启动后

浏览器看实时监控
http://127.0.0.1:8080
命令行控制拍 1 张照片

echo "one" > /tmp/webcom

命令行控制拍 11 张照片

echo "danger" > /tmp/webcom
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐