I have always been using OpenCV’s VideoCapture API to capture images from webcam or USB cameras. OpenCV supports V4L2 and I wanted to use something other than OpenCV’s VideoCapture API so I started digging up about v4l2 and got few links using and few examples using which I successfully wrote a small code to grab an image using V4L2 and convert it to OpenCV’s Mat structure and display the image.

What is V4L2?

V4L2 is the second version of Video For Linux which is a video capturing API for Linux. Hereyou can find amazing documentation about the API. So it gives you a very easy inteface to use it with C, C++ and Python. I haven’t tried Python bindings yet.

How To Use V4L2 API?

I started reading documentation but didn’t really understand much until I found this example. The code had some issues and wasn’t working properly. But I just copied it and tried understanding it. So this is my understanding of the code.

Step 1: Open the Capture Device.

In Linux, default capture devide is generally /dev/video0, but if you’re using USB webcams, the index will vary accordingly.

int fd;
fd = open("/dev/video0", O_RDWR);
if (fd == -1)
{
// couldn't find capture device
perror("Opening Video device");
return 1;
}

Step 2: Query the Capture

So, basically you check if the capture is available or not. V4L2 doesn’t support some cameras so it would throw an error here. We need to use v4l2_capability structure and VIDIOC_QUERYCAPto query the capture. Read More here.

struct v4l2_capability caps = {0};
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps))
{
perror("Querying Capabilites");
return 1;
}

Here xioctl is a wrapper function over ioctlioctl() is a function to manipulate device parameters of special files. Read more here.

#include <sys/ioctl.h>

static int xioctl(int fd, int request, void *arg)
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}


Step 3: Image Format

V4L2 provides an easy interface to check the image formats and colorspace that your webcam supports and provide. v4l2_format sturcture is to be used to change image format.

struct v4l2_format fmt = {0};
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_NONE; if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
{
perror("Setting Pixel Format");
return 1;
}

I have set image width and height to be 320 and 240 respectively. You should check out the format that your camera supports. My Camera supports MJPEG and YUV and hence I have set image format to MJPEG.

Step 4: Request Buffers

A buffer contains data exchanged by application and driver using Streaming I/O methods. v4l2_requestbuffers is used to allocate device buffers. Read more here.

struct v4l2_requestbuffers req = {0};
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
perror("Requesting Buffer");
return 1;
}

The ioctl is used to initialize memory mapped(mmap), user pointer based I/O.

Step 5: Query Buffer

After requesting buffer from the device, we need to query the buffer in order to get raw data. Read more here

struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = bufferindex;
if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
{
perror("Querying Buffer");
return 1;
} buffer = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);

The mmap() function asks to map length bytes starting at offset in the memory of the device specified by fd into the application address space, preferably at address start. Read more here

Step 6: Capture Image

After querying the buffer, the only thing left is capturing the frame and saving it in the buffer.

if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type))
{
perror("Start Capture");
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(-1 == r)
{
perror("Waiting for Frame");
return 1;
} if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
perror("Retrieving Frame");
return 1;
}

Step 7: Store data in OpenCV datatype

I wanted to stored the retrieved data in OpenCV image structure. It took me few hours to figure out the perfect way. So here’s how I did it.

CvMat cvmat = cvMat(480, 640, CV_8UC3, (void*)buffer);
IplImage * img;
img = cvDecodeImage(&cvmat, 1);

So this how I captured frames from my webcam and stored in OpenCV Image data structure.

You can find the complete code here on my GitHub

P.S. Coding period for gsoc has started and I have to start working.

Open images from USB camera on linux using V4L2 with OpenCV的更多相关文章

  1. Jetson TX1使用usb camera采集图像 (2)

    该方法只启动usb摄像头 import cv2 import numpy import matplotlib.pyplot as plot class Camera: cap = cv2.VideoC ...

  2. android4.0 USB Camera实例(三)UVC

    前面我写了两篇文章说明了zc301的实现 详细请看 http://blog.csdn.net/hclydao/article/details/21235919 以下顺便把通用的USB也写上 前面的ZC ...

  3. Android USB Camera(1) : 调试记录【转】

    转自:http://blog.csdn.net/eternity9255/article/details/53069037 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 前言 ...

  4. I.MX6 USB Camera

    /************************************************************************* * I.MX6 USB Camera * 说明: ...

  5. Android开发之《USB Camera》

    SimpleWebCam Source Code:https://bitbucket.org/neuralassembly/simplewebcam/src 1. USB摄像头UVC兼容(如今大部分兼 ...

  6. ROS_Kinetic_12 ROS程序基础Eclipse_C++(三)usb camera

    ROS_Kinetic_12 ROS程序基础Eclipse_C++(三)usb camera 软件包下载地址:https://github.com/bosch-ros-pkg/usb_cam 下载后, ...

  7. Power OFF and ON USB device in linux (ubuntu)

    Power OFF and ON USB device in linux (ubuntu) http://loginroot.com/power-off-and-on-usb-device-in-li ...

  8. Ffmpeg 获取USB Camera 视频流

    本文讲述的案例是如何通过Ffmpeg实现从USB Camera中获取视频流并将视频流保存到MP4文件. 本文亦适用于从USB Camera 获取视频流并将视频流转发到rtmp服务的案例,二者基本的原理 ...

  9. android4.0 USB Camera示例(四)CMOS

    上一页下一页说usb camera uvc标准 顺便说说CMOS一起做 操作基本一至, 前HAL在那里我已经提供了层CMOS相关接口 JNIEXPORT jint JNICALL Java_com_d ...

随机推荐

  1. Codeforces - tag::flows 大合集 [完坑 x14]

    589F 题意:给出n个时间区间,每个区间挑定长的非连续区间,求不同个区间不存在时间冲突的最大定长,输出乘上n 二分图模型+二分长度,左顶点集为区间编号,右顶点集为时间编号(1...10000),汇点 ...

  2. [转] Jenkins pipeline 踩坑集合

    [From] https://testerhome.com/topics/10328 前言 最近由于项目需要,接触到了Jenkins 2.0版本,其中最重要的特性就是提供了对pipeline的支持.简 ...

  3. 剑指offer——面试题20:表示数值的字符串

    #include"iostream" using namespace std; bool IsInt(const char **str); bool IsUnsignInt(con ...

  4. 移远EC20的使用

    一 发短信 3. 推荐短信流程3.1 查询 短信存储区AT+CPMS?+CPMS: "ME",19,255,"ME",19,255,"ME" ...

  5. link 标签中“rel=stylesheet”的作用

    最近在复习我的培训项目学子商城项目的时候在引入外部css的时候忘记加上了rel=stylesheet(因为以前看别人给的模板有所以就加了上去,所以并没有太大印象) 那rel=stylesheet到底起 ...

  6. IONIC 打包安卓apk详细过程

    参照以下链接: https://blog.csdn.net/qq_20264891/article/details/79319408 当 cordova 项目安装的 android 平台版本 与 系统 ...

  7. 【CSS】 布局之浮动float和绝对定位absolute的选择

    浮动float: 浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止. 由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样.(W3C) 绝对定位 ...

  8. JavaScript数组forEach循环

    JavaScript数组forEach循环 今天写JavaScript代码把forEach循环数组忘记写法了,在此记录一下以防止未来忘记. let a = [1, 2, 3]; a.forEach(f ...

  9. WPF的窗体设置WindowStyle=none时,如何移动窗体

    1. 在WPF中当将主窗体的WindowStyle设置为none时,使用鼠标移动不了窗体 2. 解决方法: 2.1. 在Windows的Load方法中增加一下代码: private void Wind ...

  10. Linux 命令 -- chmod

    chmod命令用来变更文件或目录的权限.在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件与目录的权限, ...