How to Capture Still Image from Webcam on Linux

Get a still frame during webcam video capture on Linux

You can have multiple outputs for FFmpeg. Combine your commands:

ffmpeg -f v4l2 -framerate 30 -video_size 1024x576 -i /dev/video0 myvideo.mp4 -r 1 -update 1 current_frame.jpg

FFmpeg and video4linux2 parameters - how to capture still images faster?

First off, thanks to https://stackoverflow.com/users/1109017/llogan
who provided me the clue I needed in the comments below.

I am recording this solution here for easy discovery by others who might not read comments.

Here is my revised program:

list_of_camera_ids = ["/dev/video1","/dev/video2", "/dev/video3", "/dev/video4",
"/dev/video5","/dev/video6", "/dev/video7", "/dev/video8",
"/dev/video9","/dev/video10", "/dev/video11", "/dev/video12",
"/dev/video13","/dev/video14", "/dev/video15", "/dev/video16",
"/dev/video17","/dev/video18"
]
for this_camera_id in list_of_camera_ids:
full_image_file_name = '/tmp/' + os.path.basename(this_camera_id) + 'jpg'
image_capture_tic = time.perf_counter()

run_cmd = subprocess.run([
'v4l2-ctl','-d',
this_camera_id,
'--stream-mmap',
'--stream-count=1',
'--stream-to=' +
full_image_file_name,"&"
],
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print(run_cmd.stderr)
image_capture_toc = time.perf_counter()
print(f"Captured {camera_id} image in: {image_capture_toc - image_capture_tic:0.0f} seconds")

Additional notes:
This code is a substantial speed up!

With my previous method, each image took 3-4 seconds each to capture. In the serialized loop as shown in the original post, 18 images would typically take between 45 and 60 seconds to complete.

With my modified code, using llogan's suggestion, capture time is now less than 1 second per camera. Furthermore, simply by spawning each one in background by appending a "&" to the command, they are automatically running in parallel, and total time for 18 cameras is now about 10 seconds so the average time per camera is now about .55 seconds on the Raspberry Pi 400.

I suspect that I might be incurring some extra overhead by spawning off processes using the trivial "&" method for parallelization. Perhaps some of that could be reduced further if I could just spawn threads instead of full blown processes. But that's a level of performance tuning that I don't have experience with yet.

Capturing a single image from my webcam in Java or Python

On windows it is easy to interact with your webcam with pygame:

from VideoCapture import Device
cam = Device()
cam.saveSnapshot('image.jpg')

I haven't tried using pygame on linux (all my linux boxen are servers without X), but this link might be helpful http://www.jperla.com/blog/post/capturing-frames-from-a-webcam-on-linux

Take picture from webcam using linux command line (bash)

Install mplayer

mplayer -vo png -frames 1 tv://

USB webcam image capture in C++ WITHOUT openCV (LINUX)

It is quite easy, you can do read on a videodevice, after you have activated some ioctls to get the cam under your control.

You can use v4l2 for this job. You do this in those steps:

  1. Open the devicefile of the camera (usually "/dev/video0")
  2. Tell v4l2 that you want to know some capability of the device
  3. Tell v4l2 to read from the device
  4. Tell v4l2 wich format you want to use

Here is a implementation I use for this job. It will set the camera to capture a video in 320x240 Pixel, but you can read the resolutions, the camera is capable of from the v4l2_capability structure.

Also I haven't tested the code on different Cameras than my PS2 EyeToy, but it is mostly taken from a sample program named qv4l2 (you can get it from here). This program should solve all other issues you usually see there.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> /* low-level i/o */
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>

#include <linux/videodev2.h>

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

int allocCamera(const char* file)
{
struct v4l2_capability cap;
struct v4l2_crop crop;
struct v4l2_format fmt;

int camera_fd = open(file, O_RDONLY);

if (-1 == xioctl (camera_fd, VIDIOC_QUERYCAP, &cap)) {
if (EINVAL == errno) {
fprintf (stderr, "%s is no V4L2 device\n", file);
exit (EXIT_FAILURE);
} else {
printf("\nError in ioctl VIDIOC_QUERYCAP\n\n");
exit(0);
}
}

if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf (stderr, "%s is no video capture device\n", file);
exit (EXIT_FAILURE);
}

if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
fprintf (stderr, "%s does not support read i/o\n", file);
exit (EXIT_FAILURE);
}

memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (-1 == xioctl(camera_fd, VIDIOC_S_FMT, &fmt)) {
printf("VIDIOC_S_FMT");
}
return camera_fd;
}


Related Topics



Leave a reply



Submit