mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-09 06:07:40 +08:00
Add: Support .gif button assets
This commit is contained in:
parent
5f17cd71d5
commit
6184d2d71e
@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
import imageio
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
@ -21,50 +22,78 @@ VALID_SERVER = ['cn', 'en', 'jp', 'tw']
|
||||
|
||||
|
||||
class ImageExtractor:
|
||||
def __init__(self, module, file, config):
|
||||
def __init__(self, module, file):
|
||||
"""
|
||||
Args:
|
||||
module(str):
|
||||
file(str): xxx.png
|
||||
config(AzurLaneConfig):
|
||||
file(str): xxx.png or xxx.gif
|
||||
"""
|
||||
self.module = module
|
||||
self.name, self.ext = os.path.splitext(file)
|
||||
self.config = config
|
||||
self.area, self.color, self.button, self.file = {}, {}, {}, {}
|
||||
for server in VALID_SERVER:
|
||||
self.load(server)
|
||||
|
||||
def get_file(self, genre='', server='cn'):
|
||||
file = f'{self.name}.{genre}{self.ext}' if genre else f'{self.name}{self.ext}'
|
||||
file = os.path.join(self.config.ASSETS_FOLDER, server, self.module, file)
|
||||
for ext in ['.png', '.gif']:
|
||||
file = f'{self.name}.{genre}{ext}' if genre else f'{self.name}{ext}'
|
||||
file = os.path.join(AzurLaneConfig.ASSETS_FOLDER, server, self.module, file).replace('\\', '/')
|
||||
if os.path.exists(file):
|
||||
return file
|
||||
|
||||
ext = '.png'
|
||||
file = f'{self.name}.{genre}{ext}' if genre else f'{self.name}{ext}'
|
||||
file = os.path.join(AzurLaneConfig.ASSETS_FOLDER, server, self.module, file).replace('\\', '/')
|
||||
return file
|
||||
|
||||
def extract(self, file):
|
||||
if os.path.splitext(file)[1] == '.gif':
|
||||
# In a gif Button, use the first image.
|
||||
bbox = None
|
||||
mean = None
|
||||
for image in imageio.mimread(file):
|
||||
image = image[:, :, :3] if len(image.shape) == 3 else image
|
||||
image = Image.fromarray(image)
|
||||
new_bbox, new_mean = self._extract(image, file)
|
||||
if bbox is None:
|
||||
bbox = new_bbox
|
||||
elif bbox != new_bbox:
|
||||
logger.warning(f'{file} has multiple different bbox, this will cause unexpected behaviour')
|
||||
if mean is None:
|
||||
mean = new_mean
|
||||
return bbox, mean
|
||||
else:
|
||||
image = Image.open(file).convert('RGB')
|
||||
return self._extract(image, file)
|
||||
|
||||
@staticmethod
|
||||
def extract(file):
|
||||
image = Image.open(file).convert('RGB')
|
||||
def _extract(image, file):
|
||||
if image.size != (1280, 720):
|
||||
logger.warning(f'Incorrect asset {image.size} {file}')
|
||||
logger.warning(f'{file} has wrong resolution: {image.size}')
|
||||
bbox = image.getbbox()
|
||||
mean = get_color(image=image, area=bbox)
|
||||
mean = tuple(np.rint(mean).astype(int))
|
||||
return bbox, mean
|
||||
|
||||
def load(self, server='cn'):
|
||||
if os.path.exists(self.get_file(server=server)):
|
||||
area, color = self.extract(self.get_file(server=server))
|
||||
file = self.get_file(server=server)
|
||||
if os.path.exists(file):
|
||||
area, color = self.extract(file)
|
||||
button = area
|
||||
if os.path.exists(self.get_file('AREA', server=server)):
|
||||
area, _ = self.extract(self.get_file('AREA', server=server))
|
||||
if os.path.exists(self.get_file('COLOR', server=server)):
|
||||
_, color = self.extract(self.get_file('COLOR', server=server))
|
||||
if os.path.exists(self.get_file('BUTTON', server=server)):
|
||||
button, _ = self.extract(self.get_file('BUTTON', server=server))
|
||||
override = self.get_file('AREA', server=server)
|
||||
if os.path.exists(override):
|
||||
area, _ = self.extract(override)
|
||||
override = self.get_file('COLOR', server=server)
|
||||
if os.path.exists(override):
|
||||
_, color = self.extract(override)
|
||||
override = self.get_file('BUTTON', server=server)
|
||||
if os.path.exists(override):
|
||||
button, _ = self.extract(override)
|
||||
|
||||
self.area[server] = area
|
||||
self.color[server] = color
|
||||
self.button[server] = button
|
||||
self.file[server] = f"{self.config.ASSETS_FOLDER}/{server}/{self.module}/{self.name}{self.ext}"
|
||||
self.file[server] = file
|
||||
else:
|
||||
logger.attr(server, f'{self.name} not found, use cn server assets')
|
||||
self.area[server] = self.area['cn']
|
||||
@ -115,10 +144,9 @@ class TemplateExtractor(ImageExtractor):
|
||||
|
||||
|
||||
class ModuleExtractor:
|
||||
def __init__(self, name, config):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.config = config
|
||||
self.folder = os.path.join(self.config.ASSETS_FOLDER, 'cn', name)
|
||||
self.folder = os.path.join(AzurLaneConfig.ASSETS_FOLDER, 'cn', name)
|
||||
|
||||
@staticmethod
|
||||
def split(file):
|
||||
@ -137,13 +165,13 @@ class ModuleExtractor:
|
||||
if file[0].isdigit():
|
||||
continue
|
||||
if file.startswith('TEMPLATE_'):
|
||||
exp.append(TemplateExtractor(module=self.name, file=file, config=self.config).expression)
|
||||
exp.append(TemplateExtractor(module=self.name, file=file).expression)
|
||||
continue
|
||||
# if file.startswith('OCR_'):
|
||||
# exp.append(OcrExtractor(module=self.name, file=file, config=self.config).expression)
|
||||
# continue
|
||||
if self.is_base_image(file):
|
||||
exp.append(ImageExtractor(module=self.name, file=file, config=self.config).expression)
|
||||
exp.append(ImageExtractor(module=self.name, file=file).expression)
|
||||
continue
|
||||
|
||||
logger.info('Module: %s(%s)' % (self.name, len(exp)))
|
||||
@ -178,14 +206,14 @@ class AssetExtractor:
|
||||
E.g. OCR_EXERCISE_TIMES.png.
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self):
|
||||
logger.info('Assets extract')
|
||||
|
||||
for module in os.listdir(config.ASSETS_FOLDER + '/cn'):
|
||||
if os.path.isdir(os.path.join(config.ASSETS_FOLDER + '/cn', module)):
|
||||
me = ModuleExtractor(name=module, config=config)
|
||||
for module in os.listdir(AzurLaneConfig.ASSETS_FOLDER + '/cn'):
|
||||
if os.path.isdir(os.path.join(AzurLaneConfig.ASSETS_FOLDER + '/cn', module)):
|
||||
me = ModuleExtractor(name=module)
|
||||
me.write()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ae = AssetExtractor(AzurLaneConfig('template'))
|
||||
ae = AssetExtractor()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import os
|
||||
import traceback
|
||||
|
||||
import imageio
|
||||
from PIL import Image
|
||||
|
||||
import module.config.server as server
|
||||
@ -35,6 +36,7 @@ class Button:
|
||||
self._match_init = False
|
||||
self.file = file[self.server] if isinstance(file, dict) else file
|
||||
self.image = None
|
||||
|
||||
if self.file:
|
||||
self.name = os.path.splitext(os.path.split(self.file)[1])[0]
|
||||
elif name:
|
||||
@ -43,6 +45,11 @@ class Button:
|
||||
(filename, line_number, function_name, text) = traceback.extract_stack()[-2]
|
||||
self.name = text[:text.find('=')].strip()
|
||||
|
||||
if self.file:
|
||||
self.is_gif = os.path.splitext(self.file)[1] == '.gif'
|
||||
else:
|
||||
self.is_gif = False
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@ -92,6 +99,7 @@ class Button:
|
||||
"""
|
||||
self.color = get_color(image, self.area)
|
||||
self.image = np.array(image.crop(self.area))
|
||||
self.is_gif = False
|
||||
return self.color
|
||||
|
||||
def load_offset(self, button):
|
||||
@ -113,7 +121,14 @@ class Button:
|
||||
If needs to call self.match, call this first.
|
||||
"""
|
||||
if not self._match_init:
|
||||
self.image = np.array(Image.open(self.file).crop(self.area).convert('RGB'))
|
||||
if self.is_gif:
|
||||
self.image = []
|
||||
for image in imageio.mimread(self.file):
|
||||
image = image[:, :, :3] if len(image.shape) == 3 else image
|
||||
image = crop(image, self.area)
|
||||
self.image.append(image)
|
||||
else:
|
||||
self.image = np.array(Image.open(self.file).crop(self.area).convert('RGB'))
|
||||
self._match_init = True
|
||||
|
||||
def match(self, image, offset=30, threshold=0.85):
|
||||
@ -132,17 +147,22 @@ class Button:
|
||||
if isinstance(offset, tuple):
|
||||
offset = np.array((-offset[0], -offset[1], offset[0], offset[1]))
|
||||
else:
|
||||
offset = np.array((0, -offset, 0, offset))
|
||||
|
||||
# offset = np.array((0, -offset, 0, offset))
|
||||
# offset = np.array((-offset, -offset, offset, offset))
|
||||
offset = np.array((3, -offset, 3, offset))
|
||||
image = np.array(image.crop(offset + self.area))
|
||||
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
|
||||
return similarity > threshold
|
||||
if self.is_gif:
|
||||
for template in self.image:
|
||||
res = cv2.matchTemplate(template, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
if similarity > threshold:
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
return similarity > threshold
|
||||
|
||||
def match_appear_on(self, image, threshold=10):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user