Using webcam to detect changes in the field-of-view.

I've meant for some time to combine live webcam images in a kind of intrusion detection scheeme. There are lots of packages 'out there' up to and including face or registration plate detection. But it's very satisfying to 'brew your own'! I was a also keen to try out the Atl way to show things like animated GIFs in a LB window, and how to incorporate images direct from the webcam.

Of course as soon as I finished I found a great article on how to do it in Mathematica. But unfortunately I can't afford it!

It is a 'work in progress'. I might add code to ftp alarming (!) frames to my webspace... or printout options. We'll see.

The idea was to create a program which compares CURRENT webcam view with a stored STANDARD view. To make the presence of changes stand out, they are displayed two ways. In one screen area you see a FLICKER animation flicking to-and-fro between the two. This has been a standard military way for at least 70 years. Since snoopy11's dll provides things like pretty frames and colour effects, you are welcome to use them, as here! By creating an animated gif you can always use it elsewhere- although I could simply have alternately 'printed' the bitmaps at timed intervals.

The other is to show a DIFFERENCE frame, where pixels that hardly change show black, and ones in areas that have changed show bright. By using ImageMagick I can composite or difference images, and change gamma and threshhold. Still experimenting here! ImageMagick takes a finite, unpredictable time to complete, so delays are built in. If closing doesn't seem to have worked, wait for the timeout!
The frame below is typical- my head was in different positions for each 'take'.

The code I developed works, if slowly. It uses ImageMagick to make animations and composites of two images. It uses techniques developed by Alyce Watson and snoopy11 for webcam interfacing. It is available to download. UnZip it to your LB working directory. The code below will not work on its own. It needs IM and the dll, and filepath editing. ImageMagick is freely available on the 'net with instructions. I find it a great add-on.

I never solved why there is a upper-left margin in the Atl window- so I just enlarged it to compensate!
You'll need to edit paths appropriately in the present version- I use Ramdisk R: and a named directory.
NB Note also that you need ImageMagick installed and working.
e-mail me on mr.john.f at if you have problems!

    '   ***************************************************************************
    '   DiffCamMark2k3.bas     JohnF     tenochtitlanuk    Nov 23 2010

    '   Thanks to Alyce (as ever!)   for her ATL explanations.
    '   Thanks to snoopy11           for the LBCam.dll and examples...
    '   Thanks to Janet for the StyleBits explanations- tho' didn't solve my prob!

    '   To-dos:-
    '               alter ergonomics so automatically does a flicker and comparison
    '                   only if current image changes more than a certain amount.
    '               add a print routine.
    '               add 'camera not present' routine?

    '   ***************************************************************************


    UpperLeftX   =  20
    UpperLeftY   =  20
    WindowWidth  = 900
    WindowHeight = 610

    graphicbox #main.gb1,   40, 40, 320, 210
    graphicbox #main.gb2,  400, 40, 320, 210
    graphicbox #main.gb3,   20,310, 350, 250
    graphicbox #main.gb4,  380,310, 350, 250

    button #main.b0, "Quit",         [quit],       LR, 100,  60, 90, 60
    button #main.b1, "Save Static",  [SaveStatic], LR, 100, 400, 90, 60
    button #main.b2, "Anim/Flicker", [MakeAnim],   LR, 100, 200, 90, 60

    statictext #main.st1, "",  70,  10, 900,  30
    statictext #main.st2, "", 770,  40, 100,  30
    statictext #main.st3, "",  70, 270, 600,  30

    hATL    = 0
    cw      = 0
    ch      = 0

    struct Rect, leftX as long, upperY as long, rightX as long, lowerY as long

    quote$  =chr$( 34)
    'f$      = "/C:/Documents%20and%20Settings/Sarita%20Gaytan/My%20Documents/Liberty%20BASIC/Image%20Differencer"
    f$      = "/R:"
    open "LBCam.dll" for Dll as #webcam

    open "DiffCamMark2, Change of Scene Detector" for window_nf as #main

    #main "trapclose [quit]"

    #main.b2 "!hide"

    open "atl" for dll as #atl
    calldll #atl, "AtlAxWinInit", Ret as void

    hBox  = hWnd( #main.gb3)
    hMain = hWnd( #main)

    calldll #user32, "GetWindowLongA", hBox  as ulong, _GWL_HINSTANCE as long, hInst as ulong
    calldll #user32, "GetClientRect",  hMain as ulong, Rect as struct, r as long
    cw = Rect.rightX.struct
    ch = Rect.lowerY.struct

    style = _WS_CHILD or _WS_VISIBLE or _WS_BORDER

    #main.gb1 "up ; goto 1 1 ; color red ; size 4 ; down ; boxfilled 320 210 ; flush"

    #main.st1 "Current ( Dynamic view)              Static ( Saved comparison frame)        Time"
    #main.st3 "          Animation                                            Differences"
    #main.st1 "!font arial 16 bold"
    #main.st2 "!font arial 16 bold"
    #main.st3 "!font arial 16 bold"

    handle = hwnd( #main)

    left    =  40   'x coordinate inside main window of camera live display
    top     =  40   'y coordinate inside main window
    right   = 320   'size of cam window
    bottom  = 210   'size of cam window

    calldll #webcam, "CameraConnect", handle as ulong, left as long, top as long, right as long, bottom as long, hRet as ulong

    timer 500, [localLoop]

    timer 0
    calldll   #webcam, "CameraShow", hRet as ulong, result as void
    #main.gb1  "getbmp  scr 0 0 319 209"
    bmpsave   "scr", "scr1.bmp"
    unloadbmp "scr"
    #main.st2 time$()
    timer 20000, [localLoop]

sub IM command$, delay
    run   "cmd.exe /c "; chr$( 34); command$; chr$( 34), HIDE
    calldll #kernel32, "Sleep", delay as long, re as void
end sub

    #main.gb1  "getbmp  scr 0 0 319 209"
    #main.gb2  "drawbmp scr 0 0"
    #main.gb2 "flush"
    bmpsave   "scr", "scr0.bmp"
    unloadbmp "scr"
    #main.b2 "!show"

    #main.gb1  "getbmp  scr 0 0 319 209"
    bmpsave   "scr", "scr1.bmp"
    unloadbmp "scr"
    call IM "convert -delay 100 -dispose None scr0.bmp scr1.bmp -loop 0 R:/flickered.gif", 20000 ' Created OK but doesn't display correctly

    'fileName$ ="file:///R:/flickered.gif" ' Doesn't work, yet next line does...
    'fileName$ ="file:///C:/Documents%20and%20Settings/Sarita%20Gaytan/My%20Documents/Liberty%20BASIC/Image%20Differencer/flickered.gif"
    'url$      = "file:///R:/animation3.gif" works in other program yet next two lnes don't here.
    'f$        = "/R:"
    'fileName$ ="file://" +f$ +"/flickered.gif"

    fileName$ = "file:///R:/flickered.gif"

    calldll #user32, "CreateWindowExA",  _WS_EX_STATICEDGE as long, "AtlAxWin" as ptr,_
      fileName$ as ptr,   style as long, 0     as long,  0 as long, cw   as long, ch as long,_
      hBox      as ulong, 100   as long, hInst as ulong, 0 as long, hATL as ulong

    #main.gb1  "getbmp  scr 0 0 319 209"
    bmpsave   "scr", "scr1.bmp"
    unloadbmp "scr"
    call IM   "composite scr0.bmp scr1.bmp -compose difference difference.bmp", 10000   'or try      "compare a.gif b.gif diffce.gif"
    call IM   "convert difference.bmp -gamma 10 diffgamma.bmp", 10000
    loadbmp "diffgamma", "diffgamma.bmp"
    #main.gb4 "drawbmp diffgamma 20 20"
    #main.gb4 "flush"

    calldll #webcam, "CameraOff", hRet as ulong, result as void
    close   #main
    close   #webcam
    close   #atl