我知道对于某些事情,用 C++ 编写某些事情会更好,但我真的很希望能够在 AHK 中做到这一点:
我希望能够从屏幕的 100x300 区域检索像素数据,但是 PixelGetColor
太慢了。下面的测试表明,每个像素大约需要 0.02 秒,即从整个 1920 x 1080 屏幕获取像素数据大约需要 11.5 小时。
在测试中,从屏幕的 15 x 15 区域获取像素数据大约需要4-5 秒。
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 文件以供检查的版本,则为 here 。
有没有更快的方法从屏幕的一部分获取像素数据?
PixelSearch
非常快地搜索屏幕上很大的区域,我不确定为什么 PixelGetColor
相比之下会如此缓慢。一定有一些 .dll
或其他一些函数可以用来比这更快地从屏幕的一小块区域获取像素数据。
最佳答案
我找到了一种比 Forivin 的解决方案快 103 倍的方法: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 上找到)的相关函数才能使其工作。
日志:
[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.
关于autohotkey - 在 AHK 中如何更快地从屏幕区域获取像素数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44621796/