文章

FindText教程

FindText教程

FindText教程

简介

FindText 是一个 AHK 库,可以替代内置的 ImageSearch 功能,并包含许多附加功能。FindText 主要用于在屏幕上快速查找图形(图像),其匹配精度比 ImageSearch 高。它将屏幕上抓取一个小图像转换成黑白图像(类似于 ASCII 艺术),然后再将黑白图像转换成单行文本。使用 FindText 时,它会截取屏幕截图,将屏幕截图中的每个像素也转换成黑白,然后尝试将抓取的图像与屏幕截图进行匹配。由于像素变成了黑白,要比较的次数要少得多(红、绿、蓝需要比较三次、黑白只需要比较一次),所以匹配速度要比 ImageSearch 快。

FindText 的一些优点:

1)它不需要图像文件,而是使用图像的文本表示。该函数将屏幕的图像抽象为具有代表意义的“0”(“0”=黑色像素=文本像素)和“”(“”=白色像素=背景像素),它们依次排列变成一行数字和字母序列。因为这是一种抽象,而不是逐位比较,所以它可以实现快速匹配及轻松调整容错。

2)它比ImageSearch更快,在我的测试中大概快了10%(在有些用例中甚至可能快2-3倍)。

3)提供了轻松存储及在脚本中获取图像的函数。

4)使用 BindWindow,实现了当窗口藏在其他窗口后面时也能使用 FindText。

5)允许创建简单的自定义 OCR 函数。

目录

入门指南

下载 FindText.ahk 后,我建议将其放入Lib 文件夹,然后使用以下命令将其包含在您的脚本中:

#include <FindText>

完成上述操作后,您可以通过将已实现的图像搜索替换为 FindText().ImageSearch 来加快其速度,如下所示:

ImageSearch, OutputVarX, OutputVarY, X1, Y1, X2, Y2, ImageFile
 ; 变成这样
FindText().ImageSearch(OutputVarX , OutputVarY, X1, Y1, X2, Y2, ImageFile)

按 抓图 按钮 -> 选择要抓取的区域 -> 右键单击两次(第一次右击选择,将鼠标移动到其他位置后再次右击以确认)-> 按灰度阈值二值化按钮 -> 按 确定。如果一切顺利,那么现在按下测试按钮后,FindText 应该会成功找到之前抓取的图像(找到图像的位置会出现一个闪烁的红色框)。

抓取图像后,在下方的文本框会显示一些自动生成的代码,如下所示:

Text:="|<>*151$101.000000000000000000000000U0000M0000000000100000k0000000400200011U0000000A0040002300000000M008000460000DVUnw7kHk7kzAA7X0vX1XUtkxktksMkvW036331UlVVUkUn11a02A6661X161V1g63A1wMAAA343A323kDy8DMkMMM286M247UM0NkFUkkkAEAkA8BUk0nVX1VVUMUNUMEPVU0b33331UV0lUUUnXU1zS7S63b21Xb1dX3a1bY7g71s431s1n33s300000000000000006000000000000000080000000000000000k00000000000000034"

if (ok:=FindText(X, Y, 312-150000, 79-150000, 312+150000, 79+150000, 0, 0, Text))
{
  ; FindText().Click(X, Y, "L")
}
...

• Text 变量包含以文本/字符串形式呈现的图像以及其他一些必要信息。 • FindText(X, Y, 312-150000, 79-150000, 312+150000, 79+150000, 0, 0, Text) 表示变量 X 和 Y 将被赋予找到的第一个图像的精确中心坐标;数字 312 和 79 是图像原始拍摄位置的 x 和 y 坐标,312-150000 和 79-150000 是搜索区域左上角的非常大的 x 和 y 坐标(以包含屏幕外的窗口或第二个显示器);312+150000 和 79+150000 是搜索区域右下角的非常大的值;0 和 0 是默认的误差范围(仅允许精确匹配)。文本变量会将图像以文本形式传递给 FindText。 • 如果从 FindText.Click 之前移除注释符号 (;),则 FindText 成功找到图像时,将单击该图像。

接下来的部分将包含一些示例脚本,您可以将其复制粘贴到 FindText 主界面示例代码框的顶部,然后按“测试”按钮即可轻松运行。请将以下图像保存到您的计算机,并在画图程序中打开它。确保在按“测试”按钮之前图像可见,并且屏幕 DPI 应为 150%。

FindText 主函数

以下内容主要摘自 FindText.ahk 的顶部描述区域(并添加了一些内容):

returnArray := FindText(
    OutputX --> 该变量用于存储找到的第一张图片中心的 X 坐标。OutputX 也可以设为"wait"、"wait1" (appear) 或"wait0" (disappear),以使 FindText 要么等待文本出现或消失。如果将 OutputX 留空,则不进行搜索,并返回一个 FindTextClass 实例:在 FindText().Click 示例中使用了这样的代码,等价于 FindText(,,,,,,,,Text).Click (Text 会被忽略)。调用 FindText 执行搜索的最简单形式为 FindText(X,,,,,,,,Text).
    , OutputY --> 该变量用于存储找到的第一张图片中心的 Y 坐标。如果 OutputX 设为 "wait",则 OutputY 可以设置为等待的秒数,负数表示无限等待。[/list]
    , X1 --> 搜索区域左上角的 X 坐标
    , Y1 --> 搜索区域左上角的 Y 坐标
    , X2 --> 搜索区域右下角的 X 坐标
    , Y2 --> 搜索区域右下角的 Y 坐标
    如果 X1, Y1, X2, Y2 都设为 0 (默认值),则 X1 和 Y1 会被设为 -150000,X2 和 Y2 被设为 150000。这样会将搜索区域设为整个屏幕以及所有不在屏幕上的东西也包括在内。
    , err1 --> 文本的容错比例(text=黑色="o")(0.1=10%)。
    , err0 --> 背景的容错比例(background=白色="_") (0.1=10%)
    如果 err1 和 err0 都为 0,并且没有找到匹配项,则 FindText 会自动使用 0.05=5% 错误容限再次进行搜索。为避免这种情况,可以将 err1 和 err0 指定为很小的一个值(如 0.000001,很接近 0,但是不等于 0)。
    , Text --> 可以是多个文本形式的图片,图片之间用 "|" 分隔
    , ScreenShot --> 取值为 0 时,使用上一次截屏,默认为 1(每次都重新截屏)
    , FindAll --> 取值为 0 时,找到第一个结果后立刻返回,默认为 1(查找全部结果)
    , JoinText --> 用于组合查询:可以是 1,也可以是要查找的单词数组,默认为 0
    , offsetX --> 设置组合查找时 X 方向最大文本偏移量
    , offsetY --> 设置组合查找时 Y 方向最大文本偏移量
    , dir --> 指定搜索方向,共9种取值:
    1 ==> ( 从左到右 ) 从上到下
    2 ==> ( 从右到左 ) 从上到下
    3 ==>(从左到右)从下到上
    4 ==>(从右到左)从下到上
    5 ==>(从上到下)从左到右
    6 ==>(从下到上)从左到右
    7 ==>(从上到下)从右到左
    8 ==>(从下到上)从右到左
    9 ==>从中心向外
)

该函数返回一个包含所有查找结果的二阶数组(returnArray[1] 表示找到的第一个结果,returnArray[2] 表示找到的第二个结果,以此类推),每个结果都是一个关联数组:{1:X, 2:Y, 3:W, 4:H, x:X+W//2, y:Y+H//2, id:Comment}。 如果 没有找到图像,则 FindText 返回 0。

例如,如果返回变量名为“ok”,则 ok[1] 表示找到的第一个结果。 ok[1][1] 和 ok[1][2] 分别是找到的第一张图像左上角的 X 和 Y 坐标, ok[1][3] 是找到的图像的宽度,ok[1][4] 是找到的图像的高度, ok[1].x <==> ok[1][1]+ok[1][3]//2 <==> OutputX(找到的图像中心的 X 坐标), ok[1].y <==> ok[1][2]+ok[1][4]//2 <==> OutputY(找到的图像中心的 Y 坐标), ok[1].id 是注释文本,包含在 Text 的 <> 部分中。 如果 OutputX 设置为“wait”或“wait1”(出现)或“wait0”(消失),则超时表示失败并返回 0,其他值表示成功。如​​果等待出现且找到图像,则返回找到的数组对象。如果等待消失但未找到图像,则返回 1。

FindText(X:="wait", Y:=3, 0,0,0,0,0,0,Text)   ; Wait 3 seconds for appear
FindText(X:="wait0", Y:=-1, 0,0,0,0,0,0,Text) ; Wait indefinitely for disappear

更多注意事项:

  • 返回的所有坐标均相对于屏幕(如同在 CoordMode Screen 模式下)。要转换为相对坐标,请使用转换函数 ScreenToWindow 和 ScreenToClient。
  • 所有颜色均为十六进制 RGB 格式。
  • FindText 函数对屏幕 DPI 敏感,这意味着使用一种 DPI 捕获的图像/文本在另一种 DPI 下将无法正常工作。为确保用户使用正确的 DPI,请使用内置变量 A_ScreenDPI 进行检查。
  • 使用多个显示器时,请勿将 X1、Y1、X2、Y2 设置为 0、0、A_ScreenWidth、A_ScreenHeight,因为这只会捕获主显示器。建议将其留空(默认值 -150000、-150000、150000、150000 应该足够大),或使用与默认值类似的大值。

对于以下示例,请使用画图程序打开第 1 节中提供的 Examples.png 文件。然后,在新脚本中运行代码,或者将不包含 #include 行的代码复制到 FindText GUI 代码框中,然后按“测试”。

示例 1。

#include <FindText>
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" ; Image of the "auto" part in "autohotkey.com". Id of the image is "auto" (between < and > characters).
ok := FindText(outX, outY,,,,,,,Text) ; Call FindText to look for the "auto" image. outX and outY will be set to X and Y coordinates for the first found result. Search range coordinates, err1 and err0 are left empty to use the default values (searching the whole screen, and looking for an exact match). Results will be stored in the "ok" variable.
if ok { ; Check if "ok" is not set to 0
    MsgBox, The image (Text) was first found at coordinates X: %outX% Y: %outY% ; Display outX and outY
    MsgBox, % ok.MaxIndex() " results were found." ; ok.MaxIndex() and ok.Length() should return how many search results were found.
    MsgBox, % "The first found image is located at X" ok[1][1] " Y" ok[1][2] ". It has a width of " ok[1][3] " and a height of " ok[1][4] ". Additionally it has a id of " ok[1].id
    if ok[2] ; ok[1] contains the first result, ok[2] contains the second result, etc... Check if ok[2] exists and if yes, display some of its contents.
        MsgBox, % "The second found image is located at X" ok[2][1] " Y" ok[2][2] " and it has a width of " ok[2][3] " and a height of " ok[2][4] ". Additionally it has a comment text of " ok[2].id
} else {
    MsgBox, The image/Text was not found. Is everything set up correctly and the image is visible in Paint? ; It seems "ok" was left empty, so nothing was found.
}

例2.

#include <FindText>

if (ok := FindText(outX, outY, 0, 0, A_ScreenWidth, A_ScreenHeight, 0.05, 0.05, "|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8")) { ; Call FindText to look for the "auto" image. outX and outY will be set to X and Y coordinates for the first found result. Search ranges top left corner is (0;0) and bottom right corner (A_ScreenWidth; A_ScreenHeight), which should search the whole screen, but might not work properly if using multiple monitors. Error margins are set to 5% for both "1"s and "0"s. Results will be stored in the "ok" variable. If "ok" contains results, then the "if" condition will be successful.
    for k, v in ok { ; Loop over all the search results in "ok". "k" will be the nth result, and "v" will contain the result itself.
        MsgBox, % "Result number " k " is located at X" v[1] " Y" v[2] " and it has a width of " v[3] " and a height of " v[4] ". Additionally it has a comment text of " v.id ; v[1] is equivalent to ok[k][1], v.id is equivalent to ok[k].id, and so on.
    }
} else {
    MsgBox, The image/Text was not found. Is everything set up correctly and the image is visible in Paint? ; It seems "ok" was left empty, so nothing was found.
}

例3.

#include <FindText>
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" ; Image of the "auto" part in "autohotkey.com". Id of the image is "auto" (between < and > characters).
Text.="|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s" ; Append an image of the "hot" part in "autohotkey.com" to the Text variable (note the ".=" operator which appends, when previously we used ":=" to set). Id of the image is "hot".
; The last two lines are the same as Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s"

WinGetPos, pX, pY, pW, pH, ahk_class MSPaintApp ; Get the Paint application location and size.

if !(ok := FindText(X, Y, pX, pY, pX+pW, pY+pH, 0.000001,, Text)) { ; Call FindText to look for either "auto" or "hot" images. X and Y will be set to X and Y coordinates for the first found result. The search range will be only the Paint application. Setting one or both of the error margins to a small non-zero value will avoid the second search with 5% error margins. Results will be stored in the "ok" variable. If "ok" doesn't contain anything ("!" is the "not" operator) then exit, otherwise continue on.
    MsgBox, The image/Text was not found. Is everything set up correctly and the image is visible in Paint? ; It seems "ok" was left empty, so nothing was found.
    ExitApp
}
; Anything after this part will happen only if any of the Text was found (either "hot" or "auto" image).

for key, value in ok { ; Loop over all the search results in "ok". "key" will be the nth result, and "value" will contain the result itself.
    FindText().MouseTip(value.x, value.y) ; Show a blinking red box at the center of the result.
    MsgBox, % "Result number " key " is located at X" value[1] " Y" value[2] " and it has a width of " value[3] " and a height of " value[4] ". Additionally it has a comment text of " value.id ; value[1] is equivalent to ok[k][1], value.id is equivalent to ok[k].id, and so on.
    if (value.id == "auto")
        MsgBox, Here we found the "auto" image.
}

(3) ImageSearch、PixelSearch、PixelCount、GetPixelColor

FindText().ImageSearch 是 FindText 的包装函数,它更易于使用。它还可以像 AHK 原生函数 ImageSearch 一样接受图像文件(但不支持 *IconN 等选项),并且它支持不同的 CoordMode(FindText 总是返回相对于屏幕的坐标,但 FindText().ImageSearch 可以使用任何一个由 CoordMode Pixel 命令设置的坐标模式,例如 Window 或 Client 坐标模式)。

FindText().ImageSearch(OutputVarX, OutputVarY, X1, Y1, X2, Y2, TextOrImageFile, Screenshot:=1, FindAll:=0)

returnValue := FindText().ImageSearch(

OutputVarX, OutputVarY –> 存储找到图像中心的 X 和 Y 坐标的变量名。除非使用 CoordMode 来更改坐标模式,否则坐标是相对于活动窗口的。 ,X1, Y1 –> 搜索矩形左上角的 X 和 Y 坐标。除非使用 CoordMode 来更改坐标,否则坐标是相对于活动窗口的。 ,X2, Y2 –> 搜索矩形右下角的 X 和 Y 坐标。除非使用 CoordMode 来更改坐标,否则坐标是相对于活动窗口的。 , TextOrImageFile –> FindText 文本或图像文件的文件名 , Screenshot –> 如果值为 0,则使用最后的截图,默认为 1(每次重新截图) , FindAll –> 如果值为0,则在找到第一个结果后返回,默认为1(查找所有结果)

)

如果搜索成功,returnValue 将被设置为 1,否则为 0。

如果搜索成功,ErrorLevel 将被设置为 0,否则为 1。

例子:

#include <FindText>
if FindText().ImageSearch(X,Y,,,,, A_ScriptDir "\Examples.png") ; Looks for the image in Examples.png on the screen
    FindText().MouseTip(X, Y)
if FindText().ImageSearch(X,Y,,,,, "|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8") ; Looks for the "auto" image contained in the Text
    FindText().MouseTip(X, Y)

以下示例使用±10的颜色变化范围,并将黑色设置为透明色:FindText().ImageSearch(X,Y,,,,, “10TransBlack A_ScriptDir “\Examples.png”)

FindText().PixelSearch是 FindText 函数中内置 PixelSearch 函数的替代方案。与内置版本类似,其坐标系取决于 CoordMode,这意味着除非另行设置,否则坐标将相对于活动窗口。FindText

().PixelSearch(OutputVarX, OutputVarY, x1, y1, x2, y2, ColorID, Variation:=0, ScreenShot:=1, FindAll:=0)

returnArray := FindText().PixelSearch( OutputVarX、OutputVarY –> 用于存储第一个找到的匹配像素的 X 和 Y 坐标的变量名。除非使用 CoordMode 更改了坐标系,否则坐标相对于活动窗口。 ,X1、Y1 –> 要搜索的矩形左上角的 X 和 Y 坐标。除非使用 CoordMode 更改了坐标系,否则坐标相对于活动窗口。 ,X2、Y2 –> 要搜索的矩形右下角的 X 和 Y 坐标。除非使用 CoordMode 更改了坐标系,否则坐标相对于活动窗口。 ,ColorID –> 要搜索的十六进制颜色 ID,默认为红绿蓝 (RGB) 格式 (RRGGBB)。可以使用 | 字符分隔多个颜色。 ,Variation –> 一个介于 0 和 255(含)之间的数字,用于指示颜色的红色、绿色和蓝色分量强度允许的色调变化数量 。Screenshot –> 如果值为 0,则使用上次的屏幕截图;默认值为 1(每次都使用新的屏幕截图) 。FindAll –> 如果值为 0(默认值),则在找到第一个结果后返回;如果值为 1,则查找所有结果。如果 FindAll<0,则仅返回找到的像素数量。

如果搜索失败,则返回 0。否则,该函数返回一个包含所有查找结果的数组(returnArray[1] 表示找到的第一个结果,returnArray[2] 表示找到的第二个结果,以此类推),每个结果都是一个关联数组:{1:X, 2:Y, 3:W, 4:H, x:X+W//2, y:Y+H//2}。 示例

:

ok := FindText().PixelSearch(,,,,,, "0xFFFFFF|0x000000") ; FFFFFF = black, 000000 = white
FindText().MouseTip(ok[1].x, ok[1].y) ; Displays first found black or white pixel

FindText().PixelCount 函数用于计算搜索区域中的像素数量。由于搜索区域可以小至 1 像素,因此也可以用它来检查特定颜色(或颜色范围)的像素。PixelCount

(x1:=0, y1:=0, x2:=0, y2:=0, ColorID:=””, Variation:=0, ScreenShot:=1)

out := PixelCount( x1:=0, y1:=0 –> 要搜索的矩形左上角的 X 和 Y 坐标。坐标相对于屏幕。 , x2:=0, y2:=0 –> 要搜索的矩形右下角的 X 和 Y 坐标。坐标相对于屏幕。 , ColorID:=”” –> 要搜索的十六进制颜色 ID,默认为红绿蓝 (RGB) 格式 (RRGGBB)。允许使用多个颜色,用 | 字符分隔。也支持颜色范围,例如 “RRGGBB-DRDGDB|RRGGBB-DRDGDB”.。 , Variation:=0 –> 介于 0 和 255(含)之间的数字,表示颜色的红色、绿色和蓝色分量强度允许的色调变化数量。 , ScreenShot:=1 –> 如果值为 0,则使用上次的屏幕截图;默认值为 1(每次都使用新的屏幕截图)。

如果搜索不成功,则返回 0。否则,返回找到的像素数量。 例如:

out := FindText().PixelCount(0, 0, A_ScreenWidth, A_ScreenHeight, "FFFFFF")
MsgBox % "The number of white pixels on the screen is " out

out := FindText().PixelCount(100, 250, 100, 250, "FFFFFF")
MsgBox % "The color at screen coordinates (100, 250) is " (out ? "" : "not ") "white."

GetPixelColor 函数 在 FindText 函数中没有像 PixelGetColor 那样的内置方法来获取屏幕上特定像素的颜色。幸运的是,我们可以编写一个包装函数来实现这个功能:


GetPixelColor(x, y, screenshot:=1) {
if (A_CoordModePixel="Window")
FindText().WindowToScreen(x, y, x, y)
else if (A_CoordModePixel="Client")
FindText().ClientToScreen(x, y, x, y)
if (screenshot)
FindText().ScreenShot(x, y, x, y)  ;// x1,y1,x2,y2
return FindText().GetColor(x, y)
}

与内置的 PixelGetColor 函数类似,此包装函数使用 CoordMode 像素坐标。此外,每次都会重新截取屏幕截图,可以通过将截图参数设置为 0 来禁用此功能,这意味着像素颜色将取自上次截取屏幕截图的 FindText 调用。

(4) 什么是 Text 文本?

Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" 
; From left to right: "|" is the separator
; "<auto>" means the id/comment of the Text is "auto"
; "*" is the capture mode, which in this case is Gray
; 159 is the Gray threshold value
; 40 (between $ and .) is the width of the original image
; 0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8 is the 64-bit representation of the image

文本字符串由 5 个部分组成:

  1. 竖线字符 | 是图像分隔符。这意味着可以将多个图像依次连接起来,同时进行搜索(或用于组合搜索)。
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" ; First set the Text variable to contain the "auto" image
Text.="|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s" ; Then append the "hot" image to Text variable using the ".=" operator
ok:=FindText(X,Y,,,,,,,Text)
for k, v in ok
    FindText().MouseTip(v.x, v.y)

相当于:

Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s"
ok:=FindText(X,Y,,,,,,,Text)
for k, v in ok
    FindText().MouseTip(v.x, v.y)

这会返回所有 auto 和 hot 图像的结果。

  1. 尖括号 <> 之间的字符是图像的 id 或“注释”,可用于为图像命名。如果 ok:=FindText(...) 成功,则 ok[1].id 将包含找到的第一个图像的 id。id 可以包含任何字母、数字和符号(如果使用 AHK 的 Unicode 版本,则包括所有 Unicode 字符),但 > 和换行符除外。
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" ; "<auto>" sets the id of the image to the word "auto".
Text.="|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s" ; "<hot>" sets the id of the image to the word "hot".
ok:=FindText(X,Y,,,,,,,Text)
for k, v in ok {
    if v.id == "hot" {
        MsgBox, % "The ""hot"" image was found at X:" v.x " Y:" v.y
    }
}
  1. > 和 $ 之间的数字和符号定义了搜索模式。共有 5 种不同的模式,我们将在后面的“捕获模式”部分详细介绍。在这些 auto 图像的示例中,* 表示使用灰度模式,159 是阈值。
  2. $ 和 . 之间的数字是图像的像素宽度。此值不应手动更改,应使用“剪切”按钮进行修改。在第一个示例中,“auto”图像的宽度为 40。
  3. . 之后的所有内容是图像的 64 位文本表示。此值不应手动更改,应使用“剪切”按钮进行修改。
  4. 有一种未公开的方法可以在文本中包含 err1 和 err0,这将覆盖传递给 FindText 函数的 err1 和 err0 值。这可以通过在 id 后添加 [err1,err0] 来实现:
Text:="|<mycomment>[0.2,0.1]*197$15.1U8A11U8C11k8600s0700Q01U004" ; Overrides err1 to be 0.2 (20%) and err0 to be 0.1 (10%)
ok:=FindText(X,Y,,,,,0.3,0.3,Text) ; Even though err1 and err0 are set to 0.3, instead the values 0.2 and 0.1 will be used for the search

5) 捕获模式

1. 灰度模式

在灰度模式下,每个像素的灰度值(0-255,其中 0 为纯黑,255 为纯白)都会与一个阈值进行比较。如果某个像素的灰度值超过阈值,则该像素将被转换为白色(白色=背景=0),否则转换为黑色(黑色=文本=1)。因此,任何比阈值更暗的像素都将被转换为黑色,任何比阈值更亮的像素都将被转换为白色。阈值 255 会将整幅图像转换为黑色,并匹配搜索范围内的所有内容。

在文本模式下,灰度模式由星号 (*) 字符及其后的阈值标识。


Text:="\|\<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8" ; The "*" after "<auto>" means that Gray mode is being used, the threshold value is 159 (found between * and$), image width is 40 pixels (found between $ and .)
  1. GrayDiff(灰度差分)。每个像素都会被逐一比较,如果被比较像素周围的任何像素(总共比较 8 次)的灰度值超过该像素的灰度值加上阈值,则被比较像素将被变为黑色,否则将被变为白色。本质上,它突出了形状的边缘,因为最大的灰度差出现在对比度高的区域,例如边缘,而纯色区域会被变为白色。在 Examples.png 的“灰度与 GrayDiff 示例”中,如果我们希望 FindText 只找到最右边的两个方块(纯色),那么使用灰度模式无法实现,但 GrayDiff 可以将它们分开(示例如下)。 在文本格式中,GrayDiff 模式用 ** 字符标识,其后是阈值。
#include <FindText>
Text:="|<solidcolorbox>**50$54.zzzzzzzzzU00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001U00000001zzzzzzzzzU" 
; "**" means GrayDiff mode, threshold is set to 50, the image in Text is 54 pixels wide
ok:=FindText(X,Y,,,,,,,Text)
for k, v in ok
    FindText().MouseTip(v.x, v.y)
  1. 颜色。在 FindText 图形用户界面中,点击图像上的一个像素即可选中该像素的颜色并将其定义为“黑色”。然后,可以使用相似度缩放器将相似颜色(同一颜色的不同色调)也包含在内,点击“Color2Two”按钮即可应用滑块所做的更改。 在文本模式下,“颜色”模式由所选颜色的十六进制表示、@ 符号和滑块值(从 0.00 到 1.00,1.00 表示 100% 相似度)标识。
Text:="\|<>505050@1.00$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s"
; Only the color 505050 will be considered Text (black pixels)
; Similarity is set to 1.00 (100%), so color-wise only exact matches are allowed
  1. 颜色位置 (ColorPos)。点击图像上的一个像素,即可确定该像素相对于图像左上角的位置,并将该像素的颜色用于黑白转换。因此,此模式可以查找单一颜色的图案,其中颜色取自指定的像素位置。与颜色模式类似,此模式也提供了一个相似度滑块,用于检测相似颜色。 在文本模式下,颜色位置由“#”符号后跟一个数字(表示所选像素的位置,从左上角开始,从左到右,再从上到下),然后是“@”符号和滑块值。
Text:="|<>#49@0.90$47.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz07zzzzzy07zzzwDwQ7zzzsTsyDzzzkzlwQ1w007Xsk1k00D7V11127yC2D2DwDw08T47sTs0kyA0kzlzVwQ0VzXz3szV3z7z7VzW7yDy22667wTy0A0A1szy0s0w3zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
; # means ColorPos mode
; 49 means that the 49th pixel (from left to right, top to bottom) is considered "black". Since the image width is 47, then it is the second pixel in the second row
; 0.90 is the similarity value (90%)
  1. 颜色差值。在 FindText 图形用户界面中,点击图像上的一个像素会选中该像素的颜色并将其定义为“黑色”。“ColorDiff2Two”按钮会使用选中的颜色将图像转换为黑白图像。现在,可以使用 R、G 和 B 上下调节框来选择允许的颜色差值(正负值,但不会从 255 到 0 或反之亦然)。例如,如果选中的颜色是 0098D9(十六进制 R=00,G=98,B=D9),并且 R 上下调节框设置为 1,则 FindText 将匹配颜色 0098D9 和 0198D9(但不会匹配 FF98D9,因为它不会循环)。然后,将 B 设置为 5 将匹配 0093D9 和 019DD9 之间的颜色。
Text:="\|<>3F627F-00050A$51.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzk1zzzzzzy07zzzwDzlUTzzzVzyD3zzzwDzlwM1s007yDW06000zlsE0EEVzyA0D27wDzk0VsETVzy0ADW0ADzlzVwM0VzyDwD3w4DzlzVsTsVzyDy02467zlzk0k0k7yDz0C0C0zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzw"
; The color defined as "black" is 3F627F
; Allowed color error margins are 00050A: 00 (0 in decimal) for red, 05 (5 in decimal) for green, 0A (10 in decimal) for blue.
  1. 多色模式。选中“查找多色”复选框后,即可选择多个像素。“查找文本”功能将仅查找所选像素,并指定其相对坐标(第一个选定像素位于 x=0, y=0,后续像素均以此为基准)和颜色。例如,如果在此模式下选择了两个像素,“查找文本”功能将仅查找两个颜色相同且相对坐标相同的像素。可以使用 RGB 滑块调整误差范围。在文本模式下,“多色模式”由 ## 符号后跟 RGB 误差范围数值(0-255)标识。$ 符号后紧跟所选像素的相对坐标和颜色:例如,“0/0/3A8000,1/0/008000”表示将查找颜色分别为 3A8000 和 008000 的两个像素,其中 008000 必须位于 3A8000 右侧一个像素的位置。

多色模式也可用于查找保存为文件的图像。这可以通过指定文件位置而非单个像素来实现。FindText().ImageSearch 函数内部使用了此方法。

Text:="|<>##1$0/0/3F627F,-7/1/FFFFFF"
; ## means MultiColor mode
; Error margin for RGB is 1
; Matches position for colors 3F627F (± 1 for each of R, G and B: matches everything between 3E617E and 406380), if the pixel 7 positions to left and 1 position down is of color FFFFFF (± 1 for R, G and B)

Text := "|<>##0$" A_ScriptDir "\Example.png" ; Using this Text in FindText would look for the image in Example.png located in the script directory, with RGB error margin set to 0

搜索图像文件时,可以指定一个或多个透明颜色,这意味着这些颜色将被忽略(类似于内置的 ImageSearch *Trans 选项)。这可以通过以下语法实现。##10-RRGGBB-RRGGBB… $ C:\image.bmp。

6) 辅助函数:Click、MouseTip、RangeTip、GetRange、ScreenToWindow、ScreenToClient、ClientToScreen、WindowToScreen

1. FindText().Click(x, y, options)

接受与 AHK 函数 Click 相同的参数,但它会在单击期间将 CoordMode Mouse 设置为 Screen。

FindText().Click(100, 200) ; Left-click at Screen coordinates x 100, y 200.
  1. FindText().MouseTip(x:="", y:="", w:=10, h:=10, d:=4) 会在指定的 x 和 y 坐标处创建一个闪烁的红色方块,以直观地确认您正在操作的位置是否正确。您可以选择性地更改边框的宽度、高度和粗细。
FindText().MouseTip(100, 200) ; Flashes a red square at Screen coordinates x 100, y 200.
  1. FindText().RangeTip(x:="", y:="", w:="", h:="", color:="Red", d:=2) 是 MouseTip 的一个更通用的变体,它会显示一个指定大小、颜色和边框粗细的红色方框。请注意,它不会像 MouseTip 那样自动消失。以下示例将在找到的图像边缘创建一个闪烁的矩形。

if (ok:=FindText(X,Y,,,,,,,"\|\<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s")) {
Loop 4
{
FindText().RangeTip(ok\[1\].1, ok\[1\].2, ok\[1\].3, ok\[1\].4, (A_Index & 1 ? "Red":"Blue"), 4) ; Show a rectangle around the edges of the found image, additionally switch the color between red and blue every 0.5 seconds.
Sleep, 500
}
}
  1. FindText().GetRange(key:="RButton", tip:="", mode:=0, width:=20, height:=8) 允许用户选择屏幕上的区域或点。如果 mode=0,则会显示一个闪烁的方框,类似于在 FindText 主 GUI 中捕获文本时显示的方框;如果 mode=1,则只能选择一个点,不会显示闪烁的方框。key 指定要按两次(如果 mode=1,则按一次)才能结束捕获的键。tip 是与当前鼠标坐标一起显示的工具提示文本。width 和 height 指定闪烁方框的大小。GetRange 返回一个数组 [x1, y1, x2, y2, winID],其中 (x1; y1) 是屏幕坐标系中捕获区域的左上角坐标,(x2; y2) 是屏幕坐标系中捕获区域的右下角坐标,winID 是捕获时光标所在的窗口 ID。 5. ScreenToClient、ScreenToWindow、WindowToScreen 和 ClientToScreen 用于在不同的坐标模式之间转换坐标。 例如,FindText().ScreenToClient(outX, outY, x1, y1, ahk_id:="") 会将屏幕坐标 x1 和 y1 转换为相对于 ID 为 ahk_id 的窗口的客户端坐标,并将 outX 和 outY 设置为转换后的值。这在 ControlClick 事件中非常有用:FindText 返回的是相对于屏幕的坐标,而 ControlClick 使用的是相对于窗口的坐标,因此可以使用 ScreenToWindow 函数。
if (ok:=FindText(X,Y,,,,,,,"|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s")) {
    FindText().ScreenToWindow(outX, outY, X, Y, WinExist("ahk_class MSPaintApp")) ; Convert the absolute coordinates X and Y to be relative to the Paint window, resulting values will be inside outX and outY variables
    ControlClick, X%outX% Y%outY%, ahk_class MSPaintApp ; Now click the coordinates in Paint
}

FindText().WindowToScreen(outX2, outY2, 200, 300) ; If ahk_id is not specified, then the active window will be used: converts relative coordinates X200 Y300 to absolute coordinates and sets outX2 and outY2 to the resulting values.

  1. 文本库函数 PicLib、PicN、PicX、PicInfo

  2. PicLib 可用于创建图像/文本库,以便使用文本 ID(注释)轻松获取文本。FindText ().PicLib(commentOrText, addToLib:=0, libraryIndex:=1)

可以通过将 addToLib 设置为 1 并指定要添加文本的库编号来添加新文本。如果多个文本具有相同的 ID,则只会添加最后一个文本。

FindText().PicLib("|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8", 1) ; Adds "auto" Text into library 1 (the default library)
FindText().PicLib("|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s",1,2) ; Adds "hot" Text into library 2

可以通过 id 从库中获取文本,addToLib 必须为 0(默认值)。可以同时获取多个 id,用 | 分隔(”comment1|comment2|…”)。


MsgBox, % "Fetching ""auto"" from library 1: " FindText().PicLib("auto") ; fetches Text with the id of "auto" from library 1
MsgBox, % "Fetching ""hot"" from library 2: " FindText().PicLib("hot",,2) ; fetches "hot" from library 2
MsgBox, % "Fetching ""hot"" from library 3: " FindText().PicLib("hot",,3) ; returns nothing, because "hot" was added into library 2, not library 3
  1. PicN(Comment, libraryIndex:=1) 将字符串分解成字符,然后使用 PicLib 获取文本。这对于组合搜索非常有用。PicN ("hot") 等价于 PicLib("h|o|t"),返回 ID 为 “h”、”o” 和 “t” 的文本。3 . PicX(Text) 将包含单词的文本切片成多个包含各个字符的文本。因此,如果文本包含单词“this”的图像,它将返回一个包含四个字符图像的文本(“t”、“h”、“i”、“s”),字符之间用竖线 (|) 分隔。如果字符之间的间距可能会变化(例如,网页每次渲染略有不同),则此方法非常有用,因为我们可以将单词切片成字符并进行组合查找(这样可以处理字符之间可变的间距)。
MsgBox, % "Sliced ""hot"" into characters: " FindText().PicX("|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s")
  1. PicInfo(Text) 返回有关文本的底层信息。返回以下数组: 代码:全选-展开-下载-行号-自动换行- V1

[v, w, h, len1, len0, e1, e0 , mode, color, n, comment, seterr] v –> Text in 0 and 1 form w –> width of Text h –> height of Text len1 –> number of “1”s in Text len0 –> number of “0”s in Text e1 –> allowed error margin for “1”s in absolute numbers (returns % of len1) e0 –> allowed error margin for “0”s in absolute numbers (returns % of len0) mode –> 0 = Color or undefined, 1 = Gray, 2 = GrayDiff, 3 = ColorPos, 4 = ColorDiff, 5 = MultiColor or external file color –> color for Color mode n –> number of colors in MultiColor comment –> comment/id of Text seterr –> if error margins were set in the Text or not 例子:


#include \<FindText>
Text:="\|\<mycomment>\[0.1,0.1\]*197$15.1U8A11U8C11k8600s0700Q01U004"
info := FindText().PicInfo(Text)
MsgBox, % "v: " info\[1\] "`nw: " info[2] "`nh: " info\[3\] "`nlen1: " info[4] "`nlen0: " info\[5\] "`ne1: " info[6] "`ne0: " info\[7\] "`nmode: " info[8] "`ncolor: " info\[9\] "`nn: " info[10] "`ncomment: " info\[11\] "\`nseterr: " info\[12\]
  1. FindText 组合查找 可以通过将 JoinText 参数设置为 1 或指定要查找的单词数组来进行组合查找。然后,offsetX 和 offsetY 将是图像之间允许的最大偏移量。如果查找成功,则返回的结果 ID 将是用于搜索的 ID 的组合(在以下示例中,ok[1].id == “autohot”)
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8"
Text.="|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s"
MsgBox, Looking for "auto" and "hot"
ok:=FindText(X,Y,,,,,,,Text) ; FindText will return all locations of both "auto" and "key" separately
for k, v in ok
    FindText().MouseTip(v.x, v.y)
MsgBox, Looking for "auto" followed by "hot"
ok:=FindText(X,Y,,,,,,,Text,,,1) ; FindText will return all locations of "auto" followed by "key", where "key" can be a maximum of 20 pixels away from "auto" in the x-axis and 10 pixels away in the y-axis
for k, v in ok
    FindText().MouseTip(v.x, v.y)

如果创建字符库,则可以使用组合查找来搜索单词。


; first lets add images of letters "a" and "s" to the default image library
FindText().PicLib("\|\<a>**50$9.TXz0MzTzXkT7TtvU", 1)
FindText().PicLib("|<s>**50$8.DbzXs7kz0wDzTc", 1)

FindText(X, Y,,,,, 0.15, 0.15, FindText().PicN("sas"),,,1,5,3) ; FindText().PicN("sas") assembles Text for the word "sas" using our image library. Error margins were set to 15%, because all the "a" and "s" characters differ a little bit and with 15% all instances of them will be found. OffsetX=5 and OffsetY=3, because the default offset values are too large for this case.
FindText().MouseTip(X, Y)
FindText(X, Y,,,,, 0.15, 0.15, FindText().PicN("asa"),,,1,5,3) ; looks for the word "asa"
FindText().MouseTip(X, Y)

有时同一个字符需要多个图像,例如当使用不同的字体、浏览器渲染方式不同或启用抗锯齿时。在这种情况下,我们可以将字符集放在 Text 变量中,然后将搜索词以数组的形式放在 JoinText 参数中。常规的 JoinText 函数只能使用一种字体。

Text:="|<A>*162$7.472VF4WzkMA"
Text.="|<A>*165$8.61UI92NWTYD1U"
Text.="|<s>**50$5.Tb3klz"
Text.="|<s>**50$5.Tb3klx"
Text.="|<a>**50$6.SH3TnnTU"
Text.="|<a>*152$5.x4/slz"
; Text now contains two fonts of "A", "s" and "a"
ok:=FindText(X, Y, , , , , 0.1, 0.1, Text,, 1,["Asa"]) ; FindText will find all instances of the word "Asa" using the provided character set
for k, v in ok
    FindText().MouseTip(v.x, v.y)
  1. 光学字符识别 (OCR) 可以使用 FindText().OCR 函数实现基本的光学字符识别 (OCR)。在找到字符集中的所有字符后,可以使用此函数。FindText

().Ocr( OK –> 获取 FindText() 的返回结果 ,offsetX:=20,offsetY:=20 –> x 和 y 方向的最大偏移量。如果超过此值,则会插入一个 * 号。默认值均为 20。 ,overlapW:=0 –> 图像的最大重叠区域,默认值为 0。

返回一个关联数组:{text:text, x:X, y:Y, w:W, h:H}

使用 Examples.bmp 的示例 :


; first lets add images of letters "a" and "s" to the default image library
FindText().PicLib("\|\<a>**50$9.TXz0MzTzXkT7TtvU", 1)
FindText().PicLib("|<s>**50$8.DbzXs7kz0wDzTc", 1)
; find all "a" and "s" characters on the screen using our library
ok:=FindText(X, Y,,,,, 0.15, 0.15, FindText().PicN("sa"))
if (ocr := FindText().OCR(ok, 3, 3))
MsgBox, % "Found " ocr.text ; should return "aaa*sss*asa*sas

这是一个更高级的示例,演示如何在记事本中实现搜索功能。首先,打开记事本,并将字体(在菜单栏“格式”->“字体…”)设置为 Consolas,常规,11 号。然后在记事本中输入一些示例文本。接下来运行以下示例并按下 F1 键,即可弹出搜索对话框。当然,在记事本中,Ctrl+F 快捷键要好用得多,因为 FindText 函数只能查找记事本窗口中可见的文本,但类似的功能也可以用于其他领域,例如在游戏中查找文本。

#NoEnv
#SingleInstance Force

#include \<FindText>

; First some character sets for numbers, uppercase characters and lowercase characters (taken from Notepad font Consolas, Regular, 11)

if (A_ScreenDPI = 96) {
numbers := "\|<0>**50$8.03laNwTDyyBWNXk0U|<1>**50$7.06D5UkMA631Xy0U\|<2>**50$7.0DAkMA667773y0U|<3>**50$6.0y333S3333y0U\|<4>**50$8.00sS7XMaNgPz1UM0U|<5>**50$6.0zkkky3333y0U\|<6>**50$7.07a631ynMwSNs0U|<7>**50$7.0TkMMAA66331U0U\|<8>**50$7.0DgqPgwzNwSNs0U|<9>**50$8.03laFgBbDkM637U0U"
uppercase := "\|\<A>*150$8.61kI92MWMbt3kE0008|<B>*150$6.yXVXyXVVXy000U\|\<C>*150$6.DEkUUUUkED000U|<D>*150$7.yFcIC73VkcrU000E\|\<E>*150$5.z24DkV27k01|<F>*150$5.z248TV24001\|\<G>*150$6.DEUUUbVVlD000U|<H>*150$6.VVVVzVVVVV000U\|**150$6.zAAAAAAAAz000U|<J>*150$4.wF4F4Fs02\|\<K>*150$7.VF9YXVkYH8oA000E|<L>*150$5.V248EV27k01\|\<M>*150$8.EaRbNphNqQ71kE0008|<N>*150$6.lltddZZXXX000U\|\<O>*150$7.SNcIC73Vkgnk000E|<P>*150$6.yXVVXyUUUU000U\|\<Q>*150$7.SNcIC73VkgnkE93k|<R>*150$7.yNgKPtgmNAKA000E\|~~*150$6.TkUkQ6113y000U|<T>*150$7.za31UkMA631U000E\|<u>*150$6.VVVVVVVVnS000U|<V>*150$7.UksK/AYGD31U000E\|\<W>*150$7.UkMAirOdNgqM000E|<X>*150$6.VnGSAASGnV000U\|\<Y>*150$7.VkgnEsMA631U000E|<Z>*150$6.z1264A8EEz000U"
lowercase := "\|\<a>**50$6.00Sn3Tnnz00U|<b>**50$7.kMDrP7XltjU01\|\<c>**50$6.00DskkksT00U|<d>**50$6.33TnnXnrT00U\|\<e>**50$7.007aP7zkM7k01|<f>**50$7.631bwMA631U01\|\<g>**50$8.000zNaNaT61yMyC|<h>**50$6.kkzvnnnnn00U\|**50$7.A0D1UkMA6Ds01|<j>**50$5.63slX6AMtk\|\<k>**50$7.kMAynlsyPgs01|<l>**50$7.A631UkMA6Ds01\|\<m>*150$7.00CqiL/ZmtM01|<n>**50$6.00zvnnnnn00U\|\<o>**50$8.000wNYD3kqMw002|<p>**50$7.00DrP7Xltja31\|\<q>**50$6.00TnnXnrT33U|<r>**50$7.00DrD7UkMA001\|**50$6.00TksS33y00U|<t>**50$8.A33zA30kA3UT002\|**50$6.00nnnnnnT00U|<v>**50$8.0033NaMaD3kM002\|\<w>**50$8.0033kxjPLqta002|<x>**50$8.001bBXkMD6Pb002\|\<y>**50$8.0033NaMYD3kM632|<z>**50$7.00DkMMM8ADs01"</u>~~*

} else if (A_ScreenDPI = 144) {
numbers :="\|<0>*139$10.7Uza6MD1wDnjQz3sD0q6DkS8|<1>*139$9.73sv4M30M30M30M30MzzzU\|<2>*139$9.D7wlk60k61UQ71kQ70zzzU|<3>*139$8.TDu70kA6D3s30E43zjm\|<4>*139$11.1k3UD0q1g6MMkVX37zzzUM0k1W|<5>*139$9.zryk60k60z7y0k70kCzbsU\|<6>*139$10.3sTXUM1U5wzvVw3kBUq6DsS8|<7>*139$10.zzzk30M1UA0k60M30A1U60k8\|<8>*139$10.7lza6MBVbCDkT7CMD0y7Tsz8|<9>*139$10.7Vz66kP0w3sRznv081UATVw8"
uppercase := "\|\<A>**50$12.000000003k3k3s7M6M6QCQCAACTyTyM7s7s30000000000U|<B>**50$10.0000003zDysvVy6svzDyszVy7sTzjw000000008\|\<C>**50$10.0000000TXzSDUC0s30A0s3UC0SAzly000000008|<D>**50$11.0000000DsTwkxUv0y1w3s7kDUP1q7jyTk000000000E\|\<E>**50$9.000000zzzk60k60zryk60k60zzz00000004|<F>**50$9.000000zzzk60k60zryk60k60k6000000004\|\<G>**50$11.00000000z3zC6s1k30CDwTs6sBkPknzVy000000000E|<H>**50$10.00000030w3kD0w3kDzzzkD0w3kD0w3000000008\|***50$9.000000zzz60k60k60k60k60kzzz00000004|<J>**50$8.00000Dzz1kQ71kQ71kQ7Xjvw0000002\|\<K>**50$10.0000003VyCsnbCsz3sDUz3iCQsvXi7000000008|<L>**50$9.000000s70s70s70s70s70s70zzz00000004\|\<M>**50$12.00000000QCQCKOSSSLPrPrPrtbs7s7s7s7s70000000000U|<N>**50$10.0000003Uz3wDsxXrDgyntjayTszXy7000000008\|\<O>**50$12.000000007sDwSSQ6M7s7s7s7s7M7QCSSDw7s0000000000U|<P>**50$10.0000003zDyszVy3sTXzyzXUC0s3UC0000000008\|\<Q>**50$12.000000007sDwSSQ6M7s7s7s7s7M7QCSSDw7s1U1n0z0S00U|<R>**50$10.0000003yDwlv3gClnyDknX7AQkv3g7000000008\|~~**50$10.0000000z7ywPUC0S0y0y0w1k7kTzbw000000008|<T>**50$10.0000003zzz30A0k30A0k30A0k30A0k000000008\|<u>**50$10.00000030w3kD0w3kD0w3kD0y7sxzXw000000008|<V>**50$12.00000000s3s7M6Q6QCACCACQ6Q6M7s3s3k3k0000000000U\|\<W>**50$11.k7UD0y1w3tbnjjPSqxhDSSwxsu|<X>**50$11.sDktnVr3w3k7UD0z1y7CCCsRUS\|\<Y>**50$11.kDUTVnX7C7MDkD0C0M0k1U3062|<Z>**50$10.0000003zzz0M3UQ1UC0k60s30M3zzz000000008"
lowercase := "\|\<a>**50$10.000000003wTtVk7Dxzy7sTXrzDQ0000008|<b>**50$10.03UC0s3UCwzvty7sDUy3sTXzyTU0000008\|\<c>**50$10.000000001yDxsr0M3UC0M1knz7s0000008|<d>**50$10.001k70Q1lzTxly7sT1y7sTbrzDQ0000008\|\<e>**50$10.000000001wTtly3zzzy0s1k7zDw0000008|<f>**50$11.003wDss1k3UzxzsQ0s1k3U70C0Q0s00000002\|\<g>**50$11.0000000007zTytnVX77yDss1k3zXzi3wCzwzW|<h>**50$10.03UC0s3UCwzvtz7sTVy7sTVy7sQ0000008\|**50$9.71s70007sz0s70s70s70szzz000000U|<j>**50$9.1kD1k003yTk60k60k60k60k60qCzXsU\|\<k>**50$9.060k60k67lqQr7ky6sr6Qlq7000000U|<l>**50$9.07sz0s70s70s70s70s70szzz000000U\|\<m>**50$11.000000000TizxrTCyNwntbnDaTAyNk0000002|<n>**50$10.00000000Cwzvtz7sTVy7sTVy7sQ0000008\|\<o>**50$10.000000003wTvny7kD0w3sTnryDk0000008|<p>**50$10.00000000Cwzvty7sDUy3sTXzyzXUC0s3U8\|\<q>**50$10.000000001zTxly7sT1y7sTbrzDQ1k70Q1s|<r>**50$9.00000006yzzbsS0k60k60k60000000U\|**50$9.00000003wzr6s7UTUS0y6zrw000000U|<t>**50$11.0000A0s1kTzzyC0Q0s1k3U7070DsDk0000002\|**50$10.00000000C7sTVy7sTVy7sRrrzDQ0000008|<v>**50$10.00000000A3sTVq6QsnXADkO1s7U0000008\|\<w>**50$12.0000000000s3s7s7NbNqPqPqOKSSSSCS00000000U|<x>**50$10.00000000C7QRnXw7US1wDlnb7sQ0000008\|\<y>**50$12.0000000000M7QCQCAACQ6M7M7s3k3k1U3U70z0w0U|<z>**50$10.000000007zTs3UQ1UA1UC1k7zzw0000008"
} else {
MsgBox, Your current screen DPI is not supported! Exiting...
ExitApp
}</u>~~*

characterset := lowercase . uppercase . numbers
; Add our newly created character set to PicLib library
FindText().PicLib(characterset, 1)

return

F1::
InputBox, searchPhrase, Search Notepad, % "Search Notepad for some text. To make the search case sensitive, put the search term in quotes."
Sleep, 500 ; Sometimes the InputBox closing animation is slow causes the search to fail, so wait for it to close

caseSensitive := (SubStr(searchPhrase,1,1) == """") && (SubStr(searchPhrase,0) == """")
if caseSensitive
searchPhrase := SubStr(searchPhrase,2,-1) ; For case-sensitive search remove double-quotes
else
StringLower, searchPhrase, searchPhrase ; For case-insensitive search, turn the search phrase into lowercase

if (ok:=FindText(X, Y,,,,, 0, 0, caseSensitive ? FindText().PicN(searchPhrase) : RegexReplace(characterset, "(?<=<)\\p{L}(?=>)", "$L0"),1,1, caseSensitive ? 1 : \[searchPhrase\])) ; If doing a case-sensitive search, glue together the images for each character in searchphrase using PicN and use FindAll=1 to look for the resulting image. If doing case-insensitive search, replace all uppercase characters in our character set with lowercase characters (which means that FindText will use both uppercase and lowercase images in the search) and then look for the lowercase searchphrase.
{
FindText().MouseTip(X, Y)
; FindText().Click(X, Y, "L")
}
return
  1. BindWindow - 窗口后方查找 BindWindow 允许 FindText 函数搜索隐藏在其他窗口后面的窗口中的文本。FindText ().BindWindow( bind_id -> 获取目标窗口的 ahk_id(例如,可以使用 WinExist() 获取)。如果设置为 0,则禁用 BindWindow,并正常搜索屏幕。bind_mode -> 指定绑定方法。某些窗口支持某些方法,而其他窗口则需要其他方法。奇数 bind_mode 会修改透明窗口以在其中进行搜索。通常 bind_mode 为 0 或 4 即可,默认值为 0。get_id -> 如果设置为 1,则返回当前绑定的窗口 ID,默认值为 0。get_mode -> 如果设置为 1,则返回当前使用的绑定模式,默认值为 0。 )
SetTitleMatchMode, 2
FindText().BindWindow(WinExist("Paint ahk_class MSPaintApp")) ; bind FindText to Paint
Text:="|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s"
FindText(X, Y, 72-150000, 228-150000, 72+150000, 228+150000, 0, 0, Text) ; Paint can be obscured by another window, but FindText still finds Text
FindText().MouseTip(X, Y)
FindText().BindWindow(0) ; unbind Paint from FindText

注意!BindWindow 将在运行脚本中全局应用于所有 FindText 函数。如果使用多个线程,则新线程可能会覆盖旧线程绑定的窗口(例如,一个热键绑定了一个窗口并循环调用 FindText,然后被另一个绑定了另一个窗口的热键打断)。可以使用 FindTextClass 来避免这种情况,我们将在下文讨论。 11

) FindTextClass FindText 的每个函数都包含在一个名为 FindTextClass 的类中。FindText() 返回 FindTextClass 的一个全局共享实例,因此 FindTextClass 的每个函数都操作同一个数据集。例如,BindWindow 会为每次 FindText 调用更改绑定的窗口,Screenshot=0 将使用每次 FindText 调用创建的最后一个屏幕截图,等等。此外,FindText(arguments) 与 FindText().FindText(arguments) 相同。

在本例中,请在画图程序中打开“Examples.png”,然后将另一个窗口移动到图像上方以隐藏图像。按 F1 键,鼠标提示将显示找到的图像的位置。按下F2键后,图像就找不到了。

 #NoEnv
#SingleInstance Force

#include <FindText>

Esc::ExitApp

F1::
FindText().BindWindow(WinExist("Examples.png - Paint"))
Text:="|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8"
while (ok:=FindText(X, Y,,,,, 0, 0, Text)) {
FindText().MouseTip(X, Y)
Sleep, 1000
}
MsgBox, Paint not found anymore!
return

F2::
FindText().BindWindow(0) ; or bind another window?
return

可以通过使用 FindTextClass 的新实例来解决这个问题:


F1::
ft := new FindTextClass
ft.BindWindow(WinExist("Examples.png - Paint"))
Text:="\|\<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8"
while (ok:=ft.FindText(X, Y,,,,, 0, 0, Text)) {
ft.MouseTip(X, Y)
Sleep, 1000
}
MsgBox, Paint not found anymore!
return
  1. 屏幕截图函数:ScreenShot、GetColor、SetColor、GetTextFromScreen、SavePic、ShowPic、ShowScreenShot

  2. FindText().ScreenShot(x1:=0, y1:=0, x2:=0, y2:=0) 截取 FindText 函数内部 x1,y1 和 x2,y2 之间的屏幕截图,供后续 FindText 调用使用。2 . RGB := FindText().GetColor(x, y, fmt:=1) 获取上次屏幕截图中某个点的 RGB 颜色值。如果 fmt=0,则返回原始数据;否则返回 RGB 格式的颜色值。3 . FindText().SetColor(x, y, color) 设置上次屏幕截图中某个点的 RGB 颜色值。

  3. Text := FindText().GetTextFromScreen(x1:=0, y1:=0, x2:=0, y2:=0, Threshold="", ScreenShot:=1, outX, outY) 使用指定的阈值将屏幕截图中 x1,y1 和 x2,y2 之间的区域转换为文本。阈值可以是“*”(表示灰度模式)或“**”(表示灰度差分模式),后跟阈值值。ScreenShot = 1 将截取新的屏幕截图,0 将使用上次的内部屏幕截图(例如由 ScreenShot 函数截取的屏幕截图)。文本将自动裁剪顶部和底部。变量 outX 和 outY 将设置为屏幕上捕获文本的中心点。

  4. FindText().SavePic(FileName, x1:=0, y1:=0, x2:=0, y2:=0, ScreenShot:=1) 将屏幕截图中 x1,y1 和 x2,y2 之间的区域保存到文件中。6 . FindText().ShowPic(FileName:=””, show:=1, outX, outY, outW, outH) 在屏幕左上角显示图像文件的内容。outX 和 outY 将被设置为图像显示的 X 和 Y 坐标(在多屏设置中,此坐标可能不为 0,0),outW 和 outH 将被设置为图像的宽度和高度。调用 ShowPic() 而不指定 FileName 将从屏幕上移除图像。FileName 也可以是格式为 HBITMAP 的句柄。HBITMAP:*%handle%7. FindText().ShowScreenShot(x1:=0, y1:=0, x2:=0, y2:=0, ScreenShot:=1) 与 ShowPic 函数类似,它会显示点 x1,y1 和 x2,y2 之间的区域。如果 ScreenShot 为 1,则会截取新的屏幕截图;否则,将使用上次的内部屏幕截图。

示例:

#include <FindText>
FindText().Screenshot(100,100,500,500) ; Take a new screenshot between coordinates 100,100 and 500,500
FindText().ShowScreenShot(100, 100,500, 500, 0) ; Shows the taken screenshot on the screen. Since we specified 0 as the last argument, the function will use the screenshot taken previously by the Screenshot function.
Sleep, 3000
FindText().ShowScreenShot() ; Hide the screenshot after 3 seconds
FindText().SavePic(A_ScriptDir "\TestScreenShot.png", 100, 100, 400, 400, 0) ; Save a portion of the taken screenshot into a file in the script directory.
  1. 其他:排序、排序2、排序3、等待更改、等待不更改、缩放参数

  2. FindText().Sort(ok, dy:=10) 接收一个 FindText 的结果数组 (ok),并返回一个从左到右、从上到下排序的数组。比较点是图像的中心(不是左上角!),可以通过更改 dy 值来忽略 y 坐标的细微差异。2 . FindText().Sort2(ok, px, py) 接收一个 FindText 的结果数组 (ok) 和一个坐标 (px, py),并使用公式 (x-px)^2 + (y-py)^2 根据返回图像与坐标的距离对数组进行排序。3. FindText().Sort3(ok, dir:=1) 接收一个 FindText 的结果数组 (ok),并按方向对其进行排序。dir 参数的值与 FindText 的 dir 参数相同(除了 9)。

  3. FindText().WaitChange(WaitTime:=-1, x1:=0, y1:=0, x2:=0, y2:=0) 等待屏幕坐标 x1,y1 和 x2,y2 之间的区域变化“WaitTime”秒。将“WaitTime”指定为 -1 将无限期等待。5 . FindText().WaitNotChange(NoChangeTime:=1, WaitTime:=30, x1:=0, y1:=0, x2:=0, y2:=0) 等待图像在 NoChangeTime 秒(默认 1 秒)内保持不变,等待 WaitTime 秒(默认 30 秒)。如果图像在 NoChangeTime 秒内保持不变(稳定),则返回 1;否则,如果达到 WaitTime,则返回 0。

FindText 函数的最后两个参数 zoomW 和 zoomH 可用于放大或缩小文本。这可用于查找大小会变化的图像:例如,按钮/元素会根据窗口大小或屏幕缩放比例而放大/缩小。对于以下示例代码,请在 Paint 中打开 Examples.png,并将图像右下角的缩放级别设置为 200%。然后尝试将缩放级别设置为 300%,并将 zoomW 和 zoomH 的值更改为 3——示例应该仍然可以正常运行。


#include \<FindText>

if (ok := FindText(outX, outY, 0, 0, A_ScreenWidth, A_ScreenHeight, 0.05, 0.05, "\|\<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8",, 0,,,,, 2, 2)) { ; Call FindText to look for the "auto" image at 200% zoom
for k, v in ok { ; Loop over all the search results in "ok". "k" will be the nth result, and "v" will contain the result itself.
MsgBox, % "Result number " k " is located at X" v\[1\] " Y" v\[2\] " and it has a width of " v\[3\] " and a height of " v\[4\] ". Additionally it has a comment text of " v.id ; v\[1\] is equivalent to ok\[k\]\[1\], v.id is equivalent to ok\[k\].id, and so on.
FindText().MouseTip(outX, outY)
}
} else {
MsgBox, The image/Text was not found. Is everything set up correctly and the image is visible in Paint? ; It seems "ok" was left empty, so nothing was found.
}
  1. FindText 速度提升技巧

  2. 使用尽可能小的搜索范围。这可以通过多种方式实现,最简单的方法是使用 WinGetPos 获取窗口位置和大小,从而将搜索范围限制在单个窗口内。

WinGetPos, pX, pY, pW, pH, ahk_class MSPaintApp ; Get the Paint application location and size.
ok := FindText(X, Y, pX, pY, pX+pW, pY+pH,,, Text) ; Set the search range to only the Paint window
有时,搜索到的图像只会出现在特定区域,因此可以进一步调整搜索范围。在画图窗口中,如果我们对菜单栏和工具栏都不感兴趣,那么我们可以从顶部裁剪掉一定量的区域:

WinGetPos, pX, pY, pW, pH, ahk_class MSPaintApp ; Get the Paint application location and size. ok := FindText(X, Y, pX, pY+150, pX+pW, pY+pH,,, Text) ; Set the search range to only the Paint window and crop by 150 pixels from the top to leave out the menubar and toolbar 2. 使用尽可能小的图像。这可以通过使用 L3/R3/L/R/U/B/自动裁剪按钮裁剪捕获的图像来实现。3 . 使用尽可能小的误差范围。例如,将 err1 和 err0 都从 0 提高到 0.3 可能会导致搜索速度明显变慢(可能慢 5-10 倍)。4 . 如果要查找精确匹配项,请为 err1、err0 或两者都指定一个非常小的非零值。FindText 的默认行为是,如果 err1 和 err0 都设置为 0,则如果搜索失败,将自动尝试再次搜索,并将 err1 和 err0 设置为 0.05。当多次调用 FindText 来查找不同的图像时,这种额外的搜索会累积耗时。但这只有在 err1 和 err0 恰好为 0 时才会发生,这意味着,如果您例如将 err1、err0 或两者都设为 0.000001(这实际上是 0 但不等于 0)(只需要其中一个非零),则只会进行一次搜索(有效误差范围为 0.000001≈0)。

FindText(X, Y,,,,,,, Text) ; If Text is not visible on the screen, then the search happens twice: first with err1 and err0 set to 0, then again with 0.05 (5% error margin)
FindText(X, Y,,,,,0.000001,, Text) ; If Text is not visible on the screen, then the search happens just once, looking for an exact match (0.000001≈0)
FindText(X, Y,,,,,0.05,0.05, Text) ; If Text is not visible on the screen, then the search happens just once, but leaves a small error margin of 5%
5. 如果要搜索多张图片,可以将文本合并为一个,只调用一次 FindText 函数;或者将 Screenshot 参数设置为 0,以便后续搜索。这样可以避免 FindText 函数多次截图,从而节省大量时间。
合并方法的示例:

Text:=”|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8” Text.=”|*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s" if (ok := FindText(X, Y,,,,,,, Text)) { if (ok\[1\].id == "auto") { ; Do something after finding the "auto" image } else if (ok\[1\].id == "hot") { ; Do something after finding the "hot" image } } 重用第一张截图的示例:

FindText().PicLib("|<auto>*159$40.0000k000003000000A00DVUnw7lr6371nUAMAA630FUkkkAT63330rgMAAA1kFUkkkD363330wAAAA62vkvkkQtt1v1kS8",1)
FindText().PicLib("|<hot>*152$29.U00010000200014000280004Hk7kzxktktVVUkX161V43A3286M24EAkA8UNUMF0lUUW1Xb1g31s1s",1)
if (ok := FindText(X, Y,,,,,,, FindText().PicLib("auto"))) {
    ; Do something after finding the "auto" image
}
if (ok := FindText(X, Y,,,,,,, FindText().PicLib("hot"), 0)) { ; Call FindText using the screenshot taken previously for searching "auto"
    ; Do something after finding the "hot" image
}
  1. 使用像素比较次数最少的采集模式。通常灰度模式速度最快;灰度差分、颜色位置和颜色模式(相似度设置为 100%)速度也很快。最慢的是颜色模式(颜色范围越大或相似度越低,搜索速度越慢)和多色模式(如果使用图像文件)。 今天就到这里。感谢阅读。😊
Update history:
09.05.22: 1) Added explanations for ScreenShot, GetTextFromScreen, SavePic, ShowPic, ShowScreenShot, WaitChange, PicInfo.
2) Specified that MultiColor mode can also use filenames.
3) Added an advanced OCR example.
17.05.22: 1) Added section "FindText speed improvement tips"
2) Added more examples under the main FindText function explanation
3) Added ColorDiff mode explanation
4) Corrected typos and made some wordings better.
31.08.22: fixed incorrect DPI for examples (150% is correct)
01.08.23: added explanations for WaitNotChange, GetRange, PixelSearch. Changed documentation for ImageSearch to include variation and transparent color options.
19.02.24: added documentation for PixelCount.
20.02.24: added documentation for GetColor, SetColor.
19.06.24: added example code for zoomW and zoomH arguments
最后由Descolada于 2024 年 6 月 19 日 13:44 编辑,共编辑 16 次。
本文由作者按照 CC BY 4.0 进行授权