1 Star 0 Fork 0

tlq-github/TFT_assistant

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
core.py 7.63 KB
一键复制 编辑 原始数据 按行查看 历史
TLQ 提交于 2023-09-20 16:46 . 更改
from PyQt5.QtWidgets import QApplication, QMainWindow,QPushButton,QMessageBox
from PyQt5.QtCore import QFile, QTextStream, Qt
import keyboard
from PIL import ImageGrab
import time
import cv2
import numpy as np
import pyautogui
import sys
'''
真正的核心就是load_and_preprocess_templates()和capture_screen()一个是预先将处理好的模板进行加载,
然后最重要的就是capture_screen(),真正实现查找图片进行点击都在这个方法里面。
其他的都是一些pyqt5的一些初始化和设置,不重要,因为哪怕没有图形化窗口,有了上面两个方法也可以轻松实现。
'''
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.hero = []
self.csvlist = [] # 初始化 CSV 文件数据列表
self.template_images_gray = [] # 保存灰度处理后的模板图片
#self.screen_size=(480,1040,1480,1070)#设置一次截图的范围
self.screen_size = (480, 920, 1480, 1080) # 设置一次截图的范围
self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
self.load_ui()
self.apply_stylesheet()
self.setFixedSize(340, 450) # 设置窗口的固定大小
self.move_to_top_right()
self.cancel_button.clicked.connect(self.clear_group_edit)
self.group_edit.textChanged.connect(self.group_edit_text_changed)
self.ok_checkbox.toggled.connect(self.update_object_list)
self.init_ui()
self.load_txt_data() # 读取文本文件数据并保存到 self.csvlist
self.show()
# 监听全局快捷键 f12
keyboard.add_hotkey('f12', self.toggle_window)
keyboard.add_hotkey('d', self.capture_screen)
def load_ui(self):
from PyQt5.uic import loadUi
loadUi('ui/云顶.ui', self)
def init_ui(self):
#搜索控件
self.button = self.findChild(QPushButton, 'exit_button')
# 绑定方法
self.button.clicked.connect(self.close_app)
def clear_group_edit(self):
self.group_edit.clear()
def group_edit_text_changed(self):
self.ok_checkbox.setChecked(False)
def load_txt_data(self):
with open(r'D:\云顶之弈辅助源码\hero.txt', 'r', encoding='utf-8') as txtfile:
for line in txtfile:
heroes = line.strip().split(',')
self.csvlist.extend(heroes)
def update_object_list(self, checked):
if checked:
text = self.group_edit.toPlainText()
objects = [item.strip() for item in text.split(',')]
invalid_heroes = [hero for hero in objects if hero not in self.csvlist]
if invalid_heroes:
error_message = "以下英雄名错误,请重新输入:\n\n"
for hero in invalid_heroes:
error_message += f"错误英雄名:{hero}\n"
QMessageBox.warning(self, "错误提示", error_message)
else:
self.hero = objects
self.load_and_preprocess_templates(self.hero)
def apply_stylesheet(self):
style_file = QFile('D:\云顶之弈辅助源码\style.qss')
if style_file.open(QFile.ReadOnly | QFile.Text):
stream = QTextStream(style_file)
self.setStyleSheet(stream.readAll())
style_file.close()
def move_to_top_right(self):
screen_geometry = QApplication.desktop().availableGeometry()
window_geometry = self.geometry()
top_right = screen_geometry.topRight() - window_geometry.topRight()
self.move(top_right)
def close_app(self):
self.close()
def toggle_window(self):
if self.isVisible():
self.hide()
else:
self.show()
self.raise_() # 窗口置于顶层,不过我已经将窗口置于顶层,这里可以不用了。
# if not self.ok_checkbox.isChecked():
# return
def capture_screen(self):
#检查选择框是否已经勾选,没勾选就不执行
if not self.ok_checkbox.isChecked():
return
time.sleep(0.1)
#进行截屏
screenshot = ImageGrab.grab(bbox=self.screen_size)
#对截图进行灰度处理
screenshot_gray = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2GRAY)
#设置模板匹配的阈值
threshold = 0.9
click_delay = 0.5
max_offset = 10
clicked_template = [] # 保存可以点击的坐标点
template_centers = [] # 保存模板的中心
#将预先加载的图片模板在截图中进行匹配
for idx, template_gray in enumerate(self.template_images_gray):
#下面是对模板进行匹配再将模板的位置转换成numpy数组,方便进行计算
result = cv2.matchTemplate(screenshot_gray, template_gray, cv2.TM_CCOEFF_NORMED)
locations = np.where(result >= threshold)
matches = list(zip(*locations[::-1]))
for match in matches:
top_left = match
h, w = template_gray.shape
# 计算模板中心
template_center = (top_left[0] + w // 2, top_left[1] + h // 2)
template_centers.append(template_center)
# 下面两个内置方法是组合起来做一个递归,因为我发现匹配出来的模板实在太多,而且点之间的距离不会超过10,我直接取巧,使用x轴距离进行计算。
def calculate_distance(p1, p2):
return abs(p1[0] - p2[0])
def cluster_points(points, threshold):
if not points:
return []
current_point = points[0]
cluster = current_point
remaining_points = []
for p in points[1:]:
if calculate_distance(current_point, p) >= threshold:
remaining_points.append(p)
next_cluster = cluster_points(remaining_points, threshold)
return [cluster] + next_cluster
# 定义阈值
threshold = 20
# 进行基于距离的聚类,调用上面的两个内置方法
clusters = cluster_points(template_centers, threshold)
screen_width, screen_height = pyautogui.size()
#因为匹配会有多张图片,因此循环获取坐标进行点击
for point in clusters:
x, y = point
screen_x = x + self.screen_size[0] # 将截图的x坐标转换为屏幕上的x坐标
screen_y = y + self.screen_size[1] # 将截图的y坐标转换为屏幕上的y坐标
# 确保点击位置在屏幕范围内
screen_x = max(0, min(screen_x, screen_width))
screen_y = max(0, min(screen_y, screen_height))
pyautogui.moveTo(screen_x, screen_y, duration=0.1)
time.sleep(0.1)
pyautogui.click(clicks=2, interval=0.25)# 双击,间隔0.25s
pyautogui.moveTo(1000, 600, duration=0.1)
time.sleep(0.2)
def load_and_preprocess_templates(self, template_names):
#将要匹配的模板预先加载,避免重复读取。
self.template_images_gray = []
for name in template_names:
template_path = rf"D:\云顶之弈辅助源码\hero_gray\{name}.png"
# opencv不支持中文,麻烦死了,只能先转numpy再转回去。
# 使用numpy.fromfile和cv2.imdecode代替cv2.imread
template_image = cv2.imdecode(np.fromfile(template_path, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
self.template_images_gray.append(template_image)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/tlq-github/TFT_assistant.git
git@gitee.com:tlq-github/TFT_assistant.git
tlq-github
TFT_assistant
TFT_assistant
master

搜索帮助