From 36884dcb14750d0eeba474351183dfe504ad29b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20W=C3=B6lfer?= Date: Tue, 23 Apr 2019 02:46:41 +0200 Subject: [PATCH] Linting, worked on catalogization --- shenzhen_solitaire/cv/adjustment.py | 4 +- shenzhen_solitaire/cv/card_finder.py | 74 +++++++++++++++++++++------- test/cv_helper.py | 41 ++++++++++++--- test/helper.py | 15 ------ 4 files changed, 92 insertions(+), 42 deletions(-) delete mode 100644 test/helper.py diff --git a/shenzhen_solitaire/cv/adjustment.py b/shenzhen_solitaire/cv/adjustment.py index 19e22d8..70c7b64 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 # type: ignore +import cv2 # type: ignore @dataclass diff --git a/shenzhen_solitaire/cv/card_finder.py b/shenzhen_solitaire/cv/card_finder.py index e9be6ca..79c709a 100644 --- a/shenzhen_solitaire/cv/card_finder.py +++ b/shenzhen_solitaire/cv/card_finder.py @@ -6,6 +6,7 @@ import itertools import numpy as np # type: ignore import cv2 # type: ignore from .adjustment import Adjustment, get_square +from ..board import Card, NumberCard, SpecialCard def _extract_squares(image: np.ndarray, @@ -71,20 +72,20 @@ def get_simplified_squares(image: np.ndarray, def _find_single_square(search_square: np.ndarray, template_square: np.ndarray) -> Tuple[int, Tuple[int, int]]: - assert search_square.shape[0] <= template_square.shape[0] - assert search_square.shape[1] <= template_square.shape[1] + 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( - range(template_square.shape[0], search_square.shape[0] - 1, -1), - range(template_square.shape[1], search_square.shape[1] - 1, -1)): - p = template_square[x - search_square.shape[0]:x, - y - search_square.shape[1]:y] - search_square + 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) if not best_result or count < best_result[0]: best_result = ( count, - (x - search_square.shape[0], - y - search_square.shape[1])) + (x - template_square.shape[0], + y - template_square.shape[1])) assert best_result return best_result @@ -96,19 +97,58 @@ def find_square(search_square: np.ndarray, best_count = 0 best_coord: Optional[Tuple[int, int]] = None for square in squares: - count, coord = _find_single_square(square, search_square) + count, coord = _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) - assert isinstance(best_coord, tuple) - cv2.imshow("Window", best_square - - search_square[best_coord[0]:best_coord[0] + - best_square.shape[0], best_coord[1]:best_coord[1] + - best_square.shape[1]]) - while cv2.waitKey(0) != 27: - pass - cv2.destroyWindow("Window") return (best_square, best_count) + + +def catalague_cards(squares: List[np.ndarray]) -> List[Tuple[np.ndarray, Card]]: + cv2.namedWindow("Catalogue", cv2.WINDOW_NORMAL) + cv2.waitKey(1) + result: List[Tuple[np.ndarray, Card]] = [] + print( + "Card ID is [B]ai, [Z]hong, [F]a, [H]ua, [R]ed, [G]reen, [B]arkblack") + print("Numbercard e.g. R3") + special_card_map = { + 'b': SpecialCard.Bai, + 'z': SpecialCard.Zhong, + 'f': SpecialCard.Fa, + 'h': SpecialCard.Hua} + suit_map = { + 'r': NumberCard.Suit.Red, + 'g': NumberCard.Suit.Green, + 'b': NumberCard.Suit.Black} + for square in squares: + while True: + cv2.imshow("Catalogue", cv2.resize(square, (500, 500))) + cv2.waitKey(1) + card_id = input("Card ID:").lower() + card_type: Optional[Card] = None + if len(card_id) == 1: + if card_id not in special_card_map: + print("hi") + continue + card_type = special_card_map[card_id] + elif len(card_id) == 2: + if not card_id[0] in suit_map: + continue + if not card_id[1].isdigit(): + continue + if card_id[1] == '0': + continue + card_type = NumberCard(number=int( + card_id[1]), suit=suit_map[card_id[0]]) + else: + continue + assert card_type is not None + result.append((square, card_type)) + break + + cv2.destroyWindow("Catalogue") + assert result is not None + return result diff --git a/test/cv_helper.py b/test/cv_helper.py index 3841c5b..1e0b383 100644 --- a/test/cv_helper.py +++ b/test/cv_helper.py @@ -1,14 +1,15 @@ import itertools from typing import Tuple, List, Dict -import numpy # type: ignore +import numpy as np # type: ignore import cv2 # type: ignore +import zipfile from .context import shenzhen_solitaire from shenzhen_solitaire.cv import adjustment from shenzhen_solitaire.cv import card_finder -def pixelcount(image: numpy.ndarray) -> List[Tuple[Tuple[int, int, int], int]]: +def pixelcount(image: np.ndarray) -> List[Tuple[Tuple[int, int, int], int]]: p: Dict[Tuple[int, int, int], int] = {(0, 0, 0): 0} for pixel in itertools.chain.from_iterable(image): x = tuple(pixel) @@ -20,22 +21,40 @@ def pixelcount(image: numpy.ndarray) -> List[Tuple[Tuple[int, int, int], int]]: return B -def simplify(image: numpy.ndarray) -> None: +def simplify(image: np.ndarray) -> None: cv2.imshow("Window", image) cv2.waitKey(0) cv2.destroyWindow("Window") - print(*card_finder.simplify(image).items(), sep='\n') + print(*card_finder.simplify(image)[1].items(), sep='\n') cv2.imshow("Window", image) cv2.waitKey(0) cv2.destroyWindow("Window") def main() -> None: - image = cv2.imread("Solitaire.png") - image2 = cv2.imread("Solitaire2.png") - image2 = cv2.resize(image2, (1000, 629)) + #image = cv2.imread("Solitaire.png") + with open("Solitaire.png", 'rb') as fd: + img_str = fd.read() + nparr = np.frombuffer(img_str, np.uint8) + image = cv2.imdecode(nparr, cv2.IMREAD_COLOR) + #image2 = cv2.imread("Solitaire2.png") + #image2 = cv2.resize(image2, (1000, 629)) + image2 = cv2.imread("Solitaire.png") adj = adjustment.adjust_field(image) + squares = card_finder.get_field_squares(image, adj) + print(squares[0]) + np.save('0.dat', squares[0], allow_pickle=False) + assert 0 + with open("0.dat", 'wb') as fd: + fd.write(squares[0].tobytes()) + catalogue = card_finder.catalague_cards(squares[:5]) + my_zip = zipfile.ZipFile('myzip.zip', mode='w') + for index, x in enumerate(catalogue): + my_zip.writestr(f"{index}.dat", x[0].tobytes()) + my_zip.close() + assert 0 + squares = card_finder.get_simplified_squares(image, adj) print("Simplified") @@ -50,7 +69,13 @@ def main() -> None: print("Finding...") found_image, certainty = card_finder.find_square( image_squares[i], squares) + print(certainty) + + +def main2() -> None: + A = np.load('0.dat.npy') + print(A) if __name__ == "__main__": - main() + main2() diff --git a/test/helper.py b/test/helper.py deleted file mode 100644 index bb1173e..0000000 --- a/test/helper.py +++ /dev/null @@ -1,15 +0,0 @@ -from .context import shenzhen_solitaire -from shenzhen_solitaire import solver - -from .boards import my_board - - -def main() -> None: - A = solver.solve(my_board) - for _, B in zip(range(1), A): - print(*B, sep='\n') - print(f"Solution: {len(B)}") - - -if __name__ == "__main__": - main()