This is a personal blog. The opinions expressed here represent my own and not those of my employer.

Webcam as light sensor

Sun 18 August 2013

I'd like to automatically start a music player when the light is turned on and stop it when the light is turned off. I didn't find any cheap USB light sensor, so I decide to go with a 4$ webcam.

Thanks to ImageMagick, mplayer and stackoverflow, this is really easy to convert a webcam to a light sensor!

Take images from a webcam

mplayer allows to take a series of consecutive pictures from the webcam with the following line:

mplayer -vo png -frames <number of picture> tv://

Note: generally the first images are green (because the webcam is not yet started ?).

Compute image brightness

The trick is to resize the image to 1x1 pixel with ImageMagick. The pixel represents the average color of the picture, by reading this pixel in HSB format we can directly get the average brigthness.

convert 00000003.png -colorspace hsb -resize 1x1 txt:-

Output:

# ImageMagick pixel enumeration: 1,1,255,hsb
0,0: ( 61, 62,134)  #3D3E86  hsb(24.1138%,24.1764%,52.4941%)

Extract the brightness

We are interested in the brightness value 52.4941%

echo previousOutput | tail -n 1 | sed -r 's/.*hsb\([^,]+,[^,]+,([^.%]+).*$/\1/gm'

Output:

52

Wrap it in a script

The script below checks every 5 seconds if the light has been turned on or off.

#!/bin/bash

ON=1
OFF=0
BRIGHTNESS_AVERAGE=0
BRIGHTNESS_THRESHOLD_ON=6
BRIGHTNESS_THRESHOLD_OFF=3
LIGHT_STATE=$OFF

function when_light_switch_on {
  echo "Light has been switch ON !"
}

function when_light_switch_off {
  echo "Light has been switch OFF!"
}

function update_average_brightness {
  mplayer -vo png -frames 3 tv://

  OUTPUT=`convert 00000003.png -colorspace hsb -resize 1x1 txt:- | tail -n 1`

  # when the pixel is black the output change 
  # BLACK:
  # 0,0: (  0,  0,  0)  #000000  black
  # OTHERWISE:
  # 0,0: ( 35,255, 36)  #23FF24  hsb(13.7072%,99.855%,14.1161%)

  IS_BLACK=`echo $OUTPUT | grep -q "black"; echo $?`
  if [ $IS_BLACK -eq 0 ]
  then
    BRIGHTNESS_AVERAGE=0
  else
    BRIGHTNESS_AVERAGE=`echo $OUTPUT | sed -r 's/.*hsb\([^,]+,[^,]+,([^.%]+).*$/\1/gm'`
  fi
}

# better to extract the picture taken from the webcam directly in memory
# /run is mounted as tmpfs on Ubuntu
cd /run/shm

while :
do
  update_average_brightness;

  if [ $BRIGHTNESS_AVERAGE -gt $BRIGHTNESS_THRESHOLD_ON ]
  then
      # the light just switch on ?
      if [ $LIGHT_STATE -eq $OFF ]
      then
        LIGHT_STATE=$ON
        when_light_switch_on
      fi
  else
      if [ $BRIGHTNESS_AVERAGE -lt $BRIGHTNESS_THRESHOLD_OFF ]
      then
        # the light just switch off ?
        if [ $LIGHT_STATE -eq $ON ]
        then
          LIGHT_STATE=$OFF
          when_light_switch_off
        fi
      fi
  fi

  echo "BRIGHTNESS_AVERAGE=$BRIGHTNESS_AVERAGE"
  echo "LIGHT_STATE=$LIGHT_STATE"

  sleep 5
done

References

Comments


Last Articles


Involved in



Guillaume Vaudaux-Ruth