Manual Exposure Control of OpenCV Video

My experiments robot localization have been frustrated by blurry images. Blurry images have been making estimating the position of Aruco tag boards difficult with OpenCV. In my case, the camera is mounted to a moving robot that is photographing tags on other moving robots. Faster shutter speeds may sharpen the images and allow for better estimation.

Controlling shutter speed was more tricky than I first imagined, so I have written this post to document my experience. This approach is very platform dependent, so even small differences may affect your success following in my footsteps.

Some details of my setup:

  • Raspberry Pi Model 3
  • Raspberry Pi Camera V2 – 8 MP
  • OpenCV 3
  • V4L2 Capture Driver

TLDR; Demo Program for Controlling Exposure

#!/local/bin/python3 

import cv2 
import subprocess

# open the capture
cap = cv2.VideoCapture(0) 

# set the exposure after opening the capture to
# avoid opencv modifying settings
command = "v4l2-ctl -d 0 -c auto_exposure=1 -c exposure_time_absolute=200"
output = subprocess.call(command, shell=True)

# watch your changes!
while(True): 
  ret, frame = cap.read() 
  cv2.imshow('frame', frame) 
  if( cv2.waitKey(1) & 0xFF == ord('q') ): 
    break 
cap.release() 
cv2.destroyAllWindows()

This program displays a stream of the camera with shutter speed of 20 milliseconds. If you want, change the exposure_time_absolute value to 400 for an exposure time of 40 milliseconds.

V4L2 Details

Install the V4L2-utils package on your system. To list the available camera controls on your system, use the following command. In my case, video0 is my preferred camera and the currently running camera in my OpenCV program.

$> v4l2-ctl -d /dev/video0 --list-ctrls

Simply setting the exposure_time_absolute value was insufficient, I also had to set the camera to manual exposure.

$> v4l2-ctl -d /dev/video0 -c auto_exposure=1
$> v4l2-ctl -d /dev/video0 -c exposure_time_absolute=100

I’m still working out the units of the exposure time, but it appears to be in 100μs units.

Other interesting settings that I will return to as I have time:

  • iso_sensitivity_auto, (0 = manual, 1 = auto )
  • iso_sensitivity, (0 = 0?, 1 = 100, 2 = 200, 3 = 400, 4 = 800)
  • image_stabilization,
  • exposure_metering_mode,
  • scene_mode,
  • compression_quality.

I have created a demo program here that I will use to demonstrate more parameters.

Interpreting the meaning of the settings:

$> v4l2-ctl --list-ctrls-menus

Related Resources:

This entry was posted in Projects, Robotics and tagged , , , , . Bookmark the permalink.

Leave a Reply