OCR Buscar una imagen dentro de otra mayor:

Robots la parte programada en el ordenador, cibernetica, autoguiado del pc, algoritmos, recursividad
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2091
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

OCR Buscar una imagen dentro de otra mayor:

Mensaje por BasicOs »

En el enlace este: http://www.autoitscript.com/forum/index ... opic=66545
Nombre: findBMP

; Descripcion: Encuentra un (.BMP) en otro fichero BMP (other formats BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF deberían funcionar pero no probados)
; Syntax: findBMP($BMP1, $BMP2, $MatchType=TRUE)

Salu22:)
Aunque hay unas modificaciones al final del tópico en http://www.autoitscript.com/forum/index ... t&p=815484
El Código original

Código: Seleccionar todo

; Function Name:    findBMP
; Description:    Finds a bitmap (.BMP) in another BMP file (other formats BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF should work but not tested)
; Syntax:          findBMP($BMP1, $BMP2, $MatchType=TRUE)
;
; Parameter(s):  $BMP1           = Filename of bitmap to search in
;                  $BMP2             = Filename of bitmap to search for
;                  $MatchType       = c24RGBFullMatch, c24RGBPartialMatch, c16RGBFullMatch, c16RGBPartialMatch
;
; 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       
;              * locking bits overview http://www.bobpowell.net/lockingbits.htm
; ToDo:
;               * Transparency (when search letters on a different background) http://www.winprog.org/tutorial/transparency.html
;               * Match quicker by doing a bitblt with srcinvert when first line is found (instead of checking line by line)
;               * $BMP1 and $BMP2 to be HBITMAP handle as input instead of filenames (will make searching within partial screen easier)
; Example(s):
;  
;===============================================================================

Func findBMP($BMP1, $BMP2, $MatchType=$c24RGBFullMatch)
    Dim $fLine[1];Line number of found line(s), redimmed when second picture size is known
    Dim $BMP1Data="", $BMP1Width=0, $BMP1Height=0, $BMP1LineWidth=0;
    Dim $BMP2Data="", $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=1;
    dim $imgBytes;
    
    local $iFuzzyDist, $searchFor, $iAbove, $bMatchPossible, $aboveLine
    local $j, $imgBits

    if ($MatchType=$c24RGBFullMatch) or ($matchtype=$c24RGBPartialMatch) then
        $imgBytes=3
    Else    
        $imgBytes=2
    endif
    
; Load the bitmap to search in
    getImage($BMP1, $BMP1Data, $BMP1Width, $BMP1Height, $BMP1LineWidth, $imgBytes)
    $BMP1Data = BinaryToString($BMP1Data)

; Load the bitmap to find
    getImage($BMP2, $BMP2Data, $BMP2Width, $BMP2Height, $BMP2LineWidth, $imgBytes)
;Make it strings to be able to use string functions for searching
    $BMP2Data = BinaryToString($BMP2Data)
    
;For reference of line where in BMP2FindIn a line of BMP2Find was found
    If $BMP2Height = 0 Then
        SetError(1,0,0)
        Return  False
    EndIf

    ReDim $fline[$BMP2Height]
    
;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
    if ($MatchType=$c24RGBFullMatch) or ($matchtype=$c16RGBFullMatch) Then
        $iFuzzyDist = 1
    Else
;Check fuzzy every 10% of lines
        $iFuzzyDist = 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 imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits
        $searchFor = StringMid($BMP2Data, 1 + ($i * $BMP2lineWidth), ($BMP2lineWidth - $imgBytes))
        $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos)
;       $iPos = StringInStr($BMP1Data, $searchFor)


;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
;Location of the match
                                                $foundAtTop = Int($iPos / $BMP1lineWidth) -$i
            $foundAtLeft =  int(mod($iPos,$bmp1linewidth) / $imgBytes)
        Else
            $bMatchPossible=false
            exitloop
        endif

        while (($i+$iAbove) <= ($BMP2Height -1)) and ($bMatchPossible=True)
            $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2lineWidth), ($BMP2lineWidth - $imgBytes))
            $aboveLine = stringmid($BMP1Data,$iPos + ($iAbove * $BMP1LineWidth), ($BMP2LineWidth - $imgBytes)) 
        
            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 = $fline[$i] + $i - $BMP2Height  
                    $foundAtTop = Int($iPos / $BMP1lineWidth);+ $i - $BMP2Height          
                    $bestMatchLine = Int($iPos / $BMP1lineWidth) 
                EndIf
                ExitLoop            
            EndIf
            $matchedLines=$matchedLines + 1
            $iAbove=$iAbove+$iFuzzyDist
        WEnd
        
;If bMatchPossible is still true most likely we have found the bitmap       
        if $bmatchPossible = True then
;~          ConsoleWrite("Could match top: " & $foundAtTop & " left: " & $foundAtLeft & " in " & TimerDiff($begin) / 1000 & "  seconds" & @LF)
;           MouseMove($foundatleft,$foundatTop)
            exitloop
        else 
;~          consolewrite("i not matched " & $ipos & " " & $matchedlines & @crlf )
        EndIf
    
    Next

;For some debugging of time
;   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

Func GetImage($BMPFile, byref $BMPDataStart, byref $Width, byRef $Height, byref $Stride, $imgBytes=3)
local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle

; Load the bitmap to search in
    If $BMPFile="SCREEN" Then
        $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
        Else
            $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap           
        EndIf
    EndIf
    
;Get $tagGDIPBITMAPDATA structure
;~  ConsoleWrite("Bitmap Width:    " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF )
;~  ConsoleWrite("Bitmap Height:      " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)

;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
    if ($imgBytes=2) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
    Else
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
    endIf
        
    If @ERROR Then MsgBox(0,"","Error locking region " & @error)
    
    $Stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
    $PixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.
    
    $pixelData = DllStructCreate("ubyte lData[" & (abs($Stride) * $Height-1) & "]", $Scan0) 
    $BMPDataStart = $BMPDataStart & DllStructGetData($pixeldata,"lData")
    
    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose ($pBitmap)
    _WinAPI_DeleteObject ($pBitmap)

EndFunc;==>GetImage
Responder