qxguoxing
发表于 2019-8-7 10:34:36
从头看到尾,一脸懵逼,感觉好高深啊。
afan
发表于 2019-8-7 10:49:16
heavenm 发表于 2019-8-7 09:46
比较大的图片,如果 x,y 不为0 AU3会崩溃
Global $aAryImage = _BitmapGetColorToArray($sImage ...
大图确实不适合。不知道你是要干啥,找图的话之前阿福的方法就很好
heavenm
发表于 2019-8-7 11:31:23
本帖最后由 heavenm 于 2019-8-7 11:32 编辑
我想随机抓几个图片里的色点
用来判断手机当前界面在哪一步
阿福找图不能找相似图,有些界面会用动态信息,所以只能在指定范围内取色点.
uiautomatorviewer判断速度特别特别慢
afan
发表于 2019-8-7 11:42:25
heavenm 发表于 2019-8-7 11:31
我想随机抓几个图片里的色点
用来判断手机当前界面在哪一步
_GDIPlus_BitmapGetPixel() ?
heavenm
发表于 2019-8-7 11:45:31
afan 发表于 2019-8-7 10:49
大图确实不适合。不知道你是要干啥,找图的话之前阿福的方法就很好
阿福的找图确实速度很快,不过图片大了要差不多1秒,还是色点速度最快!
heavenm
发表于 2019-8-7 11:54:58
afan 发表于 2019-8-7 11:42
_GDIPlus_BitmapGetPixel() ?
{:1_199:}
你别吓我,我研究了几天,有这么高级的参数.....突然感觉被雷轰了一击
我吃个饭再研究研究!
heavenm
发表于 2019-8-7 17:51:57
本帖最后由 heavenm 于 2019-8-7 17:54 编辑
afan 发表于 2019-8-7 11:42
_GDIPlus_BitmapGetPixel() ?
太牛B了,借鉴AFAN的代码,用另一种方法实现了我需要的功能!
获取色点才100多毫秒,并且还是1080*1920尺寸的图片
_bitmapGetColor ][ 141.792444350587
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#PRE_UseX64=n
#PRE_Res_requestedExecutionLevel=None
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GDIPlus.au3>
#include <Array.au3>
Local $sImageFile = @ScriptDir & '\2016.png'
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
;~ _ArrayDisplay($aAryImage)
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
$Form1 = GUICreate('Form1', 600, 600)
$pixel_size=1
For $i = 0 To UBound($aAryImage) - 1;行
For $x = 0 To UBound($aAryImage, 2) - 1
$Label1 = GUICtrlCreateLabel($aAryImage[$i][$x], $x * $pixel_size, $i * $pixel_size, $pixel_size, $pixel_size)
GUICtrlSetBkColor(-1, '0x' & $aAryImage[$i][$x])
GUICtrlSetColor(-1, 0xffffff)
Next
Next
GUISetState()
While GUIGetMsg() <> -3
WEnd
Func _BitmapGetColorToArray($__hBitmap, $__coordinate)
Local $__begin_time = TimerInit()
$__coordinate = StringRegExp($__coordinate, '\[(.+?)\]', 3)
Local $__posi = StringSplit($__coordinate, ',', 2)
Local $__size = StringSplit($__coordinate, ',', 2)
_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
If @error Then
_GDIPlus_Shutdown()
Return SetError(1)
EndIf
Local $i_Width = _GDIPlus_ImageGetWidth($hImage)
Local $i_Height = _GDIPlus_ImageGetHeight($hImage)
Local $__x = $__posi
Local $__y = $__posi
Local $iIW = $__size - $__posi
Local $iIH = $__size - $__posi
ConsoleWrite(StringFormat('%s ][ x=%s y=%s w=%s h=%s \n', '_bitmapGetColor', $__x, $__y, $iIW, $iIH))
Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iIW, $iIH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
Local $Scan0 = DllStructGetData($tBitmapData, 'Scan0')
Local $v_BufferA = DllStructCreate('byte[' & $i_Width * $i_Height * 4 & ']', $Scan0)
Local $sAllPixels = DllStructGetData($v_BufferA, 1)
$v_BufferA = 0
_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
$sAllPixels = StringTrimLeft($sAllPixels, 2)
Local $aRet[$iIH + 1][$iIW + 1]
ConsoleWrite(StringFormat('%s\n', $sAllPixels))
For $i = 0 To $iIH;行
$__xPixel = ($__x * 8) + 1;色点开始位置,X轴
$__yPixel = ($__y+$i) * $i_Width * 8;色点开始位置,Y轴
$__wPixel = ($iIW + 1) * 8;整图.色点宽度
$__rPixel = StringMid($sAllPixels, $__xPixel + $__yPixel, $__wPixel);截取的色点行
$__rPixel = StringRegExpReplace($__rPixel, '(..)(..)(..)(..)', '${3}${2}${1}');颜色格式转换
$__rPixel = StringRegExp($__rPixel, '(.{6})', 3);提取所有色点
If @error Then Return SetError(2)
ConsoleWrite(StringFormat('%s ][ sPixel=%s wPixel=%s\n', '_bitmapGetColor', $__xPixel, $__wPixel))
;~ _ArrayDisplay($__rPixel,$i)
For $r = 0 To UBound($__rPixel) - 1;列
$aRet[$i][$r] = $__rPixel[$r]
Next
Next
ReDim $__rPixel
$__rPixel = 0
ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
Return $aRet
EndFunc ;==>_BitmapGetColorToArray
heavenm
发表于 2019-8-7 18:04:14
{:1_199:}貌似实现了某种特别的功能,,在图片中截取某片区域!
不过貌似截图太大的图,不能输出数组应该是数组有上限吧!
不过还好我只要抓几个色点!
太感谢了!竟然完成了这个东西,我以为搞不定呢!
heavenm
发表于 2019-8-7 18:32:20
顺便研究了下,用_GDIPlus_BitmapGetPixel来取区域色点,速度差了5倍,还是取全图色点,再内存分析速度最快
还好,差点以为做了无用功!不知道有这个语句,不过取单色点效率很高,2者结合天下无敌!_bitmapGetColor ][ 1281.04139536952
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#PRE_UseX64=n
#PRE_Res_requestedExecutionLevel=None
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GDIPlus.au3>
#include <Array.au3>
Local $sImageFile = @ScriptDir & '\2016.png'
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
;~ _ArrayDisplay($aAryImage)
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
$Form1 = GUICreate('Form1', 600, 600)
$pixel_size = 1
For $i = 0 To UBound($aAryImage) - 1;行
For $x = 0 To UBound($aAryImage, 2) - 1
$Label1 = GUICtrlCreateLabel($aAryImage[$i][$x], $x * $pixel_size, $i * $pixel_size, $pixel_size, $pixel_size)
GUICtrlSetBkColor(-1, '0x' & $aAryImage[$i][$x])
GUICtrlSetColor(-1, 0xffffff)
Next
Next
GUISetState()
While GUIGetMsg() <> -3
WEnd
Func _BitmapGetColorToArray($__hBitmap, $__coordinate)
Local $__begin_time = TimerInit()
$__coordinate = StringRegExp($__coordinate, '\[(.+?)\]', 3)
Local $__posi = StringSplit($__coordinate, ',', 2)
Local $__size = StringSplit($__coordinate, ',', 2)
_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
If @error Then
_GDIPlus_Shutdown()
Return SetError(1)
EndIf
Local $__x = $__posi
Local $__y = $__posi
Local $iIW = $__size - $__posi
Local $iIH = $__size - $__posi
Local $aRet[$iIH + 1][$iIW + 1]
For $i = 0 To $iIH;行
For $w = 0 To $iIW
$aRet[$i][$w] =StringRight ( Hex(_GDIPlus_BitmapGetPixel($hImage, $__y + $i, $__x + $w)),6)
Next
Next
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
#cs
For $i = 0 To $iIH;行
$__xPixel = ($__x * 8) + 1;色点开始位置,X轴
$__yPixel = ($__y+$i) * $i_Width * 8;色点开始位置,Y轴
$__wPixel = ($iIW + 1) * 8;整图.色点宽度
$__rPixel = StringMid($sAllPixels, $__xPixel + $__yPixel, $__wPixel);截取的色点行
$__rPixel = StringRegExpReplace($__rPixel, '(..)(..)(..)(..)', '${3}${2}${1}');颜色格式转换
$__rPixel = StringRegExp($__rPixel, '(.{6})', 3);提取所有色点
If @error Then Return SetError(2)
ConsoleWrite(StringFormat('%s ][ sPixel=%s wPixel=%s\n', '_bitmapGetColor', $__xPixel, $__wPixel))
;~ _ArrayDisplay($__rPixel,$i)
For $r = 0 To UBound($__rPixel) - 1;列
$aRet[$i][$r] = $__rPixel[$r]
Next
Next
ReDim $__rPixel
#ce
$__rPixel = 0
ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
Return $aRet
EndFunc ;==>_BitmapGetColorToArray
afan
发表于 2019-8-7 19:10:50
你不是要取色点么_GDIPlus_BitmapGetPixel 就是干这个的。你现在取一片区域的所有点,相当于区域截图了,当然不适合用 _GDIPlus_BitmapGetPixel()。但是如果是区域截图,这也太费劲了吧,完全搞不懂你要搞啥。当然,你完成了就行…
heavenm
发表于 2019-8-8 12:55:02
再换个写法,相当于_GDIPlus_BitmapGetPixel ,不过速度就慢了_bitmapGetColor ][ 1883.49531170885
好处是更清晰
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#PRE_UseX64=n
#PRE_Res_requestedExecutionLevel=None
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GDIPlus.au3>
#include <Array.au3>
Local $sImageFile = @ScriptDir & '\2016.png'
;~ Global $aAryImage = _BitmapGetPixel($sImageFile, '')
Global $aAryImage = _BitmapGetPixel($sImageFile, '')
;~ _ArrayDisplay($aAryImage)
;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '')
$Form1 = GUICreate('Form1', 600, 600)
$pixel_size = 1
For $i = 0 To UBound($aAryImage) - 1;行
For $x = 0 To UBound($aAryImage, 2) - 1
$Label1 = GUICtrlCreateLabel($aAryImage[$i][$x], $x * $pixel_size, $i * $pixel_size, $pixel_size, $pixel_size)
GUICtrlSetBkColor(-1, '0x' & $aAryImage[$i][$x])
GUICtrlSetColor(-1, 0xffffff)
Next
Next
GUISetState()
While GUIGetMsg() <> -3
WEnd
Func _BitmapGetPixel($__hBitmap, $__coordinate)
Local $__begin_time = TimerInit()
$__coordinate = StringRegExp($__coordinate, '\[(.+?)\]', 3)
Local $__posi = StringSplit($__coordinate, ',', 2)
Local $__size = StringSplit($__coordinate, ',', 2)
_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
If @error Then
_GDIPlus_Shutdown()
Return SetError(1)
EndIf
Local $i_Width = _GDIPlus_ImageGetWidth($hImage)
Local $i_Height = _GDIPlus_ImageGetHeight($hImage)
Local $__x = $__posi
Local $__y = $__posi
Local $iIW = $__size - $__posi
Local $iIH = $__size - $__posi
ConsoleWrite(StringFormat('%s ][ x=%s y=%s w=%s h=%s \n', '_bitmapGetColor', $__x, $__y, $iIW, $iIH))
Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iIW, $iIH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
Local $Scan0 = DllStructGetData($tBitmapData, 'Scan0')
Local $v_BufferA = DllStructCreate('byte[' & $i_Width * $i_Height * 4 & ']', $Scan0)
Local $sAllPixels = DllStructGetData($v_BufferA, 1)
$v_BufferA = 0
_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
$sAllPixels = StringTrimLeft($sAllPixels, 2)
Local $aRet[$iIH][$iIW], $__PixelBits
For $c = 0 To $iIH - 1;行
For $r = 0 To $iIW - 1
$aRet[$c][$r] = _BitmapStrGetPixel($sAllPixels, ($__x + $r) & ',' & ($c + $__y), $i_Width, $i_Height)
Next
Next
#cs
For $i = 0 To $iIH - 1;行
$__xPixel = ($__x * 8) + 1;色点开始位置,X轴
$__yPixel = ($__y + $i) * $i_Width * 8;色点开始位置,Y轴
$__wPixel = ($iIW + 1) * 8;整图.色点宽度
$__rPixel = StringMid($sAllPixels, $__xPixel + $__yPixel, $__wPixel);截取的色点行
$__rPixel = StringRegExpReplace($__rPixel, '(..)(..)(..)(..)', '${3}${2}${1}');颜色格式转换
;~ $__PixelBits &= $__rPixel
;~ ConsoleWrite(StringFormat('%s ][ sPixel=%s wPixel=%s\n', '_bitmapGetColor', $__xPixel, $__wPixel))
$__rPixel = StringRegExp($__rPixel, '(.{6})', 3);提取所有色点
If @error Then Return SetError(2)
For $r = 0 To $iIW - 1;列
$aRet[$i][$r] = $__rPixel[$r]
Next
Next
#ce
$__rPixel = 0
ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
Return $aRet
EndFunc ;==>_BitmapGetPixel
Func _BitmapStrGetPixel($__str, $__coordinate, $__width, $__height);字符串提取坐标
$__coordinate = StringRegExp($__coordinate, '(\d+),(\d+)', 3);坐标转换为数组
$__x = $__coordinate
$__y = $__coordinate
$__wPixel = ($__width) * 8;一行的色点字符长度
$__xPixel = ($__x * 8) + 1;色点开始位置,X轴
$__yPixel = $__y * $__wPixel;色点开始位置,Y轴
$__cPixel = StringMid($__str, $__xPixel + $__yPixel, 8);截取的色点行
$__cPixel = StringRegExpReplace($__cPixel, '(..)(..)(..)(..)', '${3}${2}${1}');颜色格式转换
Return $__cPixel
EndFunc ;==>_BitmapStrGetPixel
heavenm
发表于 2019-8-8 14:37:20
afan 发表于 2019-8-7 19:10
你不是要取色点么_GDIPlus_BitmapGetPixel 就是干这个的。你现在取一片区域的所有点,相当于区域截图了, ...
我整理了下思路,这个准确的应该叫
特征码找图
http://www.autoitx.com/thread-71501-1-1.html
感谢,可以完美了!
haijie1223
发表于 2020-7-2 15:58:47
afan 发表于 2019-8-6 22:00
还是有用的,只是这里用处不大,帮你改了部分,试下
请教一下a版:
Local $v_BufferA = DllStructCreate('byte[' & $i_Width * $i_Height * 4 & ']', $Scan0)
这句代码里面的$i_Width * $i_Height * 4连像素格式都没有判断,这么写是准确的么?
还是我对这个函数的理解不够?
ps:https://www.autoitx.com/forum.php?mod=redirect&goto=findpost&ptid=71501&pid=739480&fromuid=7653969
afan
发表于 2020-7-2 18:21:38
haijie1223 发表于 2020-7-2 15:58
请教一下a版:
Local $v_BufferA = DllStructCreate('byte[' & $i_Width * $i_Height * 4 & ']', $Scan0 ...
因为前面就是使用的 $GDIP_PXF32ARGB,如果是24位RGB那就 * 3 吧
haijie1223
发表于 2020-7-2 19:30:38
afan 发表于 2020-7-2 18:21
因为前面就是使用的 $GDIP_PXF32ARGB,如果是24位RGB那就 * 3 吧
哦哦,忘了api里面可以指定颜色格式了。
另外,我觉得获取数据那里,应该是 Stride* Height,Width *Height * 4 这样获取的数据会全么?