linux v4l2 opencv,Open images from USB camera on linux using V4L2 with OpenCV

I have always been using OpenCV’sVideoCaptureAPI to capture images from webcam or USB cameras. OpenCV supportsV4L2and 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 usingV4L2and 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 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_capabilitystructure andVIDIOC_QUERYCAPto query the capture. Read Morehere.struct v4l2_capability caps = {0};

if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps))

{

perror("Querying Capabilites");

return 1;

}

Herexioctlis a wrapper function overioctl.ioctl()is a function to manipulate device parameters of special files. Read morehere.#include

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_formatsturcture 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_requestbuffersis used to allocate device buffers. Read morehere.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 initializememory 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 moreherestruct 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);

Themmap()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 codehere on my GitHub

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

原文:https://www.cnblogs.com/jins-note/p/9534577.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值