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. 搭建maven环境——nexus

    第一步:部署maven环境和jdk环境 jdk直接用openjdk1. :yum -y install java--openjdk maven环境 wget http://mirror.rise.ph ...

  2. ReactNative常用命令

    常用命令整理备忘 创建项目: react-native init myProject 安装RN初始化命令: yarn add react-native-cli 引用组件: npm install re ...

  3. jenkins 判断是手动触发还是定时器触发

    根据变量BUILD_CAUSE的值可以判断本次触发是手动触发还是定时器触发 手动触发:MANUALTRIGGER 定时器触发:TIMERTRIGGER

  4. Pycharm快捷键配置

    1.主题 毫无疑问Pycharm是一个具有强大快捷键系统的IDE,这就意味着你在Pycharm中的任何操作,例如打开一个文件.切换编辑区域等,都可以通过快捷键来实现.使用快捷键不仅能提高操作速度,看起 ...

  5. linux中校验文件完整性(md5,sha1)

    经常在Linux下下载软件的人,一定会有一个良好的习惯:校验文件的hash,以确定文件的完整性甚至是安全性.我配置环境的时候也恰好用到了,笔者的是一个lubuntu的机子.这里我大致做个记录.(不了解 ...

  6. es第十篇:Elasticsearch for Apache Hadoop

    es for apache hadoop(elasticsearch-hadoop.jar)允许hadoop作业(mapreduce.hive.pig.cascading.spark)与es交互. A ...

  7. 等待页面元素(webdriverwait)

    前言 在脚本中加入太多的 sleep 后会影响脚本的执行速度,虽然 implicitly_wait ()这种方法隐式等待方法一定程度上节省了很多时间.但是一旦页面上某些 js 无法加载出来(其实界面元 ...

  8. django 中间件记录所有请求及请求执行时间

    class LoggingMiddleware(object): def process_request(self, request): request.start_time = time.time( ...

  9. WPF的ComboBox简单用法

    1. ComboBox:下拉列表框 效果如下: 2.通常用法是 显示内容 + 选中内容后获得的值(也就是 Name = Value的键值对) 故以键值对来定义一个类,如: public class C ...

  10. html中超链接的target属性

    <a> 标签的 target 属性规定在何处打开链接文档.(target就是目标的意思) 一共有(4+1种选择): 用法:<a target="value"> ...