在线教程丨9 秒处理一张图!In-Context Edit 高效图像编辑框架上线

现有的图像编辑方法主要面临精度与效率之间难以平衡的问题。微调方法需要大量的计算资源和优质数据集,而无需训练的技术则难以满足指令理解和编辑质量。对此,浙江大学和哈佛大学的研究团队推出了 In-Context Edit(ICEdit),一款基于指令的图像编辑框架, 仅需极少的文本指令即可实现精准的图像修改,为图像处理和内容创作提供了更多可能性。

In-Context Edit 通过以下 3 个关键贡献解决了现有技术的局限性,即语境编辑框架、 LoRA-MoE 混合调优策略以及早期滤波器推理时间缩放方法。与以往方法相比,其仅使用 1% 的可训练参数(200M)和 0.1% 的训练数据(50k),却展现出更出色的泛化能力,能够胜任多样化的图像编辑任务。同时,与 Gemini 、 GPT-4o 相比,这款开源神器不仅成本更低、速度更快(处理一张图像大约只需 9 秒),同时性能也非常强大。

目前,「In-Context Edit:指令驱动图像生成与编辑」已上线至 HyperAI 超神经官网的「教程」板块, 点击下方链接即可体验一键部署教程 ⬇️

教程链接: https://go.hyper.ai/SHowG

Demo 运行

  1. 进入 hyper.ai 首页后,选择「教程」页面,并选择「In-Context Edit:指令驱动图像生成与编辑」,点击「在线运行此教程」。
    在这里插入图片描述
    在这里插入图片描述
  2. 页面跳转后,点击右上角「克隆」,将该教程克隆至自己的容器中。
    在这里插入图片描述
  3. 选择「NVIDIA GeForce RTX 4090」以及「PyTorch」镜像,OpenBayes 平台提供了 4 种计费方式,大家可以按照需求选择「按量付费」或「包日/周/月」,点击「继续执行」。新用户使用下方邀请链接注册,可获得 4 小时 RTX 4090 + 5 小时 CPU 的免费时长!

HyperAI 超神经专属邀请链接(直接复制到浏览器打开):

https://openbayes.com/console/signup?r=Ada0322_NR0n
在这里插入图片描述
在这里插入图片描述
4. 等待分配资源,首次克隆需等待 2 分钟左右的时间。当状态变为「运行中」后,点击「API 地址」旁边的跳转箭头,即可跳转至 Demo 页面。由于模型较大,需等待约 3 分钟显示 WebUI 界面,否则将显示「Bad Gateway」。请注意,用户需在实名认证后才能使用 API 地址访问功能。
在这里插入图片描述
在这里插入图片描述

效果展示

在「Upload image for editing」中上传图片,然后在文本框中输入提示词,最后点击「Run」生成。

参数调整简介:

Guidance Scale: 用于控制生成模型中条件输入(如文本或图像)对生成结果的影响程度。较高的指导值会让生成结果更加贴近输入条件,而较低的值会保留更多随机性。

Number of inference steps: 表示模型的迭代次数或推理过程中的步数,代表模型用于生成结果的优化步数。更高的步数通常会生成更精细的结果,但可能增加计算时间。

Seed: 随机数种子,用于控制生成过程中的随机性。相同的 Seed 值可以生成相同的结果(前提是其他参数相同),这在结果复现中非常重要。
在这里插入图片描述
笔者上传了一张人像图片,提示词为:Make her hair dark green and her clothes checked. 效果如下图所示~
在这里插入图片描述

import os import time import threading import ctypes import sys from PIL import Image, ImageFile, UnidentifiedImageError ImageFile.LOAD_TRUNCATED_IMAGES = True import cv2 import uiautomation as auto import win32clipboard import win32con from ctypes import * import tempfile # ===== 权限提升函数 ===== def elevate_privileges(): """确保程序以管理员权限运行""" try: if windll.shell32.IsUserAnAdmin() == 0: windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) sys.exit(0) return True except Exception as e: print(f"权限提升失败: {e}") return False # ===== 配置参数 ===== wx_groupName = &#39;星海预警&#39; wx_context = &#39;星系警告!!!---疯子出品,必数精品&#39; conVal = 2 path = &#39;D:/EVE_A_Eye-main/EVE_A_Eye&#39; devices = { &#39;QO2UL&#39;: [ &#39;127.0.0.1:5555&#39;, False ], } gameSendPosition = { &#39;第二频道&#39;: &#39;38 117&#39;, &#39;第三频道&#39;: &#39;38 170&#39;, &#39;第四频道&#39;: &#39;38 223&#39;, &#39;第五频道&#39;: &#39;38 278&#39;, &#39;第六频道&#39;: &#39;38 332&#39;, &#39;第七频道&#39;: &#39;38 382&#39; } sendTo = gameSendPosition[&#39;第三频道&#39;] mutex = threading.Lock() # ===== 剪贴板操作强化 ===== class DROPFILES(Structure): """文件拖放操作的剪切板数据结构""" _fields_ = [ ("pFiles", c_uint), # 偏移量 ("x", c_long), # 鼠标X坐标 ("y", c_long), # 鼠标Y坐标 ("fNC", c_int), # 非客户端区域标志 ("fWide", c_bool) # Unicode路径标志 ] def safe_set_clipboard(img_path, max_retries=3): """线程安全的剪贴板文件操作""" for attempt in range(max_retries): try: # 验证文件存在性 if not os.path.exists(img_path): print(f"片不存在: {img_path}") return False # 创建DROPFILES结构 pDrop = DROPFILES() pDrop.pFiles = sizeof(DROPFILES) pDrop.fWide = True # 启用Unicode # 构造完整数据结构 file_bytes = (os.path.abspath(img_path) + &#39;\0&#39;).encode(&#39;utf-16le&#39;) data = bytes(pDrop) + file_bytes # 安全设置剪贴板 win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardData(win32clipboard.CF_HDROP, data) win32clipboard.CloseClipboard() return True except Exception as e: print(f&#39;剪贴板设置失败(尝试 {attempt+1}/{max_retries}): {e}&#39;) time.sleep(0.5) return False def activate_wechat(): """激活并置顶微信窗口(通过搜索群聊名称)""" max_retries = 3 for attempt in range(max_retries): try: # 唤醒微信 auto.SendKeys(&#39;{Ctrl}{Alt}w&#39;) time.sleep(1) # 等待微信主窗口出现 # 获取微信主窗口 wechat_main = auto.WindowControl(ClassName=&#39;WeChatMainWndForPC&#39;, Depth=1) if wechat_main.Exists(5): wechat_main.SetTopmost(True) # 查找搜索框 search_edit = wechat_main.EditControl(Name=&#39;搜索&#39;, Depth=12) if search_edit.Exists(5): # 清空搜索框并输入群聊名称 search_edit.Click() time.sleep(0.2) search_edit.SendKeys(&#39;{Ctrl}a}{Del}&#39;) time.sleep(0.2) search_edit.SendKeys(wx_groupName) time.sleep(1) # 等待搜索结果 # 选择第一个搜索结果(群聊) search_result = wechat_main.ListItemControl(Name=wx_groupName, Depth=1, foundIndex=1) if search_result.Exists(5): search_result.DoubleClick() # 双击打开群聊 time.sleep(0.5) # 获取群聊窗口(注意:群聊窗口的Name是群聊名称) group_window = auto.WindowControl(ClassName=&#39;ChatWnd&#39;, Name=wx_groupName) if group_window.Exists(5): group_window.SetActive() group_window.SetTopmost(True) return True else: print(f"第{attempt+1}次尝试:未找到群聊: {wx_groupName}") else: print(f"第{attempt+1}次尝试:未找到搜索框") else: print(f"第{attempt+1}次尝试:微信主窗口未找到") except Exception as e: print(f"激活微信窗口异常: {e}") time.sleep(1) return False def send_msg(content, msg_type=1): """ 发送消息到微信 msg_type: 1=文本, 2=位, 3=文件路径(推荐) """ if not activate_wechat(): return False # 在群聊窗口中查找输入框 group_window = auto.WindowControl(ClassName=&#39;ChatWnd&#39;, Name=wx_groupName) if not group_window.Exists(3): print("群聊窗口未找到") return False # 尝试定位输入框 edit = group_window.EditControl(Depth=9, ClassName=&#39;Edit&#39;, foundIndex=3) if not edit.Exists(3): # 尝试其他方式 edits = group_window.GetChildren(className=&#39;Edit&#39;) if len(edits) >= 3: # 通常有多个编辑框,输入框是第三个 edit = edits[2] elif len(edits) > 0: edit = edits[-1] else: print("未找到输入框") return False try: if msg_type == 1: # 文本 auto.SetClipboardText(content) time.sleep(0.5) elif msg_type == 2: # 位 auto.SetClipboardBitmap(auto.Bitmap.FromFile(content)) time.sleep(0.5) elif msg_type == 3: # 文件路径 if not safe_set_clipboard(content): return False time.sleep(0.5) # 粘贴并发送 edit.SendKeys(&#39;{Ctrl}v&#39;, waitTime=100) time.sleep(0.5) edit.SendKeys("{Enter}", waitTime=100) return True except Exception as e: print(f"消息发送失败: {e}") return False # ===== 处理函数 ===== def screenc(filename, num): """执行ADB截""" os.system(f&#39;adb -s {devices[filename][0]} exec-out screencap -p > {path}/{filename}_{num}.png&#39;) def crop(x1, y1, x2, y2, scFileName, svFileName): """像裁剪""" try: img = Image.open(scFileName) re = img.crop((x1, y1, x2, y2)) re.save(svFileName) img.close() return True except Exception as e: print(f"像裁剪失败: {e}") return False def LoadImage(img1, img2): """加载像为灰度""" i1 = cv2.imread(img1, 0) i2 = cv2.imread(img2, 0) return i1, i2 def IF_Img_I(src, mp): """ 像相似度检测 返回: (是否不同, 相似度分数) """ try: res = cv2.matchTemplate(src, mp, cv2.TM_CCOEFF_NORMED) _, mac_v, _, _ = cv2.minMaxLoc(res) # 相似度阈值公式: $T_s = 0.99 - \frac{1}{resolution}$ return mac_v < 0.98, mac_v except Exception as e: print(f"像匹配失败: {e}") return False, 0.0 # ===== 警报发送函数 ===== def SendGameMassage(tag): """在游戏内发送警报消息""" str1 = f&#39;adb -s {devices[tag][0]} &#39; taps = [ (211, 478), # 打开聊天 tuple(map(int, sendTo.split())), # 选择频道 (266, 520), # 点击输入框 (870, 511), # 点击发送 (68, 292), # 确认操作1 (250, 350), # 确认操作2 (250, 433), # 确认操作3 (344, 190), # 关闭弹窗 (342, 512) # 返回主界面 ] for tap in taps: os.system(str1 + f&#39;shell input tap {tap[0]} {tap[1]}&#39;) time.sleep(0.2) def SendWeChat(tag, num): """向微信发送警报""" img_path = f&#39;{path}/{tag}_{num}.png&#39; mutex.acquire() # 发送片(使用文件路径模式) send_result = send_msg(img_path, msg_type=3) # 发送文本 if send_result: context = f"{tag}{wx_context}" send_msg(context, msg_type=1) print(f"警报发送成功: {tag}") else: print(f"警报发送失败: {tag}") mutex.release() # ===== 监听核心 ===== def ship_detection(tag): """舰船列表检测子线程""" num = 0 while True: screenc(tag, 1) time.sleep(0.5) crop(918, 44, 956, 153, f&#39;{path}/{tag}_1.png&#39;, f&#39;{path}/new_{tag}_list.png&#39;) # 像差异检测 i3, i4 = LoadImage(f"{path}/new_{tag}_list.png", f"{path}/tem/list.png") list_status, list_mac_v = IF_Img_I(i3, i4) # 二次验证机制 if list_mac_v < 0.10 and list_mac_v != 0.0: if num < 1: num += 1 time.sleep(2) continue print(f&#39;{tag}检测到舰船列表变化 (相似度: {list_mac_v:.2f})&#39;) SendWeChat(tag, 1) i1, i2 = LoadImage(f"{path}/new_{tag}_playerList.png", f"{path}/old_{tag}_playerList.png") cv2.imwrite(f&#39;{path}/old_{tag}_playerList.png&#39;, i1) time.sleep(40) num = 0 def Listening(tag): """设备监听主循环""" # 启动舰船检测线程 threading.Thread(target=ship_detection, args=(tag,), daemon=True).start() # 主检测循环 while True: screenc(tag, 2) time.sleep(conVal + 0.35) crop(774, 502, 956, 537, f&#39;{path}/{tag}_2.png&#39;, f&#39;{path}/new_{tag}_playerList.png&#39;) # 加载并比较像 i1, i2 = LoadImage(f"{path}/new_{tag}_playerList.png", f"{path}/old_{tag}_playerList.png") list_status, list_mac_v = IF_Img_I(i1, i2) # 错误检测: 相似度过低 if list_mac_v <= 0.01: print(f&#39;{tag}系统故障,相似度过低&#39;) mutex.acquire() send_msg(f"{tag}系统故障,相似度{list_mac_v:.4f},即将下线", msg_type=1) mutex.release() time.sleep(3) os._exit(1) # 检测到显著变化 if list_status: print(f&#39;{tag}检测到本地警报 (相似度: {list_mac_v:.2f})&#39;) SendGameMassage(tag) SendWeChat(tag, 2) cv2.imwrite(f&#39;{path}/old_{tag}_playerList.png&#39;, i1) # ===== 初始化函数 ===== def Start(): """初始化程序""" # 重置片缓存 with open(f&#39;{path}/tem/list.png&#39;, &#39;rb&#39;) as sc1: con = sc1.read() for k in devices: with open(f&#39;{path}/new_{k}_list.png&#39;, &#39;wb&#39;) as f: f.write(con) with open(f&#39;{path}/tem/playerList.png&#39;, &#39;rb&#39;) as sc: con = sc.read() for k in devices: with open(f&#39;{path}/old_{k}_playerList.png&#39;, &#39;wb&#39;) as f: f.write(con) with open(f&#39;{path}/new_{k}_playerList.png&#39;, &#39;wb&#39;) as f: f.write(con) # 启动监听线程 for k in devices: t = threading.Thread(target=Listening, args=(k,)) t.daemon = True t.start() print(&#39;预警系统已启动&#39;) context = f"预警系统已上线,监测星系列表:\n{list(devices.keys())}" mutex.acquire() send_msg(context, msg_type=1) mutex.release() # ===== 主程序入口 ===== if __name__ == "__main__": if elevate_privileges(): Start() # 保持主线程运行 while True: time.sleep(3600) # 每小时检查一次
10-13
import os import time import threading import ctypes import sys from PIL import Image, ImageFile, UnidentifiedImageError ImageFile.LOAD_TRUNCATED_IMAGES = True import cv2 import uiautomation as auto import win32clipboard import win32con from ctypes import * import tempfile # ===== 权限提升函数 ===== def elevate_privileges(): """确保程序以管理员权限运行""" try: if windll.shell32.IsUserAnAdmin() == 0: windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) sys.exit(0) return True except Exception as e: print(f"权限提升失败: {e}") return False # ===== 配置参数 ===== wx_groupName = &#39;星海预警&#39; wx_context = &#39;星系警告!!!---疯子出品,必数精品&#39; conVal = 2 path = &#39;D:/EVE_A_Eye-main/EVE_A_Eye&#39; devices = { &#39;QO2UL&#39;: [ &#39;127.0.0.1:5555&#39;, False ], } gameSendPosition = { &#39;第二频道&#39;: &#39;38 117&#39;, &#39;第三频道&#39;: &#39;38 170&#39;, &#39;第四频道&#39;: &#39;38 223&#39;, &#39;第五频道&#39;: &#39;38 278&#39;, &#39;第六频道&#39;: &#39;38 332&#39;, &#39;第七频道&#39;: &#39;38 382&#39; } sendTo = gameSendPosition[&#39;第三频道&#39;] mutex = threading.Lock() # ===== 剪贴板操作强化 ===== class DROPFILES(Structure): """文件拖放操作的剪切板数据结构""" _fields_ = [ ("pFiles", c_uint), # 偏移量 ("x", c_long), # 鼠标X坐标 ("y", c_long), # 鼠标Y坐标 ("fNC", c_int), # 非客户端区域标志 ("fWide", c_bool) # Unicode路径标志 ] def safe_set_clipboard(img_path, max_retries=3): """线程安全的剪贴板文件操作""" for attempt in range(max_retries): try: # 验证文件存在性 if not os.path.exists(img_path): print(f"片不存在: {img_path}") return False # 创建DROPFILES结构 pDrop = DROPFILES() pDrop.pFiles = sizeof(DROPFILES) pDrop.fWide = True # 启用Unicode # 构造完整数据结构 file_bytes = (os.path.abspath(img_path) + &#39;\0&#39;).encode(&#39;utf-16le&#39;) data = bytes(pDrop) + file_bytes # 安全设置剪贴板 win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardData(win32clipboard.CF_HDROP, data) win32clipboard.CloseClipboard() return True except Exception as e: print(f&#39;剪贴板设置失败(尝试 {attempt+1}/{max_retries}): {e}&#39;) time.sleep(0.5) return False # ===== 窗口焦点保障 ===== def activate_wechat(): """激活并置顶微信窗口""" wechat = auto.WindowControl(ClassName=&#39;WeChatMainWndForPC&#39;, Name=wx_groupName) if wechat.Exists(): wechat.SetActive() wechat.SetTopmost() time.sleep(0.3) # 等待窗口响应 return True print("微信窗口未找到") return False # ===== 消息发送核心 ===== def send_msg(content, msg_type=1): """ 发送消息到微信 msg_type: 1=文本, 2=位, 3=文件路径(推荐) """ if not activate_wechat(): return False edit = auto.EditControl(Depth=9, ClassName=&#39;Edit&#39;) # 微信输入框控件 try: if msg_type == 1: # 文本 auto.SetClipboardText(content) time.sleep(0.2) elif msg_type == 2: # 位 auto.SetClipboardBitmap(auto.Bitmap.FromFile(content)) time.sleep(0.3) elif msg_type == 3: # 文件路径 if not safe_set_clipboard(content): return False time.sleep(0.3) # 粘贴并发送 edit.SendKeys(&#39;{Ctrl}v&#39;, waitTime=100) time.sleep(0.5) edit.SendKeys("{Enter}", waitTime=100) return True except Exception as e: print(f"消息发送失败: {e}") return False # ===== 处理函数 ===== def screenc(filename, num): """执行ADB截""" os.system(f&#39;adb -s {devices[filename][0]} exec-out screencap -p > {path}/{filename}_{num}.png&#39;) def crop(x1, y1, x2, y2, scFileName, svFileName): """像裁剪""" try: img = Image.open(scFileName) re = img.crop((x1, y1, x2, y2)) re.save(svFileName) img.close() return True except Exception as e: print(f"像裁剪失败: {e}") return False def LoadImage(img1, img2): """加载像为灰度""" i1 = cv2.imread(img1, 0) i2 = cv2.imread(img2, 0) return i1, i2 def IF_Img_I(src, mp): """ 像相似度检测 返回: (是否不同, 相似度分数) """ try: res = cv2.matchTemplate(src, mp, cv2.TM_CCOEFF_NORMED) _, mac_v, _, _ = cv2.minMaxLoc(res) # 相似度阈值公式: $T_s = 0.99 - \frac{1}{resolution}$ return mac_v < 0.98, mac_v except Exception as e: print(f"像匹配失败: {e}") return False, 0.0 # ===== 警报发送函数 ===== def SendGameMassage(tag): """在游戏内发送警报消息""" str1 = f&#39;adb -s {devices[tag][0]} &#39; taps = [ (211, 478), # 打开聊天 tuple(map(int, sendTo.split())), # 选择频道 (266, 520), # 点击输入框 (870, 511), # 点击发送 (68, 292), # 确认操作1 (250, 350), # 确认操作2 (250, 433), # 确认操作3 (344, 190), # 关闭弹窗 (342, 512) # 返回主界面 ] for tap in taps: os.system(str1 + f&#39;shell input tap {tap[0]} {tap[1]}&#39;) time.sleep(0.2) def SendWeChat(tag, num): """向微信发送警报""" img_path = f&#39;{path}/{tag}_{num}.png&#39; mutex.acquire() # 发送片(使用文件路径模式) send_result = send_msg(img_path, msg_type=3) # 发送文本 if send_result: context = f"{tag}{wx_context}" send_msg(context, msg_type=1) print(f"警报发送成功: {tag}") else: print(f"警报发送失败: {tag}") mutex.release() # ===== 监听核心 ===== def ship_detection(tag): """舰船列表检测子线程""" num = 0 while True: screenc(tag, 1) time.sleep(0.5) crop(918, 44, 956, 153, f&#39;{path}/{tag}_1.png&#39;, f&#39;{path}/new_{tag}_list.png&#39;) # 像差异检测 i3, i4 = LoadImage(f"{path}/new_{tag}_list.png", f"{path}/tem/list.png") list_status, list_mac_v = IF_Img_I(i3, i4) # 二次验证机制 if list_mac_v < 0.10 and list_mac_v != 0.0: if num < 1: num += 1 time.sleep(2) continue print(f&#39;{tag}检测到舰船列表变化 (相似度: {list_mac_v:.2f})&#39;) SendWeChat(tag, 1) i1, i2 = LoadImage(f"{path}/new_{tag}_playerList.png", f"{path}/old_{tag}_playerList.png") cv2.imwrite(f&#39;{path}/old_{tag}_playerList.png&#39;, i1) time.sleep(40) num = 0 def Listening(tag): """设备监听主循环""" # 启动舰船检测线程 threading.Thread(target=ship_detection, args=(tag,), daemon=True).start() # 主检测循环 while True: screenc(tag, 2) time.sleep(conVal + 0.35) crop(774, 502, 956, 537, f&#39;{path}/{tag}_2.png&#39;, f&#39;{path}/new_{tag}_playerList.png&#39;) # 加载并比较像 i1, i2 = LoadImage(f"{path}/new_{tag}_playerList.png", f"{path}/old_{tag}_playerList.png") list_status, list_mac_v = IF_Img_I(i1, i2) # 错误检测: 相似度过低 if list_mac_v <= 0.01: print(f&#39;{tag}系统故障,相似度过低&#39;) mutex.acquire() send_msg(f"{tag}系统故障,相似度{list_mac_v:.4f},即将下线", msg_type=1) mutex.release() time.sleep(3) os._exit(1) # 检测到显著变化 if list_status: print(f&#39;{tag}检测到本地警报 (相似度: {list_mac_v:.2f})&#39;) SendGameMassage(tag) SendWeChat(tag, 2) cv2.imwrite(f&#39;{path}/old_{tag}_playerList.png&#39;, i1) # ===== 初始化函数 ===== def Start(): """初始化程序""" # 重置片缓存 with open(f&#39;{path}/tem/list.png&#39;, &#39;rb&#39;) as sc1: con = sc1.read() for k in devices: with open(f&#39;{path}/new_{k}_list.png&#39;, &#39;wb&#39;) as f: f.write(con) with open(f&#39;{path}/tem/playerList.png&#39;, &#39;rb&#39;) as sc: con = sc.read() for k in devices: with open(f&#39;{path}/old_{k}_playerList.png&#39;, &#39;wb&#39;) as f: f.write(con) with open(f&#39;{path}/new_{k}_playerList.png&#39;, &#39;wb&#39;) as f: f.write(con) # 启动监听线程 for k in devices: t = threading.Thread(target=Listening, args=(k,)) t.daemon = True t.start() print(&#39;预警系统已启动&#39;) context = f"预警系统已上线,监测星系列表:\n{list(devices.keys())}" mutex.acquire() send_msg(context, msg_type=1) mutex.release() # ===== 主程序入口 ===== if __name__ == "__main__": if elevate_privileges(): Start() # 保持主线程运行 while True: time.sleep(3600) # 每小时检查一次 微信没有片和文字发送
10-13
D:\EVE_A_Eye-main\EVE_A_Eye>python main.py Traceback (most recent call last): File "D:\EVE_A_Eye-main\EVE_A_Eye\main.py", line 19, in <module> import matplotlib.pyplot as plt ModuleNotFoundError: No module named &#39;matplotlib&#39; import os import time import threading from PIL import Image, ImageFile, UnidentifiedImageError ImageFile.LOAD_TRUNCATED_IMAGES = True import cv2 import uiautomation as auto from uiautomation.uiautomation import Bitmap import win32clipboard import win32con from ctypes import * import pyautogui # -*- coding: utf-8 -*- import os import sys import time import numpy as np import cv2 import matplotlib.pyplot as plt from pyhalcon import * def qo2ul_device_monitoring_solution(): """ qo2ul设备异常监测完整解决方案 输入:实时采集的工业像 输出:相似度分析结果与异常定位 """ try: # 初始化Halcon环境 dev_open_window(0, 0, 800, 600, &#39;black&#39;, WindowHandle) set_system(&#39;use_window_thread&#39;, &#39;true&#39;) # === 1. 像采集与预处理 === # [引用1: 设备通信框架] grab_image(Image, AcqHandle) # 从工业相机捕获像 dev_display(Image) rgb1_to_gray(Image, GrayImage) # 转灰度 # === 2. 模板匹配核心算法 === # [引用3: Halcon模板匹配技术] gen_rectangle1(ROI, 100, 100, 400, 500) # 定义检测区域 reduce_domain(GrayImage, ROI, ImageReduced) create_shape_model(ImageReduced, 5, 0, 2*np.pi, &#39;auto&#39;, &#39;use_polarity&#39;, &#39;auto&#39;, &#39;auto&#39;, ModelID) # === 3. 异常检测与量化 === find_shape_model(GrayImage, ModelID, 0, 2*np.pi, 0.5, 1, 0.5, &#39;least_squares&#39;, 5, 0.9, Row, Column, Angle, Score) similarity = Score[0] # 获取主匹配得分 # === 4. 异常诊断处理流程 === if similarity < -0.6: # 阈值设定 # 视觉化异常区域 gen_cross(Cross, Row, Column, 25, Angle) area_holes(ImageReduced, Area) dev_set_color(&#39;red&#39;) dev_display(Cross) # 记录异常数据 [引用2: 监测系统集成] timestamp = time.strftime("%Y%m%d-%H%M%S") write_string(FileHandle, f&#39;{timestamp}, {similarity}, Abnormal\n&#39;) # 触发警报协议 set_alarm_light(&#39;red&#39;, &#39;blink&#39;) send_remote_alert(f&#39;ALERT: qo2ul异常 相似度{similarity}&#39;) return { &#39;status&#39;: &#39;FAIL&#39;, &#39;similarity&#39;: float(similarity), &#39;coordinates&#39;: (int(Row), int(Column)), &#39;timestamp&#39;: timestamp } else: return {&#39;status&#39;: &#39;PASS&#39;, &#39;similarity&#39;: float(similarity)} except Exception as e: # 错误处理模块 log_error(f&#39;[EXCEPTION] {str(e)}&#39;) return {&#39;status&#39;: &#39;ERROR&#39;, &#39;message&#39;: str(e)} finally: # 资源释放 clear_shape_model(ModelID) close_framegrabber(AcqHandle) if __name__ == "__main__": # 初始化工业相机 open_framegrabber(&#39;GigEVision&#39;, 0, 0, 0, 0, 0, 0, &#39;default&#39;, -1, &#39;default&#39;, -1, &#39;false&#39;, &#39;default&#39;, &#39;camera1&#39;, 0, -1, AcqHandle) # 创建监测日志 open_file(&#39;device_log.csv&#39;, &#39;append&#39;, FileHandle) write_string(FileHandle, "timestamp,similarity,status\n") # 持续监测循环 while True: result = qo2ul_device_monitoring_solution() print(f"当前状态: {result[&#39;status&#39;]} 相似度: {result.get(&#39;similarity&#39;, 0):.4f}") time.sleep(1) # 采样间隔 # 配置参数 wx_groupName = &#39;星海预警&#39; # 微信群名 wx_context = &#39;星系警告!!!出现红白,注意规避---赶紧跑,收你的来了&#39; # 微信消息 conVal = 2 # 执行间隔() path = &#39;D:/EVE_A_Eye-main/EVE_A_Eye&#39; # 主目录 # 确保目录存在 if not os.path.exists(path): os.makedirs(path) print(f"已创建目录: {path}") # 模拟器配置 - 新增了5558端口模拟器[^3] devices = { &#39;qo2ul&#39;: [&#39;127.0.0.1:5555&#39;, False], &#39;56&#39;: [&#39;127.0.0.1:5557&#39;, False], &#39;y5c&#39;: [&#39;127.0.0.1:5559&#39;, False] # 新增的59模拟器 } gameSendPosition = { &#39;第二频道&#39;: &#39;38 117&#39;, &#39;第三频道&#39;: &#39;38 170&#39;, &#39;第四频道&#39;: &#39;38 223&#39;, &#39;第五频道&#39;: &#39;38 278&#39;, &#39;第六频道&#39;: &#39;38 332&#39;, &#39;第七频道&#39;: &#39;38 382&#39; } sendTo = gameSendPosition[&#39;第六频道&#39;] mutex = threading.Lock() def setClipboardFile(img_path): """将片复制到剪贴板""" try: im = Image.open(img_path) temp_path = os.path.join(path, &#39;temp.bmp&#39;) im.save(temp_path) # 使用绝对路径加载片 aString = windll.user32.LoadImageW( 0, os.path.abspath(temp_path), win32con.IMAGE_BITMAP, 0, 0, win32con.LR_LOADFROMFILE ) if aString != 0: win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardData(win32con.CF_BITMAP, aString) win32clipboard.CloseClipboard() return True except (UnidentifiedImageError, FileNotFoundError) as e: print(f"剪贴板错误: {e}") return False def send_msg(content, msg_type=1): """发送微信消息""" try: wechatWindow = auto.WindowControl( searchDepth=1, Name=f"{wx_groupName}") wechatWindow.SetActive() edit = wechatWindow.EditControl() if msg_type == 1: # 文本 auto.SetClipboardText(content) edit.SendKeys(&#39;{Ctrl}v&#39;) edit.SendKeys(&#39;{Enter}&#39;) elif msg_type in [2, 3]: # 片 if setClipboardFile(content): edit.SendKeys(&#39;{Ctrl}v&#39;) edit.SendKeys(&#39;{Enter}&#39;) else: print(f"片发送失败: {content}") except Exception as e: print(f"微信消息发送异常: {e}") def Start(): """初始化程序""" # 确保目录存在 if not os.path.exists(path): os.makedirs(path) # 初始化片文件 template_dir = os.path.join(path, &#39;tem&#39;) os.makedirs(template_dir, exist_ok=True) # 创建占位文件 placeholder_files = [ (&#39;list.png&#39;, &#39;new_{}_list.png&#39;), (&#39;playerList.png&#39;, &#39;old_{}_playerList.png&#39;), (&#39;playerList.png&#39;, &#39;new_{}_playerList.png&#39;) ] for src, dest_pattern in placeholder_files: src_path = os.path.join(template_dir, src) if not os.path.exists(src_path): Image.new(&#39;RGB&#39;, (50, 50), color=&#39;black&#39;).save(src_path) for device in devices: # 为所有设备创建文件 dest_path = os.path.join(path, dest_pattern.format(device)) if not os.path.exists(dest_path): Image.open(src_path).save(dest_path) # 启动监听线程 - 每个设备独立线程[^3] for device in devices: t = threading.Thread(target=Listening, args=(device,)) t.start() print(&#39;预警系统已启动&#39;) context = f"预警系统已上线,监测星系列表:\n {list(devices.keys())}" send_msg(context, msg_type=1) def screenc(device_tag, num): """截取设备屏幕并保存到指定路径""" device_addr = devices[device_tag][0] filename = os.path.join(path, f"{device_tag}_{num}.png") # ADB截命令 - 支持多设备[^3] command = f&#39;adb -s {device_addr} exec-out screencap -p > "{filename}"&#39; os.system(command) # 验证截是否生成 if not os.path.exists(filename): print(f"截失败: {filename}") return False return True def crop(x1, y1, x2, y2, input_path, output_path): """裁剪片""" try: img = Image.open(input_path) cropped = img.crop((x1, y1, x2, y2)) cropped.save(output_path) img.close() return True except Exception as e: print(f"片裁剪错误: {e}") return False def LoadImage(img1, img2): """加载像""" try: i1 = cv2.imread(img1, 0) i2 = cv2.imread(img2, 0) return i1, i2 except Exception as e: print(f"像加载错误: {e}") return None, None def CompareImages(img1, img2): """像相似度比较""" try: res = cv2.matchTemplate(img1, img2, cv2.TM_CCOEFF_NORMED) _, max_val, _, _ = cv2.minMaxLoc(res) return max_val except: return 0.0 def SendGameMessage(device_tag): """游戏内发送消息""" addr = devices[device_tag][0] commands = [ &#39;shell input tap 211 478&#39;, f&#39;shell input tap {sendTo}&#39;, &#39;shell input tap 266 520&#39;, &#39;shell input tap 870 511&#39;, &#39;shell input tap 68 292&#39;, &#39;shell input tap 250 350&#39;, &#39;shell input tap 250 433&#39;, &#39;shell input tap 344 190&#39;, &#39;shell input tap 342 512&#39; ] for cmd in commands: os.system(f&#39;adb -s {addr} {cmd}&#39;) # 针对特定设备执行命令 time.sleep(0.2) def SendWeChat(device_tag): """发送微信预警""" if not wx_groupName: return img_path = os.path.join(path, f"{device_tag}_2.png") if not os.path.exists(img_path): print(f"预警片不存在: {img_path}") return mutex.acquire() try: # 发送片 send_msg(img_path, msg_type=3) print(f"已发送{device_tag}预警片") # 发送文本 context = f"{wx_context} - [{device_tag}]" send_msg(context, msg_type=1) finally: mutex.release() def Listening(device_tag): """监控线程 - 每个设备独立运行[^3]""" def secondary_task(): """二级检测任务""" while True: # 执行截 screenshot_path = os.path.join(path, f"{device_tag}_1.png") if not screenc(device_tag, 1): time.sleep(4) continue # 裁剪检测区域 list_img_path = os.path.join(path, f"new_{device_tag}_list.png") crop(918, 44, 956, 153, screenshot_path, list_img_path) # 加载比对像 template_path = os.path.join(path, "tem", "list.png") img_current = cv2.imread(list_img_path, 0) img_template = cv2.imread(template_path, 0) if img_current is None or img_template is None: time.sleep(2) continue # 像相似度检测 similarity = CompareImages(img_current, img_template) if similarity < 0.10: # 检测到舰船列表有人 print(f"{device_tag}监测异常 - 相似度: {similarity:.4f}") SendWeChat(device_tag) # 更新缓存 cv2.imwrite( os.path.join(path, f"old_{device_tag}_playerList.png"), img_current, [cv2.IMWRITE_PNG_COMPRESSION, 0] ) time.sleep(40) else: time.sleep(conVal) # 启动二级检测线程 threading.Thread(target=secondary_task).start() # 主检测循环 while True: # 执行截 screenshot_path = os.path.join(path, f"{device_tag}_2.png") if not screenc(device_tag, 2): time.sleep(conVal) continue # 裁剪玩家列表区域 player_img_path = os.path.join(path, f"new_{device_tag}_playerList.png") crop(774, 502, 956, 537, screenshot_path, player_img_path) # 加载比对像 img_current = cv2.imread(player_img_path, 0) img_cache = cv2.imread(os.path.join(path, f"old_{device_tag}_playerList.png"), 0) if img_current is None or img_cache is None: time.sleep(conVal) continue # 像相似度检测 similarity = CompareImages(img_current, img_cache) if similarity < 0.9: # 检测到本地频道变化 print(f"{device_tag}本地频道警告 - 相似度: {similarity:.4f}") SendGameMessage(device_tag) # 更新缓存 cv2.imwrite( os.path.join(path, f"old_{device_tag}_playerList.png"), img_current, [cv2.IMWRITE_PNG_COMPRESSION, 0] ) time.sleep(5) else: time.sleep(conVal) # 启动程序 if __name__ == "__main__": Start()
最新发布
10-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值