diff --git a/mower/solvers/fight/auto_fight.py b/mower/solvers/fight/auto_fight.py index 29fdf1a..56f75ab 100644 --- a/mower/solvers/fight/auto_fight.py +++ b/mower/solvers/fight/auto_fight.py @@ -4,7 +4,6 @@ import cv2 from scipy.signal import argrelmax from skimage.metrics import structural_similarity -from mower.models import Digtal from mower.solvers.navigation import NavigationSolver from mower.utils import config from mower.utils import typealias as tp @@ -70,32 +69,7 @@ class AutoFight(SceneGraphSolver): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("secret_front", scope, height, thres) def cost(self) -> int: "获取部署费用" diff --git a/mower/solvers/fight/battle_choose/choose_support.py b/mower/solvers/fight/battle_choose/choose_support.py index 0238193..7ddc2a0 100644 --- a/mower/solvers/fight/battle_choose/choose_support.py +++ b/mower/solvers/fight/battle_choose/choose_support.py @@ -3,7 +3,6 @@ from scipy.signal import argrelmin from skimage.metrics import structural_similarity from mower.data import agent_list -from mower.models import Digtal from mower.utils import config from mower.utils import typealias as tp from mower.utils.character_recognize import match_portrait @@ -115,32 +114,7 @@ class ChooseSupportSolver(SceneGraphSolver): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("secret_front", scope, height, thres) def get_agent_progression(self, scope: tp.Scope) -> int: "获取干员练度" diff --git a/mower/solvers/infra/drone.py b/mower/solvers/infra/drone.py index 2149b08..7431dd7 100644 --- a/mower/solvers/infra/drone.py +++ b/mower/solvers/infra/drone.py @@ -1,15 +1,11 @@ from datetime import datetime, timedelta -import cv2 - -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.digit_reader import DigitReader from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.log import logger from mower.utils.recognize import Scene @@ -59,32 +55,7 @@ class DroneSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("riic_base", scope, height, thres) def timeout(self) -> bool: return datetime.now() > self.start_time + timedelta(seconds=20) diff --git a/mower/solvers/infra/get_agent_from_room.py b/mower/solvers/infra/get_agent_from_room.py index 7bdbe50..02fceea 100644 --- a/mower/solvers/infra/get_agent_from_room.py +++ b/mower/solvers/infra/get_agent_from_room.py @@ -2,7 +2,6 @@ from datetime import datetime, timedelta import cv2 -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config @@ -55,26 +54,10 @@ class GetAgentFromRoomSolver(SceneGraphSolver, BaseMixin): img = cv2.resize(img, None, None, scale, scale) img = thres2(img, thres) img = cv2.bitwise_not(img) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(1, 6): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = score.index(min(score)) + 1 - - return value + return ( + config.recog.num.number_int("riic_base", img=img, target_range=range(1, 6)) + + 1 + ) @staticmethod def is_power_station() -> bool: diff --git a/mower/solvers/infra/get_order_remaining_time.py b/mower/solvers/infra/get_order_remaining_time.py index 4accde2..626f656 100644 --- a/mower/solvers/infra/get_order_remaining_time.py +++ b/mower/solvers/infra/get_order_remaining_time.py @@ -1,14 +1,10 @@ from datetime import datetime, timedelta -import cv2 - -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.log import logger from mower.utils.recognize import Scene @@ -29,34 +25,10 @@ class GetOrderRemainingTimeSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> str: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = "" - for x, y, w, h in rect: - if h < 10 and w < 10: - value += ":" - continue - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value += str(score.index(min(score))) - - return value + rect_limits = [{"w": 10, "h": 10, "char": ":"}] + return config.recog.num.number( + "riic_base", scope, height, thres, rect_limits=rect_limits + ) def read_remain_time(self, pos) -> int: h, m, s = self.number(pos, 19, 115).split("::") diff --git a/mower/solvers/infra/reload.py b/mower/solvers/infra/reload.py index 6416732..339e564 100644 --- a/mower/solvers/infra/reload.py +++ b/mower/solvers/infra/reload.py @@ -1,15 +1,11 @@ from datetime import datetime, timedelta -import cv2 - -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.email import send_message from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.log import logger from mower.utils.recognize import Scene @@ -35,32 +31,7 @@ class ReloadSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("riic_base", scope, height, thres) def transition(self) -> bool: if (scene := self.scene()) == Scene.INFRA_DETAILS: diff --git a/mower/solvers/infra/report.py b/mower/solvers/infra/report.py index 05827fb..352a660 100644 --- a/mower/solvers/infra/report.py +++ b/mower/solvers/infra/report.py @@ -5,7 +5,6 @@ from sqlalchemy import Column, Date, Integer, create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker -from mower.models import Digtal from mower.utils import config from mower.utils.digit_reader import DigitReader from mower.utils.email import report_template, send_message @@ -183,25 +182,7 @@ class ReportSolver(SceneGraphSolver): scale = default_height / height img = cv2.resize(img, None, None, scale, scale) img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - value = 0 - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - - score = [] - for i in range(10): - im = Digtal().noto_sans[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("noto", img=img) def get_report_data(self): # 连接数据库 diff --git a/mower/solvers/infra/run_order/read_original_order_remaining_time.py b/mower/solvers/infra/run_order/read_original_order_remaining_time.py index 8c09ce0..992b9dd 100644 --- a/mower/solvers/infra/run_order/read_original_order_remaining_time.py +++ b/mower/solvers/infra/run_order/read_original_order_remaining_time.py @@ -1,12 +1,8 @@ -import cv2 - -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.recognize import Scene @@ -30,34 +26,10 @@ class ReadOriginalOrderRemainTimeSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> str: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = "" - for x, y, w, h in rect: - if h < 7 and w < 7: - value += ":" - continue - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value += str(score.index(min(score))) - - return value + rect_limits = [{"w": 7, "h": 7, "char": ":"}] + return config.recog.num.number( + "riic_base", scope, height, thres, rect_limits=rect_limits + ) def read_remain_time(self) -> int: h, m, s = self.number(((758, 670), (960, 705)), 30, 100).split("::") diff --git a/mower/solvers/infra/switch_assistants.py b/mower/solvers/infra/switch_assistants.py index 0b44b69..b52b18c 100644 --- a/mower/solvers/infra/switch_assistants.py +++ b/mower/solvers/infra/switch_assistants.py @@ -1,6 +1,3 @@ -import cv2 - -from mower.models import Digtal from mower.solvers.fight.battle_choose.battle_fill_choose import BattleFillChooseSolver from mower.solvers.infra.base_mixin import BaseMixin from mower.utils import config @@ -8,7 +5,6 @@ from mower.utils import typealias as tp from mower.utils.character_recognize import match_portrait from mower.utils.email import assistants_template, send_message from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.log import logger from mower.utils.recognize import Scene @@ -65,38 +61,7 @@ class SwitchAssistantsSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - try: - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours( - img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE - ) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - rect = rect[:-3] - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().noto_sans[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value - except Exception: - return 0 + return config.recog.num.number_int("noto", scope, height, thres, rect_ed=-3) def transition(self) -> bool: if (scene := self.scene()) == Scene.RIIC_REPORT: diff --git a/mower/solvers/infra/switch_product/__init__.py b/mower/solvers/infra/switch_product/__init__.py index 69bee7f..0917be5 100644 --- a/mower/solvers/infra/switch_product/__init__.py +++ b/mower/solvers/infra/switch_product/__init__.py @@ -2,7 +2,6 @@ from datetime import datetime import cv2 -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.drone import DroneSolver from mower.solvers.infra.enter_room import EnterRoomSolver @@ -85,30 +84,8 @@ class SwitchProductSolver(SceneGraphSolver, BaseMixin): img = cv2.resize(img, None, None, scale, scale) img = thres2(img, thres) img = cv2.bitwise_not(img) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = "" - for x, y, w, h in rect: - if h < 8 and w < 8: - value += "." - continue - elif h < 20 and w < 20: - continue - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value += str(score.index(min(score))) - - return value + rect_limits = [{"w": 20, "h": 20, "char": ""}, {"w": 8, "h": 8, "char": "."}] + return config.recog.num.number("riic_base", img=img, rect_limits=rect_limits) def read_speed(self) -> float: speed1 = self.number(((1185, 955), (1255, 977)), 17, 120) diff --git a/mower/solvers/infra/switch_product/choose_product.py b/mower/solvers/infra/switch_product/choose_product.py index 4895fff..ff5a9a9 100644 --- a/mower/solvers/infra/switch_product/choose_product.py +++ b/mower/solvers/infra/switch_product/choose_product.py @@ -1,14 +1,11 @@ from datetime import datetime, timedelta -import cv2 - -from mower.models import Digtal from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.email import send_message from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cmatch, cropimg, loadres, thres2 +from mower.utils.image import cmatch, cropimg, loadres from mower.utils.log import logger from mower.utils.recognize import Scene @@ -55,32 +52,7 @@ class ChooseProductSolver(SceneGraphSolver): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("riic_base", scope, height, thres) def transition(self) -> bool: if (scene := self.scene()) == Scene.INFRA_DETAILS: diff --git a/mower/solvers/infra/switch_product/get_remain_time.py b/mower/solvers/infra/switch_product/get_remain_time.py index 6bba960..f5c06e7 100644 --- a/mower/solvers/infra/switch_product/get_remain_time.py +++ b/mower/solvers/infra/switch_product/get_remain_time.py @@ -1,12 +1,8 @@ -import cv2 - -from mower.models import Digtal from mower.solvers.infra.base_mixin import BaseMixin from mower.solvers.infra.enter_room import EnterRoomSolver from mower.utils import config from mower.utils import typealias as tp from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 from mower.utils.recognize import Scene @@ -30,34 +26,10 @@ class GetRemainTimeSolver(SceneGraphSolver, BaseMixin): def number(self, scope: tp.Scope, height: int, thres: int) -> str: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = "" - for x, y, w, h in rect: - if h < 7 and w < 7: - value += ":" - continue - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().riic_base_digits[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value += str(score.index(min(score))) - - return value + rect_limits = [{"w": 7, "h": 7, "char": ":"}] + return config.recog.num.number( + "riic_base", scope, height, thres, rect_limits=rect_limits + ) def read_remain_time(self) -> int: h, m, s = self.number(((758, 670), (960, 705)), 30, 100).split("::") diff --git a/mower/solvers/operation.py b/mower/solvers/operation.py index b7545c3..6e3e7c9 100644 --- a/mower/solvers/operation.py +++ b/mower/solvers/operation.py @@ -4,13 +4,12 @@ from typing import Optional import cv2 -from mower.models import Digtal from mower.solvers.navigation.utils import generate_name from mower.utils import config from mower.utils import typealias as tp from mower.utils.datetime import get_server_weekday from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, diff_ratio, loadimg, thres2 +from mower.utils.image import cropimg, diff_ratio, loadimg from mower.utils.log import logger from mower.utils.path import get_path from mower.utils.recognize import Scene @@ -27,33 +26,10 @@ class OperationSolver(SceneGraphSolver): super().run() def number(self, scope: tp.Scope, height: Optional[int] = None): - img = cropimg(config.recog.gray, scope) - if height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, 127) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - if w < 5 or h < 5: - continue - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + rect_limits = [{"w": 5, "h": 5, "char": ""}] + return config.recog.num.number_int( + "secret_front", scope, height, rect_limits=rect_limits + ) def drop_animation(self) -> bool: drop_scope = (100, 775), (1920, 945) diff --git a/mower/solvers/operator.py b/mower/solvers/operator.py index 4cded82..8dfaa07 100644 --- a/mower/solvers/operator.py +++ b/mower/solvers/operator.py @@ -99,24 +99,7 @@ class OperatorSolver(SceneGraphSolver): img = cropimg(img, ((1334, 175), (1456, 249))) scale = 25 / 73 img = cv2.resize(img, None, None, scale, scale) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - return value + return config.recog.num.number_int("secret_front", img=img) def elite(self): img = cropimg(config.recog.gray, ((1320, 372), (1454, 451))) diff --git a/mower/solvers/secret_front.py b/mower/solvers/secret_front.py index 4da29a4..61930b2 100644 --- a/mower/solvers/secret_front.py +++ b/mower/solvers/secret_front.py @@ -8,7 +8,7 @@ from mower.utils import typealias as tp from mower.utils.csleep import MowerExit from mower.utils.email import send_message from mower.utils.graph import SceneGraphSolver -from mower.utils.image import cropimg, thres2 +from mower.utils.image import cropimg from mower.utils.log import logger from mower.utils.scene import Scene from mower.utils.vector import sa, va @@ -80,31 +80,7 @@ class SecretFront(SceneGraphSolver): self.actions[page] = {} def number(self, scope: tp.Scope, height: int | None = None): - img = cropimg(config.recog.gray, scope) - if height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, 127) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("secret_front", scope, height) def card_pos(self, total, idx): if total == 3: diff --git a/mower/solvers/shop.py b/mower/solvers/shop.py index e747dfd..0aa7796 100644 --- a/mower/solvers/shop.py +++ b/mower/solvers/shop.py @@ -1,6 +1,6 @@ import cv2 -from mower.models import Digtal, shop +from mower.models import shop from mower.utils import config from mower.utils import typealias as tp from mower.utils.graph import SceneGraphSolver @@ -41,36 +41,15 @@ class CreditShop(SceneGraphSolver): img = cropimg(config.recog.gray, scope) if font == "riic_base": - templates = Digtal().riic_base_digits default_height = 28 else: - templates = Digtal().noto_sans default_height = 29 if height and height != default_height: scale = default_height / height img = cv2.resize(img, None, None, scale, scale) img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = templates[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int(font, img=img) def credit_remain(self): credits = self.number(((1700, 39), (1800, 75)), "riic_base", thres=180) diff --git a/mower/solvers/sss/sss_fight.py b/mower/solvers/sss/sss_fight.py index eb6f062..572c94f 100644 --- a/mower/solvers/sss/sss_fight.py +++ b/mower/solvers/sss/sss_fight.py @@ -7,7 +7,6 @@ from scipy.signal import argrelmax from skimage.metrics import structural_similarity from mower.data import agent_list -from mower.models import Digtal from mower.utils import config from mower.utils import typealias as tp from mower.utils.character_recognize import match_avatar @@ -103,37 +102,7 @@ class SSSFightSolver(SceneGraphSolver): def number(self, scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - try: - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours( - img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE - ) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value - except Exception: - return 0 + return config.recog.num.number_int("secret_front", scope, height, thres) def cost(self) -> int: "获取部署费用" diff --git a/mower/solvers/sss/utils.py b/mower/solvers/sss/utils.py index b2e28fd..4c4d67f 100644 --- a/mower/solvers/sss/utils.py +++ b/mower/solvers/sss/utils.py @@ -3,10 +3,9 @@ import numpy as np from PIL import Image, ImageDraw, ImageFont from mower import __rootdir__ -from mower.models import Digtal from mower.utils import config from mower.utils import typealias as tp -from mower.utils.image import cropimg, thres2 +from mower.utils.image import cropimg def generate_image(text: str, font_size: int) -> tp.GrayImage: @@ -79,32 +78,7 @@ translate2 = { def number(scope: tp.Scope, height: int, thres: int) -> int: "数字识别" - img = cropimg(config.recog.gray, scope) - default_height = 25 - if height != default_height: - scale = 25 / height - img = cv2.resize(img, None, None, scale, scale) - img = thres2(img, thres) - contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - rect = [cv2.boundingRect(c) for c in contours] - rect.sort(key=lambda c: c[0]) - rect = rect[:-3] - value = 0 - - for x, y, w, h in rect: - digit = cropimg(img, ((x, y), (x + w, y + h))) - digit = cv2.copyMakeBorder( - digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) - ) - score = [] - for i in range(10): - im = Digtal().secret_front[i] - result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) - min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) - score.append(min_val) - value = value * 10 + score.index(min(score)) - - return value + return config.recog.num.number_int("secret_front", scope, height, thres, rect_ed=-3) def is_full() -> bool: diff --git a/mower/utils/number.py b/mower/utils/number.py index b7a8fc6..5a66e6f 100644 --- a/mower/utils/number.py +++ b/mower/utils/number.py @@ -3,9 +3,9 @@ from typing import Literal import cv2 from mower.models import Digtal - -from . import typealias as tp -from .image import cropimg +from mower.utils import config +from mower.utils import typealias as tp +from mower.utils.image import cropimg, thres2 class NumberRecognizer: @@ -71,3 +71,54 @@ class NumberRecognizer: value += str(score.index(min(score))) return value + + def number( + self, + font: Literal["riic_base", "noto", "secret_front"] = "noto", + scope: tp.Scope | None = None, + height: int = 25, + thres: int = 127, + img: tp.GrayImage | None = None, + rect_st: int | None = None, + rect_ed: int | None = None, + rect_limits: list[dict] = [], + target_range: list = range(10), + ) -> str: + try: + if img is None: + img = cropimg(config.recog.gray, scope) + default_height = 25 + if height != default_height: + scale = 25 / height + img = cv2.resize(img, None, None, scale, scale) + img = thres2(img, thres) + rect = self.segment(img) + rect = self.filter_rectangles(rect, rect_st, rect_ed, rect_limits) + return self.number_match(img, rect, font, target_range) + except Exception: + return "" + + def number_int( + self, + font: Literal["riic_base", "noto", "secret_front"] = "noto", + scope: tp.Scope | None = None, + height: int = 25, + thres: int = 127, + img: tp.GrayImage | None = None, + rect_st: int | None = None, + rect_ed: int | None = None, + rect_limits: list[dict] = [], + target_range: list = range(10), + ) -> int: + res = self.number( + font, + scope, + height, + thres, + img, + rect_st, + rect_ed, + rect_limits, + target_range, + ) + return int(res) if res else 0 diff --git a/mower/utils/recognize/__init__.py b/mower/utils/recognize/__init__.py index f67fd02..b8481c2 100644 --- a/mower/utils/recognize/__init__.py +++ b/mower/utils/recognize/__init__.py @@ -12,6 +12,7 @@ from mower.utils.csleep import MowerExit from mower.utils.image import bytes2img, cmatch, cropimg, loadres, thres2 from mower.utils.log import logger from mower.utils.matcher import Matcher +from mower.utils.number import NumberRecognizer from mower.utils.scene import Scene, SceneComment from mower.utils.vector import va @@ -36,6 +37,7 @@ class Recognizer: self._gray = None self._hsv = None self._matcher = None + self._num = None self.scene = Scene.UNDEFINED @property @@ -62,6 +64,12 @@ class Recognizer: self._matcher = Matcher(self.gray) return self._matcher + @property + def num(self): + if self._num is None: + self._num = NumberRecognizer() + return self._num + def start(self, screencap: Optional[bytes] = None) -> None: """init with screencap""" retry_times = config.MAX_RETRYTIME