The Red code is based on the following paper: Collins, R., Lipton, A., Kanade, T., Fijiyoshi, H., Duggins, D., Tsin, Y., Tolliver, D., Enomoto, N., Hasegawa, O., Burt, P., Wixson, L.: A system for video surveillance and monitoring. Tech. rep., Carnegie Mellon University, Pittsburg, PA (2000).
The idea is to use the webcam and analyse motion using differential images.
Differential Images
Differential Images are the result of the subtraction of two images: Idif (x, y) = I1(x, y) − I2(x, y).
Based on the quoted paper, we use a differential image calculated from three consecutive images It−1 (previous image), It (current image) and It+1 (next image). The advantage of this technic is that the motionless background is removed from the result, and only motion pixels are visible.
RedCV offers the possibility to subtract two images from each other using rcvAbsDiff. Since logical operations on images are also implemented, we use rcvAnd to achieve the final differential image.
Code
Implemented code is simple to understand and just requires a time event to activate the camera. When the time event occurs, differential image is calculated and updated in the base object. To-image Red function allows to copy the webcam image to a Red image. Thanks Red!
Red [
Title: "Test image operators and camera Red VID "
Author: "Francois Jouen"
File: %motion.red
Needs: 'View
]
; all we need for computer vision with red
#include %../../libs/redcv.red ; for red functions
iSize: 320x240
prevImg: rcvCreateImage iSize
currImg: rcvCreateImage iSize
nextImg: rcvCreateImage iSize
d1: rcvCreateImage iSize
d2: rcvCreateImage iSize
r1: rcvCreateImage iSize
r2: rcvCreateImage iSize
margins: 10x10
threshold: 32
to-text: function [val][form to integer! 0.5 + 128 * any [val 0]]
view win: layout [
title "Motion Detection"
origin margins space margins
text "Motion " 50
motion: field 50 rate 0:0:1 on-time [face/text: to-text rcvCountNonZero r2]
btnQuit: button "Quit" 60x24 on-click [
rcvReleaseImage prevImg
rcvReleaseImage currImg
rcvReleaseImage nextImg
rcvReleaseImage d1
rcvReleaseImage d2
rcvReleaseImage r1
rcvReleaseImage r2
quit]
return
cam: camera iSize
canvas: base 320x240 r2 rate 0:0:1 on-time [
rcv2gray/average nextImg currImg ; transforms to grayscale since, we don't need color
rcvAbsdiff prevImg currImg d1 ; difference between previous and current image
rcvAbsdiff currImg nextImg d2 ; difference between current and next image
rcvAnd d1 d2 r1 ; AND differences
rcv2BWFilter r1 r2 threshold ; Applies B&W Filter to base/image
prevImg: currImg ; previous image contains now the current image
currImg: nextImg ; current image contains the next image
nextImg: to-image cam ; updates next image
]
return
text 40 "Select"
cam-list: drop-list 180x32 on-create [
face/data: cam/data
]
onoff: button "Start/Stop" 80x24 on-click [
either cam/selected [
cam/selected: none
canvas/rate: none
motion/rate: none
canvas/image: black
][
cam/selected: cam-list/selected
rcvZeroImage prevImg
rcvZeroImage currImg
rcvZeroImage nextImg
canvas/rate: 0:0:0.04; max 1/25 fps in ms
motion/rate: 0:0:0.04
]
]
text "Filter" 40
sl1: slider 180 [filter/text: to-text sl1/data threshold: to integer! filter/data ]
filter: field 40 "32"
do [cam-list/selected: 1 motion/rate: canvas/rate: none sl1/data: 0.32 ]
]