OpenCV

How to set and verify v4l2-ctl parameters in Python using subprocess

The following code uses the v4l2-ctl executable to get and set v4l2 parameters such as exposure_absolute. It also provides means of writing a parameter and verifying if it has been set correctly.

def v4l2_set_parameters_once(params, device="/dev/video0"):
    """
    Given a dict of parameters:
    {
        "exposure_auto": 1,
        "exposure_absolute": 10,
    }
    this function sets those parameters using the v4l2-ctl command line executable
    """
    set_ctrl_str = ",".join([f"{k}={v}" for k,v in params.items()]) # expsosure_absolute=400,exposure_auto=1
    subprocess.check_output(["v4l2-ctl", "-d", device, f"--set-ctrl={set_ctrl_str}"])

def v4l2_get_parameters(params, device="/dev/video0"):
    """
    Query a bunch of v4l2 parameters.
    params is a list like
    [
        "exposure_auto",
        "exposure_absolute"
    ]
    
    Returns a dict of values:
    {
        "exposure_auto": 1,
        "exposure_absolute": 10,
    }
    """
    get_ctrl_str = ",".join([f"{k}" for k in params])
    out = subprocess.check_output(["v4l2-ctl", "-d", device, f"--get-ctrl={get_ctrl_str}"])
    out = out.decode("utf-8")
    result = {}
    for line in out.split("\n"):
        # line should be like "exposure_auto: 1"
        if ":" not in line:
            continue
        k, _, v = line.partition(":")
        result[k.strip()] = v.strip()
    return result

def v4l2_set_params_until_effective(params, device="/dev/video0"):
    """
    Set V4L2 params and check if they have been set correctly.
    If V4L2 does not confirm the parameters correctly, they will be set again until they have an effect
    
    params is a dict like {
        "exposure_auto": 1,
        "exposure_absolute": 10,
    }
    """
    while True:
        v4l2_set_parameters_once(params, device=device)
        result = v4l2_get_parameters(params.keys(), device=device)
        # Check if queried parameters match set parameters
        had_any_mismatch = False
        for k, v in params.items():
            if k not in result:
                raise ValueError(f"Could not query {k}")
            # Note: Values from v4l2 are always strings. So we need to compare as strings
            if str(result.get(k)) != str(v):
                print(f"Mismatch in {k} = {result.get(k)} but should be {v}")
                had_any_mismatch = True
        # Check if there has been any mismatch
        if not had_any_mismatch:
            return

Usage example:

v4l2_set_params_until_effective({
    "exposure_auto": 1,
    "exposure_absolute": 1000,
})

 

Posted by Uli Köhler in Audio/Video, Linux, OpenCV, Python

How to set manual white balance temperature in OpenCV (Python)

Using OpenCV on Linux, if you have a video device that interfaces a V4L2 device such as a USB webcam:

camera = cv2.VideoCapture(0)

in order to set the manual white balance temperature, you first need to disable automatic white balancing using CAP_PROP_AUTO_WB. See our previous post How to enable/disable manual white balance in OpenCV (Python) for more details on how you can do this, here’s only the short version that works with most cameras.

After that, you can set the white balance temperature using CAP_PROP_WB_TEMPERATURE:

camera.set(cv2.CAP_PROP_AUTO_WB, 0.0) # Disable automatic white balance
camera.set(cv2.CAP_PROP_WB_TEMPERATURE, 4200) # Set manual white balance temperature to 4200K

For V4L2 cameras, as you can see in our previous post on mapping of OpenCV parameters to V4L2 parameters, CAP_PROP_WB_TEMPERATURE is mapped to V4L2_CID_WHITE_BALANCE_TEMPERATURE which is shown in v4l2-ctl -d /dev/video0 --all as white_balance_temperature
. Therefore, you can easily verify if, for example, disabling the auto white balance worked for your V4L2 camera such as any USB camera by looking at the white_balance_temperature section of v4l2-ctl -d /dev/video0 --all:

white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=1 default=4600 value=4200
Posted by Uli Köhler in OpenCV, Python

How to enable/disable manual white balance in OpenCV (Python)

Using OpenCV on Linux, if you have a video device that interfaces a V4L2 device such as a USB webcam:

camera = cv2.VideoCapture(0)

you can typically enable automatic white balance (= disable manual white balance) for any camera by using

camera.set(cv2.CAP_PROP_AUTO_WB, 1.0) # Enable automatic white balance

or disable automatic white balance (= enable manual white balance) using

camera.set(cv2.CAP_PROP_AUTO_WB, 0.0) # Disable automatic white balance

When disabling automatic white balance, you should also set the manual white balance temperature – see our post How to set manual white balance temperature in OpenCV (Python)  for more details.

For V4L2 cameras, as you can see in our previous post on mapping of OpenCV parameters to V4L2 parameters, CAP_PROP_AUTO_WB is mapped to V4L2_CID_AUTO_WHITE_BALANCE which is shown in v4l2-ctl -d /dev/video0 --all as white_balance_temperature_auto. Therefore, you can easily verify if, for example, disabling the auto white balance worked for your V4L2 camera such as any USB camera by looking at the white_balance_temperature_auto section of v4l2-ctl -d /dev/video0 --all:

white_balance_temperature_auto 0x0098090c (bool)   : default=1 value=0
Posted by Uli Köhler in OpenCV, Python

How to set V4L2 exposure to manual mode in OpenCV & Python

Using OpenCV on Linux, if you have a video device that interfaces a V4L2 device such as a USB webcam:

camera = cv2.VideoCapture(0)

you can typically set the automatic exposure mode by setting exposure_auto to 1 (the following output is from v4l2-ctl -d /dev/video0 --all):

exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=3 value=1
              1: Manual Mode
              3: Aperture Priority Mode

As you can see in our previous blogpost, exposure_auto (which is named V4L2_CID_EXPOSURE_AUTO in V4L2 in C/C++) is mapped to CAP_PROP_AUTO_EXPOSURE.

Therefore, you can enable manual exposure using

camera.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1) # Set exposure to manual mode

You should, however, verify these settings using v4l2-ctl --all using your specific camera.

Posted by Uli Köhler in OpenCV, Python

How are OpenCV CAP_PROP_… mapped to V4L2 ctrls / parameters?

From both the OpenCV documentation and the V4L2 documentation, it is unclear how all the CAP_PROP_... parameters are mapped to v4l2 controls such as exposure_absolute.

However, you can easily look in the source code (int capPropertyToV4L2(int prop) in cap_v4l.cpp) in order to see how the parameters are mapped internally. Github link to the source code

Continue reading →

Posted by Uli Köhler in Audio/Video, Linux, OpenCV

List of all cv2.CAP_PROP_… properties for OpenCV in Python

This list can be easily obtained using the following Python code:

for v in [k for k in cv2.__dict__.keys() if k.startswith("CAP_PROP")]:
    print(f"cv2.{v}")

Continue reading →

Posted by Uli Köhler in OpenCV, Python

How to always get latest frame from OpenCV VideoCapture in Python

When working with OpenCV video capture, but when you only occasionally use images, you will get older images from the capture buffer.

This code example solves this issue by running a separate capture thread that continually saves images to a temporary buffer.

Therefore, you can always get the latest image from the buffer. The code is based on our basic example How to take a webcam picture using OpenCV in Python

video_capture = cv2.VideoCapture(0)

video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

if not video_capture.isOpened():
    raise Exception("Could not open video device")

class TakeCameraLatestPictureThread(threading.Thread):
    def __init__(self, camera):
        self.camera = camera
        self.frame = None
        super().__init__()
        # Start thread
        self.start()

    def run(self):
        while True:
            ret, self.frame = self.camera.read()

latest_picture = TakeCameraLatestPictureThread(video_capture)

Usage example:

# Convert latest image to the correct colorspace
rgb_img = cv2.cvtColor(latest_picture.frame, cv2.COLOR_BGR2RGB)
# Show
plt.imshow(rgb_img)

 

 

Posted by Uli Köhler in Audio/Video, OpenCV, Python

How to capture Raspi Camera image using OpenCV & Python

First, install OpenCV for Python 3:

sudo apt install python3-opencv

Here’s the code to acquire the image and store it in image.png:

#!/usr/bin/env python3
import cv2
video_capture = cv2.VideoCapture(0)
# Check success
if not video_capture.isOpened():
    raise Exception("Could not open video device")
# Read picture. ret === True on success
ret, frame = video_capture.read()

cv2.imwrite('image.png', frame)
# Close device
video_capture.release()

Run it using

python3 cv-raspicapture.py

 

Posted by Uli Köhler in OpenCV, Python, Raspberry Pi

How to set cv2.VideoCapture() image size in Python

Use cv2.CAP_PROP_FRAME_WIDTH and cv2.CAP_PROP_FRAME_HEIGHT in order to tell OpenCV which image size you would like.

import cv2

video_capture = cv2.VideoCapture(0)
# Check success
if not video_capture.isOpened():
    raise Exception("Could not open video device")
# Set properties. Each returns === True on success (i.e. correct resolution)
video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 160)
video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 120)
# Read picture. ret === True on success
ret, frame = video_capture.read()
# Close device
video_capture.release()

Note that most video capture devices (like webcams) only support specific sets of widths & heights. Use uvcdynctrl -f to find out which resolutions are supported:

$ uvcdynctrl -f
Listing available frame formats for device video0:
Pixel format: YUYV (YUYV 4:2:2; MIME type: video/x-raw-yuv)
  Frame size: 640x480
    Frame rates: 30, 20, 10
  Frame size: 352x288
    Frame rates: 30, 20, 10
  Frame size: 320x240
    Frame rates: 30, 20, 10
  Frame size: 176x144
    Frame rates: 30, 20, 10
  Frame size: 160x120
    Frame rates: 30, 20, 10
Posted by Uli Köhler in OpenCV, Python, Video

How to take a webcam picture using OpenCV in Python

This code opens /dev/video0 and takes a single picture, closing the device afterwards:

import cv2

video_capture = cv2.VideoCapture(0)
# Check success
if not video_capture.isOpened():
    raise Exception("Could not open video device")
# Read picture. ret === True on success
ret, frame = video_capture.read()
# Close device
video_capture.release()

You can also use cv2.VideoCapture("/dev/video0"), but this approach is platform-dependent. cv2.VideoCapture(0) will also open the first video device on non-Linux platforms.

In Jupyter you can display the picture using

import sys
from matplotlib import pyplot as plt

frameRGB = frame[:,:,::-1] # BGR => RGB
plt.imshow(frameRGB)

 

Posted by Uli Köhler in OpenCV, Python, Video