ubuntu V4L2摄像头采集图片 代码
时间: 2023-10-01 11:09:09 浏览: 112
基于linux的V4L2图像采集代码
4星 · 用户满意度95%
以下是一个简单的示例代码,可以在Ubuntu上使用V4L2接口来捕获摄像头图像并保存为JPEG图片。
```c++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <jpeglib.h>
#define VIDEO_DEVICE "/dev/video0"
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define IMAGE_QUALITY 80
int main(int argc, char **argv) {
int fd = open(VIDEO_DEVICE, O_RDWR);
if (fd == -1) {
perror("Failed to open video device");
return 1;
}
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
perror("Failed to query video device capabilities");
close(fd);
return 1;
}
struct v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = IMAGE_WIDTH;
format.fmt.pix.height = IMAGE_HEIGHT;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
format.fmt.pix.field = V4L2_FIELD_NONE;
if (ioctl(fd, VIDIOC_S_FMT, &format) == -1) {
perror("Failed to set video device format");
close(fd);
return 1;
}
struct v4l2_requestbuffers reqbuf;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 1;
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
perror("Failed to request video device buffers");
close(fd);
return 1;
}
struct v4l2_buffer buffer;
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) == -1) {
perror("Failed to query video device buffer");
close(fd);
return 1;
}
void *mem = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer.m.offset);
if (mem == MAP_FAILED) {
perror("Failed to map video device buffer");
close(fd);
return 1;
}
if (ioctl(fd, VIDIOC_STREAMON, &buffer.type) == -1) {
perror("Failed to start video device stream");
munmap(mem, buffer.length);
close(fd);
return 1;
}
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
unsigned char *jpeg_data;
unsigned long jpeg_size;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, &jpeg_data, &jpeg_size);
cinfo.image_width = IMAGE_WIDTH;
cinfo.image_height = IMAGE_HEIGHT;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, IMAGE_QUALITY, true);
if (ioctl(fd, VIDIOC_QBUF, &buffer) == -1) {
perror("Failed to queue video device buffer");
munmap(mem, buffer.length);
close(fd);
return 1;
}
if (ioctl(fd, VIDIOC_DQBUF, &buffer) == -1) {
perror("Failed to dequeue video device buffer");
munmap(mem, buffer.length);
close(fd);
return 1;
}
jpeg_start_compress(&cinfo, true);
JSAMPROW row_pointer[1];
for (int y = 0; y < IMAGE_HEIGHT; y++) {
row_pointer[0] = (JSAMPROW)((unsigned char *)mem + y * buffer.bytesused);
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
FILE *fp = fopen("image.jpg", "wb");
if (fp == NULL) {
perror("Failed to open image file");
munmap(mem, buffer.length);
close(fd);
return 1;
}
fwrite(jpeg_data, jpeg_size, 1, fp);
fclose(fp);
jpeg_destroy_compress(&cinfo);
munmap(mem, buffer.length);
close(fd);
return 0;
}
```
注意:这个示例代码仅仅是一个基础的例子,实际使用时需要考虑更多的情况,例如错误处理、缓冲区管理、图像分辨率、图像格式、图像质量等。此外,还需要安装libjpeg库,否则会编译错误。
阅读全文