当前位置: 首页 > news >正文

python控制Windows桌面程序自动化模块uiautomation

github仓库地址:GitHub - yinkaisheng/Python-UIAutomation-for-Windows: (Donot use 3.7.6,3.8.1):snake:Python 3 wrapper of Microsoft UIAutomation. Support UIAutomation for MFC, WindowsForm, WPF, Modern UI(Metro UI), Qt, IE, Firefox, Chrome ...

 

uiautomation封装了微软UIAutomation API,支持自动化Win32,MFC,WPF,Modern UI(Metro UI), Qt, IE, Firefox(version<=56 or >=60, Firefox57是第一个Rust开发版本,前几个Rust开发版本个人测试发现不支持), Chrome和基于Electron开发的应用程序(Chrome浏览器和Electron应用需要加启动参数--force-renderer-accessibility才能支持UIAutomation).

最新版uiautomation2.0只支持Python 3版本,依赖comtypes和typing这两个包,但不要使用3.7.6和3.8.1这两个版本,comtypes在这两个版本中不能正常工作(issue)。

2.0版本之前的代码请参考API changes修改代码。

uiautomation支持在Windows XP SP3或更高版本的Windows桌面系统上运行。

如果是Windows XP系统,请确保系统目录有这个文件:UIAutomationCore.dll。如果没有,需要安装补丁 KB971513 才能支持UIAutomtion.

在Windows 7或更高版本Windows系统上使用uiautomation时,要以管理员权限运行Python, 否则uiautomation运行时很多函数可能会执行失败或抛出异常。 或者先以管理员权限运行cmd.exe,在cmd中再调用Python,如下图中cmd窗口标题中显示了管理员

安装pip install uiautomation后,在Python的Scripts(比如C:\Python37\Scripts)目录中会有一个文件automation.py, 或者使用源码根目录里的automation.py。automation.py是用来枚举控件树结构的一个脚本。

运行'automation.py -h',查看命令帮助,写自动化代码时要根据它的输出结果来写对应的代码。 

理解上图中各个参数的意义并运行下面命令查看程序的执行结果。
automation.py -t 0, 打印当前激活窗口的所有控件
automation.py -r -d 1 -t 0, 打印桌面(树的根控件 )和它的第一层子窗口(TopLevel顶层窗口)

automation.py 显示了控件树中的各个控件(Control)的部分属性和控件支持的Pattern.

根据微软 UIAutomation API,一个具体类型的Control必须支持或选择支持某种Pattern,如下图

参考 Control Pattern Mapping for UI Automation Clients 查看全部的Control-Pattern支持表格。

uiautomation中封装了Windows UIAutomation中的各个Control和Pattern.

Control类型有ButtonControl, TextControl, TreeControl等等。

Pattern类型有ExpandCollapsePattern,InvokePattern等等。

实际使用时,要用Control或Pattern对象来获取控件信息或操作控件。

uiautomation根据你提供的控件属性在控件树中从上往下查找控件。

假设控件树如下:

root(Name='Desktop', Depth=0)
  window1(Depth=1)
    control1-001(Depth=2)
    control1-...(Depth=2)
    ...
    control1-100(Depth=2)
  window2(Name='window2', Depth=1)
    control2-1(Depth=2)
      control2-1-001(Depth=3)
      control2-1-...(Depth=3)
      ...
      control2-1-100(Depth=3)
    control2-2(Depth=2)
    control2-3(Depth=2)
    control2-4(Name='2-4', Depth=2)
      editcontrol(Name='myedit1', Depth=3)
      editcontrol(Name='myedit2', Depth=3)

如果你想找到名字为myedit2的EditControl,并在这个EditControl打字,你可以这样写:

uiautomation.EditControl(searchDepth=3, Name='myedit2').SendKeys('hi')

但是这个代码运行效率并不高,因为控件树中有很多控件,你所查找的EditControl在树的末尾, 从树根部搜索整个控件树需要遍历200多次才能找到这个EditControl, 如果用分层查找并指定查找深度,就可以只查找几次,很快就能找到控件。

代码如下:

window2 = uiautomation.WindowControl(searchDepth=1, Name='window2')#search 2 times
sub = window2.Control(searchDepth=1, Name='2-4')# search 4 times
edit = sub.EditControl(searchDepth=1, Name='myedit2')# search 2 times
edit.SendKeys('hi')

先在root的第一层子控件中查找window2,需要查找2次。 再在window2的第一层子控件中查找control2-4,需要查找4次。 最后在control2-4的第一层子控件中查找myedit2,需要查找2次。 总共需要查找8次就能找到控件。

你还可以 把上面的四行代码合并成一行:

uiautomation.WindowControl(searchDepth=1, Name='window2').Control(searchDepth=1, Name='2-4').EditControl(searchDepth=1, Name='myedit2').SendKeys('hi')

下面来看下操作系统记事本程序的例子.
运行notepad.exe,再运行automation.py -t 3,切换到记事本使记事本成为当前激活窗口, 3秒后automation.py就会把记事本的所有控件打印出来,并保存到日志文件@AutomationLog.txt。

在我的电脑上,输出如下:

ControlType: PaneControl ClassName: #32769 Name: 桌面 Depth: 0 (桌面窗口,树的根控件)
  ControlType: WindowControl ClassName: Notepad Depth: 1 (顶层窗口,记事本窗口)
    ControlType: EditControl ClassName: Edit Depth: 2
      ControlType: ScrollBarControl ClassName: Depth: 3
        ControlType: ButtonControl ClassName: Depth: 4
        ControlType: ButtonControl ClassName: Depth: 4
      ControlType: ThumbControl ClassName: Depth: 3
    ControlType: TitleBarControl ClassName: Depth: 2
      ControlType: MenuBarControl ClassName: Depth: 3
        ControlType: MenuItemControl ClassName: Depth: 4
      ControlType: ButtonControl ClassName: Name: 最小化 Depth: 3
      ControlType: ButtonControl ClassName: Name: 最大化 Depth: 3
      ControlType: ButtonControl ClassName: Name: 关闭 Depth: 3
...

运行如下代码:

# -*- coding: utf-8 -*-
# this script only works with Win32 notepad.exe
# if you notepad.exe is the Windows Store version in Windows 11, you need to uninstall it.
import subprocess
import uiautomation as autodef test():print(auto.GetRootControl())subprocess.Popen('notepad.exe', shell=True)# 首先从桌面的第一层子控件中找到记事本程序的窗口WindowControl,再从这个窗口查找子控件notepadWindow = auto.WindowControl(searchDepth=1, ClassName='Notepad')print(notepadWindow.Name)notepadWindow.SetTopmost(True)# 查找notepadWindow所有子孙控件中的第一个EditControl,因为EditControl是第一个子控件,可以不指定深度edit = notepadWindow.EditControl()try:# 获取EditControl支持的ValuePattern,并用Pattern设置控件文本为"Hello"edit.GetValuePattern().SetValue('Hello')# or edit.GetPattern(auto.PatternId.ValuePattern)except auto.comtypes.COMError as ex:# 如果遇到COMError, 一般是没有以管理员权限运行Python, 或者这个控件没有实现pattern的方法(如果是这种情况,基本没有解决方法)# 大多数情况不需要捕捉COMError,如果遇到了就加到try blockpassedit.SendKeys('{Ctrl}{End}{Enter}World')# 在文本末尾打字print('current text:', edit.GetValuePattern().Value)# 获取当前文本# 先从notepadWindow的第一层子控件中查找TitleBarControl, # 然后从TitleBarControl的子孙控件中找第二个ButtonControl, 即最大化按钮,并点击按钮notepadWindow.TitleBarControl(Depth=1).ButtonControl(foundIndex=2).Click()# 从notepadWindow前两层子孙控件中查找Name为'关闭'的按钮并点击按钮notepadWindow.ButtonControl(searchDepth=2, Name='关闭').Click()# 这时记事本弹出是否保存提示,按热键Alt+N不保存退出。auto.SendKeys('{Alt}n')if __name__ == '__main__':test()

auto.GetRootControl()返回控件树的根节点(即桌面窗口Desktop)
auto.WindowControl(searchDepth=1, ClassName='Notepad') 创建了一个WindowControl对象, 括号中的参数指定按照什么条件或控件属性在控件树中查找此控件。

控件的__init__函数中,有下列参数可以使用:
searchFromControl = None, 从哪个控件开始查找,如果为None,从根节点Desktop开始查找
searchDepth = 0xFFFFFFFF, 搜索深度
searchInterval = SEARCH_INTERVAL, 搜索间隔
foundIndex = 1 ,搜索到的满足搜索条件的控件索引,索引从1开始
Name 控件名字
SubName 控件部分名字
RegexName 使用re.match匹配符合正则表达式的名字,Name,SubName,RegexName只能使用一个,不能同时使用
ClassName 类名字
AutomationId 控件AutomationId
ControlType 控件类型
Depth 控件相对于searchFromControl的精确深度
Compare 自定义比较函数function(control: Control, depth: int)->bool

searchDepth和Depth的区别是:
searchDepth在指定的深度范围内(包括1~searchDepth层中的所有子孙控件)搜索第一个满足搜索条件的控件
Depth只在Depth所在的深度(如果Depth>1,排除1~searchDepth-1层中的所有子孙控件)搜索第一个满足搜索条件的控件

Control.Element返回IUIAutomation底层COM对象IUIAutomationElement, 基本上Control的所有属性或方法都是通过调用IUIAutomationElement COM API和Win32 API实现的。 当你使用一个Control的属性或方法时,属性或方法内部调用Control.Element并且Control.Element是None时uiautomation才开始搜索控件。 如果在uiautomation.TIME_OUT_SECOND(默认为10)秒内找不到控件,uiautomation就会抛出一个LookupError异常。 搜索到控件后,Control.Element将会有个有效值。 你可以调用Control.Exists(maxSearchSeconds, searchIntervalSeconds)来检查一个控件是否存在,此函数不会抛出异常。 另外可以调用Control.Refind或Control.Exists使Control.Element无效并触发重新搜索逻辑。

例子:

#!python3
# -*- coding:utf-8 -*-
# this script only works with Win32 notepad.exe
# if you notepad.exe is the Windows Store version in Windows 11, you need to uninstall it.
import subprocess
import uiautomation as auto
auto.uiautomation.SetGlobalSearchTimeout(15)  # 设置全局搜索超时 15def main():subprocess.Popen('notepad.exe', shell=True)window = auto.WindowControl(searchDepth=1, ClassName='Notepad')# 或者使用Compare自定义搜索条件# window = auto.WindowControl(searchDepth=1, ClassName='Notepad', Compare=lambda control,depth:control.ProcessId==100)edit = window.EditControl()# 当第一次调用SendKeys时, uiautomation开始在15秒内搜索控件window和edit# 因为SendKeys内部会间接调用Control.Element并且Control.Element值是None# 如果在15秒内找不到window和edit,会抛出LookupError异常try:edit.SendKeys('first notepad')except LookupError as ex:print("The first notepad doesn't exist in 15 seconds")return# 第二次调用SendKeys不会触发搜索, 之前的调用保证Control.Element有效edit.SendKeys('{Ctrl}a{Del}')window.GetWindowPattern().Close()  # 关闭第一个Notepad, window和edit的Element虽然有值,但是无效了subprocess.Popen('notepad.exe')  # 运行第二个Notepadwindow.Refind()  # 必须重新搜索edit.Refind()  # 必须重新搜索edit.SendKeys('second notepad')edit.SendKeys('{Ctrl}a{Del}')window.GetWindowPattern().Close()  # 关闭第二个Notepad, window和edit的Element虽然有值,但是再次无效了subprocess.Popen('notepad.exe')  # 运行第三个Notepadif window.Exists(3, 1): # 触发重新搜索if edit.Exists(3):  # 触发重新搜索edit.SendKeys('third notepad')  # 之前的Exists保证edit.Element有效edit.SendKeys('{Ctrl}a{Del}')window.GetWindowPattern().Close()else:print("The third notepad doesn't exist in 3 seconds")if __name__ == '__main__':main()

另外可以设置DEBUG_SEARCH_TIME查看搜索控件所遍历的控件数和搜索时间。

import uiautomation as auto
auto.uiautomation.DEBUG_SEARCH_TIME = True

参考demos/automation_calculator.py

目录 demos 中提供了一些例子,请根据这些例子学习使用uiautomation.


如果你发现automation.py不能打印你所看到的程序的控件,这并不是uiautomation的bug, 是因为这个程序是使用DirectUI或自定义控件实现的,不是用微软提供的标准控件实现的, 这个软件必须实现UI Automation Provider才能支持UIAutomation。 微软提供的标准控件默认支持UIAutomation。

比如Chrome浏览器,默认你只能看到最外层的PaneControl Chrome_WidgetWin_1,看不到Chrome具体的子控件, 如果加了参数--force-renderer-accessibility运行Chrome浏览器,就能看到Chrome的子控件了。 这是因为Chrome实现了UI Automation Provider,并做了参数开关 。如果一个软件是用DirectUI实现的,但没有实现UI Automation Provider,那么这个软件是不支持UIAutomation的。

 

相关文章:

python控制Windows桌面程序自动化模块uiautomation

github仓库地址&#xff1a;GitHub - yinkaisheng/Python-UIAutomation-for-Windows: (Donot use 3.7.6,3.8.1):snake:Python 3 wrapper of Microsoft UIAutomation. Support UIAutomation for MFC, WindowsForm, WPF, Modern UI(Metro UI), Qt, IE, Firefox, Chrome ... uiaut…...

Serializable 和Parcelable的区别

Serializable和Parcelable接口可以完成对象的序列化的过程&#xff0c;当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者Serializable&#xff0c;有时候我们还需要把对象持久化到存储设备上或者通过网络传输给其他客户端&#xff0c;这个时候也需要使用Seriaz…...

dubbogo-02 将服务注册到nacos

增加dubbo配置 dubbo:application:name: gotestmodule: gotestgroup: daoorganization: qiudaozhangowner: qiudaozhangversion: 0.1environment: proregistries:nacosWithCustomGroup:protocol: nacos # 注册中心选择 nacosaddress: 127.0.0.1:8848 # nacos ipgroup: RIDE # …...

postgresql 配置文件 与 修改配置如何启用

2.启用配置 postgresql显式地以表格的方式告诉我们哪些配置项需要重启数据库实例、哪些配置项仅需要重新加载配置文件即可无需重启服务 select name, context from pg_settings context 的值指示具体策略&#xff1a; internal: 编译期间的设置&#xff0c;只有重新编译才能生…...

物联网专业前景怎么样?

物联网专业前景怎么样&#xff1f; 物联网专业在当今技术发展迅速的背景下具有广阔的前景。以下是物联网专业的一些优势和就业前景&#xff1a; 1.市场需求大&#xff1a;物联网作为人工智能、云计算和大数据等技术的结合&#xff0c;已经成为许多行业的核心需求。各行各业都需…...

JVM垃圾回收算法介绍

堆的分代和区域 &#xff08;年轻代&#xff09;Young Generation&#xff08;eden、s0、s1 space&#xff09; Minor GC &#xff08;老年代&#xff09;Old Generation &#xff08;Tenured space&#xff09; Major GC|| Full GC &#xff08;永久代&#xff09;Permanent…...

紫光同创FPGA实现HSSTLP高速接口通信,8b/10b编解码数据回环,提供PDS工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、设计思路框架HSSTLP详解HSSTLP基本了解HSSTLP之时钟HSSTLP之PCSHSSTLP之PMAHSSTLP之接口说明 硬件设计HSSTLP IP调用和配置 4、PDS工程详解5、上板调试验证并演示6、福利&#xff1a;工程代码的获取 紫光同创FPGA实…...

Web前端—盒子模型:选择器、PxCook、盒子模型、正则表达式、综合案例(产品卡片与新闻列表)

版本说明 当前版本号[20231019]。 版本修改说明20231018初版20231019补充了综合案例二新闻列表的代码及完善部分代码 目录 文章目录 版本说明目录盒子模型01-选择器结构伪类选择器基本使用:nth-child(公式)伪元素选择器 02-PxCook03-盒子模型盒子模型-组成边框线四个方向单方…...

C++ vector类模拟实现

目录 一、成员变量 二、构造函数 1.默认构造 2.拷贝构造 3.迭代器构造 4.使用n个值构造 5.赋值拷贝 三、析构函数 四、vector重要成员函数 1.size和capacity函数 2.reserve函数 3.resize函数 4.push_back函数 5.insert函数 6.erase函数 7.重载operator[] 一、成…...

FastAPI+Pydantic使用自定义参数校验+自定义异常+全局异常捕获

目录 1 自定义参数校验异常 2 自定义的curr_page_v参数校验函数&#xff0c;如果不合法抛出自定义异常&#xff01; 3 配置全局异常 1 自定义参数校验异常 # 1.用户自定义异常类型&#xff0c;只要该类继承了Exception类即可 class ValDtoError(Exception):# 初始化def __in…...

Python综合练习题

题目 创建一个系统&#xff0c;里面可以添加学生、添加班级、查看班级里的学生&#xff0c;在控制台输出 效果图 关键代码 完整代码 # -*- coding: UTF-8 -*-#功能 Functionality0 #学生 Student [刘榕榕0, 秦英姿1, 王家乐0, 孟德赫3, 门子伟4, 明展宇5] #班级 Class [大…...

SpringCloud+Nacos集成Seata-1.7.0分布式事务

前言 项目中需要A服务调用B服务&#xff0c;当A服务方法体内出现异常时&#xff0c;若B服务方法已执行&#xff0c;要求B服务能够进行回滚&#xff0c;需要借助分布式事务实现。Seata是一个比较成熟的分布式事务工具&#xff0c;但官方文档比较简洁&#xff0c;查阅网上资料也…...

任务调度框架-如何实现定时任务+RabbitMQ事务+手动ACK

任务调度框架 Java中如何实现定时任务&#xff1f; 比如&#xff1a; 1.每天早上6点定时执行 2.每月最后一个工作日&#xff0c;考勤统计 3.每个月25号信用卡还款 4.会员生日祝福 5.每隔3秒&#xff0c;自动提醒 10分钟的超时订单的自动取消&#xff0c;每隔30秒或1分钟查询…...

修炼k8s+flink+hdfs+dlink(六:学习k8s)

一&#xff1a;增&#xff08;创建&#xff09;。 直接进行创建。 kubectl run nginx --imagenginx使用yaml清单方式进行创建。 二&#xff1a;删除。 kubectl delete pods/nginx 三&#xff1a;修改。 kubectl exec -it my-nginx – /bin/bash 四&#xff1a;查看。 …...

红队专题-从零开始VC++C/S远程控制软件RAT-MFC-[4]客户端与服务端连接

红队专题 招募六边形战士队员服务端编写新建工程server函数创建主线程类获取配置信息运行command 命令头文件里创建引用win32 类库/头文件startsocket 开始监听 类函数添加类StartSocketmysend/myrecv 设置 m_sockCommon 头文件MSGINFO_S 结构体 ThreadMain头文件runflag 启动 …...

Qt Designer生成ui文件,如何转py文件,如何运行

下面将逐步介绍ui文件如何转py文件&#xff0c;怎么运行的具体操作步骤 ui文件转py文件 1.使用Qt Designer生成ui文件&#xff0c;保存到本地 2.输入 cmd &#xff0c;打开命令行窗口 3.进入ui文件的目录下&#xff0c;文件路径使用你本地存放ui文件的位置 cd /d ui文件路径…...

Python数据挖掘:自动售货机销售数据分析与应用

&#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于恒川的日常汇报系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏C语言初阶、C…...

【设计模式】设计模式概述

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…...

第六届“中国法研杯”司法人工智能挑战赛进行中!

第六届“中国法研杯”司法人工智能挑战赛 赛题上新&#xff01; 第六届“中国法研杯”司法人工智能挑战赛&#xff08;LAIC2023&#xff09;目前已发布司法大模型数据和服务集成调度 、证据推理、司法大数据征文比赛、案件要素识别四大任务。本届大赛中&#xff0c;“案件要素…...

关于 passing ‘const xx’ as ‘this’ argument of 的错误

今天在写一个简单的函数时&#xff0c;编译时出现了如下的错误&#xff1a; 这个很简单的函数是这样的&#xff1a; struct bundle_set {uint32_t baseId;uint32_t endId;bool operator< (const bundle_set &a){return baseId < a.baseId;} }; 在网上搜索到都是说什…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...