开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
1 Star 2 Fork 1

keyle_xiao/模拟人类自动化点击屏幕流程工具

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
main
分支 (25)
标签 (10)
main
codex/修复readme链接错误
rstmym-codex/fix-action-file-issues-with-pip-install
codex/fix-action-file-issues-with-pip-install
codex/修复readme链接错误和缺失库引用
www3x8-codex/fix-git-push-rejection-issue-in-action
codex/fix-git-push-rejection-issue-in-action
codex/创建github-action进行打包并更新readme
codex/更新readme文件,增加使用说明及免责声明
codex/确认子项延迟功能符合描述
codex/修复鼠标长按问题
codex/修复长按功能问题
codex/修复长按功能和子项延迟
codex/移除搜索过程中窗体缩短逻辑
codex/修复窗体尺寸问题并更新设置面板
codex/修复红点定位问题冲突
codex/解决代码冲突并修改设置面板功能
codex/修复红点定位问题
codex/fix-pyautogui-fail-safe-exception
codex/修复红点无法点击移动的问题
build-12
build-13
build-11
build-10
build-9
build-8
build-7
build-5
build-1
build-2
main
分支 (25)
标签 (10)
main
codex/修复readme链接错误
rstmym-codex/fix-action-file-issues-with-pip-install
codex/fix-action-file-issues-with-pip-install
codex/修复readme链接错误和缺失库引用
www3x8-codex/fix-git-push-rejection-issue-in-action
codex/fix-git-push-rejection-issue-in-action
codex/创建github-action进行打包并更新readme
codex/更新readme文件,增加使用说明及免责声明
codex/确认子项延迟功能符合描述
codex/修复鼠标长按问题
codex/修复长按功能问题
codex/修复长按功能和子项延迟
codex/移除搜索过程中窗体缩短逻辑
codex/修复窗体尺寸问题并更新设置面板
codex/修复红点定位问题冲突
codex/解决代码冲突并修改设置面板功能
codex/修复红点定位问题
codex/fix-pyautogui-fail-safe-exception
codex/修复红点无法点击移动的问题
build-12
build-13
build-11
build-10
build-9
build-8
build-7
build-5
build-1
build-2
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
main
分支 (25)
标签 (10)
main
codex/修复readme链接错误
rstmym-codex/fix-action-file-issues-with-pip-install
codex/fix-action-file-issues-with-pip-install
codex/修复readme链接错误和缺失库引用
www3x8-codex/fix-git-push-rejection-issue-in-action
codex/fix-git-push-rejection-issue-in-action
codex/创建github-action进行打包并更新readme
codex/更新readme文件,增加使用说明及免责声明
codex/确认子项延迟功能符合描述
codex/修复鼠标长按问题
codex/修复长按功能问题
codex/修复长按功能和子项延迟
codex/移除搜索过程中窗体缩短逻辑
codex/修复窗体尺寸问题并更新设置面板
codex/修复红点定位问题冲突
codex/解决代码冲突并修改设置面板功能
codex/修复红点定位问题
codex/fix-pyautogui-fail-safe-exception
codex/修复红点无法点击移动的问题
build-12
build-13
build-11
build-10
build-9
build-8
build-7
build-5
build-1
build-2
AutoClick
/
KeyleFinderModule.py
AutoClick
/
KeyleFinderModule.py
KeyleFinderModule.py 6.90 KB
一键复制 编辑 原始数据 按行查看 历史
keylexiao 提交于 2025年06月05日 22:45 +08:00 . no message
import json
try:
import cv2
except ImportError as exc:
raise ImportError(
"OpenCV is required for KeyleFinderModule. Install it with 'pip install opencv-python-headless'."
) from exc
import numpy as np
class KeyleFinderModule:
"""Locate a sub-image within a big image using ORB feature matching."""
def __init__(self, big_image_path: str):
self.big_image = cv2.imread(big_image_path)
@staticmethod
def _draw_multiline_text(img, text, org, font, scale, color, thickness=1, line_type=cv2.LINE_AA):
if text is None:
return
x, y = org
max_width = img.shape[1] - x - 10
current = ""
lines = []
for ch in text:
if ch == "\n":
lines.append(current)
current = ""
continue
size = cv2.getTextSize(current + ch, font, scale, thickness)[0][0]
if size > max_width and current:
lines.append(current)
current = ch
else:
current += ch
if current:
lines.append(current)
line_height = cv2.getTextSize("A", font, scale, thickness)[0][1] + 5
for idx, ln in enumerate(lines):
cv2.putText(img, ln, (x, y + idx * line_height), font, scale, color, thickness, line_type)
def _show_preview(self, single_image=None, dst_points=None, angle=None, scale=None, label=None, transform=None, found=True):
preview = self.big_image.copy()
if found and dst_points is not None and single_image is not None:
cv2.polylines(preview, [np.int32(dst_points)], True, (0, 255, 0), 2)
h, w = single_image.shape[:2]
if transform is None:
if angle is None:
dx = dst_points[1][0] - dst_points[0][0]
dy = dst_points[1][1] - dst_points[0][1]
angle = np.degrees(np.arctan2(dy, dx))
if scale is None:
dst_w = np.linalg.norm(dst_points[1] - dst_points[0])
dst_h = np.linalg.norm(dst_points[3] - dst_points[0])
scale_x = dst_w / w
scale_y = dst_h / h
scale = (scale_x + scale_y) / 2.0
dst_center = tuple(np.mean(dst_points, axis=0))
transform = cv2.getRotationMatrix2D((w / 2, h / 2), angle, scale)
transform[0, 2] += dst_center[0] - w / 2
transform[1, 2] += dst_center[1] - h / 2
overlay = cv2.warpAffine(single_image, transform, (self.big_image.shape[1], self.big_image.shape[0]))
gray = cv2.cvtColor(overlay, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)
inv_mask = cv2.bitwise_not(mask)
bg = cv2.bitwise_and(preview, preview, mask=inv_mask)
fg = cv2.bitwise_and(overlay, overlay, mask=mask)
preview = cv2.add(bg, fg)
center = tuple(np.mean(dst_points, axis=0).astype(int))
cv2.drawMarker(preview, center, (255, 0, 0), cv2.MARKER_CROSS, 20, 2)
if label is not None:
self._draw_multiline_text(preview, label, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
else:
text = "Match failed" if label is None else label
self._draw_multiline_text(preview, text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.imshow('Located Image', preview)
cv2.waitKey(0)
cv2.destroyAllWindows()
def _match_feature(self, single_image_path):
single_image = cv2.imread(single_image_path)
if single_image is None or self.big_image is None:
return None
single_gray = cv2.cvtColor(single_image, cv2.COLOR_BGR2GRAY)
big_gray = cv2.cvtColor(self.big_image, cv2.COLOR_BGR2GRAY)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(single_gray, None)
kp2, des2 = orb.detectAndCompute(big_gray, None)
if des1 is None or des2 is None:
return None
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append(m)
if len(good) < 4:
return None
src_pts = np.float32([kp1[m.queryIdx].pt for m in good])
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good])
M, _ = cv2.estimateAffinePartial2D(src_pts, dst_pts, method=cv2.RANSAC)
if M is None:
return None
h, w = single_gray.shape
pts = np.float32([[0, 0], [w - 1, 0], [w - 1, h - 1], [0, h - 1]])
dst = cv2.transform(pts[None, :, :], M)[0]
x_coords = dst[:, 0]
y_coords = dst[:, 1]
top_left = (int(min(x_coords)), int(min(y_coords)))
bottom_right = (int(max(x_coords)), int(max(y_coords)))
angle = float(np.degrees(np.arctan2(M[1, 0], M[0, 0])))
scale = float(np.sqrt(M[0, 0] ** 2 + M[1, 0] ** 2))
return top_left, bottom_right, angle, scale, single_image, dst.reshape(4, 2), M
def _match_template(self, single_image_path, threshold: float = 0.8):
"""Fallback template matching when feature matching fails."""
single_image = cv2.imread(single_image_path)
if single_image is None or self.big_image is None:
return None
result = cv2.matchTemplate(self.big_image, single_image, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val < threshold:
return None
h, w = single_image.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
dst = np.float32([
[top_left[0], top_left[1]],
[top_left[0] + w - 1, top_left[1]],
[top_left[0] + w - 1, top_left[1] + h - 1],
[top_left[0], top_left[1] + h - 1],
])
transform = np.float32([[1, 0, top_left[0]], [0, 1, top_left[1]]])
return top_left, bottom_right, 0.0, 1.0, single_image, dst, transform
def locate(self, sub_image_path: str, debug: bool = False):
match = self._match_feature(sub_image_path)
if match is None:
match = self._match_template(sub_image_path)
if match is None:
result = {"status": 1}
if debug:
self._show_preview(label=json.dumps(result, ensure_ascii=False), found=False)
return result
top_left, bottom_right, angle, scale, img, pts, M = match
result = {
"status": 0,
"top_left": [top_left[0], top_left[1]],
"bottom_right": [bottom_right[0], bottom_right[1]],
"scale": scale,
}
if debug:
self._show_preview(img, pts, angle, scale, label=json.dumps(result, ensure_ascii=False), transform=M, found=True)
return result
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

简介

模拟人类自动化点击屏幕流程工具,基于 ORB 的特征匹配,失败时回退到模板匹配,本工具旨在加速自动化调试,请勿将其用于任何非法用途。
暂无标签
MIT
使用 MIT 开源许可协议
取消

发行版

暂无发行版

贡献者

全部

语言

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/keyle/AutoClick.git
git@gitee.com:keyle/AutoClick.git
keyle
AutoClick
模拟人类自动化点击屏幕流程工具
main
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /