Worked on additional tools
This commit is contained in:
@@ -41,27 +41,30 @@ def adjust_squares(
|
|||||||
|
|
||||||
if not adjustment:
|
if not adjustment:
|
||||||
adjustment = Adjustment(w=10, h=10)
|
adjustment = Adjustment(w=10, h=10)
|
||||||
|
high_speed = False
|
||||||
|
|
||||||
def _adjustment_step(keycode: int) -> None:
|
def _adjustment_step(keycode: int, high_speed: bool) -> None:
|
||||||
assert adjustment is not None
|
assert adjustment is not None
|
||||||
x_keys = {81: -1, 83: +1, 104: -10, 115: +10}
|
x_keys = {104: -1, 115: +1}
|
||||||
y_keys = {82: -1, 84: +1, 116: -10, 110: +10}
|
y_keys = {116: -1, 110: +1}
|
||||||
w_keys = {97: -1, 117: +1}
|
w_keys = {97: -1, 117: +1}
|
||||||
h_keys = {111: -1, 101: +1}
|
h_keys = {111: -1, 101: +1}
|
||||||
dx_keys = {59: -1, 112: +1}
|
dx_keys = {59: -1, 112: +1}
|
||||||
dy_keys = {44: -1, 46: +1}
|
dy_keys = {44: -1, 46: +1}
|
||||||
|
high_speed_fac = 10
|
||||||
|
cur_high_speed_fac = high_speed_fac if high_speed else 1
|
||||||
if keycode in x_keys:
|
if keycode in x_keys:
|
||||||
adjustment.x += x_keys[keycode]
|
adjustment.x += x_keys[keycode] * cur_high_speed_fac
|
||||||
elif keycode in y_keys:
|
elif keycode in y_keys:
|
||||||
adjustment.y += y_keys[keycode]
|
adjustment.y += y_keys[keycode] * cur_high_speed_fac
|
||||||
elif keycode in w_keys:
|
elif keycode in w_keys:
|
||||||
adjustment.w += w_keys[keycode]
|
adjustment.w += w_keys[keycode] * cur_high_speed_fac
|
||||||
elif keycode in h_keys:
|
elif keycode in h_keys:
|
||||||
adjustment.h += h_keys[keycode]
|
adjustment.h += h_keys[keycode] * cur_high_speed_fac
|
||||||
elif keycode in dx_keys:
|
elif keycode in dx_keys:
|
||||||
adjustment.dx += dx_keys[keycode]
|
adjustment.dx += dx_keys[keycode] * cur_high_speed_fac
|
||||||
elif keycode in dy_keys:
|
elif keycode in dy_keys:
|
||||||
adjustment.dy += dy_keys[keycode]
|
adjustment.dy += dy_keys[keycode] * cur_high_speed_fac
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
working_image = image.copy()
|
working_image = image.copy()
|
||||||
@@ -75,7 +78,10 @@ def adjust_squares(
|
|||||||
print(keycode)
|
print(keycode)
|
||||||
if keycode == 27:
|
if keycode == 27:
|
||||||
break
|
break
|
||||||
_adjustment_step(keycode)
|
if keycode == 229:
|
||||||
|
high_speed = not high_speed
|
||||||
|
continue
|
||||||
|
_adjustment_step(keycode, high_speed)
|
||||||
|
|
||||||
cv2.destroyWindow("Window")
|
cv2.destroyWindow("Window")
|
||||||
return adjustment
|
return adjustment
|
||||||
|
|||||||
@@ -99,9 +99,65 @@ def _save_adjustments(zip_file: zipfile.ZipFile, conf: Configuration) -> None:
|
|||||||
adjustments = {}
|
adjustments = {}
|
||||||
adjustments[FIELD_ADJUSTMENT_KEY] = dataclasses.asdict(conf.field_adjustment)
|
adjustments[FIELD_ADJUSTMENT_KEY] = dataclasses.asdict(conf.field_adjustment)
|
||||||
adjustments[BORDER_ADJUSTMENT_KEY] = dataclasses.asdict(conf.border_adjustment)
|
adjustments[BORDER_ADJUSTMENT_KEY] = dataclasses.asdict(conf.border_adjustment)
|
||||||
|
adjustments[GOAL_ADJUSTMENT_KEY] = dataclasses.asdict(conf.goal_adjustment)
|
||||||
|
adjustments[BUNKER_ADJUSTMENT_KEY] = dataclasses.asdict(conf.bunker_adjustment)
|
||||||
|
adjustments[HUA_ADJUSTMENT_KEY] = dataclasses.asdict(conf.hua_adjustment)
|
||||||
|
adjustments[SPECIAL_BUTTON_ADJUSTMENT_KEY] = dataclasses.asdict(
|
||||||
|
conf.special_button_adjustment
|
||||||
|
)
|
||||||
|
print(adjustments)
|
||||||
zip_file.writestr(
|
zip_file.writestr(
|
||||||
ADJUSTMENT_FILE_NAME, json.dumps(adjustment),
|
ADJUSTMENT_FILE_NAME, json.dumps(adjustments),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _save_special_images(zip_file: zipfile.ZipFile, conf: Configuration) -> None:
|
||||||
|
def _save_special_image(
|
||||||
|
zip_file: zipfile.ZipFile, images: List[np.ndarray], directory: str
|
||||||
|
) -> None:
|
||||||
|
for index, image in enumerate(images):
|
||||||
|
fd, myfile = tempfile.mkstemp(suffix=f".{PICTURE_EXTENSION}")
|
||||||
|
cv2.imwrite(myfile, image)
|
||||||
|
file_name = ""
|
||||||
|
zip_file.write(
|
||||||
|
myfile, arcname=f"{directory}/{index:03}.{PICTURE_EXTENSION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
_save_special_image(zip_file, conf.card_border, CARD_BORDER_DIRECTORY)
|
||||||
|
_save_special_image(zip_file, conf.empty_card, EMPTY_CARD_DIRECTORY)
|
||||||
|
_save_special_image(zip_file, conf.green_card, GREEN_CARD_DIRECTORY)
|
||||||
|
_save_special_image(zip_file, conf.card_back, CARD_BACK_DIRECTORY)
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_special_button_filename(
|
||||||
|
state: ButtonState, special_card: board.SpecialCard
|
||||||
|
) -> str:
|
||||||
|
state_char_map = {
|
||||||
|
ButtonState.normal: "n",
|
||||||
|
ButtonState.greyed: "g",
|
||||||
|
ButtonState.shiny: "s",
|
||||||
|
}
|
||||||
|
special_card_char_map = {
|
||||||
|
board.SpecialCard.Fa: "f",
|
||||||
|
board.SpecialCard.Zhong: "z",
|
||||||
|
board.SpecialCard.Bai: "b",
|
||||||
|
}
|
||||||
|
return f"{state_char_map[state]}{special_card_char_map[special_card]}"
|
||||||
|
|
||||||
|
|
||||||
|
def _save_special_button_images(
|
||||||
|
zip_file: zipfile.ZipFile,
|
||||||
|
special_button_images: List[Tuple[ButtonState, board.SpecialCard, np.ndarray]],
|
||||||
|
):
|
||||||
|
for index, (state, card, image) in enumerate(special_button_images):
|
||||||
|
fd, myfile = tempfile.mkstemp(suffix=f".{PICTURE_EXTENSION}")
|
||||||
|
cv2.imwrite(myfile, image)
|
||||||
|
file_name = ""
|
||||||
|
zip_file.write(
|
||||||
|
myfile,
|
||||||
|
arcname=f"{SPECIAL_BUTTON_DIRECTORY}/"
|
||||||
|
f"{_generate_special_button_filename(state,card)}"
|
||||||
|
f"{index:03}.{PICTURE_EXTENSION}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +168,8 @@ def save(conf: Configuration, filename: str) -> None:
|
|||||||
with zipfile.ZipFile(zip_stream, "w") as zip_file:
|
with zipfile.ZipFile(zip_stream, "w") as zip_file:
|
||||||
_save_adjustments(zip_file, conf)
|
_save_adjustments(zip_file, conf)
|
||||||
_save_catalogue(zip_file, conf.catalogue)
|
_save_catalogue(zip_file, conf.catalogue)
|
||||||
# TODO: Save card_borders and emtpy_card and green_card and special_buttons and card_back
|
_save_special_images(zip_file, conf)
|
||||||
|
_save_special_button_images(zip_file, conf.special_buttons)
|
||||||
with open(filename, "wb") as zip_archive:
|
with open(filename, "wb") as zip_archive:
|
||||||
zip_archive.write(zip_stream.getvalue())
|
zip_archive.write(zip_stream.getvalue())
|
||||||
|
|
||||||
|
|||||||
78
tools/generate/all_borders.py
Normal file
78
tools/generate/all_borders.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import argparse
|
||||||
|
import copy
|
||||||
|
import dataclasses
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import shenzhen_solitaire.card_detection.adjustment as adjustment
|
||||||
|
import shenzhen_solitaire.card_detection.card_finder as card_finder
|
||||||
|
import shenzhen_solitaire.card_detection.configuration as configuration
|
||||||
|
from shenzhen_solitaire.card_detection.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Generate a configuration"""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Calibrate to fit all symbols. "
|
||||||
|
"Ideally use a screenshot with cards in the bunker, "
|
||||||
|
"in the goal and also with a killed hua card"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"screenshot_path",
|
||||||
|
metavar="screenshot_path",
|
||||||
|
type=str,
|
||||||
|
help="Path to the screenshot",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--config",
|
||||||
|
metavar="config_path",
|
||||||
|
type=str,
|
||||||
|
default="test_config.zip",
|
||||||
|
help="Config path, either merge or write new",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(args.screenshot_path)
|
||||||
|
image = cv2.imread(args.screenshot_path)
|
||||||
|
|
||||||
|
if os.path.exists(args.config):
|
||||||
|
conf = configuration.load(args.config)
|
||||||
|
else:
|
||||||
|
conf = Configuration()
|
||||||
|
|
||||||
|
print("Field cards")
|
||||||
|
conf.field_adjustment = adjustment.adjust_squares(
|
||||||
|
image, count_x=8, count_y=13, adjustment=copy.deepcopy(conf.field_adjustment)
|
||||||
|
)
|
||||||
|
print("Field borders")
|
||||||
|
border_adjustment = adjustment.adjust_squares(
|
||||||
|
image, count_x=8, count_y=13, adjustment=copy.deepcopy(conf.field_adjustment)
|
||||||
|
)
|
||||||
|
conf.bunker_adjustment.w = conf.field_adjustment.w
|
||||||
|
conf.bunker_adjustment.h = conf.field_adjustment.h
|
||||||
|
print("Bunker cards")
|
||||||
|
bunker_adjustment = adjustment.adjust_squares(
|
||||||
|
image, count_x=3, count_y=1, adjustment=copy.deepcopy(conf.bunker_adjustment)
|
||||||
|
)
|
||||||
|
conf.goal_adjustment.w = conf.field_adjustment.w
|
||||||
|
conf.goal_adjustment.h = conf.field_adjustment.h
|
||||||
|
print("Goal cards")
|
||||||
|
goal_adjustment = adjustment.adjust_squares(
|
||||||
|
image, count_x=3, count_y=1, adjustment=copy.deepcopy(conf.goal_adjustment)
|
||||||
|
)
|
||||||
|
conf.hua_adjustment.w = conf.field_adjustment.w
|
||||||
|
conf.hua_adjustment.h = conf.field_adjustment.h
|
||||||
|
print("Hua card")
|
||||||
|
hua_adjustment = adjustment.adjust_squares(
|
||||||
|
image, count_x=1, count_y=1, adjustment=copy.deepcopy(conf.hua_adjustment)
|
||||||
|
)
|
||||||
|
|
||||||
|
configuration.save(conf, args.config)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -8,11 +8,19 @@ import numpy as np
|
|||||||
import shenzhen_solitaire.card_detection.adjustment as adjustment
|
import shenzhen_solitaire.card_detection.adjustment as adjustment
|
||||||
import shenzhen_solitaire.card_detection.card_finder as card_finder
|
import shenzhen_solitaire.card_detection.card_finder as card_finder
|
||||||
from shenzhen_solitaire.card_detection.configuration import Configuration
|
from shenzhen_solitaire.card_detection.configuration import Configuration
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
"""Generate a configuration"""
|
"""Generate a configuration"""
|
||||||
image = cv2.imread("pictures/20190809172213_1.jpg")
|
|
||||||
|
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||||
|
parser.add_argument('screenshot_path', metavar='screenshot_path', type=str,
|
||||||
|
help='Path to the screenshot')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(args.screenshot_path)
|
||||||
|
image = cv2.imread(args.screenshot_path)
|
||||||
|
|
||||||
border_adjustment = adjustment.adjust_squares(image, count_x=8, count_y=13)
|
border_adjustment = adjustment.adjust_squares(image, count_x=8, count_y=13)
|
||||||
border_square_pos = adjustment.adjust_squares(
|
border_square_pos = adjustment.adjust_squares(
|
||||||
|
|||||||
54
tools/generate/catalogue.py
Normal file
54
tools/generate/catalogue.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from shenzhen_solitaire.card_detection import configuration, adjustment, card_finder
|
||||||
|
from shenzhen_solitaire.card_detection.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Generate a configuration"""
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Generate pictures for symbols. "
|
||||||
|
"Requires screenshot of field with no moved cards, "
|
||||||
|
"so 8 columns of 5 cards each"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"screenshot_path",
|
||||||
|
metavar="screenshot_path",
|
||||||
|
type=str,
|
||||||
|
help="Path to the screenshot",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--conf",
|
||||||
|
dest="config_path",
|
||||||
|
type=str,
|
||||||
|
default="config.zip",
|
||||||
|
help="Path to existing config to be merged, or new config",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(args.screenshot_path)
|
||||||
|
image = cv2.imread(args.screenshot_path)
|
||||||
|
conf = configuration.load(args.config)
|
||||||
|
squares = card_finder.get_field_squares(image, conf.field_adjustment, 5, 8)
|
||||||
|
catalogue = card_finder.catalogue_cards(squares)
|
||||||
|
conf.card_border.extend(
|
||||||
|
card_finder.get_field_squares(image, conf.border_adjustment, 1, 1)
|
||||||
|
)
|
||||||
|
conf.green_card.extend(
|
||||||
|
card_finder.get_field_squares(image, conf.bunker_adjustment, 1, 3)
|
||||||
|
)
|
||||||
|
conf.green_card.extend(
|
||||||
|
card_finder.get_field_squares(image, conf.goal_adjustment, 1, 3)
|
||||||
|
)
|
||||||
|
conf.green_card.extend(
|
||||||
|
card_finder.get_field_squares(image, conf.hua_adjustment, 1, 1)
|
||||||
|
)
|
||||||
|
conf.catalogue.extend(catalogue)
|
||||||
|
configuration.save(conf, args.config_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,15 +1,42 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import shenzhen_solitaire.card_detection.configuration as configuration
|
from shenzhen_solitaire.card_detection import configuration, adjustment, card_finder
|
||||||
|
from shenzhen_solitaire.card_detection.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
"""Generate a configuration"""
|
"""Generate a configuration"""
|
||||||
image = cv2.imread("pictures/20190809172213_1.jpg")
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Generate pictures for symbols, "
|
||||||
|
"requires screenshot of field with no moved cards, "
|
||||||
|
"so 8 columns of 5 cards each"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"screenshot_path",
|
||||||
|
metavar="screenshot_path",
|
||||||
|
type=str,
|
||||||
|
help="Path to the screenshot",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--conf",
|
||||||
|
dest="config_path",
|
||||||
|
type=str,
|
||||||
|
default="config.zip",
|
||||||
|
help="Path to existing config to be merged, or new config",
|
||||||
|
)
|
||||||
|
|
||||||
generated_config = configuration.generate(image)
|
args = parser.parse_args()
|
||||||
configuration.save(generated_config, "test_config.zip")
|
print(args.screenshot_path)
|
||||||
|
image = cv2.imread(args.screenshot_path)
|
||||||
|
|
||||||
|
adj = adjustment.adjust_field(image)
|
||||||
|
squares = card_finder.get_field_squares(image, adj, 5, 8)
|
||||||
|
catalogue = card_finder.catalogue_cards(squares)
|
||||||
|
generated_config = Configuration(field_adjustment=adj, catalogue=catalogue, meta={})
|
||||||
|
configuration.save(generated_config, args.config_path)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user