Jump to content
Sign in to follow this  
JesuZ

Image Capturing, greyscaling, and comparing...

Recommended Posts

JesuZ

Ok, hello folks :)

I was thinking, is that possible to create that kind of program, that takes like 4 snapshots from screen.

Then greyscale them to black/white images.

Then compare, which ones of shots will match eatchothers, like x% (x-definable).

I was thinking it somehow like this:

Dim $image1 = TakeSnapShot( screenx1, screeny1, screenx2, screeny2 )
Dim $image2 = TakeSnapShot( screenx1, screeny1, screenx2, screeny2 )
Dim $image3 = TakeSnapShot( screenx1, screeny1, screenx2, screeny2 )
Dim $image4 = TakeSnapShot( screenx1, screeny1, screenx2, screeny2 )

; Then somehow greyscale them
for $i = 4 to 0 Step -1
   GreyScale( $image + $i )
Next
Compare( $image1, $image2 )     ; Returns how it should say... Match-% of two images, like 0.60
Compare( $image1, $image3 )
Compare( $image1, $image4 )
etc etc.

That very simple show about idea, but hopefully someone understand what I'm looking for :)

Thanks!

Share this post


Link to post
Share on other sites
SadBunny

For really cool functions for all kinds of image manipulation, check out prospeed, as for instance described here:

http://www.autoitscript.com/forum/index.php?showtopic=71654

It can greyscale, compare, take snapshots and much, much more. The grayscaling and screenshots works fine for me, I used it, the compare I have never used but it seems to work too, and fast.


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites
JesuZ

Looks pretty nice :)

How can I search smaller item from bigger image, and actually return x- and y-cordinates for top left corner of item...?

I copied small 18x17px area from greysquare left corner, and saved it as search.bmp

Now I should search where on the screen that same corner is, at the moment, and return that corners X and Y position.

How could do this...?

Tried with http://www.autoitscript.com/forum/index.php?showtopic=66545

but no perfect matches, and no partial matches. Code is below

#include <prospeed30.au3>
#include<ScreenCapture.au3>

Global Const $mcdir = "C:\Test-Images\"

$start = TimerInit()
$tResult=findBMP($mcdir & "from.bmp",$mcdir & "search.bmp",TRUE)
ConsoleWrite($tResult &  "** Square search totalmatch time elapsed: " & TimerDiff($start) / 1000 & "  seconds" & @LF)
;Again with a partial match
$start = TimerInit()
$tResult=findBMP($mcdir & "from.bmp",$mcdir & "search.bmp",FALSE)
ConsoleWrite($tResult & " ** Square search partial match time elapsed: " & TimerDiff($start) / 1000 & "  seconds" & @LF)

;===============================================================================
; Function Name:    findBMP
; Description:    Finds a bitmap (.BMP) in another BMP file
; Syntax:          findBMP($BMP1, $BMP2, $ExactMatch=TRUE)
;
; Parameter(s):  $BMP1           = Filename of bitmap to search in
;                  $BMP2             = Filename of bitmap to search for
;                  $ExactMatch     = TRUE / FALSE if an exact match is done
;
; Return Value(s):  On Success:   = Returns Array List
;                  On Failure:   = @error 1 (Control was found but there was an error with the DLLCall)
;
; Author(s):        JunkEW
;
; Note(s):        
;               * Its never an exact match even with TRUE as last few bits are disposed in algorithm and lines below
;                are not checked under assumption that those are 99.99% of the time correct       
;
; ** BMP File format documentation http://en.wikipedia.org/wiki/BMP_file_format **
;http://en.wikipedia.org/wiki/Hex_editor
;
; Example(s):
;  
;===============================================================================

Func findBMP($BMP1, $BMP2, $ExactMatch=TRUE)
    Dim $fLine[1];Line number of found line(s), redimmed when second picture size is known
    Dim $BMP1Total = "", $BMP1DataStart=0, $BMP1Size=0, $BMP1Width=0, $BMP1Height=0, $BMP1LineWidth=0;
    Dim $BMP2Total = "", $BMP2DataStart=0, $BMP2Size=0, $BMP2Width=0, $BMP2Height=0, $BMP2LineWidth=0
    Dim $foundAt = "", $matchPossible=FALSE, $matchedLines=0, $foundAtLeft=-1, $foundAtTop=-1
    Dim $bestMatchLine=-1, $HighestMatchingLines=-1; For knowing when no match is found where best area is
    Dim $iPos=0;
    
; Load the bitmap to search in
    loadbmp($BMP1, $BMP1Total, $BMP1DataStart, $BMP1Size, $BMP1Width, $BMP1Height, $BMP1LineWidth)

; Load the bitmap to find
    loadbmp($BMP2, $BMP2Total, $BMP2DataStart, $BMP2Size, $BMP2Width, $BMP2Height, $BMP2LineWidth)

;Make it strings to be able to use string functions for searching
    $BMP1Data = BinaryToString(BinaryMid($BMP1Total, $BMP1DataStart))
    $BMP2Data = BinaryToString(BinaryMid($BMP2Total, $BMP2DataStart))

;For reference of line where in BMP2FindIn a line of BMP2Find was found
    ReDim $fline[$BMP2Height]
    
;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
    if $ExactMatch=true Then
        $iFuzzyAdd = 1
    Else
;Check fuzzy every 10% of lines
        $iFuzzyAdd = ceiling(($bmp2height * 0.1))
    endIf

    $begin = TimerInit()
;Look for each line of the bitmap if it exists in the bitmap to find in
    For $i = 0 To $BMP2Height - 1
;Minus 3 as last bits are padded with unpredictable bytes (24 bits image assumption)
        $searchFor = StringMid($BMP2Data, 1 + ($i * $BMP2lineWidth), ($BMP2lineWidth - 3))
;$iPos = StringInStr($BMP1Data, $searchFor)
; Needs latest beta v3.2.11.5 (beta)
        $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos+1)

        $fline[$i] = Int($iPos / $BMP1lineWidth)

;Look for all lines above if there is also a match
;Not doing it for the lines below as speed is more important and risk of mismatch on lines below is small
        $iAbove=1
        if $iPos > 0 then
            $bMatchPossible=True
            $matchedLines=1;As first found line is matched we start counting
        Else
            $bMatchPossible=false
            exitloop
        endif
        while (($i+$iAbove) < ($BMP2Height -1)) and ($bMatchPossible=True)
            $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2lineWidth), ($BMP2lineWidth - 3))
            $aboveLine = stringmid($BMP1Data,$iPos + ($iAbove * $BMP1LineWidth), ($BMP2LineWidth - 3))

;           consolewrite($searchFor & ";" & $aboveLine & @lf & $i & ";" & ($i+$iAbove) & ";" & ($BMP2Height -1) & @lf)

            if $aboveLine <> $searchFor Then
                $bMatchPossible=False
       ;To remember the area with the best match
                if $matchedLines >= $HighestMatchingLines Then
                    $HighestMatchingLines = $matchedLines
                    
           ;Best guess of location
                    $foundAtTop = $bmp1Height - $fline[$i] - $bmp2height + $i
                    $foundAtLeft =  int(mod($iPos,$bmp1linewidth) / 3)  
                    $bestMatchLine = Int($iPos / $BMP1lineWidth)
                EndIf
                ExitLoop            
            EndIf
            $matchedLines=$matchedLines + 1
            $iAbove=$iAbove+$iFuzzyAdd
        WEnd
;If bMatchPossible is still true most likely we have found the bitmap       
        if $bmatchPossible = True then
            consolewrite("i" & $iPos)
            $foundAtTop = $bmp1Height - $fline[$i] -$bmp2height +$i
            $foundAtLeft =  int(mod($iPos,$bmp1linewidth) / 3)
            
            ConsoleWrite("Could match top: " & $foundAtTop & " left: " & $foundAtLeft & " in " & TimerDiff($begin) / 1000 & "  seconds" & @LF)
            MouseMove($foundatleft,$foundatTop)
            exitloop
        EndIf
    
    Next

    if $bMatchPossible = True Then
        ConsoleWrite("Searching took " & TimerDiff($begin) / 1000 & "  seconds " & @LF)
    Else
        ConsoleWrite("NOT FOUND Searching took " & TimerDiff($begin) / 1000 & "  seconds" & @LF)
    endif

;Return an error if not found else return an array with all information
    if $bMatchPossible = False Then
        SetError(1, 0, 0)
    endif
;   return stringsplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $bmp2width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine,";")
    return $bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $bmp2width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine
EndFunc;==>findBMP

;===============================================================================
; Function Name:    loadBMP
; Description:    Loads the BMP File into a variable
; Syntax:          LoadBMP($BMPFile, byref $BMP, byref $BMPSize, byref $BMPWidth, byRef $BMPHeight, byref $BMPLineWidth)
;
; Parameter(s):  $BMPFile = Filename of bitmap to load
;                  $BMP  = String where bitmap has to be put in
;                  $BMPSize, $BMPWidth, $BMPHeight, $BMPLineWidth are returnvariables with basic information
;
; Return Value(s):  
;
; Author(s):        JunkEW
;
; Note(s):        
;               * It's not a bullet proof loading mechanism. Its main intention is to load BMP files created in "normal" mode
;
; Example(s):
;  
;===============================================================================

func loadBMP($BMPFile, byref $BMP, byref $BMPDataStart, byref $BMPSize, byref $BMPWidth, byRef $BMPHeight, byref $BMPLineWidth)
Const $BMPHDRSize = 54

;   $begin = TimerInit()
    $fHandle = FileOpen($BMPFile, 16)
    $BMP = FileRead($fHandle);Read whole file into memory
    FileClose($fHandle)
;   ConsoleWrite("Loading took " & TimerDiff($begin) & " milliseconds " & @LF)

;All frequently used BMP information out of the header
    $BMPHDR = BinaryMid($BMP, 1, $BMPHDRSize)
    $BMPSize = Dec(StringMid(BinaryMid($BMPHDR, 6, 1) & BinaryMid($BMPHDR, 5, 1) & BinaryMid($BMPHDR, 4, 1) & BinaryMid($BMPHDR, 3, 1), 3))
    $BMPHDRS = Dec(StringMid(BinaryMid($BMPHDR, 18, 1) & BinaryMid($BMPHDR, 17, 1) & BinaryMid($BMPHDR, 16, 1) & BinaryMid($BMPHDR, 15, 1), 3))
    $BMPWidth = Dec(StringMid(BinaryMid($BMPHDR, 22, 1) & BinaryMid($BMPHDR, 21, 1) & BinaryMid($BMPHDR, 20, 1) & BinaryMid($BMPHDR, 19, 1), 3))
    $BMPHeight = Dec(StringMid(BinaryMid($BMPHDR, 26, 1) & BinaryMid($BMPHDR, 25, 1) & BinaryMid($BMPHDR, 24, 1) & BinaryMid($BMPHDR, 23, 1), 3))
    $BMPBitsPP = Dec(StringMid(BinaryMid($BMPHDR, 30, 1) & BinaryMid($BMPHDR, 29, 1), 3))
    $BMPCompression = Dec(StringMid(BinaryMid($BMPHDR, 34, 1) & BinaryMid($BMPHDR, 33, 1) & BinaryMid($BMPHDR, 32, 1) & BinaryMid($BMPHDR, 31, 1), 3))
    $BMPColors = Dec(StringMid(BinaryMid($BMPHDR, 50, 1) & BinaryMid($BMPHDR, 49, 1) & BinaryMid($BMPHDR, 48, 1) & BinaryMid($BMPHDR, 47, 1), 3))

    If $BMPColors=0 Then
        $BMPlineWidth = ($BMPSize - $BMPHDRSize) / $BMPHeight   
        $BMPDataStart = $BMPHDRSize+1
    Else
;Logic seems to be 4 * colors instead of 2^n colors
;~       $BMPlineWidth = ($BMPSize - $BMPHDRSize - (4*(2^$BMPColors))) / $BMPHeight 
;~       $BMPDataStart = $BMPHDRSize+(4*(2^$BMPColors))+1
        $BMPlineWidth = ($BMPSize - $BMPHDRSize - (4*$BMPColors)) / $BMPHeight  
        $BMPDataStart = $BMPHDRSize+(4*$BMPColors)+1
    endif
    Return 0
EndFunc

My example images below.

That code didn't find match from images.

post-28046-1211990502_thumb.gif

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  

×