如何在AHK中更快地从屏幕区域获取像素数据? [英] How can I get the pixel data from an area of the screen (much) faster in AHK?
问题描述
我了解在某些方面,最好使用C ++编写某些内容,但我真的很希望能够在AHK中做到这一点:
I understand that for some things it would be better to write certain things in C++, but I'd really like to be able to do this in AHK:
我希望能够从屏幕的100x300区域中检索像素数据,但是PixelGetColor
太慢了.这是一项测试,证明每个像素大约需要0.02秒,从整个1920 x 1080屏幕获取像素数据大约需要11.5小时.
I want to be able to retrieve the pixel data from a 100x300 area of the screen, however PixelGetColor
is way too slow. Here's a test demonstrating that it takes about 0.02 seconds per pixel, which is roughly 11.5 hours to get the pixel data from an entire 1920 x 1080 screen.
在测试中,大约需要4-5秒钟才能从屏幕的15 x 15区域中获取像素数据.
In the test, it'll take about 4-5 seconds just to get the pixel data from a 15 x 15 area of the screen.
width := 15 ; 1920
height := 15 ; 1080
searchResolution := 1 ; 3
columns := width / searchResolution
rows := height / searchResolution
resultRows := {}
columnCounter := 0
rowCounter := 0
resultCounter := 0
start := getTimestamp()
loop, %columns%
{
resultRows[columnCounter] := {}
loop, %rows%
{
PixelGetColor, pixelColor, columnCounter, rowCounter
resultRows[columnCounter][rowCounter] := pixelColor
rowCounter += searchResolution
resultCounter += 1
}
columnCounter += searchResolution
rowCounter := 0
}
end := getTimestamp()
MsgBox % "Finished! It took " . (end - start) / 1000 .
" seconds to record pixel data from a " .
width . " x " . height . " area of the screen (" . resultCounter . " pixels)."
getTimestamp()
{
DllCall("QueryPerformanceCounter", "Int64*", timestamp)
DllCall("QueryPerformanceFrequency", "Int64*", frequency)
return Round(timestamp * 1000 / frequency)
}
如果您希望使用的版本包括调试日志记录以及将数据导出到XML文件进行检查,则该版本为此处.
If you'd like the version which includes debug logging and exporting of the data to an XML file for inspection, it's here.
是否有更快的方法从屏幕的一部分获取像素数据?
Is there any faster way to get pixel data from a portion of the screen?
PixelSearch
可以非常快速地搜索屏幕上很大的区域,我不确定为什么PixelGetColor
会比较慢.必须有一些.dll
或其他一些函数,我可以用它比这更快地从屏幕的一小部分区域获取像素数据.
PixelSearch
searches very large areas of the screen very quickly, I'm not sure why PixelGetColor
would be so very slow in comparison. There must be some .dll
or some other function I can use to get pixel data from a small area of the screen much faster than this.
推荐答案
我找到了一种比Forivin解决方案快103倍的方法:D
I found a way to do it 103 times faster than Forivin's solution :D
SetBatchLines, -1
CoordMode, Pixel, screen
FileDelete, Log.txt
searchSpace := 400
jumpSize := 1 ; how many units to skip each interval
total := Round(((searchSpace * searchSpace) / jumpSize), 0)
startTimer := getTimestamp()
getPixelMapSlow(searchSpace, jumpSize)
endTimer := getTimestamp()
duration := endTimer - startTimer
rate := total / duration
FileAppend, % "[getPixelMapSlow] Retrieved " . total . " pixels from bitmap, duration: " . duration . "ms at at a rate of " . rate . " pixels/ms.`n", Log.txt
searchSpace := 400
jumpSize := 1 ; how many units to skip each interval
total := Round(((searchSpace * searchSpace) / jumpSize), 0)
startTimer := getTimestamp()
getPixelMapFast(searchSpace, jumpSize)
endTimer := getTimestamp()
duration := endTimer - startTimer
rate := total / duration
FileAppend, % "[getPixelMapFast] Retrieved " . total . " pixels from bitmap, duration: " . duration . "ms at at a rate of " . rate . " pixels/ms.`n", Log.txt
getPixelMapFast(searchSpace, jumpSize){
width := 1920
height := 1080
centerX := width / 2
centerY := height / 2
searchSpacehalf := searchSpace / 2
searchCounterX := 0
searchCounterY := 0
pixelMap := {}
pBitmap := Gdip_BitmapFromScreen((centerX - searchSpacehalf) . "|" . (centerY - searchSpacehalf) . "|" . searchSpace . "|" . searchSpace)
E1 := Gdip_LockBits(pBitmap, 0, 0, Gdip_GetImageWidth(pBitmap), Gdip_GetImageHeight(pBitmap), Stride, Scan0, BitmapData)
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_X := tick
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_Y := tick
color1ARGB := Gdip_GetLockBitPixel(Scan0, New_Index_X, New_Index_Y, Stride)
SetFormat, Integer, H
color1RGB := 0x00ffffff & color1ARGB
SetFormat, Integer, D
if (!pixelMap[New_Index_X]){
pixelMap[New_Index_X] := {}
}
pixelMap[New_Index_X][New_Index_Y] := color1RGB
}
}
}
}
Gdip_UnlockBits(pBitmap, BitmapData)
Gdip_DisposeImage(pBitmap)
return pixelMap
}
getPixelMapSlow(searchSpace, jumpSize){
width := 1920
height := 1080
centerX := width / 2
centerY := height / 2
searchSpacehalf := searchSpace / 2
searchCounterX := 0
searchCounterY := 0
pixelMap := {}
pBitmap := Gdip_BitmapFromScreen((centerX - searchSpacehalf) . "|" . (centerY - searchSpacehalf) . "|" . searchSpace . "|" . searchSpace)
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_X := tick
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_Y := tick
color1ARGB := Gdip_GetPixel(pBitmap, New_Index_X, New_Index_Y)
if (!pixelMap[New_Index_X]){
pixelMap[New_Index_X] := {}
}
color1RGB := ARGBtoRGB(color1ARGB)
pixelMap[New_Index_X][New_Index_Y] := color1RGB
}
}
}
}
Gdip_DisposeImage(pBitmap)
return pixelMap
}
ARGBtoRGB( ARGB ) {
VarSetCapacity( RGB,6,0 )
DllCall( "msvcrt.dll\sprintf", Str,RGB, Str,"%06X", UInt,ARGB<<8 )
Return "0x" RGB
}
getTimestamp()
{
DllCall("QueryPerformanceCounter", "Int64*", timestamp)
DllCall("QueryPerformanceFrequency", "Int64*", frequency)
return Round(timestamp * 1000 / frequency)
}
当然要在您的代码中包含AHK Gdip库(在Github上找到)的相关功能,以使其正常工作.
Of course include the relevant functions of the AHK Gdip library (found on Github) in your code for this to work.
日志:
[getPixelMapSlow] Retrieved 160000 pixels from bitmap, duration: 33161ms at at a rate of 4.824945 pixels/ms.
[getPixelMapFast] Retrieved 160000 pixels from bitmap, duration: 321ms at at a rate of 498.442368 pixels/ms.
这篇关于如何在AHK中更快地从屏幕区域获取像素数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!