Here is a nifty tool from netpbm called "pnmpsnr":
pnmpsnr reads two PBM, PGM, or PPM files, or PAM equivalents, as input and prints the peak signal-to-noise ratio (PSNR) difference between the two images. This metric is typically used in image compression papers to rate the distortion between original and decoded image.Feed it two images and it shows the difference in dB for each color element (Y, Cb, and Cr). The change in Y (luma) between comparing image "A" to "B", then "B" to "C", seems to give a good enough indication of something substantial changing in the image.
For example, compare the ouptut of pnmpsnr
between these
three pairs of images. Three pairs are shown so you can compare the sameness
as well as the difference.
You can move the mouse over the left image in each pair to see how the images change:
$ /usr/bin/pnmpsnr a0.pnm a1.pnm pnmpsnr: PSNR between a0.pnm and a1.pnm: pnmpsnr: Y color component: 34.94 dB pnmpsnr: Cb color component: 41.38 dB pnmpsnr: Cr color component: 40.54 dB
$ /usr/bin/pnmpsnr a1.pnm a2.pnm pnmpsnr: PSNR between a1.pnm and a2.pnm: pnmpsnr: Y color component: 34.22 dB pnmpsnr: Cb color component: 41.37 dB pnmpsnr: Cr color component: 40.54 dB
$ /usr/bin/pnmpsnr a2.pnm a3.pnm pnmpsnr: PSNR between a2.pnm and a3.pnm: pnmpsnr: Y color component: 23.58 dB pnmpsnr: Cb color component: 40.04 dB pnmpsnr: Cr color component: 37.81 dBIn summary:
Y (a->b): 34.94 dB Y (b->c): 34.22 dB (-0.72 dB, tiny change) Y (c->d): 23.58 dB (-10.64 dB, large change)Therefore, writing a mon script to detect a substantial change in an image is trivial:
Here's a first-try implementation that actually works. For illustration, some almost pseudocode so you can get the idea about how it operates:
$SECS = 5; $TOLERANCE = 10; $COUNT = 20; $lastY = undef; $Y = undef; $MOVEMENT = 0; $prev_img = getimage; sleep $SECS; # # this will run until $COUNT images are sampled or until a change # in the image is identified # for ($i = 0; $i < $COUNT; $i++) { $cur_img = getimage; $output = `pnmpsnr $prev_img $cur_img`; ($Y) = ($output =~ /Y.*component: (\d+(\.\d+)?)/) if (defined $lastY && abs ($Y - $lastY) > $TOLERANCE) { $MOVEMENT++; last; } sleep $SECS; } # eventually give the mon server a status update exit ($MOVEMENT);