Compare commits

...

2 commits

Author SHA1 Message Date
0b1043b849 返回首页优化,避免公告场景与退出游戏同时触发时返回信号失效
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-21 11:28:02 +08:00
8eee4520bf 节点相关方法补充优化
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-19 17:42:11 +08:00
6 changed files with 103 additions and 24 deletions

BIN
mower/resources/rogue/node_Sarkaz/狭路相逢.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -1,5 +1,6 @@
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.image import cmatch, cropimg, loadres
from .utils import template
@ -17,6 +18,7 @@ node_type = {
"思维边界",
"先行一步",
"兴致盎然",
"狭路相逢",
"Boss",
]
}
@ -25,25 +27,32 @@ node_type = {
class Node:
def __init__(self, scope):
self.scope: tp.Scope = scope # 节点范围
self.status = False # 是否为下一步可前往的节点
self.next_nodes = [] # 可前往的下一个节点
self.detect_type()
def detect_type(self):
for type in node_type[config.conf.maa_rg_theme]:
res_name = f"rogue/node_{config.conf.maa_rg_theme}/{type}"
res = loadres(res_name)
match_scope = (
(self.scope[0][0] + 50, self.scope[1][0]),
(self.scope[0][1] - 50, self.scope[1][1]),
)
score, scope = template(scene_image, res_name, self.scope)
score, scope = template(scene_image, res, self.scope)
if score > 0.75:
self.type = type
self.type_scope = scope
# 用平均色判断可否前往
img = cropimg(scene_image, scope)
if cmatch(img, res) and self.type != "Boss":
self.status = True
return
self.type = "未知"
self.type_scope = match_scope
nodes: dict[str, Node] = {}
current_layer = 0
scene_image = None
nodes: dict[str, Node] = {} # 节点编号:节点对象
next_step: dict[str, int] = {} # 节点编号:剩余刷新次数
current_layer = 0 # 当前层数
scene_image = None # 整层的图像

View file

@ -2,9 +2,10 @@ import cv2
import numpy as np
from mower.solvers.rogue import data
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.image import thres2
from mower.utils.vector import in_scope
from mower.utils.image import cropimg, loadres, thres2
from mower.utils.vector import in_scope, sa, vs
from .utils import template
@ -17,6 +18,7 @@ class NodeDetector:
self.detect_nodes()
self.detect_x_edges()
self.detect_y_edges()
self.check_next_step()
def merge_rectangles(self, rects: list):
"合并有重叠的矩形"
@ -141,7 +143,24 @@ class NodeDetector:
data.nodes[next_id].type_scope[0][1],
),
)
score, _ = template(data.scene_image, "rogue/y_edge", scope)
res = loadres("rogue/y_edge")
score, _ = template(data.scene_image, res, scope)
if score > 0.7:
data.nodes[node_id].next_nodes.append(next_id)
data.nodes[next_id].next_nodes.append(node_id)
def check_next_step(self):
for node_id in data.nodes:
if data.nodes[node_id].status:
data.next_step[node_id] = 2
def check_node_in_screen(self, node_id: str) -> tp.Scope | None:
score, scope = template(
data.scene_image, cropimg(config.recog.img, ((0, 150), (1920, 880)))
)
node_scope = data.nodes[node_id].scope
if in_scope(scope, node_scope[0]) and in_scope(scope, node_scope[1]):
res_scope = vs(node_scope[0], scope[0]), vs(node_scope[1], scope[0])
res_scope = sa(res_scope, (0, 150))
return res_scope
return None

View file

@ -5,7 +5,7 @@ import cv2
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.generate_image import generate_image
from mower.utils.image import cropimg, loadres
from mower.utils.image import cropimg
from mower.utils.log import logger
@ -21,17 +21,17 @@ def find_text(text: str, size: int, threshold: float = 0.8) -> tp.Coordinate | N
def template(
image: tp.Image, res: str, scope: Optional[tp.Scope] = None
img1: tp.Image, img2: tp.Image, scope: Optional[tp.Scope] = None
) -> Tuple[float, tp.Scope]:
"全景图中找模板"
"img1中模板匹配img2"
try:
logger.debug(f"{res=}")
template = loadres(res)
h, w, _ = template.shape
h, w, _ = img2.shape
if scope:
x, y = scope[0]
img = cropimg(image, scope)
result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
img1 = cropimg(img1, scope)
else:
x, y = (0, 0)
result = cv2.matchTemplate(img1, img2, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
score = max_val
p1 = (max_loc[0] + x, max_loc[1] + y)

View file

@ -1,5 +1,5 @@
import cv2
from matplotlib import pyplot as plt
import numpy as np
from mower.solvers.rogue import data
from mower.utils import config
@ -26,12 +26,51 @@ class WholeScene(BaseSolver):
logger.error(f"拼接过程中出现错误: {e}")
raise
def get_whole_scene(self):
def horizontal_stitch(self, images: list) -> np.ndarray:
"""
水平方向拼接多张图像利用重叠区域对齐
"""
# 初始化最终拼接结果为第一张图像
stitched_image = images[0]
for i in range(1, len(images)):
# 当前图像和已拼接的图像
prev_img = stitched_image
curr_img = images[i]
# 转为灰度图,用于计算重叠区域
gray_prev = cv2.cvtColor(prev_img, cv2.COLOR_RGB2GRAY)
gray_curr = cv2.cvtColor(curr_img, cv2.COLOR_RGB2GRAY)
# 匹配 prev_img 的右侧区域和 curr_img 的左侧区域
match_width = min(
800, gray_prev.shape[1]
) # 假设重叠区域宽度最大为 800 像素
prev_region = gray_prev[:, -match_width:] # 取 prev_img 的右侧区域
result = cv2.matchTemplate(
gray_curr, prev_region, method=cv2.TM_CCOEFF_NORMED
)
_, _, _, max_loc = cv2.minMaxLoc(result)
overlap_x = max_loc[0] # 获取匹配的 x 坐标
# 校验重叠区域的合理性
if overlap_x >= 0 and overlap_x < curr_img.shape[1]:
# 拼接:保留 curr_img 中非重叠部分
non_overlap_part = curr_img[:, overlap_x + match_width :]
stitched_image = np.hstack((prev_img, non_overlap_part))
else:
logger.info("未检测到有效的重叠区域,直接拼接当前图像")
stitched_image = np.hstack((prev_img, curr_img))
return stitched_image
def get_whole_scene(self, draw=False):
images = []
new = cropimg(config.recog.img, ((0, 150), (1920, 880)))
images.append(new)
while True:
self.swipe_ext([(1820, 870), (1400, 870)], [200], 400, 0.1)
self.swipe_ext([(1820, 870), (1000, 870)], [200], 400, 0.1)
new = cropimg(config.recog.img, ((0, 150), (1920, 880)))
gray1 = cv2.cvtColor(new, cv2.COLOR_RGB2GRAY)
gray2 = cv2.cvtColor(images[-1], cv2.COLOR_RGB2GRAY)
@ -42,10 +81,15 @@ class WholeScene(BaseSolver):
logger.info("滑到底了")
break
logger.info(f"截图读取完了,有{len(images)}张截图")
for img in images:
plt.imshow(img)
plt.show()
if len(images) > 1:
data.scene_image = self.stitch_images(images)
data.scene_image = self.horizontal_stitch(images)
else:
data.scene_image = images[0]
if draw:
from matplotlib import pyplot as plt
for img in images:
plt.imshow(img)
plt.show()
plt.imshow(data.scene_image)
plt.show()

View file

@ -29,10 +29,14 @@ from .utils import edge
@edge(Scene.SIGN_IN_DAILY, Scene.INDEX)
@edge(Scene.INDEX_ORIGINITE, Scene.INDEX)
@edge(Scene.INDEX_SANITY, Scene.INDEX)
@edge(Scene.ANNOUNCEMENT, Scene.INDEX)
@edge(Scene.SIGN_IN_ORUNDUM, Scene.INDEX)
def back_to_index(solver: BaseSolver):
solver.back()
solver.cback(1, id="back_to_index")
@edge(Scene.ANNOUNCEMENT, Scene.INDEX)
def close_announcement(solver: BaseSolver):
solver.ctap("announcement_close", 3)
@edge(Scene.LEAVE_INFRASTRUCTURE, Scene.INDEX)