SIone Posted July 12, 2008 Share Posted July 12, 2008 (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 expandcollapse popup#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 July 12, 2008 by SIone Perilous to all of us are the devices of an art deeper than we ourselves possess. Link to comment Share on other sites More sharing options...
SIone Posted July 13, 2008 Author Share Posted July 13, 2008 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. Link to comment Share on other sites More sharing options...
SIone Posted July 15, 2008 Author Share Posted July 15, 2008 bump Perilous to all of us are the devices of an art deeper than we ourselves possess. Link to comment Share on other sites More sharing options...
Triblade Posted July 15, 2008 Share Posted July 15, 2008 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) Link to comment Share on other sites More sharing options...
SIone Posted July 15, 2008 Author Share Posted July 15, 2008 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. Link to comment Share on other sites More sharing options...
Triblade Posted July 15, 2008 Share Posted July 15, 2008 (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 muttleyEdit: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. Edited July 15, 2008 by Triblade My active project(s): A-maze-ing generator (generates a maze) My archived project(s):Â Pong3 (Multi-pinger) Link to comment Share on other sites More sharing options...
SIone Posted July 15, 2008 Author Share Posted July 15, 2008 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,SIoneP.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. Link to comment Share on other sites More sharing options...
Triblade Posted July 15, 2008 Share Posted July 15, 2008 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) Link to comment Share on other sites More sharing options...
SIone Posted July 31, 2008 Author Share Posted July 31, 2008 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. Link to comment Share on other sites More sharing options...
weaponx Posted July 31, 2008 Share Posted July 31, 2008 (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=lockbitsWhat 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 July 31, 2008 by weaponx Link to comment Share on other sites More sharing options...
SIone Posted August 3, 2008 Author Share Posted August 3, 2008 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!) expandcollapse popup;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. Link to comment Share on other sites More sharing options...
davecollinsnz Posted August 4, 2008 Share Posted August 4, 2008 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... Link to comment Share on other sites More sharing options...
SIone Posted August 5, 2008 Author Share Posted August 5, 2008 Not sure if this helps but I've found that when there is this sort of setup:For $x=1 to 100PixelGetColor($x,1)Nextthe speed is not very good. I found out that simply writing out thisPixelGetColor(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. Link to comment Share on other sites More sharing options...
Confuzzled Posted August 13, 2008 Share Posted August 13, 2008 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. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now