home / blog / podcasts / notes / photos / about / more

Auto adjust exposure in webcam

on Linux

Posted by Jeena

My parents have a summer house in Poland and we had many problems with people who would break in and break stuff in the house. After a couple of years we got us some CCTV which is working nice but is not extendible.

This year I bought a Intel NUC where I connected two cheap USB webcams and installed Zoneminder on which works really great, the only problem is that the cheap webcam doesn't handle bright daylight very well. During the day the whole picture is mostly just white, and in the evening it is black even though there is still enough light for hours to see.

I tested some settings and saw that all the problems can be fixed by ajusting the exposure of the webcam. So today I wrote a shellscript which downloads a current picture from zoneminder, tests it for how brigt it is and adjusts the exposure slightly so the brightness is always at about 50% (through testing I fround this is a good value).

This is the script, compleatly in bash:

#!/bin/bash

# This script, when run continously with cron, adapts
# the Exposure of a cheap webcam which can't do it on
# on its own.
#
# You need to have installed:
# - ImageMagick
# - curl
# - uvcdynctrl

CAMDEVICE="video0"
STILLURL="http://localhost/cgi-bin/nph-zms?mode=single&monitor=1&scale=100"

EXPOSURE_ORIG=`uvcdynctrl -d /dev/$CAMDEVICE -g "Exposure (Absolute)"`
IMG=/tmp/$CAMDEVICE-latest.jpg
curl -s $STILLURL > $IMG

B=`convert $IMG -colorspace hsb -resize 1x1 txt:- | tail -n1 | tr "," "\n" | tail -n1 | tr "%" "\n" | head -n1`
rm $IMG

OPERATOR=`awk -vb=$B 'BEGIN { print (b >= 50) ? "-" : "+" }'`
EXPOSURE=`echo "$EXPOSURE_ORIG $OPERATOR 1" | bc -l`

if (( $EXPOSURE < 100 )); then # more than 100 exposure is too dark
    sudo uvcdynctrl -d /dev/$CAMDEVICE -s "Exposure (Absolute)" $EXPOSURE
fi

echo "`date +%D-%H:%M` | b: $B | e: $EXPOSURE_ORIG -> $EXPOSURE"

Have you written a response? Let me know the URL:

There's also indie comments (webmentions) support.