diff --git a/Makefile b/Makefile index 9de82e9..32ee964 100644 --- a/Makefile +++ b/Makefile @@ -12,4 +12,4 @@ typing: mypy --strict ${PROJECTNAME} test linting: - pylint ${PROJECTNAME} test + pylint --extension-pkg-whitelist=cv2 ${PROJECTNAME} test diff --git a/shenzhen_solitaire/cv/adjustment.py b/shenzhen_solitaire/cv/adjustment.py index 70c7b64..1890739 100644 --- a/shenzhen_solitaire/cv/adjustment.py +++ b/shenzhen_solitaire/cv/adjustment.py @@ -2,8 +2,8 @@ from typing import Optional, Tuple from dataclasses import dataclass -import numpy # type: ignore -import cv2 # type: ignore +import numpy +import cv2 @dataclass diff --git a/shenzhen_solitaire/cv/board_parser.py b/shenzhen_solitaire/cv/board_parser.py index 79b939c..81c50dc 100644 --- a/shenzhen_solitaire/cv/board_parser.py +++ b/shenzhen_solitaire/cv/board_parser.py @@ -1,11 +1,13 @@ +"""Contains parse_board function""" + import numpy as np from .configuration import Configuration from ..board import Board from . import card_finder -import copy def parse_board(image: np.ndarray, conf: Configuration) -> Board: + """Parse a screenshot of the game, using a given configuration""" squares = card_finder.get_field_squares( image, conf.field_adjustment, count_x=13, count_y=8) squares = [card_finder.simplify(square)[0] for square in squares] diff --git a/shenzhen_solitaire/cv/card_finder.py b/shenzhen_solitaire/cv/card_finder.py index 3753289..77d4ef8 100644 --- a/shenzhen_solitaire/cv/card_finder.py +++ b/shenzhen_solitaire/cv/card_finder.py @@ -22,6 +22,7 @@ def get_field_squares(image: np.ndarray, adjustment: Adjustment, count_x: int, count_y: int) -> List[np.ndarray]: + """Return all squares in the field, according to the adjustment""" squares = [] for index_x, index_y in itertools.product(range(count_y), range(count_x)): squares.append(get_square(adjustment, index_x, index_y)) @@ -46,6 +47,7 @@ GREYSCALE_COLOR = { def simplify(image: np.ndarray) -> Tuple[np.ndarray, Dict[Cardcolor, int]]: + """Reduce given image to the colors in Cardcolor""" result_image: np.ndarray = np.zeros( (image.shape[0], image.shape[1]), np.uint8) result_dict: Dict[Cardcolor, int] = {c: 0 for c in Cardcolor} @@ -69,40 +71,42 @@ def _find_single_square(search_square: np.ndarray, assert search_square.shape[0] >= template_square.shape[0] assert search_square.shape[1] >= template_square.shape[1] best_result: Optional[Tuple[int, Tuple[int, int]]] = None - for x, y in itertools.product( + for margin_x, margin_y in itertools.product( range(search_square.shape[0], template_square.shape[0] - 1, -1), range(search_square.shape[1], template_square.shape[1] - 1, -1)): - p = search_square[x - template_square.shape[0]:x, - y - template_square.shape[1]:y] - template_square - count = cv2.countNonZero(p) + search_region = search_square[margin_x - + template_square.shape[0]:margin_x, margin_y - + template_square.shape[1]:margin_y] + count = cv2.countNonZero(search_region - template_square) if not best_result or count < best_result[0]: best_result = ( count, - (x - template_square.shape[0], - y - template_square.shape[1])) + (margin_x - template_square.shape[0], + margin_y - template_square.shape[1])) assert best_result return best_result def find_square(search_square: np.ndarray, squares: List[np.ndarray]) -> Tuple[np.ndarray, int]: + """Compare all squares in squares with search_square, return best matching one. + Requires all squares to be simplified.""" best_set = False best_square: Optional[np.ndarray] = None best_count = 0 - best_coord: Optional[Tuple[int, int]] = None for square in squares: - count, coord = _find_single_square(search_square, square) + count, _ = _find_single_square(search_square, square) if not best_set or count < best_count: best_set = True best_square = square best_count = count - best_coord = coord assert isinstance(best_square, np.ndarray) return (best_square, best_count) def catalogue_cards(squares: List[np.ndarray] ) -> List[Tuple[np.ndarray, Card]]: + """Run manual cataloging for given squares""" cv2.namedWindow("Catalogue", cv2.WINDOW_NORMAL) cv2.waitKey(1) result: List[Tuple[np.ndarray, Card]] = [] diff --git a/shenzhen_solitaire/solver.py b/shenzhen_solitaire/solver.py index d2dd125..d5bddad 100644 --- a/shenzhen_solitaire/solver.py +++ b/shenzhen_solitaire/solver.py @@ -57,7 +57,7 @@ def solve(board: Board) -> Iterator[List[board_actions.Action]]: stack.push(board) def _limit_stack_size(stack_size: int) -> None: - if len(stack) == -1: + if len(stack) == stack_size: stack.pop() assert stack.action_stack[-1] is not None stack.action_stack[-1].undo(board)