Strony

Pokazywanie postów oznaczonych etykietą webcam. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą webcam. Pokaż wszystkie posty

piątek, 17 maja 2013

(simple) webcam image analysis

Here I present simple webcam image analysis and it's variation in time.

Intro


I have a webcam, connected to my Raspberry Pi server. Photos are taken every five minutes with fswebcam. Such collection of photos you can use for creating eg. time lapse video (here is an example of one-day video taken from my window). But you can also perform an analysis of image composition and it's variation over time.

Howto


Gathering data


Wen we have photos taken during a day gargered in one directory, we can use a simple script to analyse subsequent frames. ImageMagick is used to convert photos to 1x1 px size and get their HSB and RGB values.

#!/bin/bash

OUT=webcam.dat

echo "#i        h       s       v       r       g       b" > $OUT

for image in *.jpg
do

((i++))

hsb=`convert "$image" -colorspace hsb  -resize 1x1  txt:- | sed 1d  | tr '()%,:' ' '`

h=`echo $hsb | awk '{print $8}'`
s=`echo $hsb | awk '{print $9}'`
v=`echo $hsb | awk '{print $10}'`

rgb=`convert "$image" -colorspace rgb  -resize 1x1  txt:- | sed 1d  | tr '()%,:' ' '`

r=`echo $rgb | awk '{print $3}'`
g=`echo $rgb | awk '{print $4}'`
b=`echo $rgb | awk '{print $5}'`

echo "$i        $h      $s      $v      $r      $g      $b" >> $OUT

done

Data visualisation


Then we use a gnuplot script to get pretty plots:

set pointsize 2
# Line style for axes
set style line 80 lt rgb "#808080"
# Line style for grid
set style line 81 lt 0  # dashed
set style line 81 lt rgb "#808080"  # grey
set grid back linestyle 81
set border 3 back linestyle 80
set xtics nomirror
set ytics nomirror
set xlabel "frame number"
set terminal png nocrop enhanced font "Gill Sans,8" size 700,500

plik='webcam.dat'

set ylabel "HSB [%]"

set output "out/hsv-csplines.png"
plot plik using 1:2 smooth csplines title "Hue" lt rgb "red" lw 1,\
plik using 1:3 smooth csplines title "Saturation" lt rgb "green" lw 1,\
plik using 1:4 smooth csplines title "Brightness" lt rgb "blue" lw 1

set output "out/hsv-bezier.png"
plot plik using 1:2 smooth bezier title "Hue" lt rgb "red" lw 1,\
plik using 1:3 smooth bezier title "Saturation" lt rgb "green" lw 1,\
plik using 1:4 smooth bezier title "Brightness" lt rgb "blue" lw 1

set ylabel "RGB"

set output "out/rgb-csplines.png"
plot plik using 1:5 smooth csplines title "Red" lt rgb "red" lw 1,\
plik using 1:6 smooth csplines title "Green" lt rgb "green" lw 1,\
plik using 1:7 smooth csplines title "Blue" lt rgb "blue" lw 1

set output "out/rgb-bezier.png"
plot plik using 1:5 smooth bezier title "Red" lt rgb "red" lw 1,\
plik using 1:6 smooth bezier title "Green" lt rgb "green" lw 1,\
plik using 1:7 smooth bezier title "Blue" lt rgb "blue" lw 1


Output: plots


HSB, with different methods of curves smoothing

 

RGB, with different methods of curves smoothing

 

Live monitoring


To get the plots almost live, we can use rrdtool to gather, store and plot those data. First, create rrd database:


#!/bin/bash
rrdtool create hsb-rgb.rrd \
--step 300 \
DS:h:GAUGE:600:0:100 \
DS:s:GAUGE:600:0:100 \
DS:j:GAUGE:600:0:100 \
DS:r:GAUGE:600:0:255 \
DS:g:GAUGE:600:0:255 \
DS:b:GAUGE:600:0:255 \
RRA:AVERAGE:0.5:1:288                   \
RRA:AVERAGE:0.5:6:336                   \
RRA:AVERAGE:0.5:24:732                  \
RRA:AVERAGE:0.5:144:14600       \
RRA:MIN:0.5:1:288                       \
RRA:MIN:0.5:6:336                       \
RRA:MIN:0.5:24:732                      \
RRA:MIN:0.5:144:14600   \
RRA:MAX:0.5:1:288                       \
RRA:MAX:0.5:6:336                       \
RRA:MAX:0.5:24:732                      \
RRA:MAX:0.5:144:14600



Then add such lines to your webcam script (launched from cron every 5 minutes). $OUT_FILE is variable pointing to a just taken photo.

hsb=`convert "$OUT_FILE" -colorspace hsb  -resize 1x1  txt:- | sed 1d  | tr '()%,:' ' '`

h=`echo $hsb | awk '{print $8}'`
s=`echo $hsb | awk '{print $9}'`
v=`echo $hsb | awk '{print $10}'`

rgb=`convert "$OUT_FILE" -colorspace rgb  -resize 1x1  txt:- | sed 1d  | tr '()%,:' ' '`

r=`echo $rgb | awk '{print $3}'`
g=`echo $rgb | awk '{print $4}'`
b=`echo $rgb | awk '{print $5}'`

# update rrd database:
rrdtool update hsb-rgb.rrd "N:$h:$s:$v:$r:$g:$b"


Finally, after some data are collected, we can plot a nice graph (actually, we can plot it every five minutes, as new data arrives):

#!/bin/bash

BAZA=hsb-rgb.rrd

rrdtool graph hsb-24h.png  \
        --imgformat PNG \
        --start "now-24h"\
        --title="HSB [%]"       \
        --height 240    \
        --width 420    \
        --lazy \
        --alt-autoscale \
        --alt-y-grid \
        DEF:h=$BAZA:h:AVERAGE \
        DEF:s=$BAZA:s:AVERAGE \
        DEF:j=$BAZA:j:AVERAGE \
        LINE2:h#FF0000:"Hue"\
        LINE2:s#00FF00:"Saturation"\
        LINE2:j#0000FF:"Brightness"</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFCZoyRIhEXYQEgSiiI3RGEZFtSfnJog6hNDprEf8JzjU7_1v8DCDAnxSUuxBcq3tqSYGJkfdr4UoZ2rHV-BBREHFU8KE4Flnob8XnD7_5PhWOzuxG9B8sidzWmhX8PGtMGFU0Rlo_l7XL/s1600/HSB-24h.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFCZoyRIhEXYQEgSiiI3RGEZFtSfnJog6hNDprEf8JzjU7_1v8DCDAnxSUuxBcq3tqSYGJkfdr4UoZ2rHV-BBREHFU8KE4Flnob8XnD7_5PhWOzuxG9B8sidzWmhX8PGtMGFU0Rlo_l7XL/s320/HSB-24h.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyGserUs6dUyqdudZA5_UagqTuZTj_weClykD_LKd_6ENAYSKw5tuqsugFVGbGH73rxJAH1kDhs2dCF_DBLB_H_dxZsD6k7XRRYFcdzP9uVgJKxIdA675z53hNIAeX0BXE2UsswMLBRK9D/s1600/RGB-24h.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyGserUs6dUyqdudZA5_UagqTuZTj_weClykD_LKd_6ENAYSKw5tuqsugFVGbGH73rxJAH1kDhs2dCF_DBLB_H_dxZsD6k7XRRYFcdzP9uVgJKxIdA675z53hNIAeX0BXE2UsswMLBRK9D/s320/RGB-24h.png" /></a>


Conclusions

I don't know, if this makes any sense, but looks cool :)

sobota, 6 kwietnia 2013

Enhance night images from webcam

Night images taken by cheap webcams are usually blurry, pixelized and low quality:


But the quality of final image can be enhanced by averaging multiple subsequent expositions. Here is simple bash script. All we need is:program which takes photo by your webcam (here I use fswebcam) and convert from ImageMagick suite. Both available in repositories of main linux distributions.

    for i in {1..5}
    do
    echo -n "$i "
    fswebcam --save $1.jpg

    sleep 2s
    done

    echo
    echo "Averaging...."
    convert *.jpg -evaluate-sequence mean averaged.jpg

This script takes five photos, with two seconds pauses, a nd then "averages" those photos to eliminate artifacts. Here is "averaged" image:


As we can see, the quality is better than before. Good. But next problem is: we would like to perform such averaging only for dark images (images taken in good light conditions are acceptable quality).

Checking image brightness

Simple metod to asses brightness of image. By issuing command:

convert 0.jpg -colorspace hsb  -resize 1x1  txt:-

we gets some information, including "brightness":

# ImageMagick pixel enumeration: 1,1,255,hsb
0,0: (154,193,  1)  #9AC101  hsb(60.441%,75.8801%,0.488289%)

here 0.488289% is brightness.

To get the value, we use some bash tricks:

convert 0.jpg -colorspace hsb  -resize 1x1  txt:- | \
sed 1d | tr '()%' ' ' | awk -F "," '{print $6}'

then we can make some conditional if to check if image brightness is acceptable or low - in this case we will perform averaging. The script could look like:


#!/bin/bash

OUTPUT_DIR=/var/www/webcam/`date +"%Y/%m/%d"`
OUT_FILE=`date +"%Y-%m-%d_%H:%M:%S"`
TEMP=/var/www/webcam/temp

BRIGHTNESS_TRESHOLD_MIN=10      # for too dark images
BRIGHTNESS_TRESHOLD_MAX=60      # for too bright images


mkdir -p $OUTPUT_DIR
mkdir -p $TEMP



function take_photo {
fswebcam  -S 32 --jpeg 65 \
        -r 640x480 \
        --banner-colour "#35000000" --line-colour "#35000000" \
        --timestamp "%Y-%m-%d %H:%M (%Z)" \
        --set lights=off \
        --set "White Balance Temperature, Auto"=True \
        --set brightness=$2  \
        -q \
        --set "Saturation"=58 \
        --save $TEMP/$1.jpg
}


echo ------------------------ first photo -------------

take_photo 0 "50%"

jasnosc=`convert $TEMP/0.jpg -colorspace hsb  -resize 1x1  txt:- | \
sed 1d | tr '()%' ' ' | awk -F "," '{print $6}'`

#echo `echo "$jasnosc <= $BRIGHTNESS_TRESHOLD" | bc`
#exit

if [ `echo "$jasnosc <= $BRIGHTNESS_TRESHOLD_MIN" | bc` -eq 1 ]
then
    echo -n "Brightness: $jasnosc ... too low - averaging more photos ....: "
    for i in {1..5}
    do
    echo -n "$i "
    take_photo $i "66%"
        sleep 2s
    done

    echo

   echo "Averaging...."
    cd $TEMP
    convert *.jpg -evaluate-sequence mean averaged.jpg
    mv averaged.jpg $OUTPUT_DIR/"$OUT_FILE".jpg
    rm *

elif [ `echo "$jasnosc >= $BRIGHTNESS_TRESHOLD_MAX" | bc` -eq 1 ]
then
    echo "Brightness: $jasnosc ... too high - reducing brightness  ..."
    take_photo 0 "30%"
    mv $TEMP/0.jpg $OUTPUT_DIR/"$OUT_FILE".jpg

else
    echo "Brightness: $jasnosc :  one photo is enoguh ...."
    mv $TEMP/0.jpg $OUTPUT_DIR/"$OUT_FILE".jpg
fi

tehere is another elseif: if image is too bright, we are taking another one with reduced brightness.


Additional features


We can log the calculated brightness and then make a nice plot of this relative brightness during days:


Overexposed images from cheap webcam

It sometimes happens with cheap webcams, that as images taken inside (in the room) are well exposed, the images taken outside (eg from window) are far too bright. They are overexposed. This is because those webcams have fixed aperture, which is set for low light environment (like room). When we want to take photo outside, especially during sunny day, too much light gets into the sensor and image is too bright:

The solution could be disassemble the camera and install new aperture, with smaller hole (like here). But there is simpler (and probably better) solution.

Our cheap webcam needs sunglasses. Yes:






After this operation, the images are better exposed:



Of course, the best solution would be obtaining camera with adjustable aperture :)