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 = ; i < ; i++) {
int r = ioctl(fd, request, arg);
if (r != - || errno != EINTR) return r;
}
return -;
} 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, );
if (fd == -) quit("open");
camera_t* camera = malloc(sizeof (camera_t));
camera->fd = fd;
camera->width = width;
camera->height = height;
camera->buffer_count = ;
camera->buffers = NULL;
camera->head.length = ;
camera->head.start = NULL;
return camera;
} void camera_init(camera_t* camera) {
struct v4l2_capability cap;
if (xioctl(camera->fd, VIDIOC_QUERYCAP, &cap) == -) 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, , sizeof cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl(camera->fd, VIDIOC_CROPCAP, &cropcap) == ) {
struct v4l2_crop crop;
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect;
if (xioctl(camera->fd, VIDIOC_S_CROP, &crop) == -) {
// cropping not supported
}
} struct v4l2_format format;
memset(&format, , 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) == -) quit("VIDIOC_S_FMT"); struct v4l2_requestbuffers req;
memset(&req, , sizeof req);
req.count = ;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (xioctl(camera->fd, VIDIOC_REQBUFS, &req) == -) quit("VIDIOC_REQBUFS");
camera->buffer_count = req.count;
camera->buffers = calloc(req.count, sizeof (buffer_t)); size_t buf_max = ;
for (size_t i = ; i < camera->buffer_count; i++) {
struct v4l2_buffer buf;
memset(&buf, , sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (xioctl(camera->fd, VIDIOC_QUERYBUF, &buf) == -)
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 = ; i < camera->buffer_count; i++) {
struct v4l2_buffer buf;
memset(&buf, , sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (xioctl(camera->fd, VIDIOC_QBUF, &buf) == -) quit("VIDIOC_QBUF");
} enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl(camera->fd, VIDIOC_STREAMON, &type) == -)
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) == -)
quit("VIDIOC_STREAMOFF");
} void camera_finish(camera_t* camera)
{
for (size_t i = ; i < camera->buffer_count; i++) {
munmap(camera->buffers[i].start, camera->buffers[i].length);
}
free(camera->buffers);
camera->buffer_count = ;
camera->buffers = NULL;
free(camera->head.start);
camera->head.length = ;
camera->head.start = NULL;
} void camera_close(camera_t* camera)
{
if (close(camera->fd) == -) quit("close");
free(camera);
} int camera_capture(camera_t* camera)
{
struct v4l2_buffer buf;
memset(&buf, , sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (xioctl(camera->fd, VIDIOC_DQBUF, &buf) == -) 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) == -) 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 + , &fds, , , &timeout);
if (r == -) quit("select");
if (r == ) 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 = ; i < height; i++) {
image[i] = calloc(width * , sizeof (JSAMPLE));
for (size_t j = ; j < width; j++) {
image[i][j * + ] = rgb[(i * width + j) * + ];
image[i][j * + ] = rgb[(i * width + j) * + ];
image[i][j * + ] = rgb[(i * width + j) * + ];
}
} 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 = ;
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 = ; 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 * , sizeof (uint8_t));
for (size_t i = ; i < height; i++) {
for (size_t j = ; j < width; j += ) {
size_t index = i * width + j;
int y0 = yuyv[index * + ] << ;
int u = yuyv[index * + ] - ;
int y1 = yuyv[index * + ] << ;
int v = yuyv[index * + ] - ;
rgb[index * + ] = minmax(, (y0 + * v) >> , );
rgb[index * + ] = minmax(, (y0 + * v - * u) >> , );
rgb[index * + ] = minmax(, (y0 + * u) >> , );
rgb[index * + ] = minmax(, (y1 + * v) >> , );
rgb[index * + ] = minmax(, (y1 + * v - * u) >> , );
rgb[index * + ] = minmax(, (y1 + * u) >> , );
}
}
return rgb;
} int main()
{
camera_t* camera = camera_open("/dev/video0", , );
camera_init(camera);
camera_start(camera); struct timeval timeout;
timeout.tv_sec = ;
timeout.tv_usec = ;
/* skip 5 frames for booting a cam */
for (int i = ; i < ; 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, );
fclose(out);
free(rgb); camera_stop(camera);
camera_finish(camera);
camera_close(camera);
return ;
}
ubuntu-Linux系统读取USB摄像头数据(uvc)的更多相关文章
- ubuntu-Linux系统读取USB摄像头数据(gspca)
将摄像头图像保存为jpg格式.摄像头需要是gspca免驱的.uvc若用uvc格式的需要在图像中插入Huffman表.否则无法正常显示. 程序代码: #include <stdio.h> # ...
- 虚拟机上使用 opecnv 读取USB摄像头无法显示
使用opecv读取USB摄像头时候,无法显示图像. 设置 首先查看虚拟机Ubuntu检测摄像头是否已正常插入: ls /dev/video* 结果为: 设置虚拟机USB属性: USB的兼容性设置为US ...
- [r]Ubuntu Linux系统下apt-get命令详解
Ubuntu Linux系统下apt-get命令详解(via|via) 常用的APT命令参数: apt-cache search package 搜索包 apt-cache show package ...
- Ubuntu Linux系统三种方法添加本地软件库
闲着没事教教大家以Ubuntu Linux系统三种方法添加本地软件库,ubuntu Linux使用本地软件包作为安装源——转2007-04-26 19:47新手重新系统的概率很高,每次重装系统后都要经 ...
- 安装Ubuntu Linux系统时硬盘分区最合理的方法
无论是安装Windows还是Linux操作系统,硬盘分区都是整个系统安装过程中最为棘手的环节,网上的一些Ubuntu Linux安装教程一般都是自动分区,给初学者带来很大的不便,下面我就根据多年来在合 ...
- 查看Linux系统的USB设备
查看Linux系统的USB设备 lsusb (centos没有该命令) dmesg (内核日志会输出) 执行dmesg
- 虚拟机下Linux读取USB设备的问题虚拟机下Linux无法读取USB设备的解决方案
我们在虚拟机中识别USB设备有三种情况导致Linux系统不能读取到USB设备: 1. .当虚拟机的USB服务没有开启的时候 2. 若虚拟机的USB连接的设置选项没有设置好 3. Widows抢先一步, ...
- 使用openCV打开USB摄像头(UVC 小米micro接口)
之前在AndroidStudio上就用了别人用写的库成功地打开了USB摄像头. 于是我之后又在PC上尝试了一下,首先去淘宝买了个MICRO母转USB公的转接口,然后在Qt上配置了一下OPENCV后开始 ...
- Linux系统编程——线程私有数据
在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...
随机推荐
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(59)-BLL层重构
系列目录 前言: 这应该是本系统最后一次重构,将重构BLL层和Model层.来完全取代代码生成器生成的BLL层和DAL层.完全废掉了代码生成器的DAL,BLL,MODEL层. 全自动生成增,删,改 ...
- 真实记录疑似Linux病毒导致服务器 带宽跑满的解决过程
案例描述 由于最近我在重构之前的APP,需要和server端进行数据交互,发现有一个现象,那么就是隔1~2天总会发生获取数据超时的问题,而且必须要重启服务器才能解决.早在之前,我有留意到这个问题,但是 ...
- Jquery中的bind(),live(),delegate(),on()绑定事件方式
博客转载为作者:枫上善若水http://www.cnblogs.com/xilipu31/p/4105794.html 前言 因为项目中经常会有利用jquery操作dom元素的增删操作,所以会涉及到d ...
- BZOJ3095 : 二元组
\[\begin{eqnarray*}&&\sum_{i=0}^{n-1}\left(ki+b-a_i\right)^2\\&=&\sum_{i=0}^{n-1}\le ...
- 时隔两个月再写的Echarts(Enterprise Charts,商业级数据图表)一文
简介 ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9/10 ...
- 和transformjs一起摇摆
写在前面 记得以前facebook做过一款HTML5游戏.开场动画是一块软体类似豆腐的东西一起摇摆.类似的效果如下面的gif所示: facebook当时使用的是createjs下的子项目easeljs ...
- css3 transition属性
最近打算学习css3知识,觉得css3写出来的效果好炫好酷,之前一直想要学习来着.可能之前的决心,毅力,耐心不够,所以想要重整起来,放下浮躁的心态,一步一个脚印,踏踏实实的来学习. 首先学习的是css ...
- 商业智能BI推动制造业智能化转型
制造业是我国国民经济的支柱产业,是我国经济增长的主导部门和经济转型的基础,如今我国制造业面临技术工艺不精.缺乏市场意识.商贸流通环节多.物流成本大.仓储效率低下等问题,正处在转型的特殊时期. 内忧: ...
- DataView详解
dataview可以用于对你的datatable筛选,搜索,排序,编辑和导航.可以方便对databale的操作. 先来看一下它有哪些属性: 接下来是方法: 我们怎么使用它呢? public datat ...
- 最便捷的免费 SSL 证书解决方案(实测start SSL、Let's Encrypt、七牛免费SSL证书)
谷歌从 2017 年起,Chrome 浏览器将也会把采用 HTTP 协议的网站标记为「不安全」网站:苹果从 2017 年 iOS App 将强制使用 HTTPS:在国内热火朝天的小程序也要求必须使用 ...