import threading import cv2 as cv import numpy as np from window_capture import WindowCapture from vision import Vision from config_file import UserConfigs O_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]] D_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]] L_FULL = [[0, 0, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]] J_FULL = [[0, 0, 0, 0], [1, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]] I_FULL = [[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]] C_FULL = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]] B_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]] A_FULL = [[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]] S_FULL = [[0, 0, 0, 0], [0, 0, 1, 1], [0, 1, 1, 0], [0, 0, 0, 0]] Z_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]] T_FULL = [[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]] class NewStoneID(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.config = UserConfigs() self.capture_window = WindowCapture(None, None, self.config) self.vision_stun = Vision() self.stone_coordinates = np.zeros((4, 4), dtype=object) self.data_coordinates = np.zeros((20, 20), dtype=object) self.fill_data_coordinates() self.needles = {'Q': cv.imread("litris/blue_needle.jpg", cv.IMREAD_UNCHANGED)} self.run_mode = 'run' self.actual_letter = "" self.to_pick_up = False self.start() def run(self): while self.run_mode == 'run': current_stone = self.new_stone_detection() if current_stone is None: cv.waitKey(50) continue else: current_letter = self.get_letter_for_stone(current_stone) if current_letter is None: continue else: self.actual_letter = current_letter self.to_pick_up = True while self.to_pick_up: cv.waitKey(10) self.actual_letter = "" def get_actual_letter(self): return self.actual_letter def set_pick_up_status(self, status): self.to_pick_up = status def get_pick_up_status(self): return self.to_pick_up def callback(self): pass def destroy(self): self.destroy() def get_run_mode(self): return self.run_mode def new_stone_detection(self): screenshot = self.capture_window.get_screenshot() screenshot = screenshot[580:845, 1148:1412] rectangles = self.vision_stun.find(screenshot, self.needles['Q'], 0.85, 16) if len(rectangles) == 0: return None points = self.vision_stun.get_click_points(rectangles) stone_coords = np.zeros((4, 4), dtype=object) for point in points: x, y = self.point_in_small_rect(point) if x is not None and y is not None: stone_coords[x][y] = 1 # self.change_value(x, y, int(needle_key)) # print(field.data_value_grid) #cv.circle(screenshot, points[0], 7, (0, 255, 0), -1) #output_image = self.vision_stun.draw_rectangles(screenshot, rectangles) #cv.imshow("output_image", output_image) #cv.waitKey(150) return stone_coords def get_letter_for_stone(self, stone): if np.array_equal(stone, O_FULL): return "O" elif np.array_equal(stone, D_FULL): return "D" elif np.array_equal(stone, L_FULL): return "L" elif np.array_equal(stone, J_FULL): return "J" elif np.array_equal(stone, I_FULL): return "I" elif np.array_equal(stone, C_FULL): return "C" elif np.array_equal(stone, B_FULL): return "B" elif np.array_equal(stone, A_FULL): return "A" elif np.array_equal(stone, S_FULL): return "S" elif np.array_equal(stone, Z_FULL): return "Z" elif np.array_equal(stone, T_FULL): return "T" else: return None def point_in_small_rect(self, point): for e in range(0, 4, 1): for i in range(0, 4, 1): x1, y1, w, h = self.stone_coordinates[e][i] x2, y2 = x1 + w, y1 + h x, y = point if x1 < x and x < x2: if y1 < y and y < y2: return e, i return None, None def get_current_board_state(self): # get an updated image of the game screenshot = self.capture_window.get_screenshot() #screenshot = cv.imread("litris/main_playfield.jpg") screenshot = screenshot[40:1380, 610:1950] # 1000,1000 # cv.imshow("screenshot", screenshot) # cv.waitKey(150) # continue #data_coords = np.zeros((20, 20), dtype=object) data_coords = np.full((20, 20), ' ', dtype=object) #field = Pickaxe_Field() for needle_key in self.needles.keys(): #gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY) #thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.8, 200) if len(rectangles) == 0: continue points = self.vision_stun.get_click_points(rectangles) for point in points: x, y = self.point_in_rect(point) if x is not None and y is not None: data_coords[x][y] = needle_key #self.change_value(x, y, int(needle_key)) # print(field.data_value_grid) # cv.circle(screenshot, points[0], 7, (0, 255, 0), -1) #output_image = self.vision_stun.draw_rectangles(screenshot, rectangles) #cv.imshow("output_image", output_image) #cv.waitKey(150) return data_coords.tolist() def point_in_rect(self, point): for e in range(0, 20, 1): for i in range(0, 20, 1): x1, y1, w, h = self.data_coordinates[e][i] x2, y2 = x1 + w, y1 + h x, y = point if x1 < x and x < x2: if y1 < y and y < y2: return e, i return None, None def fill_data_coordinates(self): # 610 to 1950 = 1340 - 76 / 20 = 63 # 40 to 1380 = 1340 - 76 / 20 = 63 # spacing 19 * 4 dim = 63 e_spacing = 4 i_spacing = 4 for e in range(0, 4, 1): for i in range(0, 4, 1): self.stone_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim] for e in range(0, 20, 1): for i in range(0, 20, 1): self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]