├── __init__.py ├── targets ├── Book.jpg ├── Box.jpg ├── Chair.jpg ├── Cloth.jpg ├── Coal.jpg ├── Food.jpg ├── Heels.jpg ├── Kit.jpg ├── Lamp.jpg ├── Mic.jpg ├── Mine.jpg ├── Oil.jpg ├── Quilt.jpg ├── Screw.jpg ├── Silk.jpg ├── Sofa.jpg ├── Steel.jpg ├── Straw.jpg ├── Wood.jpg ├── Bottle.jpg ├── Chicken.jpg ├── Cotton.jpg ├── FlatCar.jpg ├── Helmet.jpg ├── Potting.jpg ├── Chlorine.jpg ├── Computer.jpg ├── Cupboard.jpg ├── Fertilizer.jpg ├── Gasoline.jpg ├── Rank_btn.jpg ├── Schoolbag.jpg ├── Vegetable.jpg ├── Refrigerator.jpg └── BeachUmbrella.jpg ├── config.json ├── main.py ├── flusher.py ├── LICENSE ├── target.py ├── config.py ├── .gitignore ├── cv.py ├── prop.py ├── README.md └── automator.py /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /targets/Book.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Book.jpg -------------------------------------------------------------------------------- /targets/Box.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Box.jpg -------------------------------------------------------------------------------- /targets/Chair.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Chair.jpg -------------------------------------------------------------------------------- /targets/Cloth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Cloth.jpg -------------------------------------------------------------------------------- /targets/Coal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Coal.jpg -------------------------------------------------------------------------------- /targets/Food.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Food.jpg -------------------------------------------------------------------------------- /targets/Heels.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Heels.jpg -------------------------------------------------------------------------------- /targets/Kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Kit.jpg -------------------------------------------------------------------------------- /targets/Lamp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Lamp.jpg -------------------------------------------------------------------------------- /targets/Mic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Mic.jpg -------------------------------------------------------------------------------- /targets/Mine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Mine.jpg -------------------------------------------------------------------------------- /targets/Oil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Oil.jpg -------------------------------------------------------------------------------- /targets/Quilt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Quilt.jpg -------------------------------------------------------------------------------- /targets/Screw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Screw.jpg -------------------------------------------------------------------------------- /targets/Silk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Silk.jpg -------------------------------------------------------------------------------- /targets/Sofa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Sofa.jpg -------------------------------------------------------------------------------- /targets/Steel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Steel.jpg -------------------------------------------------------------------------------- /targets/Straw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Straw.jpg -------------------------------------------------------------------------------- /targets/Wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Wood.jpg -------------------------------------------------------------------------------- /targets/Bottle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Bottle.jpg -------------------------------------------------------------------------------- /targets/Chicken.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Chicken.jpg -------------------------------------------------------------------------------- /targets/Cotton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Cotton.jpg -------------------------------------------------------------------------------- /targets/FlatCar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/FlatCar.jpg -------------------------------------------------------------------------------- /targets/Helmet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Helmet.jpg -------------------------------------------------------------------------------- /targets/Potting.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Potting.jpg -------------------------------------------------------------------------------- /targets/Chlorine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Chlorine.jpg -------------------------------------------------------------------------------- /targets/Computer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Computer.jpg -------------------------------------------------------------------------------- /targets/Cupboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Cupboard.jpg -------------------------------------------------------------------------------- /targets/Fertilizer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Fertilizer.jpg -------------------------------------------------------------------------------- /targets/Gasoline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Gasoline.jpg -------------------------------------------------------------------------------- /targets/Rank_btn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Rank_btn.jpg -------------------------------------------------------------------------------- /targets/Schoolbag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Schoolbag.jpg -------------------------------------------------------------------------------- /targets/Vegetable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Vegetable.jpg -------------------------------------------------------------------------------- /targets/Refrigerator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/Refrigerator.jpg -------------------------------------------------------------------------------- /targets/BeachUmbrella.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dwayneten/JGM-Automator/HEAD/targets/BeachUmbrella.jpg -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "swipe_interval_sec": 5, 3 | "upgrade_interval_sec": 10, 4 | "building_pos": [ 5 | ["零件厂", "人民石油", "企鹅机械"], 6 | ["商贸中心", "媒体之声", "民食斋"], 7 | ["花园洋房", "复兴公馆", "小型公寓"] 8 | ], 9 | "train_get_rank": [2], 10 | "debug_mode": false, 11 | "upgrade_building": true, 12 | "upgrade_building_list": [7], 13 | "refresh_train": true, 14 | "detect_goods": true 15 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from automator import Automator 2 | from prop import END, RUN 3 | 4 | from flusher import flush 5 | from multiprocessing import Process, Queue 6 | 7 | KEYBOARD = Queue() 8 | 9 | 10 | def main(kb): 11 | # 连接 adb 。 12 | instance = Automator('127.0.0.1:7555', kb) 13 | 14 | # 启动脚本。 15 | instance.start() 16 | 17 | 18 | if __name__ == '__main__': 19 | p = Process(target=main, args=(KEYBOARD,)) 20 | p.start() 21 | while True: 22 | flush() 23 | txt = input() 24 | if txt == END or txt.split(' ')[0] == RUN: 25 | KEYBOARD.put(txt) 26 | if txt == END: 27 | break 28 | else: 29 | KEYBOARD.put('') 30 | p.join() 31 | -------------------------------------------------------------------------------- /flusher.py: -------------------------------------------------------------------------------- 1 | class _Flush: 2 | def __init__(self): 3 | try: 4 | self.work = _FlushUnix() 5 | except ModuleNotFoundError: 6 | self.work = _FlushWindows() 7 | 8 | def __call__(self): return self.work() 9 | 10 | class _FlushUnix: 11 | def __init__(self): 12 | from termios import tcflush, TCIFLUSH 13 | 14 | def __call__(self): 15 | from termios import tcflush, TCIFLUSH 16 | import sys 17 | tcflush(sys.stdin, TCIFLUSH) 18 | 19 | class _FlushWindows: 20 | def __init__(self): 21 | import msvcrt 22 | 23 | def __call__(self): 24 | import msvcrt 25 | while msvcrt.kbhit(): 26 | msvcrt.getch() 27 | 28 | flush = _Flush() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 DwayneTen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /target.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class TargetType(Enum): 5 | """ 6 | 货物枚举类型。通过截屏制作货物图片时,请确保截屏符合实际大小。 7 | """ 8 | Chair = 'targets/Chair.jpg' 9 | Vegetable = 'targets/Vegetable.jpg' 10 | Bottle = 'targets/Bottle.jpg' 11 | Wood = 'targets/Wood.jpg' 12 | Food = 'targets/Food.jpg' 13 | Box = 'targets/Box.jpg' 14 | Sofa = 'targets/Sofa.jpg' 15 | Coal = 'targets/Coal.jpg' 16 | Screw = 'targets/Screw.jpg' 17 | Book = 'targets/Book.jpg' 18 | Cloth = 'targets/Cloth.jpg' 19 | Cotton = 'targets/Cotton.jpg' 20 | Quilt = 'targets/Quilt.jpg' 21 | Straw = 'targets/Straw.jpg' 22 | Mine = 'targets/Mine.jpg' 23 | Chicken = 'targets/Chicken.jpg' 24 | Kit = 'targets/Kit.jpg' 25 | Lamp = 'targets/Lamp.jpg' 26 | Mic = 'targets/Mic.jpg' 27 | Oil = 'targets/Oil.jpg' 28 | Silk = 'targets/Silk.jpg' 29 | Fertilizer = 'targets/Fertilizer.jpg' 30 | Cupboard = 'targets/Cupboard.jpg' 31 | Heels = 'targets/Heels.jpg' 32 | Steel = 'targets/Steel.jpg' 33 | Computer = 'targets/Computer.jpg' 34 | Gasoline = 'targets/Gasoline.jpg' 35 | Potting = 'targets/Potting.jpg' 36 | Chlorine = 'targets/Chlorine.jpg' 37 | Schoolbag = 'targets/Schoolbag.jpg' 38 | Rank_btn = 'targets/Rank_btn.jpg' 39 | Refrigerator = 'targets/Refrigerator.jpg' 40 | FlatCar = 'targets/FlatCar.jpg' 41 | BeachUmbrella = 'targets/BeachUmbrella.jpg' 42 | Helmet = 'targets/Helmet.jpg' -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import json 2 | import prop 3 | from numpy import array 4 | from building import BuildingType 5 | 6 | CONFIG_FILE = './config.json' 7 | 8 | class Reader: 9 | building_pos = None 10 | goods_2_building_seq = None 11 | swipe_interval_sec = None 12 | upgrade_interval_sec = None 13 | debug_mode = False 14 | refresh_train = False 15 | detect_goods = False 16 | upgrade_building = False 17 | upgrade_building_list = None 18 | 19 | @staticmethod 20 | def _building_name_2_building_enum(building_name): 21 | for building in BuildingType: 22 | enum_name = str(building).split('.')[1] 23 | if enum_name == building_name: 24 | return building 25 | raise Exception(f'Wrong building name [{building_name}]') 26 | 27 | def _flatten_list(self, leveled_building_pos): 28 | tmp_list = array(leveled_building_pos[::-1]).flatten().tolist() 29 | return [self._building_name_2_building_enum(ele) for ele in tmp_list] 30 | 31 | @staticmethod 32 | def _generate_building_pos(flattened_building_pos): 33 | return [ele for ele in flattened_building_pos] 34 | 35 | @staticmethod 36 | def _generate_goods_2_building_seq(building_pos, train_get_rank): 37 | mask_building_pos = list(filter(lambda building: prop.BUILDING_RANK[building] in train_get_rank, building_pos)) 38 | 39 | res = {} 40 | for i, building in enumerate(building_pos): 41 | building_seq = i + 1 42 | goods = prop.BUILDING_2_GOODS[building] 43 | if goods is not None and building in mask_building_pos: 44 | res[goods] = building_seq 45 | return res 46 | 47 | def refresh(self): 48 | with open(CONFIG_FILE, 'r', encoding='utf-8') as f: 49 | config = json.load(f) 50 | self.swipe_interval_sec = config['swipe_interval_sec'] 51 | self.upgrade_interval_sec = config['upgrade_interval_sec'] 52 | flattened_building_pos = self._flatten_list(config['building_pos']) 53 | self.building_pos = self._generate_building_pos(flattened_building_pos) 54 | self.goods_2_building_seq = self._generate_goods_2_building_seq(self.building_pos, config['train_get_rank']) 55 | 56 | self.debug_mode = config['debug_mode'] 57 | self.detect_goods = config['detect_goods'] 58 | if self.detect_goods: 59 | self.refresh_train = config['refresh_train'] 60 | self.expect_target_rank = [0, 1, 2] 61 | for i in config['train_get_rank']: 62 | self.expect_target_rank.remove(i) 63 | self.goods_2_building_seq_excpet_target = self._generate_goods_2_building_seq(self.building_pos, self.expect_target_rank) 64 | self.upgrade_building = config['upgrade_building'] 65 | if self.upgrade_building: 66 | self.upgrade_building_list = config['upgrade_building_list'] 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # JetBrains 2 | .idea 3 | venv/ 4 | 5 | # Visual Studio Code 6 | .vscode 7 | 8 | 9 | # Created by https://www.gitignore.io/api/macos,python,opencv,windows 10 | # Edit at https://www.gitignore.io/?templates=macos,python,opencv,windows 11 | 12 | ### macOS ### 13 | # General 14 | .DS_Store 15 | .AppleDouble 16 | .LSOverride 17 | 18 | # Icon must end with two \r 19 | Icon 20 | 21 | # Thumbnails 22 | ._* 23 | 24 | # Files that might appear in the root of a volume 25 | .DocumentRevisions-V100 26 | .fseventsd 27 | .Spotlight-V100 28 | .TemporaryItems 29 | .Trashes 30 | .VolumeIcon.icns 31 | .com.apple.timemachine.donotpresent 32 | 33 | # Directories potentially created on remote AFP share 34 | .AppleDB 35 | .AppleDesktop 36 | Network Trash Folder 37 | Temporary Items 38 | .apdisk 39 | 40 | ### OpenCV ### 41 | #OpenCV for Mac and Linux 42 | #build and release folders 43 | */CMakeFiles 44 | */CMakeCache.txt 45 | */Makefile 46 | */cmake_install.cmake 47 | 48 | ### Python ### 49 | # Byte-compiled / optimized / DLL files 50 | __pycache__/ 51 | *.py[cod] 52 | *$py.class 53 | 54 | # C extensions 55 | *.so 56 | 57 | # Distribution / packaging 58 | .Python 59 | build/ 60 | develop-eggs/ 61 | dist/ 62 | downloads/ 63 | eggs/ 64 | .eggs/ 65 | lib/ 66 | lib64/ 67 | parts/ 68 | sdist/ 69 | var/ 70 | wheels/ 71 | pip-wheel-metadata/ 72 | share/python-wheels/ 73 | *.egg-info/ 74 | .installed.cfg 75 | *.egg 76 | MANIFEST 77 | 78 | # PyInstaller 79 | # Usually these files are written by a python script from a template 80 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 81 | *.manifest 82 | *.spec 83 | 84 | # Installer logs 85 | pip-log.txt 86 | pip-delete-this-directory.txt 87 | 88 | # Unit test / coverage reports 89 | htmlcov/ 90 | .tox/ 91 | .nox/ 92 | .coverage 93 | .coverage.* 94 | .cache 95 | nosetests.xml 96 | coverage.xml 97 | *.cover 98 | .hypothesis/ 99 | .pytest_cache/ 100 | 101 | # Translations 102 | *.mo 103 | *.pot 104 | 105 | # Scrapy stuff: 106 | .scrapy 107 | 108 | # Sphinx documentation 109 | docs/_build/ 110 | 111 | # PyBuilder 112 | target/ 113 | 114 | # pyenv 115 | .python-version 116 | 117 | # pipenv 118 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 119 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 120 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 121 | # install all needed dependencies. 122 | #Pipfile.lock 123 | 124 | # celery beat schedule file 125 | celerybeat-schedule 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # Mr Developer 138 | .mr.developer.cfg 139 | .project 140 | .pydevproject 141 | 142 | # mkdocs documentation 143 | /site 144 | 145 | # mypy 146 | .mypy_cache/ 147 | .dmypy.json 148 | dmypy.json 149 | 150 | # Pyre type checker 151 | .pyre/ 152 | 153 | ### Windows ### 154 | # Windows thumbnail cache files 155 | Thumbs.db 156 | Thumbs.db:encryptable 157 | ehthumbs.db 158 | ehthumbs_vista.db 159 | 160 | # Dump file 161 | *.stackdump 162 | 163 | # Folder config file 164 | [Dd]esktop.ini 165 | 166 | # Recycle Bin used on file shares 167 | $RECYCLE.BIN/ 168 | 169 | # Windows Installer files 170 | *.cab 171 | *.msi 172 | *.msix 173 | *.msm 174 | *.msp 175 | 176 | # Windows shortcuts 177 | *.lnk 178 | 179 | # End of https://www.gitignore.io/api/macos,python,opencv,windows 180 | 181 | *.log 182 | tmp/* 183 | assets/* -------------------------------------------------------------------------------- /cv.py: -------------------------------------------------------------------------------- 1 | from target import TargetType 2 | import os 3 | import re 4 | import cv2 5 | import time 6 | import subprocess 7 | import numpy as np 8 | 9 | TARGET_DIR = './assets/' 10 | TMP_DIR = './tmp/' 11 | 12 | SIMILAR = { 13 | '1': ['i', 'I', 'l', '|', ':', '!', '/', '\\'], 14 | '2': ['z', 'Z'], 15 | '3': [], 16 | '4': [], 17 | '5': ['s', 'S'], 18 | '6': [], 19 | '7': [], 20 | '8': ['&'], 21 | '9': [], 22 | '0': ['o', 'O', 'c', 'C', 'D'] 23 | } 24 | 25 | 26 | class UIMatcher: 27 | @staticmethod 28 | def match(screen, target: TargetType): 29 | """ 30 | 在指定快照中确定货物的屏幕位置。 31 | """ 32 | # 获取对应货物的图片。 33 | # 有个要点:通过截屏制作货物图片时,请在快照为实际大小的模式下截屏。 34 | template = cv2.imread(target.value) 35 | # 获取货物图片的宽高。 36 | th, tw = template.shape[:2] 37 | 38 | # 调用 OpenCV 模板匹配。 39 | res = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) 40 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) 41 | rank = max_val 42 | 43 | # 矩形左上角的位置。 44 | tl = max_loc 45 | 46 | # 阈值判断。 47 | if rank < 0.82: 48 | return None 49 | 50 | # 这里,我随机加入了数字(15),用于补偿匹配值和真实位置的差异。 51 | return tl[0] + tw / 2 + 15, tl[1] + th / 2 + 15, rank 52 | 53 | @staticmethod 54 | def read(filepath: str): 55 | """ 56 | 工具函数,用于读取图片。 57 | """ 58 | return cv2.imread(filepath) 59 | 60 | @staticmethod 61 | def write(image): 62 | """ 63 | 工具函数,用于读取图片。 64 | """ 65 | ts = str(int(time.time())) 66 | return cv2.imwrite(f'{TARGET_DIR}{ts}.jpg', image) 67 | 68 | @staticmethod 69 | def image_to_txt(image, cleanup=False, plus=''): 70 | # cleanup为True则识别完成后删除生成的文本文件 71 | # plus参数为给tesseract的附加高级参数 72 | image_url = f'{TMP_DIR}tmp.jpg' 73 | txt_name = f'{TMP_DIR}tmp' 74 | txt_url = f'{txt_name}.txt' 75 | if not os.path.exists(TMP_DIR): os.mkdir(TMP_DIR) 76 | cv2.imwrite(image_url, image) 77 | 78 | subprocess.check_output('tesseract --dpi 72 ' + image_url + ' ' + 79 | txt_name + ' ' + plus, shell=True) # 生成同名txt文件 80 | text = '' 81 | with open(txt_url, 'r') as f: 82 | text = f.read().strip() 83 | if cleanup: 84 | os.remove(txt_url) 85 | os.remove(image_url) 86 | return text 87 | 88 | @staticmethod 89 | def normalize_txt(txt: str): 90 | for key, sim_list in SIMILAR.items(): 91 | for sim in sim_list: 92 | txt = txt.replace(sim, key) 93 | txt = re.sub(r'\D', '', txt) 94 | return txt 95 | 96 | @staticmethod 97 | def cut(image, left_up, len_width=(190, 50)): 98 | sx = left_up[0] 99 | sy = left_up[1] 100 | dx = left_up[0] + len_width[0] 101 | dy = left_up[1] + len_width[1] 102 | return image[sy:dy, sx:dx] 103 | 104 | @staticmethod 105 | def plain(image): 106 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) 107 | erode = cv2.erode(image, kernel) 108 | dilate = cv2.dilate(erode, kernel) 109 | return dilate 110 | 111 | @staticmethod 112 | def fill_color(image): 113 | copy_image = image.copy() 114 | h, w = image.shape[:2] 115 | mask = np.zeros([h + 2, w + 2], np.uint8) 116 | cv2.floodFill(copy_image, mask, (0, 0), (255, 255, 255), (100, 100, 100), (50, 50, 50), 117 | cv2.FLOODFILL_FIXED_RANGE) 118 | return copy_image 119 | 120 | @staticmethod 121 | def pre(image): 122 | image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) 123 | lower_blue = np.array([103, 43, 46]) 124 | upper_blue = np.array([103, 255, 255]) 125 | image = cv2.inRange(image, lower_blue, upper_blue) 126 | return image 127 | 128 | @staticmethod 129 | def pre_building_panel(image): 130 | image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) 131 | mask_orange = cv2.inRange(image, (10, 40, 40), (40, 255, 255)) 132 | mask_blue = cv2.inRange(image, (80, 40, 40), (140, 255, 255)) 133 | image = cv2.bitwise_or(mask_orange, mask_blue) 134 | return image 135 | -------------------------------------------------------------------------------- /prop.py: -------------------------------------------------------------------------------- 1 | from building import BuildingType 2 | from target import TargetType 3 | 4 | # 坐标相关 5 | # 每个建筑等级显示的左上角坐标 6 | BUILDING_LEVEL_POS = { 7 | 1: (219, 1205), 8 | 2: (469, 1078), 9 | 3: (719, 950), 10 | 4: (216, 947), 11 | 5: (467, 822), 12 | 6: (728, 697), 13 | 7: (215, 696), 14 | 8: (468, 570), 15 | 9: (725, 445) 16 | } 17 | # 建筑坐标 18 | BUILDING_POS = { 19 | 1: (294, 1184), 20 | 2: (551, 1061), 21 | 3: (807, 961), 22 | 4: (275, 935), 23 | 5: (535, 810), 24 | 6: (799, 687), 25 | 7: (304, 681), 26 | 8: (541, 568), 27 | 9: (787, 447) 28 | } 29 | # 查看每个建筑等级的按钮坐标 30 | BUILDING_DETAIL_BTN = (982, 1151) 31 | # 建筑升级按钮坐标 32 | BUILDING_UPGRADE_BTN = (863, 1703) 33 | 34 | # 建筑中心-建筑详细面板中 35 | # 等级数字左上角坐标 36 | BUILDING_INFO_PANEL_LEVEL_POS = (790, 500) 37 | # 升级按钮坐标 38 | BUILDING_INFO_PANEL_UPGRADE_BTN = (540, 1390) 39 | 40 | # 导航栏建设按钮坐标 41 | CONSTRUCT_BTN = (190, 1800) 42 | 43 | # 商店面板的各种坐标 44 | # 导航栏商店按钮坐标 保证能点到商店 45 | SHOP_BTN = (420, 1820) 46 | # 红包标题栏中间坐标 47 | REDPACKET_TITLE_POS = (530, 350) 48 | # 各按钮打开两字附近的坐标 49 | # 福气红包/小红包按钮坐标 50 | REDPACKET_BTN_S = (200, 850) 51 | # 多福红包/中红包按钮坐标 52 | REDPACKET_BTN_M = (530, 850) 53 | # 满福红包/大红包按钮坐标 54 | REDPACKET_BTN_L = (870, 850) 55 | # 相册按钮坐标 56 | ALBUM_BTN = (530, 1530) 57 | 58 | # 游戏属性相关 59 | # 建筑对应加buff的对象 60 | BUFF_PAIR = { 61 | BuildingType.木屋: [BuildingType.木材厂], 62 | BuildingType.居民楼: [BuildingType.便利店], 63 | BuildingType.钢结构房: [BuildingType.钢铁厂], 64 | BuildingType.平房: [], 65 | BuildingType.小型公寓: [], 66 | BuildingType.人才公寓: [], 67 | BuildingType.花园洋房: [BuildingType.商贸中心], 68 | BuildingType.中式小楼: [], 69 | BuildingType.空中别墅: [BuildingType.民食斋], 70 | BuildingType.复兴公馆: [], 71 | BuildingType.便利店: [BuildingType.居民楼], 72 | BuildingType.五金店: [BuildingType.零件厂], 73 | BuildingType.服装店: [BuildingType.纺织厂], 74 | BuildingType.菜市场: [BuildingType.食品厂], 75 | BuildingType.学校: [BuildingType.图书城], 76 | BuildingType.图书城: [BuildingType.学校, BuildingType.造纸厂], 77 | BuildingType.商贸中心: [BuildingType.花园洋房], 78 | BuildingType.加油站: [BuildingType.人民石油], 79 | BuildingType.民食斋: [BuildingType.空中别墅], 80 | BuildingType.媒体之声: [], 81 | BuildingType.木材厂: [BuildingType.木屋], 82 | BuildingType.食品厂: [BuildingType.菜市场], 83 | BuildingType.造纸厂: [BuildingType.图书城], 84 | BuildingType.水厂: [], 85 | BuildingType.电厂: [], 86 | BuildingType.钢铁厂: [BuildingType.钢结构房], 87 | BuildingType.纺织厂: [BuildingType.服装店], 88 | BuildingType.零件厂: [BuildingType.五金店], 89 | BuildingType.企鹅机械: [BuildingType.零件厂], 90 | BuildingType.人民石油: [BuildingType.加油站], 91 | BuildingType.梦想公寓: [BuildingType.游泳馆, BuildingType.强国煤业], 92 | BuildingType.追梦快递: [], 93 | BuildingType.游泳馆: [BuildingType.梦想公寓], 94 | BuildingType.强国煤业: [BuildingType.梦想公寓], 95 | } 96 | # 建筑品质 97 | _RANK_NORMAL = 0 98 | _RANK_RARE = 1 99 | _RANK_EPIC = 2 100 | BUILDING_RANK = { 101 | BuildingType.木屋: _RANK_NORMAL, 102 | BuildingType.居民楼: _RANK_NORMAL, 103 | BuildingType.钢结构房: _RANK_NORMAL, 104 | BuildingType.平房: _RANK_NORMAL, 105 | BuildingType.小型公寓: _RANK_NORMAL, 106 | BuildingType.人才公寓: _RANK_RARE, 107 | BuildingType.花园洋房: _RANK_RARE, 108 | BuildingType.中式小楼: _RANK_RARE, 109 | BuildingType.空中别墅: _RANK_EPIC, 110 | BuildingType.复兴公馆: _RANK_EPIC, 111 | BuildingType.便利店: _RANK_NORMAL, 112 | BuildingType.五金店: _RANK_NORMAL, 113 | BuildingType.服装店: _RANK_NORMAL, 114 | BuildingType.菜市场: _RANK_NORMAL, 115 | BuildingType.学校: _RANK_NORMAL, 116 | BuildingType.图书城: _RANK_RARE, 117 | BuildingType.商贸中心: _RANK_RARE, 118 | BuildingType.加油站: _RANK_RARE, 119 | BuildingType.民食斋: _RANK_EPIC, 120 | BuildingType.媒体之声: _RANK_EPIC, 121 | BuildingType.木材厂: _RANK_NORMAL, 122 | BuildingType.食品厂: _RANK_NORMAL, 123 | BuildingType.造纸厂: _RANK_NORMAL, 124 | BuildingType.水厂: _RANK_NORMAL, 125 | BuildingType.电厂: _RANK_NORMAL, 126 | BuildingType.钢铁厂: _RANK_RARE, 127 | BuildingType.纺织厂: _RANK_RARE, 128 | BuildingType.零件厂: _RANK_RARE, 129 | BuildingType.企鹅机械: _RANK_EPIC, 130 | BuildingType.人民石油: _RANK_EPIC, 131 | BuildingType.梦想公寓: _RANK_EPIC, 132 | BuildingType.追梦快递: _RANK_RARE, 133 | BuildingType.游泳馆: _RANK_EPIC, 134 | BuildingType.强国煤业: _RANK_EPIC, 135 | } 136 | # 建筑对应火车货物 137 | BUILDING_2_GOODS = { 138 | BuildingType.木屋: TargetType.Chair, 139 | BuildingType.居民楼: TargetType.Box, 140 | BuildingType.钢结构房: TargetType.Sofa, 141 | BuildingType.平房: TargetType.Potting, 142 | BuildingType.小型公寓: TargetType.Cupboard, 143 | BuildingType.人才公寓: TargetType.Computer, 144 | BuildingType.花园洋房: TargetType.Fertilizer, 145 | BuildingType.中式小楼: TargetType.Quilt, 146 | BuildingType.空中别墅: TargetType.Lamp, 147 | BuildingType.复兴公馆: TargetType.Silk, 148 | BuildingType.便利店: TargetType.Bottle, 149 | BuildingType.五金店: TargetType.Screw, 150 | BuildingType.服装店: TargetType.Cloth, 151 | BuildingType.菜市场: TargetType.Vegetable, 152 | BuildingType.学校: TargetType.Schoolbag, 153 | BuildingType.图书城: TargetType.Book, 154 | BuildingType.商贸中心: TargetType.Heels, 155 | BuildingType.加油站: TargetType.Gasoline, 156 | BuildingType.民食斋: TargetType.Chicken, 157 | BuildingType.媒体之声: TargetType.Mic, 158 | BuildingType.木材厂: TargetType.Wood, 159 | BuildingType.食品厂: TargetType.Food, 160 | BuildingType.造纸厂: TargetType.Straw, 161 | BuildingType.水厂: TargetType.Chlorine, 162 | BuildingType.电厂: TargetType.Mine, 163 | BuildingType.钢铁厂: TargetType.Coal, 164 | BuildingType.纺织厂: TargetType.Cotton, 165 | BuildingType.零件厂: TargetType.Steel, 166 | BuildingType.企鹅机械: TargetType.Kit, 167 | BuildingType.人民石油: TargetType.Oil, 168 | BuildingType.梦想公寓: TargetType.Refrigerator, 169 | BuildingType.追梦快递: TargetType.FlatCar, 170 | BuildingType.游泳馆: TargetType.BeachUmbrella, 171 | BuildingType.强国煤业: TargetType.Helmet, 172 | } 173 | 174 | # 终止信号 175 | END = 'end' 176 | 177 | # 命令信号 178 | RUN = 'run' 179 | 180 | # 命令集 181 | # 升级至 x 级 182 | UPGRADE_TO = 'upgrade_to' 183 | # 升级 x 次 184 | UPGRADE_TIMES = 'upgrade_times' 185 | # 命令模式信号 186 | COMMAND_MODE = 'command_mode' 187 | # 开红包 188 | UNPACK = 'unpack' 189 | # 开相册 190 | OPEN_ALBUM = 'album' 191 | # 输出总结信息 192 | SUMMARY = 'summary' -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |