Skip to content

Commit

Permalink
#172 增加列式录制大地图
Browse files Browse the repository at this point in the history
  • Loading branch information
DoctorReid committed Feb 8, 2024
1 parent dda13d3 commit eb72743
Showing 1 changed file with 173 additions and 93 deletions.
266 changes: 173 additions & 93 deletions src/sr/app/large_map_recorder.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import time

from cv2.typing import MatLike

from basic import Point
from basic.img import cv2_utils
from basic.log_utils import log
from sr.app import Application, Application2
from sr.app import Application2
from sr.const import map_const
from sr.const.map_const import Region, region_with_another_floor, PLANET_2_REGION
from sr.context import Context, get_context
from sr.image.cv2_matcher import CvImageMatcher
from sr.image.image_holder import ImageHolder
from sr.image.sceenshot import large_map
from sr.operation import Operation, StateOperationNode
from sr.operation import Operation, StateOperationNode, OperationOneRoundResult
from sr.operation.unit.choose_planet import ChoosePlanet
from sr.operation.unit.choose_region import ChooseRegion
from sr.operation.unit.open_map import OpenMap
from sr.operation.unit.scale_large_map import ScaleLargeMap
from sr.win import Window, WinRect
Expand All @@ -25,103 +24,81 @@ class LargeMapRecorder(Application2):
"""

def __init__(self, ctx: Context, region: Region, way: int = 1):
edges = []
nodes = []

open_map = StateOperationNode('打开地图', op=OpenMap(ctx))
nodes.append(StateOperationNode('打开地图', op=OpenMap(ctx)))
nodes.append(StateOperationNode('缩放地图', op=ScaleLargeMap(ctx, -5)))
nodes.append(StateOperationNode('选择星球', op=ChoosePlanet(ctx, region.planet)))
nodes.append(StateOperationNode('截图', self._do_screenshot))
nodes.append(StateOperationNode('保存', self._do_save))

super().__init__(ctx)
self.planet = region.planet
self.region = region
super().__init__(ctx, op_name='大地图录制 %s' % region.cn,
nodes=nodes)

def _execute_one_round(self) -> bool:
"""
先拉到最左上角 然后一行一行地截图 最后再拼接起来。
多层数的话需要一次性先将所有楼层截图再处理 保证各楼层大小一致
:return:
"""
region_list = []
for l in [-1, 0, 1, 2, 3]:
region = region_with_another_floor(self.region, l)
if region is not None:
region_list.append(region)
self.region: Region = region
self.current_floor: int = -1
self.raw_image: dict[str, MatLike] = {}
self.way: int = way

raw_img = {}
def _init_before_execute(self):
super()._init_before_execute()
self.current_floor = -1
self.raw_image = {}

ops = [OpenMap(ctx), ScaleLargeMap(ctx, -5)]
if not self.run_ops(ops):
return False
def _do_screenshot(self) -> OperationOneRoundResult:
if self.current_floor > 3:
return Operation.round_success()

for region in region_list:
ops = [ChoosePlanet(ctx, region.planet), ChooseRegion(ctx, region)]
if not self.run_ops(ops):
return False
region = region_with_another_floor(self.region, self.current_floor)
self.current_floor += 1

win: Window = self.ctx.controller.win
rect: WinRect = win.get_win_rect()
if region is None:
return Operation.round_wait()

center = Point(rect.w // 2, rect.h // 2)
for _ in range(2):
self.ctx.controller.drag_to(end=Point(rect.w, rect.h), start=center, duration=1) # 先拉到左上角
time.sleep(1)
img = []
for i in range(10):
if not self.ctx.running:
return False
row_img = self.screenshot_horizontally(center) # 对一行进行水平的截图
cv2_utils.show_image(row_img, win_name='row %d' % i)
if len(img) == 0 or not cv2_utils.is_same_image(img[len(img) - 1], row_img):
img.append(row_img)
self.ctx.controller.drag_to(end=Point(center.x, center.y - 200), start=center, duration=1) # 往下拉一段
time.sleep(1)
self.ctx.controller.drag_to(end=Point(rect.w, center.y), start=center, duration=1) # 往左拉到尽头
time.sleep(1)
self.ctx.controller.drag_to(end=Point(rect.w, center.y), start=center, duration=1) # 往左拉到尽头
time.sleep(1)
else:
break
if self.way == 1:
self._do_screenshot_1(region)

merge = img[0]
for i in range(len(img)):
if i == 0:
merge = img[i]
else:
merge = cv2_utils.concat_vertically(merge, img[i], decision_height=large_map.CUT_MAP_RECT.y2 - large_map.CUT_MAP_RECT.y1 - 300)
return Operation.round_wait()

raw_img[region.prl_id] = merge
cv2_utils.show_image(merge, win_name='region.prl_id')
def _do_screenshot_1(self, region: Region):
"""
先拉到最左上角 然后一行一行地截图 最后再拼接起来。
多层数的话需要一次性先将所有楼层截图再处理 保证各楼层大小一致
:return:
"""
win: Window = self.ctx.controller.win
rect: WinRect = win.get_win_rect()

# 检测几个楼层是否大小一致
shape = None
lp, rp, tp, bp = None, None, None, None
for region in region_list:
raw = raw_img[region.prl_id]
if shape is None:
shape = raw.shape
center = Point(rect.w // 2, rect.h // 2)
for _ in range(2):
self.ctx.controller.drag_to(end=Point(rect.w, rect.h), start=center, duration=1) # 先拉到左上角
time.sleep(1)
img = []
for i in range(10):
if not self.ctx.running:
return False
row_img = self.screenshot_horizontally(center) # 对一行进行水平的截图
cv2_utils.show_image(row_img, win_name='row %d' % i)
if len(img) == 0 or not cv2_utils.is_same_image(img[len(img) - 1], row_img):
img.append(row_img)
self.ctx.controller.drag_to(end=Point(center.x, center.y - 200), start=center, duration=1) # 往下拉一段
time.sleep(1)
self.ctx.controller.drag_to(end=Point(rect.w, center.y), start=center, duration=1) # 往左拉到尽头
time.sleep(1)
self.ctx.controller.drag_to(end=Point(rect.w, center.y), start=center, duration=1) # 往左拉到尽头
time.sleep(1)
else:
shape2 = raw.shape
if shape[0] != shape2[0] or shape[1] != shape2[1]:
log.error('层数截图大小不一致')

# 不同楼层需要拓展的大小可能不一致 保留一个最大的
lp2, rp2, tp2, bp2 = large_map.get_expand_arr(raw)
if lp is None or lp2 > lp:
lp = lp2
if rp is None or rp2 > rp:
rp = rp2
if tp is None or tp2 > tp:
tp = tp2
if bp is None or bp2 > bp:
bp = bp2

# cv2.waitKey(0)
break

for region in region_list:
raw = raw_img[region.prl_id]
large_map.save_large_map_image(raw, region, 'raw')
large_map.init_large_map(region, raw, self.ctx.im,
expand_arr=[lp, rp, tp, bp], save=True)
merge = img[0]
for i in range(len(img)):
if i == 0:
merge = img[i]
else:
merge = cv2_utils.concat_vertically(merge, img[i], decision_height=large_map.CUT_MAP_RECT.y2 - large_map.CUT_MAP_RECT.y1 - 300)

return Operation.SUCCESS
self.raw_image[region.prl_id] = merge
cv2_utils.show_image(merge, win_name='region.prl_id')

def screenshot_horizontally(self, center):
"""
Expand Down Expand Up @@ -153,12 +130,115 @@ def screenshot_horizontally(self, center):
merge = cv2_utils.concat_horizontally(merge, img[i])
return merge

def run_ops(self, ops) -> bool:
for op in ops:
if not op.execute().success:
log.error('前置打开地图失败')
def _do_screenshot_2(self, region: Region):
"""
先拉到最左上角 然后一列一列地截图 最后再拼接起来。
多层数的话需要一次性先将所有楼层截图再处理 保证各楼层大小一致
:return:
"""
win: Window = self.ctx.controller.win
rect: WinRect = win.get_win_rect()

center = Point(rect.w // 2, rect.h // 2)
for _ in range(2):
self.ctx.controller.drag_to(end=Point(rect.w, rect.h), start=center, duration=1) # 先拉到左上角
time.sleep(1)
img = []
for i in range(10):
if not self.ctx.running:
return False
return True
row_img = self.screenshot_vertically(center) # 对一列进行垂直的截图
cv2_utils.show_image(row_img, win_name='row %d' % i)
if len(img) == 0 or not cv2_utils.is_same_image(img[len(img) - 1], row_img):
img.append(row_img)
self.ctx.controller.drag_to(end=Point(center.x, center.y - 200), start=center, duration=1) # 往右拉一段
time.sleep(1)
for _ in range(2):
self.ctx.controller.drag_to(end=Point(center.x, rect.h), start=center, duration=1) # 往上拉到尽头
time.sleep(1)
else:
break

merge = img[0]
for i in range(len(img)):
if i == 0:
merge = img[i]
else:
merge = cv2_utils.concat_horizontally(merge, img[i], decision_width=large_map.CUT_MAP_RECT.x2 - large_map.CUT_MAP_RECT.x1 - 300)

self.raw_image[region.prl_id] = merge
cv2_utils.show_image(merge, win_name='region.prl_id')

def screenshot_vertically(self, center):
"""
垂直滚动地截取地图部分 然后拼接在一起
:param center: 中心点
:return: 拼接好的图片
"""
img = []
# 每秒往右拉一段距离截图
for i in range(10):
if not self.ctx.running:
return
screen = self.screenshot()
map_part = cv2_utils.crop_image_only(screen, large_map.CUT_MAP_RECT)
print(map_part.shape)
cv2_utils.show_image(map_part, win_name='screenshot_vertically_map_part')
if len(img) == 0 or not cv2_utils.is_same_image(img[len(img) - 1], map_part):
img.append(map_part)
self.ctx.controller.drag_to(end=Point(center.x, center.y - 200), start=center, duration=1) # 往下拉一段
time.sleep(1)
else:
break

merge = img[0]
for i in range(len(img)):
if i == 0:
merge = img[i]
else:
merge = cv2_utils.concat_vertically(merge, img[i])
return merge

def _do_save(self) -> OperationOneRoundResult:
# 检测几个楼层是否大小一致
shape = None
lp, rp, tp, bp = None, None, None, None
for l in [-1, 0, 1, 2, 3]:
target_region = region_with_another_floor(self.region, l)
if target_region is None:
continue

raw = self.raw_image[target_region.prl_id]
if shape is None:
shape = raw.shape
else:
shape2 = raw.shape
if shape[0] != shape2[0] or shape[1] != shape2[1]:
log.error('层数截图大小不一致')

# 不同楼层需要拓展的大小可能不一致 保留一个最大的
lp2, rp2, tp2, bp2 = large_map.get_expand_arr(raw)
if lp is None or lp2 > lp:
lp = lp2
if rp is None or rp2 > rp:
rp = rp2
if tp is None or tp2 > tp:
tp = tp2
if bp is None or bp2 > bp:
bp = bp2

# cv2.waitKey(0)

for l in [-1, 0, 1, 2, 3]:
target_region = region_with_another_floor(self.region, l)
if target_region is None:
continue
raw = self.raw_image[target_region.prl_id]
large_map.save_large_map_image(raw, target_region, 'raw')
large_map.init_large_map(target_region, raw, self.ctx.im,
expand_arr=[lp, rp, tp, bp], save=True)

return Operation.round_success()


def _init_map_for_sim_uni():
Expand Down

0 comments on commit eb72743

Please sign in to comment.