如何在AHK中更快地从屏幕区域获取像素数据? [英] How can I get the pixel data from an area of the screen (much) faster in AHK?

查看:1003
本文介绍了如何在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆