【已解决】纯AU3模糊找图,求帮忙提高效率 汇编找图 模糊找图 后台找图
本帖最后由 3131210 于 2025-4-18 23:33 编辑关于AU3本身实现模糊找图的问题,有没有大神可以帮提高一下找图的效率,下面的代码,在小范围内找一张小图都要十几秒 附件里面的图片要搜索200多秒。。。不是死机
附件里面有测试图片 AU3有没有可能实现毫秒级的模糊找图
#include <GDIPlus.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
; 初始化GDI+
_GDIPlus_Startup()
;~ ; 查找单个匹配(精确匹配)
$aResult = _FindPicture("sub.bmp", "parent.bmp", Default, 5, 0.9, False)
; 查找所有匹配(90%匹配率,5像素容错)
;~ $aResult = _FindPicture("sub.bmp", "parent.bmp", Default, 5, 0.9, True)
; 在指定区域内查找
;~ $aSearchRect = ; x, y, width, height
;~ $aResult = _FindPicture("sub.bmp", "parent.bmp", $aSearchRect, 0, 1.0, False)
_GDIPlus_Shutdown()
; 找图函数
; @param $sSubPic 子图路径
; @param $sParPic 父图路径
; @param $aSearchRect 搜索区域 ,默认为空数组则搜索整图
; @param $iErrorRange 容错值 (0-255)
; @param $fMatchRate 匹配率 (0.0-1.0),默认0.9
; @param $bFindAll 是否查找所有匹配,默认False
; @return 包含所有匹配点的二维数组 ,每行是找到的中心点坐标
Func _FindPicture($sSubPic, $sParPic, $aSearchRect = Default, $iErrorRange = 0, $fMatchRate = 0.9, $bFindAll = False)
Local $aPoints ; 存储结果的数组
; 加载图片 - 先用默认格式加载
Local $hSubBitmap = _GDIPlus_BitmapCreateFromFile($sSubPic)
Local $hParBitmap = _GDIPlus_BitmapCreateFromFile($sParPic)
; 获取图片尺寸
Local $iSubWidth = _GDIPlus_ImageGetWidth($hSubBitmap)
Local $iSubHeight = _GDIPlus_ImageGetHeight($hSubBitmap)
Local $iParWidth = _GDIPlus_ImageGetWidth($hParBitmap)
Local $iParHeight = _GDIPlus_ImageGetHeight($hParBitmap)
; 确定搜索区域
Local $iSearchX = 0, $iSearchY = 0, $iSearchWidth = $iParWidth, $iSearchHeight = $iParHeight
If IsArray($aSearchRect) And UBound($aSearchRect) >= 4 Then
$iSearchX = $aSearchRect
$iSearchY = $aSearchRect
$iSearchWidth = $aSearchRect
$iSearchHeight = $aSearchRect
EndIf
; 使用24位BGR格式锁定位图数据
Local $tSubBitmapData = _GDIPlus_BitmapLockBits($hSubBitmap, 0, 0, $iSubWidth, $iSubHeight, $GDIP_ILMREAD, $GDIP_PXF24RGB)
Local $tParBitmapData = _GDIPlus_BitmapLockBits($hParBitmap, 0, 0, $iParWidth, $iParHeight, $GDIP_ILMREAD, $GDIP_PXF24RGB)
; 获取扫描行宽度和指针
Local $iSubStride = DllStructGetData($tSubBitmapData, "Stride")
Local $pSubScan0 = DllStructGetData($tSubBitmapData, "Scan0")
Local $iParStride = DllStructGetData($tParBitmapData, "Stride")
Local $pParScan0 = DllStructGetData($tParBitmapData, "Scan0")
; 获取子图第一个像素颜色作为起始匹配点 (24位BGR格式)
Local $tStartPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pSubScan0)
Local $iStartB = DllStructGetData($tStartPixel, "B")
Local $iStartG = DllStructGetData($tStartPixel, "G")
Local $iStartR = DllStructGetData($tStartPixel, "R")
; 计算搜索范围
Local $iMaxY = $iSearchY + $iSearchHeight - $iSubHeight
Local $iMaxX = $iSearchX + $iSearchWidth - $iSubWidth
; 开始计时
Local $hTimer = TimerInit()
; 开始搜索
Local $iPointX = -1, $iPointY = -1
ConsoleWrite("子图尺寸: " & $iSubWidth & "x" & $iSubHeight & @CRLF)
ConsoleWrite("父图尺寸: " & $iParWidth & "x" & $iParHeight & @CRLF)
ConsoleWrite("搜索区域: X=" & $iSearchX & ", Y=" & $iSearchY & ", 宽=" & $iSearchWidth & ", 高=" & $iSearchHeight & @CRLF)
For $i = $iSearchY To $iMaxY
For $j = $iSearchX To $iMaxX
; 获取父图当前位置的像素 (24位BGR)
Local $pParPixel = $pParScan0 + $i * $iParStride + $j * 3
Local $tParPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParPixel)
Local $iParB = DllStructGetData($tParPixel, "B")
Local $iParG = DllStructGetData($tParPixel, "G")
Local $iParR = DllStructGetData($tParPixel, "R")
; 检查起始像素是否匹配
If _ColorBGREqualBGR($iParB, $iParG, $iParR, $iStartB, $iStartG, $iStartR, $iErrorRange) Then
; 起始像素匹配,对整个子图进行匹配
Local $iSum = 0 ; 总像素数
Local $iMatch = 0 ; 匹配的像素数
For $m = 0 To $iSubHeight - 1
For $n = 0 To $iSubWidth - 1
; 子图像素位置 (24位BGR)
Local $pSubPixel = $pSubScan0 + $m * $iSubStride + $n * 3
Local $tSubPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pSubPixel)
Local $iSubB = DllStructGetData($tSubPixel, "B")
Local $iSubG = DllStructGetData($tSubPixel, "G")
Local $iSubR = DllStructGetData($tSubPixel, "R")
; 对应的父图像素位置
Local $y2 = $i + $m
Local $x2 = $j + $n
Local $pParRelPixel = $pParScan0 + $y2 * $iParStride + $x2 * 3
Local $tParRelPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParRelPixel)
Local $iParRelB = DllStructGetData($tParRelPixel, "B")
Local $iParRelG = DllStructGetData($tParRelPixel, "G")
Local $iParRelR = DllStructGetData($tParRelPixel, "R")
$iSum += 1
; 比较颜色 (BGR格式)
If _ColorBGREqualBGR($iParRelB, $iParRelG, $iParRelR, $iSubB, $iSubG, $iSubR, $iErrorRange) Then
$iMatch += 1
EndIf
Next
Next
; 计算匹配率
Local $fCurrentMatch = $iMatch / $iSum
; 如果匹配率超过阈值,添加到结果
If $fCurrentMatch >= $fMatchRate Then
$iPointX = $j
$iPointY = $i
ConsoleWrite("找到匹配点(左上角): X=" & $iPointX & ", Y=" & $iPointY & ", 匹配率: " & $fCurrentMatch & @CRLF)
; 检查是否已存在相似的点(避免重复)
If Not _ListContainsPoint($aPoints, $iPointX, $iPointY, 10) Then
ReDim $aPoints
$aPoints = $iPointX
$aPoints = $iPointY
EndIf
; 如果不需要找所有匹配,直接退出
If Not $bFindAll Then
ExitLoop 2
EndIf
EndIf
EndIf
Next
Next
; 解锁位图并释放资源
_GDIPlus_BitmapUnlockBits($hSubBitmap, $tSubBitmapData)
_GDIPlus_BitmapUnlockBits($hParBitmap, $tParBitmapData)
_GDIPlus_BitmapDispose($hSubBitmap)
_GDIPlus_BitmapDispose($hParBitmap)
; 报告搜索时间
ConsoleWrite("搜索时间: " & TimerDiff($hTimer) & " 毫秒" & @CRLF)
ConsoleWrite("找到 " & UBound($aPoints) & " 个匹配" & @CRLF)
Return $aPoints
EndFunc ;==>_FindPicture
; 24位BGR格式颜色比较函数
Func _ColorBGREqualBGR($iB1, $iG1, $iR1, $iB2, $iG2, $iR2, $iErrorRange)
Return (Abs($iB1 - $iB2) <= $iErrorRange) And _
(Abs($iG1 - $iG2) <= $iErrorRange) And _
(Abs($iR1 - $iR2) <= $iErrorRange)
EndFunc ;==>_ColorBGREqualBGR
; 检查点列表中是否已包含某个点(或在指定距离内的点)
Func _ListContainsPoint($aList, $iX, $iY, $iDistance)
For $i = 0 To UBound($aList) - 1
If Sqrt(($aList[$i] - $iX) ^ 2 + ($aList[$i] - $iY) ^ 2) <= $iDistance Then
Return True
EndIf
Next
Return False
EndFunc ;==>_ListContainsPoint
本帖最后由 3131210 于 2025-4-18 23:35 编辑
AU3 纯汇编找图 支持后台 模糊找图
效果非常好 速度可以到毫秒级别
重要的还是快 2500*1500的图片,只要16毫秒
使用方法是 先绑定句柄,然后要查找的图片通过 _LoadBMPPTR 按照指定格式写到内存,然后调用_FindPic 找图。有什么其他需求的可以自己改 逻辑已经很简单了
全程可以不生成任何缓存,速度极快
本帖最后由 3131210 于 2025-4-5 12:28 编辑
再贴一个快速版本 但是还是不够快 上面提供的图片,能在1秒内找到,但是还是太慢了
; 高效率版本的找图函数
Func _FindPicture_Fast($sSubPic, $sParPic, $aSearchRect = Default, $iErrorRange = 0, $fMatchRate = 0.9, $bFindAll = False)
Local $aPoints ; 存储结果的数组
; 加载图片
Local $hSubBitmap = _GDIPlus_BitmapCreateFromFile($sSubPic)
Local $hParBitmap = _GDIPlus_BitmapCreateFromFile($sParPic)
; 获取图片尺寸
Local $iSubWidth = _GDIPlus_ImageGetWidth($hSubBitmap)
Local $iSubHeight = _GDIPlus_ImageGetHeight($hSubBitmap)
Local $iParWidth = _GDIPlus_ImageGetWidth($hParBitmap)
Local $iParHeight = _GDIPlus_ImageGetHeight($hParBitmap)
; 确定搜索区域
Local $iSearchX = 0, $iSearchY = 0, $iSearchWidth = $iParWidth, $iSearchHeight = $iParHeight
If IsArray($aSearchRect) And UBound($aSearchRect) >= 4 Then
$iSearchX = $aSearchRect
$iSearchY = $aSearchRect
$iSearchWidth = $aSearchRect
$iSearchHeight = $aSearchRect
EndIf
; 使用24位BGR格式锁定位图数据
Local $tSubBitmapData = _GDIPlus_BitmapLockBits($hSubBitmap, 0, 0, $iSubWidth, $iSubHeight, $GDIP_ILMREAD, $GDIP_PXF24RGB)
Local $tParBitmapData = _GDIPlus_BitmapLockBits($hParBitmap, 0, 0, $iParWidth, $iParHeight, $GDIP_ILMREAD, $GDIP_PXF24RGB)
; 获取扫描行宽度和指针
Local $iSubStride = DllStructGetData($tSubBitmapData, "Stride")
Local $pSubScan0 = DllStructGetData($tSubBitmapData, "Scan0")
Local $iParStride = DllStructGetData($tParBitmapData, "Stride")
Local $pParScan0 = DllStructGetData($tParBitmapData, "Scan0")
; 获取子图第一个像素颜色作为起始匹配点
Local $tStartPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pSubScan0)
Local $iStartB = DllStructGetData($tStartPixel, "B")
Local $iStartG = DllStructGetData($tStartPixel, "G")
Local $iStartR = DllStructGetData($tStartPixel, "R")
; 修改特征像素数组定义
Local $aFeaturePoints ; - 5行5列
$aFeaturePoints = 0
$aFeaturePoints = 0
$aFeaturePoints = $iStartR
$aFeaturePoints = $iStartG
$aFeaturePoints = $iStartB
; 中心点
$aFeaturePoints = Int($iSubWidth / 2)
$aFeaturePoints = Int($iSubHeight / 2)
Local $pCenterPixel = $pSubScan0 + $aFeaturePoints * $iSubStride + $aFeaturePoints * 3
Local $tCenterPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pCenterPixel)
$aFeaturePoints = DllStructGetData($tCenterPixel, "R")
$aFeaturePoints = DllStructGetData($tCenterPixel, "G")
$aFeaturePoints = DllStructGetData($tCenterPixel, "B")
; 右下角
$aFeaturePoints = $iSubWidth - 1
$aFeaturePoints = $iSubHeight - 1
Local $pCornerPixel = $pSubScan0 + $aFeaturePoints * $iSubStride + $aFeaturePoints * 3
Local $tCornerPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pCornerPixel)
$aFeaturePoints = DllStructGetData($tCornerPixel, "R")
$aFeaturePoints = DllStructGetData($tCornerPixel, "G")
$aFeaturePoints = DllStructGetData($tCornerPixel, "B")
; 左下角
$aFeaturePoints = 0
$aFeaturePoints = $iSubHeight - 1
Local $pBottomLeftPixel = $pSubScan0 + $aFeaturePoints * $iSubStride + $aFeaturePoints * 3
Local $tBottomLeftPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pBottomLeftPixel)
$aFeaturePoints = DllStructGetData($tBottomLeftPixel, "R")
$aFeaturePoints = DllStructGetData($tBottomLeftPixel, "G")
$aFeaturePoints = DllStructGetData($tBottomLeftPixel, "B")
; 右上角
$aFeaturePoints = $iSubWidth - 1
$aFeaturePoints = 0
Local $pTopRightPixel = $pSubScan0 + $aFeaturePoints * $iSubStride + $aFeaturePoints * 3
Local $tTopRightPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pTopRightPixel)
$aFeaturePoints = DllStructGetData($tTopRightPixel, "R")
$aFeaturePoints = DllStructGetData($tTopRightPixel, "G")
$aFeaturePoints = DllStructGetData($tTopRightPixel, "B")
; 优化2: 采用跳跃式扫描 - 先每隔几个像素检查一次
Local $iStepSize = 4 ; 可以根据图像大小调整
; 计算搜索范围
Local $iMaxY = $iSearchY + $iSearchHeight - $iSubHeight
Local $iMaxX = $iSearchX + $iSearchWidth - $iSubWidth
; 开始计时
Local $hTimer = TimerInit()
; 开始搜索
ConsoleWrite("开始快速搜索..." & @CRLF)
; 第一阶段:快速跳跃扫描
Local $aCandidates ; 存储候选点
For $i = $iSearchY To $iMaxY Step $iStepSize
For $j = $iSearchX To $iMaxX Step $iStepSize
; 检查特征点是否匹配
Local $bFeatureMatch = True
For $f = 0 To UBound($aFeaturePoints) - 1
Local $fx = $aFeaturePoints[$f]
Local $fy = $aFeaturePoints[$f]
Local $fR = $aFeaturePoints[$f]
Local $fG = $aFeaturePoints[$f]
Local $fB = $aFeaturePoints[$f]
Local $px = $j + $fx
Local $py = $i + $fy
; 检查特征点坐标是否在有效范围内
If $px >= 0 And $px < $iParWidth And $py >= 0 And $py < $iParHeight Then
Local $pParPixel = $pParScan0 + $py * $iParStride + $px * 3
Local $tParPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParPixel)
Local $pR = DllStructGetData($tParPixel, "R")
Local $pG = DllStructGetData($tParPixel, "G")
Local $pB = DllStructGetData($tParPixel, "B")
If Not _ColorBGREqualBGR($pB, $pG, $pR, $fB, $fG, $fR, $iErrorRange) Then
$bFeatureMatch = False
ExitLoop
EndIf
Else
$bFeatureMatch = False
ExitLoop
EndIf
Next
; 如果特征点匹配,加入候选列表
If $bFeatureMatch Then
ReDim $aCandidates
$aCandidates = $j
$aCandidates = $i
EndIf
Next
Next
ConsoleWrite("找到 " & UBound($aCandidates) & " 个候选位置" & @CRLF)
; 第二阶段:详细检查候选点
For $c = 0 To UBound($aCandidates) - 1
Local $j = $aCandidates[$c]
Local $i = $aCandidates[$c]
; 更精确地检查候选区域周围的像素
For $offsetY = -$iStepSize + 1 To 0
For $offsetX = -$iStepSize + 1 To 0
Local $checkX = $j + $offsetX
Local $checkY = $i + $offsetY
; 确保在搜索范围内
If $checkX >= $iSearchX And $checkX <= $iMaxX And $checkY >= $iSearchY And $checkY <= $iMaxY Then
; 获取父图当前位置的像素
Local $pParPixel = $pParScan0 + $checkY * $iParStride + $checkX * 3
Local $tParPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParPixel)
Local $iParB = DllStructGetData($tParPixel, "B")
Local $iParG = DllStructGetData($tParPixel, "G")
Local $iParR = DllStructGetData($tParPixel, "R")
; 检查起始像素是否匹配
If _ColorBGREqualBGR($iParB, $iParG, $iParR, $iStartB, $iStartG, $iStartR, $iErrorRange) Then
; 优化3: 采样匹配 - 不检查所有像素,只检查部分
Local $iSampleStep = 2 ; 可以根据需要调整
Local $iSum = 0 ; 总采样数
Local $iMatch = 0 ; 匹配的采样数
For $m = 0 To $iSubHeight - 1 Step $iSampleStep
For $n = 0 To $iSubWidth - 1 Step $iSampleStep
; 子图像素位置
Local $pSubPixel = $pSubScan0 + $m * $iSubStride + $n * 3
Local $tSubPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pSubPixel)
Local $iSubB = DllStructGetData($tSubPixel, "B")
Local $iSubG = DllStructGetData($tSubPixel, "G")
Local $iSubR = DllStructGetData($tSubPixel, "R")
; 对应的父图像素位置
Local $y2 = $checkY + $m
Local $x2 = $checkX + $n
; 确保在父图范围内
If $x2 < $iParWidth And $y2 < $iParHeight Then
Local $pParRelPixel = $pParScan0 + $y2 * $iParStride + $x2 * 3
Local $tParRelPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParRelPixel)
Local $iParRelB = DllStructGetData($tParRelPixel, "B")
Local $iParRelG = DllStructGetData($tParRelPixel, "G")
Local $iParRelR = DllStructGetData($tParRelPixel, "R")
$iSum += 1
; 比较颜色
If _ColorBGREqualBGR($iParRelB, $iParRelG, $iParRelR, $iSubB, $iSubG, $iSubR, $iErrorRange) Then
$iMatch += 1
EndIf
EndIf
Next
Next
; 如果采样匹配率高,进行全像素匹配
If $iSum > 0 And $iMatch / $iSum >= $fMatchRate Then
$iSum = 0
$iMatch = 0
For $m = 0 To $iSubHeight - 1
For $n = 0 To $iSubWidth - 1
; 子图像素位置
Local $pSubPixel = $pSubScan0 + $m * $iSubStride + $n * 3
Local $tSubPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pSubPixel)
Local $iSubB = DllStructGetData($tSubPixel, "B")
Local $iSubG = DllStructGetData($tSubPixel, "G")
Local $iSubR = DllStructGetData($tSubPixel, "R")
; 对应的父图像素位置
Local $y2 = $checkY + $m
Local $x2 = $checkX + $n
Local $pParRelPixel = $pParScan0 + $y2 * $iParStride + $x2 * 3
Local $tParRelPixel = DllStructCreate("BYTE B;BYTE G;BYTE R", $pParRelPixel)
Local $iParRelB = DllStructGetData($tParRelPixel, "B")
Local $iParRelG = DllStructGetData($tParRelPixel, "G")
Local $iParRelR = DllStructGetData($tParRelPixel, "R")
$iSum += 1
; 比较颜色
If _ColorBGREqualBGR($iParRelB, $iParRelG, $iParRelR, $iSubB, $iSubG, $iSubR, $iErrorRange) Then
$iMatch += 1
EndIf
Next
Next
; 计算匹配率
Local $fCurrentMatch = $iMatch / $iSum
; 如果匹配率超过阈值,添加到结果
If $fCurrentMatch >= $fMatchRate Then
ConsoleWrite("找到匹配点(左上角): X=" & $checkX & ", Y=" & $checkY & ", 匹配率: " & $fCurrentMatch & @CRLF)
; 检查是否已存在相似的点(避免重复)
If Not _ListContainsPoint($aPoints, $checkX, $checkY, 10) Then
ReDim $aPoints
$aPoints = $checkX
$aPoints = $checkY
EndIf
; 如果不需要找所有匹配,直接退出
If Not $bFindAll Then
ExitLoop 3
EndIf
EndIf
EndIf
EndIf
EndIf
Next
Next
Next
; 解锁位图并释放资源
_GDIPlus_BitmapUnlockBits($hSubBitmap, $tSubBitmapData)
_GDIPlus_BitmapUnlockBits($hParBitmap, $tParBitmapData)
_GDIPlus_BitmapDispose($hSubBitmap)
_GDIPlus_BitmapDispose($hParBitmap)
; 报告搜索时间
ConsoleWrite("搜索时间: " & TimerDiff($hTimer) & " 毫秒" & @CRLF)
ConsoleWrite("找到 " & UBound($aPoints) & " 个匹配" & @CRLF)
Return $aPoints
EndFunc ;==>_FindPicture_Fast
阿福找图你值得拥有!!
例子:
$a1Result = search_pic(0,0,@DesktopWidth - 1,@DesktopHeight - 1,@ScriptDir & "\system\SAP\Input1.png")
If $a1Result<>"" Then
$Mouse=StringSplit ($a1Result,",",2)
MouseClick('left',$Mouse+10,$Mouse+5)
Sleep(500)
endif
#include <GdiPlus.au3>
;#include <myOcrFunc.au3>
#include <ScreenCapture.au3>
#include <Clipboard.au3>
Global $x1,$y1,$x2,$y2,$pic,$aPosMsg
Func search_pic($x1,$y1,$x2,$y2,$pic,$type=0) ;当前屏幕找图,说明:$x1:屏幕上的左上角X坐标,$y1:屏幕上的左上角Y坐标,$x2:屏幕上的右下角X坐标,$y2:屏幕上的右下角Y坐标,$pic:要找图的路径及名称,$aPosMsg:返回坐标值(X坐标,Y坐标,长,高)
_GDIPlus_Startup ()
$s_dir = @ScriptDir
If $type==0 Then
_ScreenCapture_Capture ( $s_dir & "\Source.bmp",$x1,$y1,$x2,$y2 )
ConsoleWrite("X1="&$x1&@CRLF&"X2="&$x2&@CRLF&"Y1="&$y1&@CRLF&"Y2="&$y1&@CRLF)
$hBitmap1 = _GDIPlus_BitmapCreateFromFile($s_dir & "\Source.bmp")
Else
ClipPut("")
Send("{PRINTSCREEN}")
$Timer = TimerInit()
While TimerDiff($Timer) < 1000
_ClipBoard_Open(0)
$hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
_ClipBoard_Close()
If $hBitmap Then ExitLoop
Sleep(10)
WEnd
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
_GDIPlus_ImageSaveToFile($hImage, $s_dir & "\Source.bmp")
$hBitmap1 = _GDIPlus_BitmapCreateFromFile($s_dir & "\Source.bmp")
EndIf
$array1 = _myReadBitmapMsg($hBitmap1, 1)
$search_pic=$pic
$hBitmap2 = _GDIPlus_BitmapCreateFromFile($search_pic)
$array2 = _myReadBitmapMsg($hBitmap2, 1)
$iMax = _GDIPlus_ImageGetWidth ($hBitmap1) / _GDIPlus_ImageGetWidth ($hBitmap2)
$t=TimerInit()
$aPosMsg = _ArrayComp($array1, $array2, False, $iMax)
;ConsoleWrite("找到一个图片块用去时间:"&TimerDiff($t)&'毫秒,位置信息(为空未找到):'&$aPosMsg&@CRLF)
;$t=TimerInit()
;$aPosMsg = _ArrayComp($array1, $array2, True, $iMax)
;ConsoleWrite("找到所有图片块用去时间:"&TimerDiff($t)&'毫秒,位置信息(为空未找到):'&$aPosMsg&@CRLF)
;~ If $aPosMsg<>"" Then
;~ Local $aPos, $i, $hGraphics = _GDIPlus_ImageGetGraphicsContext ($hBitmap1)
;~ $aPosMsg = StringSplit($aPosMsg,"|",2)
;~ For $i = 0 To UBound($aPosMsg)-1
;~ $aPos = StringSplit($aPosMsg[$i],",",2)
;~ _GDIPlus_GraphicsDrawRect($hGraphics, $aPos, $aPos, $aPos, $aPos)
;~ Next
;~ ;_GDIPlus_ImageSaveToFile($hBitmap1, $s_dir&"\Target.bmp")
;~ _GDIPlus_GraphicsDispose ($hGraphics)
;~ EndIf
_GDIPlus_ImageDispose ($hBitmap1)
_WinAPI_DeleteObject ($hBitmap1)
_GDIPlus_ImageDispose ($hBitmap2)
_WinAPI_DeleteObject ($hBitmap2)
_GDIPlus_ShutDown ()
Return $aPosMsg
Exit
EndFunc
;一般来说,当$hBitmap2是小图时$iType=1, 较大时$iType=0, 如果已知$array2哪个元素进行搜索比较合理,直接指定为$iY
Func _ArrayComp($array1, $array2, $SearchAll=False, $iMax=0, $iY=0, $iType=0)
Local $iExtended=0
If $iMax>0 And $iY=0 Then
Local $t=TimerInit()
Local $sBmpData1 = ""
For $i = 0 To UBound($array1)-1;相当于_ArrayToString或_myReadBitmapMsg($hBitmap,0),但更快
$sBmpData1 &= $array1[$i]
Next;===>当多个$array2搜索时,这个内容考虑在udf外执行,_ArrayComp($sBmpData1, $array1, $array2, $SearchAll=False, $iMax=0, $iY=0, $iType=0)
For $i = 0 To UBound($array2)-1
If StringReplace($array2[$i], StringLeft($array2[$i],6),"")="" Then ContinueLoop
Select
Case $iType = 0
$iY = $i
ExitLoop
#cs
Case $iType = 1 And Not @AutoItX64 ;pusofalse提供的多线程方法
;该方法中映射文件到内容部分 $pBaseAddress 暂用本段代替
Local $tBuff = DllStructCreate("char ["&StringLen($sBmpData1)+1&"]")
DllStructSetData($tBuff, 1, $sBmpData1)
$pBaseAddress = DllStructGetPtr($tBuff)
;http://www.autoitx.com/thread-20592-1-3.html
#ce
Case Else
StringReplace($sBmpData1,$array2[$i],"",0, 1)
If $iExtended=0 Or $iExtended>@extended Then
$iExtended=@extended
If $iExtended=0 Then Return "";没有匹配的图块
$iY = $i
If $iExtended<=$iMax Then ExitLoop
EndIf
EndSelect
Next
;ConsoleWrite("获取最佳搜索串"&TimerDiff($t)&','&$iExtended&@CRLF)
EndIf
;Local $t=TimerInit()
If UBound($array1)<UBound($array2) Then Return ""
Local $s_re="", $y, $y2, $iW2=StringLen($array2[$iY]), $iPos;, $iSearchPos
For $y = $iy To UBound($array1)-1
$iPos = 0;$iSearchPos = 1
While $y+UBound($array2)<=UBound($array1)
$iPos = StringInStr($array1[$y], $array2[$iY], 1, 1, $iPos+1);$iPos = StringInStr($array1[$y], $array2[$iY], 1, 1, $iSearchPos)
Select
Case $iPos = 0
ContinueLoop(2)
Case Mod($iPos-1,6)<>0 ;Or $y<$iy
;$iSearchPos = $iPos+1
ContinueLoop
EndSelect
For $y2 = $iY To UBound($array2)-1
If StringMid($array1[$y+$y2-$iy], $iPos, $iW2)<>$array2[$y2] Then
;$iSearchPos = $iPos+1
ContinueLoop(2)
EndIf
Next
For $y2 = 0 To $iY-1
If StringMid($array1[$y+$y2-$iy], $iPos, $iW2)<>$array2[$y2] Then
;$iSearchPos = $iPos+1
ContinueLoop(2)
EndIf
Next
$s_re &= ($iPos-1)/6&','&$y-$iy&','&$iW2/6&','&UBound($array2)&"|"
StringReplace($s_re,"|","")
If (Not $SearchAll) Or ($iExtended>0 And @extended>=$iExtended) Then ExitLoop(2)
;$iSearchPos = $iPos+1
WEnd
Next
If StringRight($s_re,1)="|" Then $s_re = StringTrimRight($s_re,1)
;ConsoleWrite(TimerDiff($t)&@CRLF);18
Return $s_re
EndFunc
Func _myReadBitmapMsg($hBitmap, $iType=1);
Local $aBmpData
$aBmpData = _GDIPlus_ImageGetWidth ($hBitmap)
$aBmpData = _GDIPlus_ImageGetHeight ($hBitmap)
Local $BitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $aBmpData, $aBmpData, $GDIP_ILMREAD, $GDIP_PXF24RGB)
$aBmpData = Abs(DllStructGetData($BitmapData, "Stride"))
$aBmpData = DllStructGetData($BitmapData, "Scan0");
_GDIPlus_BitmapUnlockBits($hBitmap, $BitmapData)
Local $tBuff, $iH
Switch $iType;已测试比StringRegExp快
Case -1
Return $aBmpData
Case 0
For $iH = 1 To $aBmpData
$tBuff = DllStructCreate("byte[" & ($aBmpData*3) & "]", $aBmpData + ($iH-1)*$aBmpData)
$aBmpData &= StringTrimLeft(DllStructGetData($tBuff, 1),2)
Next
Return $aBmpData
Case Else
Local $aRet[$aBmpData]
For $iH = 1 To $aBmpData
$tBuff = DllStructCreate("byte[" & ($aBmpData*3) & "]", $aBmpData + ($iH-1)*$aBmpData)
$aRet[$iH-1] = StringTrimLeft(DllStructGetData($tBuff, 1), 2)
Next
Return $aRet
EndSwitch
EndFunc
模糊找图... Au3单线程干这事不会快 kemyliu 发表于 2025-4-7 08:30
阿福找图你值得拥有!!
例子:
$a1Result = search_pic(0,0,@DesktopWidth - 1,@DesktopHeight - 1,@Scrip ...
阿福是只能1比1找图,不能有半点误差啊 afan 发表于 2025-4-7 09:23
模糊找图... Au3单线程干这事不会快
那估计得有汇编大神,通过汇编开启多线程才能追得上其他语言的步伐了 好像听说按键精灵有DLL调用速度好像还可以,我以前试的时候感觉也不快,但不知现在的效果怎么样了 试试这个UDF:
_ImageSearch_UDF.au3
echo88 发表于 2025-4-13 16:45
试试这个UDF:
_ImageSearch_UDF.au3
这个效率很低 而且不支持后台和窗口句柄的截图对比 不灵活 本帖最后由 繁星 于 2025-4-16 02:49 编辑
试试我写的这个库,不喜欢带库可以从内存加载,你提供的实例图片找到5毫秒,我自己测试4K图片找个地方截个小图找到也就50毫秒
好像WIN11用不了
3131210 发表于 2025-4-17 07:23
好像WIN11用不了
我win11运行了,没有报错。返回Found 1: X=268 Y=31 Conf=100.00% Time=2.35ms 3131210 发表于 2025-4-17 07:23
好像WIN11用不了
vc运行库https://aka.ms/vs/17/release/vc_redist.x64.exe
页:
[1]