Друзья помогите реализовать поиск в определенной области, имеется:
Код выше работает, в фоном режиме, что очень хорошо, но мне очень сильно не хватает нескольких функций при использовании:
1) Хотелось бы иметь возможность указать зону поиска
2) Задать Толерантність поиска, т.е учитывать погрешность в % соотношении
Ps/ друзья, буду рад помощи, несколько дней бороздю просторы интернета, пока не получается самостоятельно, скорее всего связанно с не высоким уровнем знаний.
Код:
#include <WinAPIGdi.au3>
; #FUNCTION# ====================================================================================================================
; Name ..........: _BmpSearch
; Description ...: Searches for Bitmap in a Bitmap
; Syntax ........: _BmpSearch($hSource, $hFind, $iMax=5000)
; Parameters ....: $hSource - Handle to bitmap to search
; $hFind - Handle to bitmap to find
; $iMax - Max matches to find
; Return values .: Success: Returns a 2d array with the following format:
; $aCords[0][0] = Total Matches found
; $aCords[$i][0] = Width of bitmap
; $aCords[$i][1] = Hight of bitmap
; $aCords[$i][2] = X cordinate
; $aCords[$i][3] = Y cordinate
;
; Failure: Returns 0 and sets @error to 1
;
; Author ........: Brian J Christy (Beege)
; ===============================================================================================================================
Func _BmpSearch($hSource, $hFind, $iMax = 5000)
Static Local $aMemBuff, $tMem, $fStartup = True
If $fStartup Then
;####### (BinaryStrLen = 490) #### (Base64StrLen = 328 )####################################################################################################
Local $Opcode = 'yBAAAFCNRfyJRfSNRfiJRfBYx0X8AAAAAItVDP8yj0X4i10Ii0UYKdiZuQQAAAD38YnBi0X4OQN0CoPDBOL36akAAACDfSgAdB1TA10oO10YD4OVAAAAi1UkORN1A1vrBluDwwTrvVOLVSyLRTADGjtdGHd3iwg5C3UhA1oEi0gEO10Yd2Y5C3USA1oIi0gIO10Yc1c5' & _
'C3UDW+sGW4PDBOuCi1UUid6LfQyLTRCJ2AHIO0UYczfzp4P5AHcLSoP6AHQNA3Uc6+KDwwTpVP///4tFIIkYg0UgBIPDBP9F/ItVNDlV/HQG6Tj///9bi0X8ycIwAA=='
Local $aDecode = DllCall("Crypt32.dll", "bool", "CryptStringToBinary", "str", $Opcode, "dword", 0, "dword", 1, "struct*", DllStructCreate("byte[254]"), "dword*", 254, "ptr", 0, "ptr", 0)
If @error Or (Not $aDecode[0]) Then Return SetError(1, 0, 0)
$Opcode = BinaryMid(DllStructGetData($aDecode[4], 1), 1, $aDecode[5])
$aMemBuff = DllCall("kernel32.dll", "ptr", "VirtualAlloc", "ptr", 0, "ulong_ptr", BinaryLen($Opcode), "dword", 4096, "dword", 64)
$tMem = DllStructCreate('byte[' & BinaryLen($Opcode) & ']', $aMemBuff[0])
DllStructSetData($tMem, 1, $Opcode)
;####################################################################################################################################################################################
$fStartup = False
EndIf
Local $iTime = TimerInit()
Local $tSizeSource = _WinAPI_GetBitmapDimension($hSource)
Local $tSizeFind = _WinAPI_GetBitmapDimension($hFind)
Local $iRowInc = ($tSizeSource.X - $tSizeFind.X) * 4
Local $tSource = _GetBmpPixelStruct($hSource)
Local $tFind = _GetBmpPixelStruct($hFind)
Local $aFD = _FindFirstDiff($tFind)
Local $iFirstDiffIdx = $aFD[0]
Local $iFirstDiffPix = $aFD[1]
Local $iFirst_Diff_Inc = _FirstDiffInc($iFirstDiffIdx, $tSizeFind.X, $tSizeSource.X)
If $iFirst_Diff_Inc < 0 Then $iFirst_Diff_Inc = 0
Local $tCornerPixs = _CornerPixs($tFind, $tSizeFind.X, $tSizeFind.Y)
Local $tCornerInc = _CornerInc($tSizeFind.X, $tSizeFind.Y, $tSizeSource.X)
Local $pStart = DllStructGetPtr($tSource)
Local $iEndAddress = Int($pStart + DllStructGetSize($tSource))
Local $tFound = DllStructCreate('dword[' & $iMax & ']')
Local $ret = DllCallAddress('dword', DllStructGetPtr($tMem), 'struct*', $tSource, 'struct*', $tFind, _
'dword', $tSizeFind.X, 'dword', $tSizeFind.Y, _
'dword', $iEndAddress, 'dword', $iRowInc, 'struct*', $tFound, _
'dword', $iFirstDiffPix, 'dword', $iFirst_Diff_Inc, _
'struct*', $tCornerInc, 'struct*', $tCornerPixs, _
'dword', $iMax)
If Not $ret[0] Then Return SetError(1, 0, 0)
Local $aCords = _GetCordsArray($ret[0], $tFound, $tSizeSource.X, $pStart, $tSizeFind.X, $tSizeFind.Y)
Return SetExtended(Int(TimerDiff($iTime) * 1000), $aCords)
EndFunc ;==>_BmpSearch_MC
#Region Internal Functions
;Returns a Dllstructure will all pixels
Func _GetBmpPixelStruct($hBMP)
Local $tSize = _WinAPI_GetBitmapDimension($hBMP)
Local $tBits = DllStructCreate('dword[' & ($tSize.X * $tSize.Y) & ']')
_WinAPI_GetBitmapBits($hBMP, DllStructGetSize($tBits), DllStructGetPtr($tBits))
Return $tBits
#Tidy_Off
#cs
This is how the dllstructure index numbers correspond to the pixel cordinates:
An 5x5 dimension bmp:
X0 X1 X2 X3 X4
Y0 1 2 3 4 5
Y1 6 7 8 9 10
Y2 11 12 13 14 15
Y3 16 17 18 19 20
Y4 21 22 23 24 25
An 8x8 dimension bmp:
X0 X1 X2 X3 X4 X5 X6 X7
Y0 1 2 3 4 5 6 7 8
Y1 9 10 11 12 13 14 15 16
Y2 17 18 19 20 21 22 23 24
Y3 25 26 27 28 29 30 31 32
Y4 33 34 35 36 37 38 39 40
Y5 41 42 43 44 45 46 47 48
Y6 49 50 51 52 53 54 55 56
Y7 57 58 59 60 61 62 63 64
#ce
#Tidy_On
EndFunc ;==>_GetBmpPixelStruct
;Find first pixel that is diffrent than ....the first pixel
Func _FindFirstDiff($tPix)
;####### (BinaryStrLen = 106) ########################################################################################################################
Static Local $Opcode = '0xC80000008B5D0C8B1383C3048B4D103913750C83C304E2F7B800000000EB118B5508FF338F028B451029C883C002EB00C9C20C00'
Static Local $aMemBuff = DllCall("kernel32.dll", "ptr", "VirtualAlloc", "ptr", 0, "ulong_ptr", BinaryLen($Opcode), "dword", 4096, "dword", 64)
Static Local $tMem = DllStructCreate('byte[' & BinaryLen($Opcode) & ']', $aMemBuff[0])
Static Local $fSet = DllStructSetData($tMem, 1, $Opcode)
;#####################################################################################################################################################
Local $iMaxLoops = (DllStructGetSize($tPix) / 4) - 1
Local $aRet = DllCallAddress('dword', DllStructGetPtr($tMem), 'dword*', 0, 'struct*', $tPix, 'dword', $iMaxLoops)
Return $aRet
EndFunc ;==>_FindFirstDiff
; Calculates the value to increase pointer by to check first different pixel
Func _FirstDiffInc($iDx, $iFind_Xmax, $iSource_Xmax)
Local $aFirstDiffCords = _IdxToCords($iDx, $iFind_Xmax)
Local $iXDiff = ($iDx - ($aFirstDiffCords[1] * $iFind_Xmax)) - 1
Return (($aFirstDiffCords[1] * $iSource_Xmax) + $iXDiff) * 4
EndFunc ;==>_FirstDiffInc
;Converts the pointer addresses to cordinates
Func _GetCordsArray($iTotalFound, $tFound, $iSource_Xmax, $pSource, $iFind_Xmax, $iFind_Ymax)
Local $aRet[$iTotalFound + 1][4]
$aRet[0][0] = $iTotalFound
For $i = 1 To $iTotalFound
$iFoundIndex = ((DllStructGetData($tFound, 1, $i) - $pSource) / 4) + 1
$aRet[$i][0] = $iFind_Xmax
$aRet[$i][1] = $iFind_Ymax
$aRet[$i][3] = Int(($iFoundIndex - 1) / $iSource_Xmax) ; Y
$aRet[$i][2] = ($iFoundIndex - 1) - ($aRet[$i][3] * $iSource_Xmax) ; X
Next
Return $aRet
EndFunc ;==>_GetCordsArray
;converts cordinates to dllstructure index number
Func _CordsToIdx($iX, $iY, $iMaxX)
Return ($iY * $iMaxX) + $iX + 1
EndFunc ;==>_CordsToIdx
;convert dllstructure index number to cordinates
Func _IdxToCords($iDx, $iMaxX)
Local $aCords[2]
$aCords[1] = Int(($iDx - 1) / $iMaxX) ; Y
$aCords[0] = ($iDx - 1) - ($aCords[1] * $iMaxX) ; X
Return $aCords
EndFunc ;==>_IdxToCords
;Retrieves the Pixel Values of Right Top, Left Bottom, Right Bottom. Returns dllstructure
Func _CornerPixs(ByRef $tFind, $iFind_Xmax, $iFind_Ymax)
Local $tCornerPixs = DllStructCreate('dword[3]')
DllStructSetData($tCornerPixs, 1, DllStructGetData($tFind, 1, $iFind_Xmax), 1) ; top right corner
DllStructSetData($tCornerPixs, 1, DllStructGetData($tFind, 1, ($iFind_Xmax + ($iFind_Xmax * ($iFind_Ymax - 2)) + 1)), 2) ; bottom left corner
DllStructSetData($tCornerPixs, 1, DllStructGetData($tFind, 1, ($iFind_Xmax * $iFind_Ymax)), 3); bottom right corner
Return $tCornerPixs
EndFunc ;==>_CornerPixs
;Retrieves the pointer adjust values for Right Top, Left Bottom, Right Bottom. Returns dllstructure
Func _CornerInc($iFind_Xmax, $iFind_Ymax, $iSource_Xmax)
Local $tCornerInc = DllStructCreate('dword[3]')
DllStructSetData($tCornerInc, 1, ($iFind_Xmax - 1) * 4, 1)
DllStructSetData($tCornerInc, 1, (($iSource_Xmax - $iFind_Xmax) + $iSource_Xmax * ($iFind_Ymax - 2) + 1) * 4, 2)
DllStructSetData($tCornerInc, 1, ($iFind_Xmax - 1) * 4, 3)
Return $tCornerInc
EndFunc ;==>_CornerInc
#EndRegion Internal Functions
Код:
$anhlocal=@ScriptDir&"\images\1.bmp"
$hwnd=0x00031896;handle
$p=imageSearchEX($hwnd,$anhlocal)
if $p=0 Then
MsgBox(0,"","Ошибка")
EndIf
_ArrayDisplay($p)
MouseClick("left",$p[0],$p[1],3,1)
Func imageSearchEX($hwnd,$bmpLocal)
$iWidth = _WinAPI_GetWindowWidth($hwnd)
$iHeight = _WinAPI_GetWindowHeight($hwnd)
Return imageSearchEXarea($hwnd,$bmpLocal,$iWidth,$iHeight)
EndFunc
Func imageSearchEXarea($hwnd,$bmpLocal,$iWidth,$iHeight)
Local $p[2]
_GDIPlus_Startup()
;Get the hBitmap of the image i want to search for
$Bitmap = _GDIPlus_BitmapCreateFromFile($bmpLocal)
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($Bitmap)
;Doing the actual window capture and saving it inside $hBMP
$iWidth = _WinAPI_GetWindowWidth($hwnd) ; $browser = the handle of the window which I am capturing
$iHeight = _WinAPI_GetWindowHeight($hwnd)
$hDDC = _WinAPI_GetDC($hwnd)
$hCDC = _WinAPI_CreateCompatibleDC($hDDC)
$hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
_WinAPI_SelectObject($hCDC, $hBMP)
DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hwnd, "hwnd", $hCDC, "int", 0)
;Searching for the image
$pos = _BmpSearch($hBMP, $hBitmap,10)
_ArrayDisplay($pos)
if $pos=0 Then
Return 0
EndIf
$p[0]=$pos[1][2]
$p[1]=$pos[1][3]
_WinAPI_ReleaseDC($hwnd, $hDDC)
_WinAPI_DeleteDC($hCDC)
_WinAPI_DeleteObject($hBMP)
_GDIPlus_Shutdown()
Return $p
EndFunc
Код выше работает, в фоном режиме, что очень хорошо, но мне очень сильно не хватает нескольких функций при использовании:
1) Хотелось бы иметь возможность указать зону поиска
2) Задать Толерантність поиска, т.е учитывать погрешность в % соотношении
Ps/ друзья, буду рад помощи, несколько дней бороздю просторы интернета, пока не получается самостоятельно, скорее всего связанно с не высоким уровнем знаний.