有一个需求,需要在Linux客户机上,实现调用摄像头(webcam)来捕捉图像。经过研究,可以使用V4L(Video for Linux2)来实现,一个在Linux下通用的视频驱动框架,支持绝大多数的摄像头(外置和内置摄像头都支持),目前有很多基于linux的网络摄像头和图像采集卡都在使用此框架程序。
如果需要更高级的应用开发,可以选择使用Libcamera,基于V4L开发,是作为V4L的上层扩展,解决了V4L接口的复杂性问题,大幅降低了开发难度,为开发者提供更高级、更建议的摄像头开发框架。
V4L
定位:内核驱动接口(用户空间通过ioctl调用)。
架构层级:底层接口,可以直接操作硬件。
目标场景:高性能、低延迟的应用场景(如工业摄像头、实时处理)
依赖关系:仅需内核支持(大部分Linux系统都已内置)
用法范例
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE "/dev/video0"
#define WIDTH 640
#define HEIGHT 480
#define FILENAME "capture.jpg"
int main(){
int fd=open(DEVICE, O_RDWR);
if(fd<0){
perror("无法打开设备");
return -1;
}
//查询设备能力
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("查询设备能力失败");
close(fd);
return -1;
}
//设置视频格式
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = WIDTH;
fmt.fmt.pix.height = HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; // 直接捕获JPEG格式
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("设置格式失败");
close(fd);
return -1;
}
//请求缓冲区
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof(req));
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
perror("请求缓冲区失败");
close(fd);
return -1;
}
//查询缓冲区并映射
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
perror("查询缓冲区失败");
close(fd);
return -1;
}
unsigned char* buffer_start = mmap(NULL, buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, buf.offset);
if(buffer_start == MAP_FAILED){
perror("内存映射失败");
close(fd);
return -1;
}
//将缓冲区放入队列
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
perror("将缓冲区放入队列失败");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
//开始捕获
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
perror("开始捕获失败");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
//等待帧就绪(这里简化处理,实际应用中可能需要循环等待)
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd + 1, &fds, NULL, NULL, &tv);
if (r < 0) {
perror("select出错");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
else if (r == 0) {
fprintf(stderr, "捕获超时\n");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
//从队列中取出缓冲区
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
perror("从队列中取出缓冲区失败");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
//保存图像到文件
FILE* file = fopen(FILENAME, "wb");
if (!file) {
perror("无法创建文件");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
fwrite(buffer_start, buf.bytesused, 1, file);
fclose(file);
//停止捕获并释放资源
if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
perror("停止捕获失败");
}
munmap(buffer_start, buf.length);
close(fd);
printf("图像已保存为: %s\n", FILENAME);
return 0;
} Libcamera
定位:基于V4L的更高级框架。
架构层级:高层扩展,提供统一的API和设备管理
目标场景:通用场景(如Linxu桌面应用、APP应用)
依赖关系:需要额外安装libcamera库和相关工具
用法范例
import time
from picamera2 import Picamera2
picam2 = Picamera2()
config = picam2.create_still_configuration(main={"size": (1920, 1080)})
picam2.configure(config)
picam2.start()
#等待相机稳定
time.sleep(2)
picam2.capture_file("image.jpg")
picam2.stop()
Zenmap是专为Nmap安全扫描器而设计的免费开源的软件,支持跨平台,拥有图形用户界面(GUI)。在Parrot OS中,安装Zenmap成功,但运行Zenmap时却提示File "/usr/bin/zenmap"...
使用mysql在查询数据,涉及使用中文排序时,出现了排序结果不对的情况,如图:select * from area order by name asc;由上图可见,排序结果是乱的,并不是根据拼音ABCD按顺序排序的,引起这样的原因是为什...
目前前端框架比较流行,很多软件项目都采用了前后端分离的方式进行开发,其中作为前端框架的代表,React和Vue是最主流的两个框架。很多同学咨询,React和Vue的区别是什么?做一个新系统的话,是采用React比较好,还是使用Vue比较...
有客户咨询丁老师,他们目前有一款安卓APP,想转为鸿蒙应用,以适配在鸿蒙手机和华为电脑上,想问下安卓的APP可以转为鸿蒙应用吗?大概需要多少钱呢?由于近期咨询相关问题的人太多,丁老师针对这个问题做一下解答。安卓APP可以转为鸿蒙应用吗?...
fontawesome所有图标class类名单,适用于4.7.0版本。总计有593个图标class类(包含别名):fa-500pxfa-address-bookfa-address-book-ofa-address-cardfa-addre...
挺不错的浏览器,强加入了edge image viewer图片浏览器,感觉不是那么好,对于开发者来说,更想要原生的东西。包括微信网页版里的表情图片,用edge image viewer打开的话,无法保存为gif格式,即使保存了,也只是第一帧...
今天有同学在群里提问,在使用photoshop编辑文字时,经常会弹出一个文字选择的面板如图:这时文字也无法输入,也无法取消和关闭,很是烦人,怎么取消这个功能呢?经过丁老师研究,方法很简单:1.打开photoshop菜单-编辑2.选择首选项-...
在使用wordpress的过程中,有的时候部分页面打不开,或是程序不能正常使用,也没有显示具体的错误信息,这个时候该怎么办呢?首先是查看错误日志,可以查看wordpress本身的错误日志,以及php的错误日志。这时有朋友提问了,wordpr...