以下是AHK单次找色和取色的效率,和10次截图并保存到文件的效率测试【计时单位为:毫秒】

因为用的是C++实现,所以能1毫秒内完成截图和取色找色,适合游戏压枪等需要高效率的场景

 

简介

GDI:第一代桌面采集

Windows 图形设备接口(GDI)是为与设备无关的图形设计的。基于 Windows 的应用程序不能直接访问图形硬件,应用程序通过 GDI 来与设备驱动程序进行交互。GDI 截图就是通过屏幕的DC获取到当前屏幕的位图数据。

Ø 特点:不受windows版本限制,基本兼容各版本的系统;

Ø 缺点:使用CPU,消耗大量cpu运算时间,若不单采鼠标,则使用gdi采集时,鼠标会出现闪烁,无法实现过滤指定窗口。

 

DXGI:高性能桌面采集技术

DXGI(Microsoft DirectX Graphics Infrastructure)是微软提供的一种可以在win8及以上系统使用的图形设备接口。它负责枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程之间(例如,在应用程序和桌面窗口管理器(DWM)之间)共享资源,以及将呈现的帧传给窗口或监视器以供显示。其直接和硬件设备进行交互,具有很高的效率和性能。

Ø 特点:Win Vista 以后支持,使用GPU直接处理纹理,效率最高;

Ø 缺点:根据Direct3D 版本不同,存在硬件的支持以及调用特性 的区别。鼠标需要额外采集。

 

WGC:新世代采集技术

WGC 全称为 Windows Graphics Capture 是微软目前主推的一个桌面/窗口采集技术,使用 D3D11 库实现。该采集技术最早在Windows 10 18年3月份的更新中提供。WGC 对比放大镜采集(Magnification Capture) 具有更高的性能、更低CPU及GPU消耗。但是在 使用方面比起其他采集方式会更复杂。

Ø 特点:效率高,拓展屏采集支持高,1080p采集消耗gpu达到个位数;

Ø 缺点:系统要求高,需要WIN10 1903及以后版本才能支持。低版本系统绑定窗口会有黄线边框存在

 

DWM:窗口采集技术

DWM 全称为 Desktop Window Manager 是Windows操作系统中的一个窗口管理器,它负责管理桌面上的窗口和图形效果,包括透明效果、窗口动画等。通过DWM截图技术,可以捕捉到当前显示屏幕上所有窗口的内容,并保存为图像文件。

Ø 特点:效率高,支持窗口截图(不包括最小化窗口)。和WGC的性能一致,但不会有WGC黄线边框的问题

Ø 缺点:只能指定窗口截图,不能截全屏。

 

文件与示例打包下载:

 

以下为AHKv1调用实现的示例,由于WGC要求版本高和绑定窗口后有黄线框,效率上和DWM一样。所以用DWM截图窗口即可

SetBatchLines -1
#SingleInstance Force

WinCapture_init()  ; WinCapture.dll加载与初始化

; ==================== DXGI截图+单色查找与单点取色示例 ====================

计时()
tu := DXGIcaptureAndSave()  ; 截屏取范围就是,范围找色
tu.findColor(x, y, "0xFFFFFF")  ; 找色示例
Logg("全屏找色:" x ", " y " - 耗时:" 计时())

计时()
color := tu.getHexColor(x, y)  ; 取色示例,示例沿用找到的x,y坐标。所以打印颜色只会是0xFFFFFF或者0【未找到】
Logg("取色数据:" color " 耗时:" 计时())

计时()
arr := []
Loop 10 {
  tu:=DXGIcaptureAndSave([960-320, 540-320, 960+320, 540+320])  ; 坐标系为xywh,示例参数为截图1080p中央部分
  ; tu.Show()
  tu.Save("DXGIScreenShot.bmp")
  arr.push(tu)
}
Logg("10次截屏保存+数组 耗时:" 计时())

计时()
For _, _ in arr  ; 将之前存到数组里的截图数据用另一个名称保存文件
  _.Save("ArrScreenShot.bmp")

Logg("10次数组读取+保存 耗时:" 计时())
Return


; ==================== 仿FindText多色查找+热键取色 ====================

; WinCapture多色查找,找到立即返回坐标示例
Loop 10 {
  计时()
  tu:=DXGIcaptureAndSave([500, 500, 1920, 1080])  ; 范围搜索
  tu.findMultiColors(x, y, [["0xFFFFFF", 0, 0], ["0xFFFFFF", 1, 0]])  ; 多色查找-返回仅第一个坐标
  Logg(x ", " y " 耗时:" 计时())
}

Text:="|<>##0$0/0/723859,0/5/713859,0/8/723859,5/5/723859,10/2/723859,10/6/723859,10/9/723859,5/12/CAE4FC"

arr := FtoW(Text)  ; 将FindText的多色查找字符串,转换成WinCapture可识别的字典

; arr:=[ ["0x723859", 0, 0], ["0x713859", 0, 5], ["0x723859", 0, 8], ["0x723859", 5, 5], ["0x723859", 10, 2], ["0x723859", 10, 6], ["0x723859", 10, 9], ["0xCAE4FC", 5, 12] ]  ; WinCapture可识别的字典结构

计时()
tu := DXGIcaptureAndSave()
tu.findAllMultiColors(RtnArray, arr)  ; 多色查找【默认返回20个匹配坐标】
Logg("全屏多色查找:" 计时())

Loop % RtnArray.Length()
  Logg("找到坐标" A_Index ":" RtnArray[A_Index]["x"] ", " RtnArray[A_Index]["y"])


F1::
x:=26, y:=12
tu := DXGIcaptureAndSave()
color := tu.getHexColor(x, y)
Logg("F1取色数据:" color)
Return


; ==================== DWM实现后台截图找图 ====================

hwnd := WinExist("微信 ahk_class WeChatMainWndForPC")

tu := DWMcapture(hwnd)  ; 用DWM实现后台截图找图
tu.Show()

; 以下仅为找图片的示例,建议还是用多点找色取到目标的特征像素,来找更加好用。还不用附带图片文件

bmp := A_ScriptDir "\找图.bmp"  ; 替换成自己想要找的目标截图
目标找图 := BitmapBuffer.LoadPicture(bmp)
loop 10 {
  计时()
  tu := DWMcapture(hwnd)
  tu.findPic(x, y, 目标找图)
  Logg(x ", " y " 耗时:" 计时())
}

tu.findAllPic(RtnArray, 目标找图)  ; 找图,返回找到的所有目标坐标
Loop % RtnArray.Length()
  Logg(RtnArray[A_Index]["x"] ", " RtnArray[A_Index]["y"])


; ==================== 截图与保存文件 ====================

计时()
tu := DXGIcaptureAndSave()  ; 不填范围为全屏截图
; tu := DXGIcaptureAndSave([200, 200, 900, 999])
tu.Save("ScreenShot.bmp")  ; 保存成文件
Logg("耗时:" 计时())
tu.Show("截图全屏窗口展示")

改变大小 := tu.range(900, 500)  ; 改变截图大小
改变大小.Show("改变截图大小后的显示")


; ==================== 加载图片文件与Gui显示 ====================

bmp := A_ScriptDir "\ScreenShot.bmp"
tu := BitmapBuffer.LoadPicture(bmp)
; tu.Show()

hBitmap := tu.hBM()
Gui Add, Picture, , % "HBITMAP:*" hBitmap
Gui Show, AutoSize, AHK窗口显示写法


; ==================== 复杂应用:快速获取多个颜色+统计颜色浓度 ====================

计时()
x1 := 0
y1 := 0
w := 110
h := 64
; x1 := 146, y1 := 321, w := 616, h := 280
arr:=[]
n := 0
tu := DXGIcaptureAndSave()
Loop %w% {
  Loop %h%
    color:=tu.getHexColor(x1, y1+A_Index), arr[color] := arr[color] ? arr[color]+1 : 1, n++
  x1++
}

MsgBox % "指定坐标范围内色值出现的次数:" arr[0xFFFFFF] "`n指定坐标范围内的总像素:" n "`n耗时:" 计时() " ms"

; 键值总数量
MsgBox % "共捕获颜色数量:" arr.count()
Return

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。