ubuntu-Linux系统读取USB摄像头数据(uvc)
这几天在做小车的过程中,需要用到图像采集。我想现在用的摄像头是UVC免驱的。根据国嵌的教程中有一个gspca摄像头的程序。我发现把gspca的采集程序用到uvc上时,在显示图像的时候提示没有huffman表。但是在显示gspca的摄像头时却没有问题。为此特别找了以下的程序来获取uvc摄像头的数据。
程序代码:
/** capturing from UVC cam* requires: libjpeg-dev* build: gcc -std=c99 capture.c -ljpeg -o capture*/#include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h>#include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <asm/types.h> #include <linux/videodev2.h>#include <sys/time.h> #include <sys/types.h> #include <unistd.h>#include <jpeglib.h>void quit(const char * msg) {fprintf(stderr, "[%s] %d: %s\n", msg, errno, strerror(errno));exit(EXIT_FAILURE); }int xioctl(int fd, int request, void* arg) {for (int i = 0; i < 100; i++) {int r = ioctl(fd, request, arg);if (r != -1 || errno != EINTR) return r;}return -1; }typedef struct {uint8_t* start;size_t length; } buffer_t;typedef struct {int fd;uint32_t width;uint32_t height;size_t buffer_count;buffer_t* buffers;buffer_t head; } camera_t;camera_t* camera_open(const char * device, uint32_t width, uint32_t height) {int fd = open(device, O_RDWR | O_NONBLOCK, 0);if (fd == -1) quit("open");camera_t* camera = malloc(sizeof (camera_t));camera->fd = fd;camera->width = width;camera->height = height;camera->buffer_count = 0;camera->buffers = NULL;camera->head.length = 0;camera->head.start = NULL;return camera; }void camera_init(camera_t* camera) {struct v4l2_capability cap;if (xioctl(camera->fd, VIDIOC_QUERYCAP, &cap) == -1) quit("VIDIOC_QUERYCAP");if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) quit("no capture");if (!(cap.capabilities & V4L2_CAP_STREAMING)) quit("no streaming");struct v4l2_cropcap cropcap;memset(&cropcap, 0, sizeof cropcap);cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (xioctl(camera->fd, VIDIOC_CROPCAP, &cropcap) == 0) {struct v4l2_crop crop;crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;crop.c = cropcap.defrect;if (xioctl(camera->fd, VIDIOC_S_CROP, &crop) == -1) {// cropping not supported }}struct v4l2_format format;memset(&format, 0, sizeof format);format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;format.fmt.pix.width = camera->width;format.fmt.pix.height = camera->height;format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;format.fmt.pix.field = V4L2_FIELD_NONE;if (xioctl(camera->fd, VIDIOC_S_FMT, &format) == -1) quit("VIDIOC_S_FMT");struct v4l2_requestbuffers req;memset(&req, 0, sizeof req);req.count = 4;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_MMAP;if (xioctl(camera->fd, VIDIOC_REQBUFS, &req) == -1) quit("VIDIOC_REQBUFS");camera->buffer_count = req.count;camera->buffers = calloc(req.count, sizeof (buffer_t));size_t buf_max = 0;for (size_t i = 0; i < camera->buffer_count; i++) {struct v4l2_buffer buf;memset(&buf, 0, sizeof buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (xioctl(camera->fd, VIDIOC_QUERYBUF, &buf) == -1)quit("VIDIOC_QUERYBUF");if (buf.length > buf_max) buf_max = buf.length;camera->buffers[i].length = buf.length;camera->buffers[i].start =mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,camera->fd, buf.m.offset);if (camera->buffers[i].start == MAP_FAILED) quit("mmap");}camera->head.start = malloc(buf_max); }void camera_start(camera_t* camera) {for (size_t i = 0; i < camera->buffer_count; i++) {struct v4l2_buffer buf;memset(&buf, 0, sizeof buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (xioctl(camera->fd, VIDIOC_QBUF, &buf) == -1) quit("VIDIOC_QBUF");}enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (xioctl(camera->fd, VIDIOC_STREAMON, &type) == -1)quit("VIDIOC_STREAMON"); }void camera_stop(camera_t* camera) {enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (xioctl(camera->fd, VIDIOC_STREAMOFF, &type) == -1)quit("VIDIOC_STREAMOFF"); }void camera_finish(camera_t* camera) {for (size_t i = 0; i < camera->buffer_count; i++) {munmap(camera->buffers[i].start, camera->buffers[i].length);}free(camera->buffers);camera->buffer_count = 0;camera->buffers = NULL;free(camera->head.start);camera->head.length = 0;camera->head.start = NULL; }void camera_close(camera_t* camera) {if (close(camera->fd) == -1) quit("close");free(camera); }int camera_capture(camera_t* camera) {struct v4l2_buffer buf;memset(&buf, 0, sizeof buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if (xioctl(camera->fd, VIDIOC_DQBUF, &buf) == -1) return FALSE;memcpy(camera->head.start, camera->buffers[buf.index].start, buf.bytesused);camera->head.length = buf.bytesused;if (xioctl(camera->fd, VIDIOC_QBUF, &buf) == -1) return FALSE;return TRUE; }int camera_frame(camera_t* camera, struct timeval timeout) {fd_set fds;FD_ZERO(&fds);FD_SET(camera->fd, &fds);int r = select(camera->fd + 1, &fds, 0, 0, &timeout);if (r == -1) quit("select");if (r == 0) return FALSE;return camera_capture(camera); }void jpeg(FILE* dest, uint8_t* rgb, uint32_t width, uint32_t height, int quality) {JSAMPARRAY image;image = calloc(height, sizeof (JSAMPROW));for (size_t i = 0; i < height; i++) {image[i] = calloc(width * 3, sizeof (JSAMPLE));for (size_t j = 0; j < width; j++) {image[i][j * 3 + 0] = rgb[(i * width + j) * 3 + 0];image[i][j * 3 + 1] = rgb[(i * width + j) * 3 + 1];image[i][j * 3 + 2] = rgb[(i * width + j) * 3 + 2];}}struct jpeg_compress_struct compress;struct jpeg_error_mgr error;compress.err = jpeg_std_error(&error);jpeg_create_compress(&compress);jpeg_stdio_dest(&compress, dest);compress.image_width = width;compress.image_height = height;compress.input_components = 3;compress.in_color_space = JCS_RGB;jpeg_set_defaults(&compress);jpeg_set_quality(&compress, quality, TRUE);jpeg_start_compress(&compress, TRUE);jpeg_write_scanlines(&compress, image, height);jpeg_finish_compress(&compress);jpeg_destroy_compress(&compress);for (size_t i = 0; i < height; i++) {free(image[i]);}free(image); }int minmax(int min, int v, int max) {return (v < min) ? min : (max < v) ? max : v; }uint8_t* yuyv2rgb(uint8_t* yuyv, uint32_t width, uint32_t height) {uint8_t* rgb = calloc(width * height * 3, sizeof (uint8_t));for (size_t i = 0; i < height; i++) {for (size_t j = 0; j < width; j += 2) {size_t index = i * width + j;int y0 = yuyv[index * 2 + 0] << 8;int u = yuyv[index * 2 + 1] - 128;int y1 = yuyv[index * 2 + 2] << 8;int v = yuyv[index * 2 + 3] - 128;rgb[index * 3 + 0] = minmax(0, (y0 + 359 * v) >> 8, 255);rgb[index * 3 + 1] = minmax(0, (y0 + 88 * v - 183 * u) >> 8, 255);rgb[index * 3 + 2] = minmax(0, (y0 + 454 * u) >> 8, 255);rgb[index * 3 + 3] = minmax(0, (y1 + 359 * v) >> 8, 255);rgb[index * 3 + 4] = minmax(0, (y1 + 88 * v - 183 * u) >> 8, 255);rgb[index * 3 + 5] = minmax(0, (y1 + 454 * u) >> 8, 255);}}return rgb; }int main() {camera_t* camera = camera_open("/dev/video0", 352, 288);camera_init(camera);camera_start(camera);struct timeval timeout;timeout.tv_sec = 1;timeout.tv_usec = 0;/* skip 5 frames for booting a cam */for (int i = 0; i < 5; i++) {camera_frame(camera, timeout);}camera_frame(camera, timeout);unsigned char* rgb =yuyv2rgb(camera->head.start, camera->width, camera->height);FILE* out = fopen("result.jpg", "w");jpeg(out, rgb, camera->width, camera->height, 100);fclose(out);free(rgb);camera_stop(camera);camera_finish(camera);camera_close(camera);return 0; }
转载于:https://www.cnblogs.com/ynxf/p/6137091.html
ubuntu-Linux系统读取USB摄像头数据(uvc)相关推荐
- Win10+OpenCV无法正常读取USB摄像头数据解决方案
采用OpenCV中的VideoCapture类获取USB摄像头的数据时,使用下列代码 VideoCapture VideoStream(0);if (!VideoStream.isOpened()) ...
- Win10+OpenCV4.5 无法正常读取USB摄像头数据解决方案
借鉴了这个博客. 采用OpenCV中的VideoCapture类获取USB摄像头的数据时,使用下列代码 #include "pch.h" #include "highgu ...
- linux系统下 USB 摄像头1080分辨率采集帧率低问题的解决方法
linux系统上一般使用 video4linux2来操作系统摄像. 1.安装一个 v4l2-ctrl工具: sudo apt install v4l-utils 2.查看摄像头支持的视频参数 sudo ...
- linux usb摄像头图像分辨率,linux系统下 USB 摄像头1080分辨率采集帧率低问题的解决方法...
linux系统上一般使用 video4linux2来操作系统摄像. 1.安装一个 v4l2-ctrl工具: sudo apt install v4l-utils 2.查看摄像头支持的视频参数 sudo ...
- 国外linux内核视频播放器,基于Video for Linux内核的USB摄像头视频信号采集实现
摘要:Video for Linux是Linux中关于视频设备的内核驱动,本文介绍了在Video for Linux内 >> 基于ARM9和USB摄像头的网络视频采集系统设计 基于嵌入式V ...
- Python OpenCV 读取USB摄像头报错问题解决
报错信息: Traceback (most recent call last): File "G:\Python图像识别相关学习视频\人体姿势检测.py", line 32, ...
- 大疆妙算Manifold刷机换源,cuda,opencv,qt配置以及实现opencv读取usb摄像头,qmake nvcc交叉编译
大疆妙算Manifold刷机换源,cuda,opencv,qt配置以及实现opencv读取usb摄像头,qmake nvcc交叉编译 一.刷机 1.解压安装包 2.制作镜像 3.然后按照妙算说明书进入 ...
- linux是否有免安装程序,在线Ubuntu Linux系统,免安装体验Linux系统
如果你觉得安装Linux系统有困难,又或者你只想体验一下Linux系统是什么样的,有没有这样的好事?我可以肯定的回答你,有的,今天为你介绍在线Ubuntu Linux系统,你只需要点击Ubuntu在线 ...
- 移动硬盘备份linux系统盘,将Ubuntu Linux系统放到你的移动硬盘
将Ubuntu Linux系统放到你的移动硬盘 作者:佚名 来源:网络整理 2008-7-11 1.用livecd启动,插上移动硬盘,然后一切安正常的安装步骤进行,只是选择安装目标时选择你的移动硬盘, ...
最新文章
- Bitmap Font 报错“characters from the file are not available in the font”解决办法
- no output in console for unittests in pycharm 2017
- 【Java Web开发指南】解析Spring中Ioc和DI(入门Demo)
- Magento获取指定分类下的所有子分类信息
- 项目前端页面框架介绍
- 87-区间线段树(板子)--那个苑区的人最瘦
- 18.12.04 有品面试小记
- TDL(HDU-6641)
- bzoj 1662: [Usaco2006 Nov]Round Numbers 圆环数(枚举)
- 毕业后,她用1年时间拿下了30W年薪的阿里数据分析岗
- 【大数据处理技术】实验7(推荐林子雨老师的教程)
- 安装打印机驱动时报错 -536870329 或 1FFFFDB9
- spring-ant-处理zip
- QT 与日置、安捷伦测试仪 通讯 232串口 GPIB
- Bash Shellshock(Bash远程代码执行)漏洞分析及利用思路
- 中式风格室内装修 如何打造中式风格家居
- 计算机组装与维护我要自学网,【答疑】3D机械建模软件有哪些,3D机械建模一般用的是哪个软件? - 视频教程线上学...
- USB TYPE -A -B -C 接口
- 音响为什么要做CCC认证以及流程有哪些
- 安利一个Mac下好用的抓包工具-Charles