找回密码
 加入
搜索
楼主: heavenm

[AU3基础] 还是图片取色的问题,有句代码看不懂是啥意思

[复制链接]
发表于 2019-8-7 10:34:36 | 显示全部楼层
从头看到尾,一脸懵逼,感觉好高深啊。
发表于 2019-8-7 10:49:16 | 显示全部楼层
heavenm 发表于 2019-8-7 09:46
比较大的图片,如果 x,y 不为0 AU3会崩溃

Global $aAryImage = _BitmapGetColorToArray($sImage ...

大图确实不适合。不知道你是要干啥,找图的话之前阿福的方法就很好
 楼主| 发表于 2019-8-7 11:31:23 | 显示全部楼层
本帖最后由 heavenm 于 2019-8-7 11:32 编辑

我想随机抓几个图片里的色点

用来判断手机当前界面在哪一步
阿福找图不能找相似图,有些界面会用动态信息,所以只能在指定范围内取色点.
uiautomatorviewer判断速度特别特别慢

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2019-8-7 11:42:25 | 显示全部楼层
heavenm 发表于 2019-8-7 11:31
我想随机抓几个图片里的色点

用来判断手机当前界面在哪一步

_GDIPlus_BitmapGetPixel() ?
 楼主| 发表于 2019-8-7 11:45:31 | 显示全部楼层
afan 发表于 2019-8-7 10:49
大图确实不适合。不知道你是要干啥,找图的话之前阿福的方法就很好

阿福的找图确实速度很快,不过图片大了要差不多1秒,还是色点速度最快!
 楼主| 发表于 2019-8-7 11:54:58 | 显示全部楼层
afan 发表于 2019-8-7 11:42
_GDIPlus_BitmapGetPixel() ?


你别吓我,我研究了几天,有这么高级的参数.....突然感觉被雷轰了一击
我吃个饭再研究研究!
 楼主| 发表于 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, '[2,2][4,4]')
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '[0,66][103,189]')
;~ _ArrayDisplay($aAryImage)

;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '[0,66][103,189]')
$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[0], ',', 2)
        Local $__size = StringSplit($__coordinate[1], ',', 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[0]
        Local $__y = $__posi[1]
        Local $iIW = $__size[0] - $__posi[0]
        Local $iIH = $__size[1] - $__posi[1]
        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[0]
        $__rPixel = 0
        ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
        Return $aRet
EndFunc   ;==>_BitmapGetColorToArray

 楼主| 发表于 2019-8-7 18:04:14 | 显示全部楼层
貌似实现了某种特别的功能,,在图片中截取某片区域!
不过貌似截图太大的图,不能输出数组应该是数组有上限吧!
不过还好我只要抓几个色点!

太感谢了!竟然完成了这个东西,我以为搞不定呢!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 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, '[2,2][4,4]')
Global $aAryImage = _BitmapGetColorToArray($sImageFile, '[401,598][679,876]')
;~ _ArrayDisplay($aAryImage)

;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '[0,66][103,189]')
$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[0], ',', 2)
        Local $__size = StringSplit($__coordinate[1], ',', 2)

        _GDIPlus_Startup()
        Local $hImage = _GDIPlus_ImageLoadFromFile($__hBitmap)
        If @error Then
                _GDIPlus_Shutdown()
                Return SetError(1)
        EndIf


        
        Local $__x = $__posi[0]
        Local $__y = $__posi[1]
        Local $iIW = $__size[0] - $__posi[0]
        Local $iIH = $__size[1] - $__posi[1]
        
        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[0]
        #ce

        $__rPixel = 0
        ConsoleWrite(StringFormat('%s ][ %s \n', '_bitmapGetColor', TimerDiff($__begin_time)))
        Return $aRet
EndFunc   ;==>_BitmapGetColorToArray


发表于 2019-8-7 19:10:50 | 显示全部楼层
你不是要取色点么  _GDIPlus_BitmapGetPixel 就是干这个的。你现在取一片区域的所有点,相当于区域截图了,当然不适合用 _GDIPlus_BitmapGetPixel()。但是如果是区域截图,这也太费劲了吧,完全搞不懂你要搞啥。当然,你完成了就行…
 楼主| 发表于 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, '[0,0][6,6]')

Global $aAryImage = _BitmapGetPixel($sImageFile, '[401,598][679,876]')

;~ _ArrayDisplay($aAryImage)



;~ Global $aAryImage = _BitmapGetColorToArray($sImageFile, '[0,66][103,189]')

$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[0], ',', 2)

        Local $__size = StringSplit($__coordinate[1], ',', 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[0]

        Local $__y = $__posi[1]

        Local $iIW = $__size[0] - $__posi[0]

        Local $iIH = $__size[1] - $__posi[1]

        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[0]

        $__y = $__coordinate[1]

        $__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
 楼主| 发表于 2019-8-8 14:37:20 | 显示全部楼层
afan 发表于 2019-8-7 19:10
你不是要取色点么  _GDIPlus_BitmapGetPixel 就是干这个的。你现在取一片区域的所有点,相当于区域截图了, ...

我整理了下思路,这个准确的应该叫
特征码找图
http://www.autoitx.com/thread-71501-1-1.html

感谢,可以完美了!
发表于 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.ph ... amp;fromuid=7653969
发表于 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 吧
发表于 2020-7-2 19:30:38 | 显示全部楼层
afan 发表于 2020-7-2 18:21
因为前面就是使用的 $GDIP_PXF32ARGB,如果是24位RGB那就 * 3 吧

哦哦,忘了api里面可以指定颜色格式了。
另外,我觉得获取数据那里,应该是      Stride* Height  ,Width *  Height * 4 这样获取的数据会全么?
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-6-1 17:49 , Processed in 0.080066 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表