Sign in to follow this  
Followers 0
SIone

Motion sensing with bluetooth forwarding

14 posts in this topic

#1 ·  Posted (edited)

Hi Folks,

Firstly I like to say thanks for those of you who have helping previously with the 'mouse of control' issue i had previously.

Im having to work on this project while having my young son for a while so my time for checking on any replies will be erratic!

Using AMCAP, a driver program supplied with my cheap webcam, and using PixelGetColor, i have managed to contruct a program that creates a rolling average of the displayed image (in steps of 10 pixels to decrease response times), and to detect how much the value changes from each 'capture'.

The issue im trying to address is how to overcome the percentage of change, which is not always linear.

To clarify, if there is a small amount of change i may see a small difference between the rolling averages of each capture BUT the value indicating the amount of change depends on the colours in the picture.( a white car pulling into the car park often goes undetected, but someone with a red jacket on- a smaller object- throws up a bigger difference value.)

I'd be gratefull if you, dear reader, could just throw in any/some suggestions on how to tackle this because.

And before anyone says 'Where is your code', i will upload it asap, but i'm having to use a backup machine while my 'main' PC is undergoing virus removal and restoration (normally this is not a major challange to me but please bear in mind that my time is limited due my responsibilities as outlined above.)

Nearly forgot, but the completed program is to be GUI and the goal is to notify other tennants in our block of flats of visitor by bluetooth by their phones or PC.

Many thanks for bearing wih me, and for any assistance.

SIone

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <SliderConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Include <ScreenCapture.au3>
Global $roll =0
Global $count =0
Global $avg = 0
Global $sus =0
Global $sensitivity=0
Global $ndsEvents=0
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=C:\Documents and Settings\Luser1\Desktop\Kids Games\WebCamSecurity.kxf
$Form2 = GUICreate("Nigels WebCam Security Program V1.2  30-6-08", 367, 147, 411, 377)
GUISetOnEvent($GUI_EVENT_CLOSE, "Form2Close")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "Form2Minimize")
GUISetOnEvent($GUI_EVENT_MAXIMIZE, "Form2Maximize")
GUISetOnEvent($GUI_EVENT_RESTORE, "Form2Restore")
$Button1 = GUICtrlCreateButton("Start", 8, 8, 75, 25, 0)
GUICtrlSetOnEvent(-1, "Button1Click")
$Button2 = GUICtrlCreateButton("STOP", 96, 8, 75, 25, 0)
GUICtrlSetOnEvent(-1, "Button2Click")
$Slider1 = GUICtrlCreateSlider(8, 72, 345, 25)
GUICtrlSetOnEvent(-1, "Slider1Change")
$Label1 = GUICtrlCreateLabel("Sensitivity Sider", 136, 48, 78, 17)
GUICtrlSetOnEvent(-1, "Label1Click")
$Label2 = GUICtrlCreateLabel("Events Detected", 16, 120, 84, 17)
GUICtrlSetOnEvent(-1, "Label2Click")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    Sleep(200)
WEnd

Func ScanAMCAP()
    $roll=0
    For $y = 50 to 320 step 10
        for $x = 10 to 350 step 10
            $pval = PixelGetColor($x,$y)
            $roll = $roll + $pval
            $count = $count+ 1
        Next
    Next
    Return $roll & $count
EndFunc

Func Button1Click(); the start button 
    Run("C:\Program Files\USB PC Cam Plus\Amcap.exe")
    TrayTip("AMCAP is running","Please wait for the camera to stablise!",10)
    Sleep(5000)
    WinMove("AMCAP","",0,0)
    Sleep(250)
    $ndsi = 0
    while $ndsi <> 9
        Sleep(200)
        ScanAMCAP(); perform the scan
        $Aavg = $roll/$count; 
        $ndsx = Round($Aavg,-1)
        if $ndsx >= $sensitivity*10000 Then
            $ndsEvents = $ndsEvents + 1
            GUICtrlCreateLabel($ndsEvents, 110, 120, 84, 17)
            endif
    WEnd
EndFunc

Func Button2Click()

EndFunc
Func Form2Close()
    Exit
EndFunc
Func Form2Maximize()

EndFunc
Func Form2Minimize()

EndFunc
Func Form2Restore()

EndFunc
Func Label1Click()

EndFunc
Func Label2Click()

EndFunc
Func Slider1Change()
 $ndsSen = GuiCtrlRead($Slider1)
 $Label3 = GUICtrlCreateLabel($ndsSen&"%", 220, 48, 78, 17)
 $sensitivity = $ndsSen
EndFunc

Thank god for backups......

WebCamSecurityApp.au3

Edited by SIone

Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites



Bump!

Just to add that i have most of the bluetooth work done, as a seperate code project, and plan to consolidate it when i have solved this problem with threshold detection before and i can test it and then release the code for all to enjoy.

Any and all advise/tips/suggestions are appreciated!


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

bump


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

I don't know if the following is usefull but:

I would first try to define when a color is a bit different, somewhat different or very different from another color. Maybe put that in a function.

Then make a routine that via a pattern or randomly take pixel samples (or block of pixels) from the image, store it (array?) and then compare it with the next 'snapshot'.


My active project(s): A-maze-ing generator (generates a maze)

My archived project(s): Pong3 (Multi-pinger)

Share this post


Link to post
Share on other sites

I don't know if the following is usefull but:

I would first try to define when a color is a bit different, somewhat different or very different from another color. Maybe put that in a function.

Then make a routine that via a pattern or randomly take pixel samples (or block of pixels) from the image, store it (array?) and then compare it with the next 'snapshot'.

Thanks for your suggestion.

The main issue is detecting the threshold of change, so when the sensitivity slider is set, say to 50%, i can find a 50% change in the rolling average.

I did try using arrays, but the performance of the PC that this is going to run on is very poor (333Mhz 32MB Ram P2), hence the rolling average method im using at present.

I think its a maths method im overlooking, but your idea of using blocks gives me an idea: to target certain areas, such as the entrance to our car park, with a smaller step (high resolution of testing).

Although, if i get time today, I will also try black and white mode for the 'scan' and then change AMCAP to colour for the capture before sending via BT.


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

If you don't have the processing power to generate a sensitivity list then you should limit your sensitivity to 4 or 5 possible settings and precalculate the list. (And then depending on the chosen setting read it from a certain text file?)

This will discard your main issue muttley

Edit:

This picture is somewhat a visualisation of what I mean.

Rules: Within the blue area put the pixels of the red area in a variable/array.

Do that two times for two pictures and compare those according to the above sentitivity choice.

post-20969-1216114436_thumb.jpg

Edited by Triblade

My active project(s): A-maze-ing generator (generates a maze)

My archived project(s): Pong3 (Multi-pinger)

Share this post


Link to post
Share on other sites

If you don't have the processing power to generate a sensitivity list then you should limit your sensitivity to 4 or 5 possible settings and precalculate the list. (And then depending on the chosen setting read it from a certain text file?)

This will discard your main issue :)

Edit:

This picture is somewhat a visualisation of what I mean.

Rules: Within the blue area put the pixels of the red area in a variable/array.

Do that two times for two pictures and compare those according to the above sentitivity choice.

Now thats the kind of smarts I like!

Thank you!

Even the target machine should be able to deal with the smaller scan areas - I'll just have to glue the cam down to enure it cant move.

I'm on it now so i'll post it all up as soon as done and tested.

Cheers again,

SIone

P.S. I may have the code paste an image of the terminator into the forwarded images on april fools to see who's awake..... muttley


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

Now thats the kind of smarts I like!

Thank you!

If you have to much information (pixels) to gather and save, just think very simple like me and reduce the amount of data.

Np, that's what's the forum for :)

I'll just have to glue the cam down to enure it cant move.

Good luck AutoItting that muttley

I'm on it now so i'll post it all up as soon as done and tested.

Cool.

My active project(s): A-maze-ing generator (generates a maze)

My archived project(s): Pong3 (Multi-pinger)

Share this post


Link to post
Share on other sites

Well, i've been on this now for a while:

The crux of the matter is the problem of the rolling average.

No matter the number or location of pixels the same problem keeps raising it head: how to perform a rolling average.

I know that arrays will hold the answer here, so im wondering if someone can provide a quick pointer.

and then i can translate a code example on http://www.codeproject.com/KB/recipes/Simp...ingAverage.aspx


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Speed is a big concern here. I see you are using PixelGetColor() which is entirely wrong for your needs. Most likely you can use GDI+ to do the heavy lifting. I recently posted an example of how to use the _GDIPlus_BitmapLockBits function which would shows there are faster ways to retrieve an area of pixels.

http://www.autoitscript.com/forum/index.ph...amp;hl=lockbits

What this function does is takes a handle to a GDI Bitmap object and locks a portion of it for reading or writing. When you lock an area, you can quickly dump all of the pixels or write to them directly.

EDIT:

Also it looks to me like you are loading up webcam software and reading pixels directly from the screen, this is very wasteful. There are examples in this forum of how to grab an image directly from your webcam.

http://www.autoitscript.com/forum/index.ph...5&hl=webcam

Edited by weaponx

Share this post


Link to post
Share on other sites

Speed is a big concern here. I see you are using PixelGetColor() which is entirely wrong for your needs. Most likely you can use GDI+ to do the heavy lifting. I recently posted an example of how to use the _GDIPlus_BitmapLockBits function which would shows there are faster ways to retrieve an area of pixels.

http://www.autoitscript.com/forum/index.ph...amp;hl=lockbits

What this function does is takes a handle to a GDI Bitmap object and locks a portion of it for reading or writing. When you lock an area, you can quickly dump all of the pixels or write to them directly.

EDIT:

Also it looks to me like you are loading up webcam software and reading pixels directly from the screen, this is very wasteful. There are examples in this forum of how to grab an image directly from your webcam.

http://www.autoitscript.com/forum/index.ph...5&hl=webcam

Thanks for your input: i had stumbled upon the _GDI, and i WILL be making a start to digest how it works soon.

My time on this project is limited to the time my son spends sleeping, so please bear with me...

In the meanwhile I have solved the rolling samples and trend spottingproblem so i can detect when a threshold has been reached.

So far with the methods i know i have made a program that tests the pixel colour under the mouse.

The idea being that ANY webcam software can be used in conjunction with this script.

It does seem to work quite quickly, and if you run a fast (2GHz and upwards) PC you many need to insert a sleep at the start of the for loop used to collect the samples overwise it will act as being too sensitive due to the real-time element of motion detection!

I know that this has some ugly methods but i have tested this and with a $threshold =250 it is perfect for spotting cars pulling into our drive at nightime.

Here is my code: (p.s. to change the how sensitive the program adjust the value of $threshold!)

;new try
;get 10 samples
;get the average for the 10 samples
; get another 10 samples and the average for them
; compare the 2 sets of averages and print them out
;2-8-08 need to functionise the 'trim up' proceduce that normalised the maths results for threshold testing
;   when debuging i noticed that the program beeps twice for notification of car headlings in the pm.
;   need to deal with 1st and second notification events
#include <ScreenCapture.au3>
#Include <Date.au3>
global $avg=0
Global $secavg=0
global $roll=0
Global $rll=0
local $nds
Global $diff
Global $threshold=400
HotKeySet("{F4}","nds"); kill the program.
$old = 0
Sleep(1000); wait while i get the pointer into place
Beep(500,10);beep to let me know the process is starting
While 1;----------------------------------------------------------------------------------Start of main program.
    $nds = $diff; remember the previous result.
            ; need to remember that this means just 2 points of change are considered
                
    roll();     collect, generate, and store the rolling average.
    
    $diff = int($old-$avg); remove any decimal points generated by the averaging process.---------$old used here
    $u = StringInStr($diff,"-",0,1); test the first character is to see if it a "-"
    if $u = 1 Then              ; if - is present then clean it up
        $dog = StringTrimLeft($diff,1); then remove the 1st diget from the string.
        $diff=$dog                  ; and store the modified string.
    EndIf   
;ConsoleWrite("Difference ="&$diff)
    $test = $nds-$diff              ;store the difference between present and previous results
    $o = StringInStr($test,"-",0,1) ; and again check to see if the var string starts with a -neg sign.
    if $o = 1 Then                  ;check if the strings needs a cleanup
        $tat = StringTrimLeft($test,1); and is its there then remove the 1st character from the string.
        $test=$tat              ; and save the modified string in the $test variable.
    EndIf
    
    if $test > $threshold Then;         now to see if the change of average colour code samples goes over a 200 value threshold.
        Beep(900,20)            ;if it does then sound a beep for debuging purposes.
        $nme = _now()           ;get now time and date.
        ConsoleWrite(">test ="&$nme&"@"&$test&@lf); and display the difference in the console also for debug.
    EndIf   
    $old = $avg                 ;copy the contents of the average-----but for what reason:where is $old used?
WEnd;'-------------------------------------Main program ^^^^^^^^^^^^^^^

;ConsoleWrite("Difference ="&$diff&@lf)
func roll();                        get the a set of 10 samples
;housekeeping
    $e=0
    $p=0
    $roll = 0
    for $e = 0 to 9             ;working with 10 samples
        $x = MouseGetPos()      ;get the mouse position for monitoring pixel colour
        $z = PixelGetColor($x[0],$x[1]);get the colour codes for the spot the mouse is at.
        $p = int($z/10000)          ; make the math easyier by making the numbers smaller and removing any - signs
        $roll=$roll+$p              ;add the number of code sames: sum up
        $avg = int($roll/10)    ;now get the average
    Next                    ;do the above in the for loop.
    Return($avg)            ; return from the function with the average of the samples.
EndFunc


Func nds()
    Exit
EndFunc

Now i am working on 'mating' the detect event beep with the program i have that sends a capture off via bluetooth.

Please feel free to comment: i only respond to positive input!

Cheers,

sione


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

Not sure if this helps but I've found that when there is this sort of setup:

For $x=1 to 100

PixelGetColor($x,1)

Next

the speed is not very good. I found out that simply writing out this

PixelGetColor(1,1)

PixelGetColor(2,1)

PixelGetColor(3,1)

PixelGetColor(4,1)

...

makes the script run faster.

(but again I don't know if this would help)


Trust me to make SkyNet with AutoIt...

Share this post


Link to post
Share on other sites

Not sure if this helps but I've found that when there is this sort of setup:

For $x=1 to 100

PixelGetColor($x,1)

Next

the speed is not very good. I found out that simply writing out this

PixelGetColor(1,1)

PixelGetColor(2,1)

PixelGetColor(3,1)

PixelGetColor(4,1)

...

makes the script run faster.

(but again I don't know if this would help)

Thanks for the heads-up about the speed of that method.

I was using a variable amount of samples to find the balance of samples/accuracy on this pc before putting it onto the steam powered machine that it will end up living in.

Basicly a way of compensating for real-time events and guarding against false alert events due to real time issues.

So,yes when i have sussed how many samples i need i can drop the loop and straight-code it as you sugggest.

Thanks,

SIone


Perilous to all of us are the devices of an art deeper than we ourselves possess.

Share this post


Link to post
Share on other sites

Im having to work on this project while having my young son for a while so my time for checking on any replies will be erratic!

============

Using AMCAP, a driver program supplied with my cheap webcam, and using PixelGetColor, i have managed to contruct a program that creates a rolling average of the displayed image (in steps of 10 pixels to decrease response times), and to detect how much the value changes from each 'capture'.

============

Nearly forgot, but the completed program is to be GUI and the goal is to notify other tenants in our block of flats of visitor by bluetooth by their phones or PC.

Some web cams come with baby monitoring software. Maybe you can adapt one of these to link any alert raised to a bluetooth alert. Keep in mind that bluetooth (by design) is very short range - you may not get enough signal strength to reach other tenants.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0