Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure the code to make it simpler #153

Merged
merged 4 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
**/__pycache__
.idea/
clashroyalebuildabot/screenshots
clashroyalebuildabot/labels
clashroyalebuildabot/logs
clashroyalebuildabot/debug
.venv
.vscode
*.egg-info
Expand Down
2 changes: 1 addition & 1 deletion clashroyalebuildabot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Exports for clashroyalebuildabot
from . import constants
from .bot import Action
from .bot import Bot
from .bot import PeteBot
from .bot import RandomBot
from .bot import TwoSixHogCycle
from .data import constants
from .namespaces import Cards
from .namespaces import Units
from .screen import Screen
Expand Down
28 changes: 14 additions & 14 deletions clashroyalebuildabot/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
from loguru import logger

from clashroyalebuildabot.bot.action import Action
from clashroyalebuildabot.data.constants import ALLY_TILES
from clashroyalebuildabot.data.constants import DISPLAY_CARD_DELTA_X
from clashroyalebuildabot.data.constants import DISPLAY_CARD_HEIGHT
from clashroyalebuildabot.data.constants import DISPLAY_CARD_INIT_X
from clashroyalebuildabot.data.constants import DISPLAY_CARD_WIDTH
from clashroyalebuildabot.data.constants import DISPLAY_CARD_Y
from clashroyalebuildabot.data.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.data.constants import LEFT_PRINCESS_TILES
from clashroyalebuildabot.data.constants import RIGHT_PRINCESS_TILES
from clashroyalebuildabot.data.constants import SCREEN_CONFIG
from clashroyalebuildabot.data.constants import TILE_HEIGHT
from clashroyalebuildabot.data.constants import TILE_INIT_X
from clashroyalebuildabot.data.constants import TILE_INIT_Y
from clashroyalebuildabot.data.constants import TILE_WIDTH
from clashroyalebuildabot.constants import ALLY_TILES
from clashroyalebuildabot.constants import DISPLAY_CARD_DELTA_X
from clashroyalebuildabot.constants import DISPLAY_CARD_HEIGHT
from clashroyalebuildabot.constants import DISPLAY_CARD_INIT_X
from clashroyalebuildabot.constants import DISPLAY_CARD_WIDTH
from clashroyalebuildabot.constants import DISPLAY_CARD_Y
from clashroyalebuildabot.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.constants import LEFT_PRINCESS_TILES
from clashroyalebuildabot.constants import RIGHT_PRINCESS_TILES
from clashroyalebuildabot.constants import SCREEN_CONFIG
from clashroyalebuildabot.constants import TILE_HEIGHT
from clashroyalebuildabot.constants import TILE_INIT_X
from clashroyalebuildabot.constants import TILE_INIT_Y
from clashroyalebuildabot.constants import TILE_WIDTH
from clashroyalebuildabot.screen import Screen
from clashroyalebuildabot.state.detector import Detector

Expand Down
8 changes: 4 additions & 4 deletions clashroyalebuildabot/bot/example/custom_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

from clashroyalebuildabot.bot import Bot
from clashroyalebuildabot.bot.example.custom_action import CustomAction
from clashroyalebuildabot.data.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.data.constants import DISPLAY_WIDTH
from clashroyalebuildabot.data.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.data.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.constants import DISPLAY_WIDTH
from clashroyalebuildabot.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.namespaces.cards import Cards


Expand Down
8 changes: 4 additions & 4 deletions clashroyalebuildabot/bot/pete/pete_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

from clashroyalebuildabot.bot.bot import Bot
from clashroyalebuildabot.bot.pete.pete_action import PeteAction
from clashroyalebuildabot.data.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.data.constants import DISPLAY_WIDTH
from clashroyalebuildabot.data.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.data.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.constants import DISPLAY_WIDTH
from clashroyalebuildabot.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.constants import SCREENSHOT_WIDTH


class PeteBot(Bot):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from clashroyalebuildabot.bot.two_six_hog_cycle.two_six_hog_cycle_action import (
TwoSixHogCycleAction,
)
from clashroyalebuildabot.data.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.data.constants import DISPLAY_WIDTH
from clashroyalebuildabot.data.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.data.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.constants import DISPLAY_WIDTH
from clashroyalebuildabot.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.namespaces.cards import Cards


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from clashroyalebuildabot.namespaces import Units

# Directories
SRC_DIR = os.path.dirname(os.path.dirname(__file__))
DATA_DIR = os.path.join(SRC_DIR, "data")
SCREENSHOTS_DIR = os.path.join(SRC_DIR, "screenshots")
LABELS_DIR = os.path.join(SRC_DIR, "labels")
SRC_DIR = os.path.dirname(__file__)
DEBUG_DIR = os.path.join(SRC_DIR, "debug")
MODELS_DIR = os.path.join(SRC_DIR, "models")
IMAGES_DIR = os.path.join(SRC_DIR, "images")
SCREENSHOTS_DIR = os.path.join(DEBUG_DIR, "screenshots")
LABELS_DIR = os.path.join(DEBUG_DIR, "labels")

# Display dimensions
DISPLAY_WIDTH = 720
Expand Down Expand Up @@ -73,8 +75,6 @@
DISPLAY_CARD_DELTA_X = 136

# Cards
HAND_SIZE = 5
DECK_SIZE = 8
CARD_Y = 543
CARD_INIT_X = 84
CARD_WIDTH = 61
Expand Down Expand Up @@ -196,8 +196,6 @@
]

# Units
UNIT_Y_START = 0.05
UNIT_Y_END = 0.80
DETECTOR_UNITS = [
Units.ARCHER,
Units.BARBARIAN,
Expand Down Expand Up @@ -233,10 +231,3 @@
Units.WALL_BREAKER,
Units.X_BOW,
]

# Multihash coefficients
MULTI_HASH_SCALE = 0.355
MULTI_HASH_INTERCEPT = 163

# Side
SIDE_SIZE = 16
4 changes: 0 additions & 4 deletions clashroyalebuildabot/data/__init__.py

This file was deleted.

9 changes: 4 additions & 5 deletions clashroyalebuildabot/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
from PIL import Image
import yaml

from clashroyalebuildabot.data.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.data.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.constants import SCREENSHOT_HEIGHT
from clashroyalebuildabot.constants import SCREENSHOT_WIDTH
from clashroyalebuildabot.constants import SRC_DIR


class Screen:
def __init__(self):
config_path = os.path.join(
os.path.dirname(__file__), "config", "config.yml"
)
config_path = os.path.join(SRC_DIR, "config.yaml")
with open(config_path, encoding="utf-8") as file:
config = yaml.safe_load(file)

Expand Down
32 changes: 20 additions & 12 deletions clashroyalebuildabot/state/card_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
from PIL import Image
from scipy.optimize import linear_sum_assignment

from clashroyalebuildabot.data.constants import CARD_CONFIG
from clashroyalebuildabot.data.constants import DATA_DIR
from clashroyalebuildabot.data.constants import HAND_SIZE
from clashroyalebuildabot.data.constants import MULTI_HASH_INTERCEPT
from clashroyalebuildabot.data.constants import MULTI_HASH_SCALE
from clashroyalebuildabot.constants import CARD_CONFIG
from clashroyalebuildabot.constants import IMAGES_DIR
from clashroyalebuildabot.namespaces.cards import Cards


class CardDetector:
HAND_SIZE = 5
MULTI_HASH_SCALE = 0.355
MULTI_HASH_INTERCEPT = 163

def __init__(self, cards, hash_size=8, grey_std_threshold=5):
self.cards = cards
self.hash_size = hash_size
Expand All @@ -23,8 +24,12 @@ def __init__(self, cards, hash_size=8, grey_std_threshold=5):

def _calculate_multi_hash(self, image):
gray_image = self._calculate_hash(image)
light_image = MULTI_HASH_SCALE * gray_image + MULTI_HASH_INTERCEPT
dark_image = (gray_image - MULTI_HASH_INTERCEPT) / MULTI_HASH_SCALE
light_image = (
self.MULTI_HASH_SCALE * gray_image + self.MULTI_HASH_INTERCEPT
)
dark_image = (
gray_image - self.MULTI_HASH_INTERCEPT
) / self.MULTI_HASH_SCALE
multi_hash = np.vstack([gray_image, light_image, dark_image]).astype(
np.float32
)
Expand All @@ -40,18 +45,21 @@ def _calculate_hash(self, image):

def _calculate_card_hashes(self):
card_hashes = np.zeros(
(len(self.cards), 3, self.hash_size * self.hash_size, HAND_SIZE),
(
len(self.cards),
3,
self.hash_size * self.hash_size,
self.HAND_SIZE,
),
dtype=np.float32,
)
for i, card in enumerate(self.cards):
path = os.path.join(
DATA_DIR, "images", "cards", f"{card.name}.jpg"
)
path = os.path.join(IMAGES_DIR, "cards", f"{card.name}.jpg")
pil_image = Image.open(path)

multi_hash = self._calculate_multi_hash(pil_image)
card_hashes[i] = np.tile(
np.expand_dims(multi_hash, axis=2), (1, 1, HAND_SIZE)
np.expand_dims(multi_hash, axis=2), (1, 1, self.HAND_SIZE)
)

return card_hashes
Expand Down
6 changes: 3 additions & 3 deletions clashroyalebuildabot/state/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from PIL import ImageDraw
from PIL import ImageFont

from clashroyalebuildabot.data.constants import CARD_CONFIG
from clashroyalebuildabot.data.constants import LABELS_DIR
from clashroyalebuildabot.data.constants import SCREENSHOTS_DIR
from clashroyalebuildabot.constants import CARD_CONFIG
from clashroyalebuildabot.constants import LABELS_DIR
from clashroyalebuildabot.constants import SCREENSHOTS_DIR
from clashroyalebuildabot.namespaces.units import NAME2UNIT


Expand Down
17 changes: 9 additions & 8 deletions clashroyalebuildabot/state/detector.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import os

from clashroyalebuildabot.data.constants import DATA_DIR
from clashroyalebuildabot.data.constants import DECK_SIZE
from clashroyalebuildabot.constants import MODELS_DIR
from clashroyalebuildabot.state.card_detector import CardDetector
from clashroyalebuildabot.state.debugger import Debugger
from clashroyalebuildabot.state.number_detector import NumberDetector
from clashroyalebuildabot.state.screen_detector import ScreenDetector
from clashroyalebuildabot.state.side_detector import SideDetector
from clashroyalebuildabot.state.unit_detector import UnitDetector


class Detector:
DECK_SIZE = 8

def __init__(self, cards, debug=False):
if len(cards) != DECK_SIZE:
raise ValueError(f"You must specify all {DECK_SIZE} of your cards")
if len(cards) != self.DECK_SIZE:
raise ValueError(
f"You must specify all {self.DECK_SIZE} of your cards"
)

self.cards = cards
self.debug = debug

self.card_detector = CardDetector(self.cards)
self.number_detector = NumberDetector(
os.path.join(DATA_DIR, "numbers_S_128x32.onnx")
os.path.join(MODELS_DIR, "numbers_S_128x32.onnx")
)
self.unit_detector = UnitDetector(
os.path.join(DATA_DIR, "units_M_480x352.onnx"), self.cards
os.path.join(MODELS_DIR, "units_M_480x352.onnx"), self.cards
)
self.screen_detector = ScreenDetector()
self.side_detector = SideDetector(os.path.join(DATA_DIR, "side.onnx"))

self.debugger = None
if self.debug:
Expand Down
12 changes: 6 additions & 6 deletions clashroyalebuildabot/state/number_detector.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import numpy as np

from clashroyalebuildabot.data.constants import ELIXIR_BOUNDING_BOX
from clashroyalebuildabot.data.constants import KING_HP
from clashroyalebuildabot.data.constants import KING_LEVEL_2_X
from clashroyalebuildabot.data.constants import NUMBER_CONFIG
from clashroyalebuildabot.data.constants import NUMBER_HEIGHT
from clashroyalebuildabot.data.constants import NUMBER_WIDTH
from clashroyalebuildabot.constants import ELIXIR_BOUNDING_BOX
from clashroyalebuildabot.constants import KING_HP
from clashroyalebuildabot.constants import KING_LEVEL_2_X
from clashroyalebuildabot.constants import NUMBER_CONFIG
from clashroyalebuildabot.constants import NUMBER_HEIGHT
from clashroyalebuildabot.constants import NUMBER_WIDTH
from clashroyalebuildabot.state.onnx_detector import OnnxDetector


Expand Down
6 changes: 3 additions & 3 deletions clashroyalebuildabot/state/screen_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import numpy as np
from PIL import Image

from clashroyalebuildabot.data.constants import DATA_DIR
from clashroyalebuildabot.data.constants import SCREEN_CONFIG
from clashroyalebuildabot.constants import IMAGES_DIR
from clashroyalebuildabot.constants import SCREEN_CONFIG


class ScreenDetector:
Expand All @@ -19,7 +19,7 @@ def _calculate_screen_hashes(self):
dtype=np.int32,
)
for i, name in enumerate(SCREEN_CONFIG.keys()):
path = os.path.join(DATA_DIR, "images", "screen", f"{name}.jpg")
path = os.path.join(IMAGES_DIR, "screen", f"{name}.jpg")
image = Image.open(path)
hash_ = np.array(
image.resize(
Expand Down
10 changes: 6 additions & 4 deletions clashroyalebuildabot/state/side_detector.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import numpy as np
from PIL import Image

from clashroyalebuildabot.data.constants import SIDE_SIZE
from clashroyalebuildabot.state.onnx_detector import OnnxDetector


class SideDetector(OnnxDetector):
@staticmethod
def _preprocess(image):
image = image.resize((SIDE_SIZE, SIDE_SIZE), Image.Resampling.BICUBIC)
SIDE_SIZE = 16

def _preprocess(self, image):
image = image.resize(
(self.SIDE_SIZE, self.SIDE_SIZE), Image.Resampling.BICUBIC
)
image = np.array(image, dtype=np.float32) / 255
return np.expand_dims(image, axis=0)

Expand Down
Loading