Search the Community
Showing results for tags 'motion tracking'.
-
A few days ago I wrote a script to get the relative difference between two sets of data. When this comes to images we can detect all sorts of things, more accurately. Take for example you have two images with different lighting. http://prodynamics.co/link.php?CMD=file&ID=compare1 (1600x976) http://prodynamics.co/link.php?CMD=file&ID=compare2 (1600x976) (These are both jpg images, their format is stored in the database) You will notice that the second image is considerably brighter than the first. Every pixel of the second image is at least one shade brighter than the second, this means that there was an absolute change of 100% to the image, HOWEVER, lets say we only want to know how much light was added to the image, that's one of the things this script can detect. The script would say the image has only changed by 12%, that's because the new data is only 12% different than the old data, even though 100% of it has changed. Now in order to be efficient, the script which converts the images into pixel data are set to skip by default ever 2nd row of pixels and read every other pixel in each row. This still provides pretty accurate results for changes larger than 1px(1px changes may be missed sometimes), and could still accurately display where a change occurred or track a moving object.(with modification to use processed data in said way) In the case you are comparing images which have many 1px changes, you can set the step for both y and x to 1, and the function will compare every single pixel. Be warned though, this is very slow. Large images can use a higher step, but using too high of a step may exclude certain changes from being observed. That being said, if you want to compare large images quickly, without leaving out too much data, there is an alternative, you can size the image down to 1/4th 1/6th or 1/8th it's size and compare it. Scaling down two images keeps the relative data in them the same places, so the comparison will return almost identical results (off by maybe 2% max)Note: In most cases scaling will result in more accurate results than stepping. The below example compares the above two images, and output the data to the console. ;~ #include <_PixelGetColor.au3> #include <GDIPlus.au3> #include <inet.au3> #include <array.au3> $hDll = DllOpen("gdi32.dll") _GDIPlus_Startup() Global $image1, $image2 $f1 = binary(_INetGetSource("http://prodynamics.co/link.php?CMD=file&ID=compare1")) ;image 1 $f2 = binary(_INetGetSource("http://prodynamics.co/link.php?CMD=file&ID=compare2")) ;image 2 brighter ;here we use the default step options $t1 = TimerInit() $image1 = _Capturepixels($f1) ;get image 1 pixel ConsoleWrite(TimerDiff($t1)/1000 &' Default Step'&@CRLF) $t1 = TimerInit() $image2 = _CapturePixels($f2) ;get image 2 pixels ConsoleWrite(TimerDiff($t1)/1000& ' Default Step'&@CRLF) $timer = TimerInit() $compare = _datacompare($image1[0], $image2[0]);compare them ConsoleWrite($compare[0]&'% Different(Localized) '&$compare[1]&'% Different(Global)'&@CRLF&'Took '&(TimerDiff($timer)/1000)&' seconds. Default Step'&@CRLF) ;here we double them, notice the preformance increase $t1 = TimerInit() $image1 = _Capturepixels($f1, 4, 8) ;get image 1 pixels ConsoleWrite(TimerDiff($t1)/1000 &' Double Step'&@CRLF) $t1 = TimerInit() $image2 = _CapturePixels($f2,4 , 8) ;get image 2 pixels ConsoleWrite(TimerDiff($t1)/1000& ' Double Step'&@CRLF) $timer = TimerInit() $compare = _datacompare($image1[0], $image2[0]) ConsoleWrite($compare[0]&'% Different(Localized) '&$compare[1]&'% Different(Global)'&@CRLF&'Took '&(TimerDiff($timer)/1000)&' seconds. Default Step'&@CRLF) sleep(5000) ;~ $t1 = TimerInit() ;~ $diffarray = _mapchange($image1[0], $image2[0], $image1[1], $image1[2]) ;compare two images for difference ;~ ConsoleWrite(TimerDiff($t1)/1000& ' _mapchange'&@CRLF) ;~ $t1 = TimerInit() ;~ $image = _toimage($diffarray) ;here we turn the array of colors back into an image ;~ ConsoleWrite(TimerDiff($t1)/1000& ' _toimage'&@CRLF) ;~ _GDIPlus_ImageSaveToFile($image, @scriptdir&'\test.jpg') ;write it to a file ;~ shellexecute(@scriptdir&'\test.jpg') #cs Function _datacompare($data1, $data2, [$declimal]) -$data1: A string of data, any length. -$data2: A string of data, must be the same length as $data1 -$decimal: 1=Binary 9=Base-10, 15=Base-16, 31=Base-32 Note: If you just want to compare two sets of binary data you probably want to use base-16. Unless you are sure your binary is in 1's and 0's. Returns: An array containing two floats. The first value is the localized change, and the second is the global change #ce func _datacompare($data1, $data2, $decimal=15) Local $difference $data1 = StringSplit($data1, "") $data2 = StringSplit($data2, "") $difference = 0 $found = 0 for $i=1 to $data1[0] if $data1[$i] <> $data2[$i] Then $temp = Abs(_tonum($data1[$i]) - _tonum($data2[$i])) $difference += $temp $found +=1 EndIf Next dim $ret[2] $ret[0] = ((($difference/$found))/$decimal)*100 $ret[1] = ((($difference/$data1[0]))/$decimal)*100 Return $ret EndFunc #cs Function: _mapchange($base, $new, $x, $y, [$decimal]) $base: Base data to compare from $new: Data to compare $x: Width of output data (should be returned by capturepixels) $y: Height of outout data (should be returned by capturepixels) $decimal: Decimal system, you shouldn't change this Note: Use _toimage on data returned by this function to visually see a image of the change. (The lighter the color the more change the occured) Returns an 2D array of data. Each value of the array represents one pixel of the image. Each value is a percent between 0-100 representing the change that occured in that pixel #ce func _mapchange($base, $new, $y, $x, $decimal = 10) Local $difference, $xx = 0, $yy = 0 dim $result[1][$x+1] $t1 = TimerInit() $data1 = _StringequalSplit($base, 8) $data2 = _StringequalSplit($new, 8) $difference = 0 for $i=1 to UBound($data1)-1 if $xx > $x Then $xx=0 $yy+=1 ConsoleWrite($yy&'/'&$y&' ('&($yy/$y)*100&') '&@CRLF) redim $result[$yy+1][$x+1] EndIf if $data1[$i] <> $data2[$i] Then $values1 = StringSplit($data1[$i], "") $values2 = stringSplit($data2[$i], "") $diff = "" for $ix=1 to $values1[0] $diff += round((Abs(_tonum($values1[$ix]) - _tonum($values2[$ix]))/$decimal)*100) Next $diff = Round($diff/$values1[0]) $result[$yy][$xx] = $diff Else $result[$yy][$xx] = 0 EndIf $xx += 1 Next return $result EndFunc #cs Function _tonum($info) -$info: A single digit or carachter. Returns: A 0-based value. #ce func _tonum($info) if $info+0 > 0 Then Return $info $info = StringLower($info) $return = asc($info)-87 switch $return Case -39 Return 0 Case Else Return $return EndSwitch EndFunc #cs Function _CapturePixels($data, [[$stepy], $stepx]) -$data: Binary Data -$stepy: How often to skip a row of pixelxs. 1 = Never -$stepx: How often to skip a single pixel. 1 = Nevere Note: Use higher steps for larger images and lower steps for smaller images. #ce Func _CapturePixels($data, $stepy = 2, $stepx = 2) $ret = "" $HBITMAP2 = _GDIPlus_BitmapCreateFromMemory($data) $y=_GDIPlus_ImageGetWidth($HBITMAP2) $x=_GDIPlus_ImageGetHeight($HBITMAP2) For $iY = 0 To $x step $stepy For $iX = 0 To $y step $stepx $rety = StringRight(hex(_GDIPlus_BitmapGetPixel($hBitmap2, $ix, $iy)),8) ;get current pixel color $ret &= $rety ;~ ConsoleWrite($iy&'/'&$x&' '&$rety&@CRLF) Next Next ;For $x = 0 To _GDIPlus_ImageGetWidth($HBITMAP2) ; For $y = 0 To _GDIPlus_ImageGetHeight($HBITMAP2) ; $ret &= _PixelGetColor_GetPixel($vDC, $x, $y, $hDll) ; Next ;Next _WinAPI_DeleteObject($HBITMAP2) dim $retx[3] $retx[0] = $ret $retx[1] = $x/$stepx $retx[2] = $y/$stepy Return $retx EndFunc ;==>Capturepixels Func _toimage($colors) _GDIPlus_Startup() Local $hBitmap = _GDIPlus_BitmapCreateFromScan0(UBound($colors, 2), UBound($colors, 1)) ;create an empty bitmap Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the graphics context of the bitmap _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hBmpCtxt, 0x00000000) ;clear bitmap with color white for $i=0 to UBound($colors)-1 for $i2=0 to UBound($colors,2 )-1 ;~ if $colors[$i][$i2] > 30 Then ;~ ConsoleWrite($i&","&$i2&' - '&$colors[$i][$i2]&@CRLF) _GDIPlus_BitmapSetPixel($hBitmap, $i2, $i, $colors[$i][$i2]&'0') ;~ ConsoleWrite($i2&','&$i&' '&$colors[$i][$i2]&@CRLF) ;~ EndIf Next Next return $hBitmap ;return bitmap ;cleanup GDI+ resources _GDIPlus_GraphicsDispose($hBmpCtxt) EndFunc ;==>Example Func _StringEqualSplit($sString, $iNumChars) If (Not IsString($sString)) Or $sString = "" Then Return SetError(1, 0, 0) If (Not IsInt($iNumChars)) Or $iNumChars < 1 Then Return SetError(2, 0, 0) Return StringRegExp($sString, "(?s).{1," & $iNumChars & "}", 3) EndFunc Cheers,NullSchritt PS: If I find the time, I'll add a motion tracking version of the script as well. (It can detect but not track motion in it's current form)
- 16 replies
-
I'd like to take a dll someone wrote in C# for motion detection and motion tracking: http://www.codeproject.com/Articles/10248/Motion-Detection-Algorithms And use these functionalities in a Autoit script. Can anyone help me with advice, or pointing me in the right direction? I use something called ImageSearch which is an autoit script that uses a dll for its functionality and on the imagesearch.au3 everything looks really straight forward; it just calls a function within the dll, and everything works. but I don't know anything about the DLL side, because I'm not a developer. But if tapping into these motion detection dll could be done it'd make for a really cool library so people could use it in their autoit projects. Anyway, best case scenario the Motion dlls are written in such a way that I can just call them within a script, but I don't know how to tell if this is possible. can a C# programmer look at the source code on that site and let me know if it is? I suspect this is a longshot but we might get lucky Thanks!!! motion_src.zip motion_demo.zip
- 2 replies
-
- motion
- motion detection
- (and 3 more)