在 AHK 中如何更快地从屏幕区域获取像素数据?

2023-12-09

我知道对于某些事情,用 C++ 编写某些事情会更好,但我真的很希望能够在 AHK 中做到这一点:

我希望能够从屏幕的 100x300 区域检索像素数据,但是PixelGetColor太慢了。下面的测试表明,每个像素大约需要 0.02 秒,即从整个 1920 x 1080 屏幕获取像素数据大约需要 11.5 小时。

在测试中,大约需要仅需要 4-5 秒即可从 15 x 15 区域获取像素数据屏幕的。

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 上找到)的相关函数才能使其工作。

Log:

[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.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 AHK 中如何更快地从屏幕区域获取像素数据? 的相关文章

  • windows, 放方向键设置为vim格式,autohotkey-windows

    安装 Autohotkey https www autohotkey com download 设置快捷键 随便找个目录 鼠标右键新建一个autohotkey的脚本 映射一个键 上左下右 经常打字的人都知道 我们编辑文本时要上下左右移动光标
  • 【AutoHotkey】 解析并执行 字符串中的 函数表达式

    预期效果 str func1 123 456 ExecFunc str 实现方式 正则文本解析出函数名及其参数 array形式 执行 该函数与其参数 难点
  • 将windows按键修改成mac的快捷键

    下载工具autoHotKey AutoHotkey 使用autoHotKey 下载后创建一个脚本 ahk文件 将下面的进行粘贴 右键run script运行当前的脚本 ahk文件 就可以实现mac的快捷键了 a Send a 将 Alt A
  • 【ahk】映射按键到执行函数

    global zFuncCallPattern w IsFuncCallStr callFuncStr Return RegExMatch callFuncStr O zFuncCallPattern matchObj EvalStrArg
  • 如何使用 AutoHotkey

    AutoHotkey 本身并不会做任何事情 你需要编写一个脚本来告诉它怎么做 所谓脚本就是一个以 ahk 为后缀的纯文本文件 里面包含了多个程序指令 就像配置文件一样 但是功能更加强大 一个脚本可以只是简单地执行一个动作后就退出 也可以定义
  • AutoHotkey中的变量名 全局与局部冲突问题 - double-ref 双重引用

    文章目录 test 测试脚本 AutoHotkey中 全局变量与局部变量的作用域要缕清 已知一个 变量名foo 被一个全局变量 和 一个函数中的局部变量 使用 在该函数中 foo默认是局部变量 直接使用foo 其内容为空 双重解引用的变量
  • 在 Windows 上的 Emacs 中将 Caps Lock 映射到 Control

    当阅读任一these 问题 or the EmacsWiki 文章关于在 Windows 中的 emacs 中将 Caps Lock 映射到 Control 最好的答案似乎涉及注册表 我的问题是 当用户因为没有管理员权限而无法修改计算机的注
  • Autohotkey:发送 5 位十六进制 unicode 字符

    我一直在尝试找到一种方法来重新映射键盘并发送 5 位十六进制 unicode 字符 方法如下所述 ahk Send只支持 4 位十六进制代码 U nnnn 我知 道在过去 autohotkey 本身不支持 unicode 因此需要一些函数才
  • 使用 AHK 关闭 Visual Studio 中的弹出对话框

    我重新映射了几个键 效果很好 然而 我在尝试摆脱视觉工作室中的弹出对话框时遇到了困难 这是我尝试过的 WinWaitActive Microsoft Visual Studio If WinActive Microsoft Visual S
  • Autohotkey 和 Windows 10:如何获取当前资源管理器路径

    我使用 autohotkey 版本 1 0 48 05 因为我坚 持使用 activeaid 读取当前路径的脚本如下 一直有效到Win 7 Get full path from open Explorer window WinGetText
  • 什么是 AU3_Spy.exe?我在哪里可以找到它?

    每当我尝试在 AutoHotkey 中启动 Windows Spy 实用程序时 都会失败并显示错误 无法启动文件 U Software AutoHotkey 1 1 26 00 AU3 Spy exe 最初我以为我下载的文件可能已损坏 然而
  • 重新启动自动热键脚本的热键?

    假设我有一个自动热键脚本C path to my script跑步 有没有办法定义一个重新启动的热键 In order to prevent duplicate instances I normally do not re launch a
  • 缓解 R for Windows 中的反斜杠问题

    在我的 R 生活早期 当涉及到目录和子目录之间的分隔符时 我发现 R 和 Windows 位于不同页面上的痛苦 尽管我知道这个问题 但我仍然对必须手动在所有反斜杠前面放置反斜杠或将它们全部替换为正斜杠感到痛苦 我喜欢使用计算机上运行的多个应
  • 如何在自动热键中将字符串转换为数字?

    FormatTime CurrentMinute m将当前分钟分配给变量 CurrentMinute 其值是字符串 而不是数字 我想做一些计算 CurrentMinute 那么如何将其转换为数字呢 感谢您提前提供任何帮助 AutoHotke
  • 我可以列出几个键来执行相同的操作吗? [AHK]

    AHK允许绑定按键 就是我们a z每当按下 a 时 都会触发 z 如果我想在按下 a b 或 c 时触发 z 怎么办 我显然可以重复我的代码 a z b z c z 我可能可以使用 Gosub 像 a Gosub abc b Gosub a
  • 自动热键窗口出现事件

    我正在使用 WorkRave 休息提醒 并希望在休息窗口出现时关闭屏幕 我知道如何将其关闭 如何在指定窗口 IfWinActive ahk class 出现时创建事件 另外 我可以绑定 符号吗 不起作用 而是其他的 要获得出现窗口的即时通知
  • 使用 WinHttp.WinHttpRequest 查找检索到的二进制数据的大小

    我最近意识到 URLDownloadToFile 使用 IE 代理设置 所以我正在寻找替代方案 发现 WinHttp WinHttpRequest 可能有效 ResponseBody 属性似乎包含获取的数据 我需要将其写入文件 问题是我找不
  • Autohotkey 错误的击键发送到控制台

    我正在尝试理解这个错误并寻找解决方法 使用这个脚本 NoEnv SingleInstance force SendMode Input Alt t to send keystrokes t Send It send the correct
  • 如何在 AutoHotkey 中读取多行用户输入?

    我有一个 AutoHotkey 脚本 需要从用户读取多行员工数据 InputBox userInput Employee Records Please enter employee records One per line Unfortun
  • 使用 AutoHotkey 读取目录中的文件名

    我正在寻找一种读取文件夹并将每个文件名保存到变量的方法 到目前为止 这就是我所拥有的 Loop C My Documents Notes 在我的笔记目录中 有 pdf 文件 我想读取该目录并将文件名 Homework1 pdf 保存到变量中

随机推荐

  • Firebase crashlytics 未在 iOS 中初始化

    在我们的项目中 我们使用该结构来报告崩溃 之后我们使用 Firebase 迁移了该结构 并且由于 Firebase 处于测试阶段而没有删除该结构 现在我们正在尝试删除整个代码中的 Fabric 和 crashlytics 依赖项 pod F
  • 无法导入 ParseImageView - Android

    我在我的项目中使用 Parse 我可以从解析库导入所有其他类 例如 import com parse ParseException import com parse ParseFile import com parse ParseGeoPo
  • es6 导入 using.mjs 后缀失败并出现 MIME 错误

    在最新的chrome浏览器中 import foo from dist foo mjs 失败了 无法加载模块脚本 服务器响应非 JavaScript MIME 类型 根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查 但是如果
  • 提升内部函数 - 内部函数和变量具有相同的名称 - 输出?

    function y var x hi function x return bye return x x is not a function return x hi console log y 无法执行此函数 有人可以解释一下吗 函数和变量
  • 如何在 Emacs Elisp 中获得类似格式化的 LSP?

    这是我在 Rust 开发中经常使用的一个场景 Rust LSP 始终开启 我将 LSP 功能称为 格式化当前缓冲区 或其他名称 LSP 返回格式化的缓冲区 LSP 在内部使用rustfmt 由于 Emacs Elisp 没有 LSP 实现
  • 将带有换行符的TextArea数据存储在数据库中并以与换行符相同的格式显示

    我有一个带有文本区域 HTML 组件的 JSP 页面 当用户在文本区域中输入时按 Enter 键并转到下一行 并且单击 保存 按钮时 会将文本区域中的数据保存到数据库中 但是当我加载数据库的内容时 换行符消失了 方法 HELLO WORLD
  • Java 中的 ^ 运算符有什么作用?

    有什么功能 插入符号 运算符在 Java 中服务 当我尝试这个时 int a 5 n 它给了我 对于 n 5 返回 0对于 n 4 返回 1对于 n 6 返回 3 所以我猜它不执行求幂 但那又是什么呢 Java 中的 运算符 在Java中是
  • 查找具有 3 个或更多连续相同值的记录

    我的表中有一个日期交易列表 其中包含日期 客户编号 交易类型和价值 如果该客户按日期排序时连续有 3 个或更多连续 现金 交易 我需要返回该客户的所有交易 因此 在下面的示例数据中 我想返回客户 1 和 3 的所有交易 包括信用交易 因为这
  • 如何获取当前类中的方法名称

    你好 在我的 java 类 Toto 中 我有 3 个静态方法 我想知道当我使用这些方法之一时 如何在 try catch 块中获取并显示 package class methode 的名称 我在方法A中尝试过 public static
  • 如何使用 Amazon AMI 在 Amazon AWS EC2 或 EMR 上安装 GUI

    我需要运行一个需要 GUI 界面来启动和配置的应用程序 我还需要能够在 Amazon 的 EC2 服务和 EMR 服务上运行此应用程序 EMR 要求意味着它必须在 Amazon 的 Linux AMI 上运行 经过大量搜索后 我无法找到任何
  • 如何返回两个字符串是否仅大小写不同?

    我正在编写一个方法 其输入是两个字符串 该方法应返回三个值之一 1当字符串具有完全相同的值 其字符的 Unicode 值 时 0当字符串具有完全相同的值 除了基本拉丁语 ASCII 字符大小写不同之外 时 并且 1否则 我有 public
  • 使用spring security告诉ajax请求登录页面在哪里

    我有一些用 spring 保护的 url 通过 xml 配置 有用 但是 当我尝试使用 ajax 请求访问该端点时 我收到 302 已找到 响应 这将我的 ajax 调用重定向到登录页面 因此我获取了 html 不过 我希望获得 401 未
  • 如何在Startup.cs中注册通用类型的接口

    我在 ASP NET Core 中使用 Web API 这有效 services AddScoped
  • 有没有办法只将样式应用于 Safari?

    我正在尝试找到一种将 CSS 仅应用于 Safari 的方法 但我发现的所有内容也适用于 Chrome 我知道这些目前都是 WebKit 浏览器 但我在 Chrome 和 Safari 中遇到了 div 对齐问题 每个显示都不同 我一直在尝
  • 使用 Rmpfr/gmp 库,x>170 的阶乘(x)

    我想解决的问题是以下函数的无限和 对于总和 我使用 FTOL 确定标准 整个术语不会产生任何问题 直到z变得非常大 我期望的最大值z大约 220 正如您所看到的 第一项在阶乘 221 附近具有最大值 因此必须在阶乘 500 附近移动 直到达
  • 如何获取 py2exe 中可执行文件的当前目录?

    我在脚本中使用这段代码以跨平台的方式查明它的运行位置 SCRIPT ROOT os path dirname os path realpath file 很简单 然后我继续使用SCRIPT ROOT在我的脚本的其他区域 以确保一切都是正确相
  • 使用合作伙伴级证书将应用程序安装到 Samsung Tizen TV

    我在将开发的应用程序安装到三星电视设备时遇到问题 现在我找到了解决方案 我想分享我的经验 如果您添加合作伙伴级别权限 例如http developer samsung com privilege drminfo http developer
  • 使用ajax将数据从服务器发送到客户端

    我有一个场景 我正在制作一个基于内联网的网络应用程序 供公司内部使用 每当客户端更新应用程序中的任何内容时 其他客户端都应该更新 Steps 一个客户端更新一些任务 然后服务器自动将更新的数据发送给当前连接的客户端 因此 客户端无需向服务器
  • 使用“id”列中的键值从 MySQL 生成 PHP 数组

    我有一个 MySQL 数据库 如下所示 ID TEXT PARENTID 20 Item1 null 23 Item2 20 27 Item3 20 80 Item4 27 我想要的是在数组中检索这些数据 如下所示 Array 20 gt
  • 在 AHK 中如何更快地从屏幕区域获取像素数据?

    我知道对于某些事情 用 C 编写某些事情会更好 但我真的很希望能够在 AHK 中做到这一点 我希望能够从屏幕的 100x300 区域检索像素数据 但是PixelGetColor太慢了 下面的测试表明 每个像素大约需要 0 02 秒 即从整个