尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python窗口级UI自动化:pywin32+PIL图像识别实战
简介本资源是一套面向Python初学者与游戏自动化爱好者的技术实践项目聚焦于《梦幻西游》手游的计算机视觉辅助脚本开发解决重复操作效率低、手动识别界面元素耗时等问题。压缩包共21个文件469KB含3个核心Python源码mhxy_fz.py、memory_pic.py等、8张实测游戏界面截图用于图像匹配验证、4个XML配置文件支撑界面逻辑、1份详细说明文档附赠资源.docx及1份README.md使用指南另有pyc缓存与IDE配置文件便于快速部署。已有553人学习下载适合希望掌握窗口捕获pywin32、图像相似度比对PIL、GUI交互设计tkinter及PyInstaller打包全流程的实战学习者。读者可直接运行图形化界面配置参数复现自动点击、场景识别与任务循环等典型功能并基于开源代码进行功能扩展或适配其他游戏。1. 这不是外挂是窗口级自动化调试工具用 Python 搭建《梦幻西游》手游辅助脚本的最小可行闭环你刚打开模拟器发现《梦幻西游》手游窗口标题是“MuMu模拟器 - 梦幻西游”但窗口类名却是Qt5QWindowIcon你用pyautogui.locateOnScreen()找不到“自动战斗”按钮不是因为图片没截准而是游戏用了动态纹理抗锯齿UI缩放三重干扰你写完tkinter界面点了“开始”脚本却卡在pywin32的GetDC()调用上——这不是玄学是 Windows 窗口消息机制、GDI 截图权限、图像相似度阈值三者咬合失败的典型症状。这个标题指向的是一套基于真实窗口捕获而非内存读取的轻量级自动化方案它不破解游戏协议、不注入 DLL、不依赖 root 或模拟器底层 API只靠pywin32获取窗口句柄与设备上下文、PIL做无损截图与模板匹配、tkinter提供可调参的控制面板最后打包成单文件pyi.exe。它适合两类人一是想验证 CV 自动化逻辑是否能在真实 UI 层生效的工程师比如测试 UI 可访问性或做 RPA 验证二是需要快速搭建「条件触发 图像反馈」闭环的非专业开发者比如帮家人自动完成每日师门任务。它不能绕过防外挂检测但能帮你把“人工点三次屏幕再等两秒”的重复动作压缩成一个带日志、可暂停、可调阈值的图形化开关。提示本方案所有操作均在用户态完成不修改系统策略、不请求管理员权限、不访问进程内存符合绝大多数模拟器与游戏客户端的运行沙箱边界。它解决的是“如何让脚本像人一样看屏幕、认图标、点位置”而不是“如何跳过验证”。2. 从窗口句柄到像素矩阵用 pywin32 PIL 实现稳定截图链路2.1 为什么不用 pyautogui——窗口句柄才是可控性的起点pyautogui.screenshot()默认抓全屏而《梦幻西游》手游在多显示器、高 DPI 缩放、窗口最小化时行为不可控。更致命的是当模拟器窗口被其他程序遮挡pyautogui仍会返回旧帧缓存导致图像匹配永远失败。而pywin32的FindWindowGetWindowRectGetDC组合能精确锁定目标窗口的客户区坐标并强制刷新 GDI 位图。这是整个链路稳定性的第一道闸门。import win32gui import win32ui from PIL import Image import numpy as np def capture_window_by_title(window_title: str) - np.ndarray: hwnd win32gui.FindWindow(None, window_title) if not hwnd: raise ValueError(f未找到窗口{window_title}) # 获取客户区坐标不含标题栏和边框 left, top, right, bottom win32gui.GetClientRect(hwnd) # 转换为客户区相对于屏幕的绝对坐标 left, top win32gui.ClientToScreen(hwnd, (left, top)) right, bottom win32gui.ClientToScreen(hwnd, (right, bottom)) width, height right - left, bottom - top # 创建设备上下文并截图 hwndDC win32gui.GetWindowDC(hwnd) mfcDC win32ui.CreateDCFromHandle(hwndDC) saveDC mfcDC.CreateCompatibleDC() saveBitMap win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, width, height) saveDC.SelectObject(saveBitMap) saveDC.BitBlt((0, 0), (width, height), mfcDC, (0, 0), win32con.SRCCOPY) # 转为 PIL.Image 并转为 numpy array bmpinfo saveBitMap.GetInfo() bmpstr saveBitMap.GetBitmapBits(True) img Image.frombuffer( RGB, (bmpinfo[bmWidth], bmpinfo[bmHeight]), bmpstr, raw, BGRX, 0, 1 ) win32gui.DeleteObject(saveBitMap.GetHandle()) win32gui.ReleaseDC(hwnd, hwndDC) return np.array(img)这段代码的关键参数说明GetClientRect()返回的是客户区内坐标必须用ClientToScreen()转为屏幕绝对坐标否则截图区域偏移BitBlt的SRCCOPY模式确保像素逐位复制避免CAPTUREBLT在某些显卡驱动下返回黑图BGRX格式对应 Windows GDI 的默认位图排列BGR 通道 1 字节填充若直接用RGB会导致颜色错乱DeleteObject和ReleaseDC必须成对调用否则每截图一次就泄漏一个 GDI 句柄100 次后 Windows 会拒绝新截图请求现象saveDC.BitBlt返回 0。2.2 PIL 图像预处理为什么模板匹配总在 92% 相似度卡死游戏 UI 存在三种干扰源字体抗锯齿边缘灰度过渡、动态粒子特效每帧微小位移、UI 缩放125% DPI 下按钮尺寸变化 25%。直接用cv2.matchTemplate的CV_TM_CCOEFF_NORMED会因灰度分布偏移而失效。我们改用 PIL 的ImageChops.differenceImageStat.Stat计算像素级差异均值再归一化为 0~1 的相似度from PIL import Image, ImageChops, ImageStat def calc_similarity(pil_img: Image.Image, template: Image.Image) - float: # 裁剪模板到目标图尺寸或反之确保同尺寸比较 if pil_img.size ! template.size: # 优先缩放 template 到 img 尺寸保留原图细节 template template.resize(pil_img.size, Image.LANCZOS) # 计算差分图逐像素绝对差 diff ImageChops.difference(pil_img.convert(RGB), template.convert(RGB)) # 统计差分图的均值越小越相似 stat ImageStat.Stat(diff) # 归一化(255 - mean) / 255使 1.0 表示完全一致 mean_diff sum(stat.mean) / len(stat.mean) return max(0.0, (255.0 - mean_diff) / 255.0) # 示例加载模板图提前截取“自动战斗”按钮 template_btn Image.open(assets/auto_fight.png) current_screen Image.fromarray(capture_window_by_title(MuMu模拟器 - 段梦西游)) # 注意窗口标题需实际匹配 similarity calc_similarity(current_screen, template_btn) print(f相似度{similarity:.3f}) # 输出如 0.967关键设计点Image.LANCZOS缩放比Image.BILINEAR更锐利减少模板失真ImageChops.difference是整数像素运算比 OpenCV 的浮点卷积更鲁棒stat.mean返回 RGB 三通道均值列表取平均后再归一化比单通道更抗色偏max(0.0, ...)防止浮点误差导致负值避免后续逻辑崩溃。3. 图像定位与动作执行从“找到按钮”到“精准点击”的毫秒级时序控制3.1 坐标转换陷阱为什么点击总偏移 20 像素pywin32截图得到的是客户区像素坐标但mouse_event发送的是屏幕绝对坐标。而GetClientRect返回的(left, top)是客户区左上角在屏幕上的位置所以点击坐标 (left x_in_client, top y_in_client)。但这里还藏一个坑Windows 的WM_MOUSEMOVE消息坐标系以左上角为原点而mouse_event的MOUSEEVENTF_ABSOLUTE模式要求坐标归一化到 0~65535 范围即x * 65535 // screen_width。多数人直接用SetCursorPos(x, y)但它受 DPI 缩放影响——在 125% DPI 下SetCursorPos(100, 100)实际移动到 125×125 像素处。正确做法是使用SendInputAPIimport ctypes from ctypes import wintypes class MOUSEINPUT(ctypes.Structure): _fields_ [ (dx, wintypes.LONG), (dy, wintypes.LONG), (mouseData, wintypes.DWORD), (dwFlags, wintypes.DWORD), (time, wintypes.DWORD), (dwExtraInfo, wintypes.ULONG_PTR), ] def click_at_absolute(x: int, y: int): # 获取主屏幕尺寸DPI 感知 user32 ctypes.windll.user32 screen_w user32.GetSystemMetrics(0) # SM_CXSCREEN screen_h user32.GetSystemMetrics(1) # SM_CYSCREEN # 归一化坐标0~65535 norm_x int(x * 65535 / screen_w) norm_y int(y * 65535 / screen_h) # 构造输入事件 inputs (ctypes.c_ulong * 2)() mi MOUSEINPUT(norm_x, norm_y, 0, 0x0001 | 0x8000, 0, 0) # MOVE ABSOLUTE inputs[0] ctypes.cast(ctypes.byref(mi), ctypes.c_ulong).value mi MOUSEINPUT(0, 0, 0, 0x0002, 0, 0) # LEFTDOWN inputs[1] ctypes.cast(ctypes.byref(mi), ctypes.c_ulong).value ctypes.windll.user32.SendInput(2, inputs, ctypes.sizeof(MOUSEINPUT)) # 使用示例在客户区坐标 (120, 85) 处点击 hwnd win32gui.FindWindow(None, MuMu模拟器 - 梦幻西游) left, top, _, _ win32gui.GetClientRect(hwnd) left, top win32gui.ClientToScreen(hwnd, (left, top)) # 客户区左上角屏幕坐标 click_at_absolute(left 120, top 85)注意SendInput是 Windows 推荐的输入模拟方式它绕过窗口焦点检查且 DPI 感知准确。SetCursorPosmouse_event组合在高 DPI 下必然偏移这是血泪经验。3.2 动作队列与防抖为什么连点三次反而触发不了技能游戏 UI 对连续点击有防抖机制如 300ms 内重复点击视为无效。我们设计一个带时间戳的动作队列确保每次点击间隔 ≥ 350ms且支持“等待 UI 变化”条件import time from typing import List, Tuple, Optional class ActionQueue: def __init__(self, hwnd: int): self.hwnd hwnd self.last_click_time 0 self.timeout 5.0 # 等待 UI 变化的最大秒数 def safe_click(self, x_client: int, y_client: int, min_interval: float 0.35): now time.time() if now - self.last_click_time min_interval: time.sleep(min_interval - (now - self.last_click_time)) self.last_click_time time.time() left, top, _, _ win32gui.GetClientRect(self.hwnd) left, top win32gui.ClientToScreen(self.hwnd, (left, top)) click_at_absolute(left x_client, top y_client) def wait_for_change(self, region: Tuple[int, int, int, int], timeout: float None) - bool: 等待指定区域图像变化用于技能释放后界面刷新 timeout timeout or self.timeout start_time time.time() base_img capture_window_by_title(MuMu模拟器 - 梦幻西游) base_crop base_img[region[1]:region[3], region[0]:region[2]] while time.time() - start_time timeout: current_img capture_window_by_title(MuMu模拟器 - 梦幻西游) current_crop current_img[region[1]:region[3], region[0]:region[2]] # 计算差异均值5 表示显著变化 diff np.abs(current_crop.astype(int) - base_crop.astype(int)).mean() if diff 5: return True time.sleep(0.1) return False # 使用示例点击技能按钮等待技能图标消失表示已释放 aq ActionQueue(hwnd) aq.safe_click(240, 180) # 技能按钮客户区坐标 if aq.wait_for_change((220, 160, 260, 200)): # 监控技能图标区域 print(技能释放成功) else: print(等待超时可能未触发)该队列的核心价值在于把“点击”从原子操作升级为带状态感知的动作单元让脚本能响应 UI 反馈而非盲目轮询。4. tkinter 图形界面不只是按钮而是可调试的自动化控制台4.1 为什么不用 PyQt——tkinter 的不可替代性PyQt/PySide启动慢、包体积大、与pywin32在多线程 GUI 中易冲突。而tkinter是 Python 标准库启动快100ms、内存占用低5MB、与pywin32共享同一消息循环。更重要的是tkinter的after()方法天然支持非阻塞定时任务完美适配“每 500ms 截图一次”的轮询需求无需threading.Timer或asyncio复杂调度。import tkinter as tk from tkinter import ttk, messagebox class AutoHelperGUI: def __init__(self, root: tk.Tk): self.root root self.root.title(梦幻西游辅助控制台 v1.0) self.root.geometry(520x480) self.is_running False self.action_queue None # 窗口标题输入框 ttk.Label(root, text模拟器窗口标题).grid(row0, column0, stickytk.W, padx5, pady5) self.title_var tk.StringVar(valueMuMu模拟器 - 梦幻西游) ttk.Entry(root, textvariableself.title_var, width40).grid(row0, column1, columnspan2, padx5, pady5) # 相似度阈值滑块0.7 ~ 0.95 ttk.Label(root, text匹配阈值).grid(row1, column0, stickytk.W, padx5, pady5) self.threshold_var tk.DoubleVar(value0.85) ttk.Scale(root, from_0.7, to0.95, variableself.threshold_var, orienttk.HORIZONTAL, length300).grid(row1, column1, columnspan2, padx5, pady5) ttk.Label(root, textvariabletk.StringVar(value0.85)).grid(row1, column3, padx5, pady5) # 操作按钮区 btn_frame ttk.Frame(root) btn_frame.grid(row2, column0, columnspan4, pady10) ttk.Button(btn_frame, text开始, commandself.start_loop).pack(sidetk.LEFT, padx5) ttk.Button(btn_frame, text暂停, commandself.pause_loop).pack(sidetk.LEFT, padx5) ttk.Button(btn_frame, text停止, commandself.stop_loop).pack(sidetk.LEFT, padx5) # 日志文本框 self.log_text tk.Text(root, height12, width60, statetk.DISABLED) self.log_text.grid(row3, column0, columnspan4, padx5, pady5, stickytk.NSEW) # 状态栏 self.status_var tk.StringVar(value就绪) status_bar ttk.Label(root, textvariableself.status_var, relieftk.SUNKEN, anchortk.W) status_bar.grid(row4, column0, columnspan4, stickytk.EW, pady(0, 2)) # 配置网格权重 root.grid_rowconfigure(3, weight1) root.grid_columnconfigure(1, weight1) def log(self, msg: str): self.log_text.config(statetk.NORMAL) self.log_text.insert(tk.END, f[{time.strftime(%H:%M:%S)}] {msg}\n) self.log_text.see(tk.END) self.log_text.config(statetk.DISABLED) def start_loop(self): if self.is_running: return try: hwnd win32gui.FindWindow(None, self.title_var.get()) if not hwnd: raise ValueError(未找到目标窗口) self.action_queue ActionQueue(hwnd) self.is_running True self.status_var.set(运行中...) self.root.after(500, self.main_loop) # 启动轮询 except Exception as e: messagebox.showerror(错误, f启动失败{e}) def main_loop(self): if not self.is_running: return try: # 此处插入你的核心逻辑截图 → 匹配 → 点击 screen capture_window_by_title(self.title_var.get()) # 示例匹配“自动战斗”按钮 template Image.open(assets/auto_fight.png) sim calc_similarity(Image.fromarray(screen), template) if sim self.threshold_var.get(): self.log(f匹配成功{sim:.3f}执行点击) # 转换坐标并点击此处省略具体坐标计算 self.action_queue.safe_click(120, 85) except Exception as e: self.log(f执行异常{e}) finally: self.root.after(500, self.main_loop) # 每 500ms 循环一次 def pause_loop(self): self.is_running False self.status_var.set(已暂停) def stop_loop(self): self.is_running False self.status_var.set(已停止) if __name__ __main__: root tk.Tk() app AutoHelperGUI(root) root.mainloop()这个界面的价值远超“好看”after()实现的轮询不阻塞 GUI用户随时可点暂停StringVar绑定的阈值滑块让非程序员也能调参Text日志框带时间戳方便回溯哪次匹配失败messagebox错误弹窗比控制台 traceback 更友好。5. 避坑指南那些让你调试三天却只差一行代码的致命细节5.1 现象pywin32截图返回全黑图原因目标窗口处于最小化状态或GetWindowDC()获取的是非客户区 DC如标题栏而BitBlt复制了不可见区域。解决调用win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)强制恢复窗口用win32gui.IsIconic(hwnd)判断是否最小化最小化时先ShowWindow(SW_RESTORE)再SetForegroundWindow()确保GetClientRect()后调用ClientToScreen()而非直接用GetWindowRect()后者包含标题栏。5.2 现象tkinter界面点击后无响应pywin32报错invalid window handle原因tkinter主线程与pywin32的FindWindow不在同一线程上下文Windows 拒绝跨线程访问窗口句柄。解决所有win32gui/win32ui调用必须在tkinter的主线程中执行即after()回调内禁止在threading.Thread中调用FindWindow必须用root.after(ms, func)替代若需后台耗时操作如 OCR用queue.Queueafter()轮询结果而非多线程。5.3 现象PIL图像匹配在 Debug 模式下正常打包成pyi.exe后失败原因pyinstaller默认不打包PIL的图像解码插件如libjpeg、libpng导致Image.open()加载 PNG 模板失败静默返回空图。解决打包时添加--collect-all PIL参数或手动复制venv\Lib\site-packages\PIL\plugins下的.pyd文件到dist\your_app\目录验证方法在pyi.exe启动后立即打印Image.PILLOW_VERSION若为None则插件缺失。5.4 现象pywin32在 Windows 11 上频繁报错pywintypes.error: (5, OpenProcess, 拒绝访问。)原因Windows 11 默认启用“核心隔离”内存完整性Core Isolation阻止用户态程序访问进程句柄。解决无需关闭安全功能pywin32的FindWindow/GetWindowDC不需要OpenProcess权限此错误来自误用win32process模块检查代码是否混用了win32process.EnumProcesses()等需权限的函数替换为纯窗口 API 操作本方案全程未调用win32process故可忽略此警告。5.5 现象tkinter界面在高 DPI 显示器上文字模糊、按钮挤压原因tkinter默认不启用 DPI 感知Windows 将其渲染为 96 DPI 后放大导致模糊。解决在tkinter初始化后立即调用try: ctypes.windll.shcore.SetProcessDpiAwareness(1) # Windows 8.1 except: ctypes.windll.user32.SetProcessDPIAware() # Windows Vista并设置root.tk.call(tk, scaling, 1.0)强制禁用内部缩放让系统负责 DPI 适配。6. 进阶技巧用图像哈希构建可复用的 UI 元件库告别重复截图6.1 为什么模板图要按“元件”而非“页面”管理你不会为每个“师门任务”页面截 10 张图而是提取其中 5 个稳定元件task_accept_btn.png接受任务按钮task_submit_btn.png提交任务按钮npc_dialogue_box.png对话框背景item_icon_12345.png特定物品图标map_mini_icon.png小地图定位点这些元件在不同场景下复用率极高。但问题来了同一按钮在不同分辨率下尺寸不同直接缩放模板会模糊。解决方案是用感知哈希pHash代替像素匹配——它对缩放、旋转、亮度变化鲁棒且哈希值可存为 JSON体积仅几 KB。from PIL import Image import imagehash def generate_phash(image_path: str, hash_size: int 8) - str: 生成图像的感知哈希字符串格式 img Image.open(image_path).convert(L).resize((hash_size, hash_size), Image.LANCZOS) return str(imagehash.phash(img, hash_sizehash_size)) # 生成元件哈希库 components { accept_btn: generate_phash(assets/task_accept_btn.png), submit_btn: generate_phash(assets/task_submit_btn.png), dialogue_box: generate_phash(assets/npc_dialogue_box.png) } # 保存为 JSON import json with open(components.json, w) as f: json.dump(components, f, indent2)6.2 实时哈希匹配把“找按钮”变成“查字典”def match_component(pil_img: Image.Image, component_hash: str, threshold: int 5) - bool: 用 pHash 匹配元件threshold 越小越严格0~64 img_hash imagehash.phash(pil_img.convert(L), hash_size8) return img_hash - imagehash.hex_to_hash(component_hash) threshold # 使用示例从当前屏幕中识别“接受任务”按钮 screen Image.fromarray(capture_window_by_title(MuMu模拟器 - 梦幻西游)) with open(components.json) as f: comp_hashes json.load(f) # 滑动查找避免全图扫描 for y in range(100, screen.height - 50, 20): # 从 y100 开始步长 20 for x in range(50, screen.width - 100, 20): crop screen.crop((x, y, x 80, y 40)) # 80×40 区域 if match_component(crop, comp_hashes[accept_btn]): print(f找到接受按钮({x}, {y})) # 转换为客户区坐标并点击 break表格pHash 与传统模板匹配对比特性像素模板匹配pHash 匹配分辨率适应性需为每种 DPI 单独截图✅ 自动适应缩放抗抗锯齿❌ 边缘灰度导致失败✅ 对灰度变化不敏感存储体积一张图 50~200KB一个哈希 16 字符20B匹配速度O(n²) 卷积O(1) 字符串汉明距离适用场景精确位置定位快速存在性判断 粗略定位我一般会把两者结合先用 pHash 在全图快速定位“按钮大概在哪一片区域”再用像素匹配在该区域内精确定位点击坐标。这样既保证速度又不失精度。这套元件库一旦建好新增一个“帮派任务”功能只需截 3 张新图、生成哈希、更新 JSON5 分钟就能接入原有流程。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Mac微信多开原理与实现方法详解

Mac微信多开原理与实现方法详解

1. 为什么需要Mac多开微信?在Mac上同时登录多个微信账号的需求,主要来自以下几类典型场景:商务人士需要区分工作号和生活号自媒体运营者管理多个公众号电商从业者同时处理客户咨询和供应商沟通普通用户希望区分国内版和国际版账号Mac版微信客…

📅 2026/10/28 17:40:31
MCP机制:解决插件生态冲突的高效方案

MCP机制:解决插件生态冲突的高效方案

1. 项目概述:插件生态的秩序挑战在当今软件生态中,插件化架构已成为提升系统扩展性的主流方案。以VSCode为例,其市场已上架超过4万款插件,单编辑器平均加载15-20个插件协同工作。这种多插件并行运行的场景下,插件间的上…

📅 2026/10/28 17:40:31
MCP多插件上下文冲突协调机制解析与实践

MCP多插件上下文冲突协调机制解析与实践

1. MCP多插件上下文冲突协调机制概述在当今软件生态中,插件系统已成为扩展应用功能的主流方式。MCP(Multi-Plugin Context)作为一种新兴的插件架构模式,正在被越来越多的开发工具和平台采用。我最近在几个企业级项目中深度实践了M…

📅 2026/10/28 17:40:31
MORE NEWS

更多资讯

📰

Python+MySQL图书馆管理系统实战:Tkinter GUI与数据库安全联动

简介:这是一套基于Python与MySQL开发的图形化界面图书馆管理系统实战项目,面向Python初学者、数据库入门学习者及课程设计学生,解决传统图书管理效率低、操作不直观等实际问题。资源包共13个文件,含6个核心Python源码(…

📰

BP神经网络电力负荷预测:MATLAB实现全流程与避坑指南

简介:基于BP神经网络的电力负荷预测完整方案,系统讲解利用历史负荷数据预测未来电力需求的方法,面向电力系统调度与规划人员、电气类专业学生,以及希望掌握神经网络建模的开发者。资源共8个文件,压缩包约410KB&#xf…

📰

倾转旋翼机悬停仿真代码拆解:MATLAB/Simulink配平、线性化与避坑指南

简介:这份资源面向倾转旋翼机飞行动力学与控制方向的初学者及研究人员,聚焦悬停状态下的仿真建模与代码实现,帮助读者理解旋翼气动、动力系统与飞行控制之间的耦合关系。压缩包共7个文件,约59KB,以MATLAB脚本&#xff…

📰

Python+PyQt5+MySQL酒店管理系统课设源码与避坑指南

简介:这是一套面向高校数据库课程设计场景的酒店管理系统完整项目,采用Python结合PyQt5与MySQL实现,适合正在准备课设或想练习GUI编程与数据库应用开发的学生参考。项目围绕酒店住宿、餐饮与娱乐服务管理展开,涵盖员工管理、客房管…

📰

小区网络规划论文写作:拓扑选型、LAN接入与IP规划

简介:围绕智能化小区网络规划展开的毕业设计文档,面向通信、网络工程及计算机相关专业学生与小区组网方案初学者,可用于课程设计、毕业设计选题参考及宽带接入方案梳理。内容从智能化小区系统组成与基本功能切入,依次讨论宽带网络…

📰

PDFMathTranslate 从零部署:完整保留排版的 PDF 全文翻译服务实战

PDFMathTranslate 从零部署:完整保留排版的 PDF 全文翻译服务实战 【免费下载链接】PDFMathTranslate [EMNLP 2025 Demo] PDF scientific paper translation with preserved formats - 基于 AI 完整保留排版的 PDF 文档全文双语翻译,支持 Google/DeepL/O…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬