Capture images using V4L2 on Linux
来源:互联网 发布:数据库中范式的作用 编辑:程序博客网 时间:2024/06/07 05:04
这文章相当好,没有理由不转载
I have always been using OpenCV’s VideoCapture API to capture images from webcam or USB cameras. OpenCV supportsV4L2 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 usingV4L2 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.Here you 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 foundthis 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 usev4l2_capability structure and VIDIOC_QUERYCAP to query the capture. Read Morehere.
struct v4l2_capability caps = {0};if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)){ perror("Querying Capabilites"); return 1;}
Here xioctl is a wrapper function over ioctl. ioctl() is a function to manipulate device parameters of special files. Read morehere.
#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 morehere
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 morehere
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.
If you have some feedback or questions regarding this post, please add comments. I’d be happy to get some feedback.
- Capture images using V4L2 on Linux
- How to capture video frames from the camera as images using AV Foundation on iOS
- Loading Images Asynchronously on iPhone using NSInvocationOperation
- ios学习--How to capture video frames from the camera as images using AV Foundation
- How to capture video frames from the camera as images using AV Foundation
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence---part2
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- V4l2 Capture Sequence
- 敌兵布阵
- 01-密码学扫盲
- genymotion unable to start the device的解决方案
- bzoj2820: YY的GCD
- 硬币等于骰子(在统计学意义上)
- Capture images using V4L2 on Linux
- 搭建了一个多项目、插件化的ASP.net MVC开发框架
- C++ 中的this指针
- jerror.h文件找不到及出错的原因
- 八皇后问题-C语言
- PostgreSQL主备流复制机制详解
- 随笔
- 关于前端的一些东西--记住了一些,闲时再看看
- 封装自定义瀑布流,实现原理