def __get_handle_rect(hwnd) -> Rect: # Get the size of the rectangle x, y, x1, y1 = GetClientRect(hwnd) # Get the position of the rectangle top corner on screen. x, y = ClientToScreen(hwnd, (x, y)) # Move the bottom right corner by the offset x1 += x y1 += y return Rect(Point(x, y), Point(x1, y1))
def run_in_layout_build_mode(canvas): data_provider = DataProvider() detector = Detector(data_provider) suggester = Suggester(data_provider) thread_pool = ThreadPoolExecutor(4) canvas_image = canvas.capture() draft_state = detector.get_draft_state(canvas_image) pick_suggestions_future = thread_pool.submit( lambda: suggester.get_draft_suggestions(draft_state.map, draft_state. locked_ally_picks, draft_state. enemy_picks, draft_state.bans)) unlocked_pick_suggestions_future = thread_pool.submit( lambda: suggester.get_draft_suggestions( draft_state.map, draft_state.ally_picks, draft_state.enemy_picks, draft_state.bans)) ban_suggestions_future = thread_pool.submit( lambda: suggester.get_ban_suggestions(draft_state.map, draft_state. locked_ally_picks, draft_state. enemy_picks, draft_state.bans)) unlocked_ban_suggestions_future = thread_pool.submit( lambda: suggester.get_ban_suggestions( draft_state.map, draft_state.ally_picks, draft_state.enemy_picks, draft_state.bans)) logging.info("Submitted suggestion requests") pick_suggestions = pick_suggestions_future.result() unlocked_pick_suggestions = unlocked_pick_suggestions_future.result() ban_suggestions = ban_suggestions_future.result() unlocked_ban_suggestions = unlocked_ban_suggestions_future.result() logging.info("Suggestions retrieved") annotation = Annotation(draft_state, pick_suggestions, ban_suggestions, unlocked_pick_suggestions, unlocked_ban_suggestions) size = Point(canvas_image.shape[1], canvas_image.shape[0]) import importlib while True: try: canvas.clear_paint_commands() importlib.reload(layout) layouts = [layout.DraftSuggestionLayout(), layout.LabelLayout()] paint_commands = [] for current_layout in layouts: paint_commands.extend( current_layout.get_paint_commands(size, annotation)) canvas.execute_paint_commands(paint_commands) except Exception as e: logging.exception("Exception") keyboard.wait('F8') logging.info("Rerender")
def __get_image_cuts(image) -> List[ImageCut]: h, w = image.shape[:2] cuts = [] # These offsets adjust x axis based on the height of the image, as it seems the UI elements are either # left or right aligned in case of wide screen monitors. ally_picks_offset = Point(0, int(h * 0.06)) ally_picks = image[ally_picks_offset.y:int(h * 0.85), ally_picks_offset.x:int(h / 3.6)] cuts.extend( Detector.__get_pick_portrait_slices(ally_picks, ally_picks_offset, (0.47, 0.97), (0.14, 0.65), Region.ALLY_PICKS)) enemy_picks_offset = Point(int(w - (h / 3.6)), int(h * 0.06)) enemy_picks = image[enemy_picks_offset.y:int(h * 0.85), enemy_picks_offset.x:w] cuts.extend( Detector.__get_pick_portrait_slices(enemy_picks, enemy_picks_offset, (0.03, 0.54), (0.34, 0.87), Region.ENEMY_PICKS)) ally_bans_offset = Point(int(h / 4), int(h / 100)) ally_bans = image[ally_bans_offset.y:int(h / 10), ally_bans_offset.x:int(2.05 * h / 4)] cuts.extend( Detector.__get_ban_portrait_slices(ally_bans, ally_bans_offset, Region.ALLY_BANS)) enemy_bans_offset = Point(w - int(2.05 * h / 4), int(h / 100)) enemy_bans = image[enemy_bans_offset.y:int(h / 10), enemy_bans_offset.x:w - int(h / 4)] cuts.extend( Detector.__get_ban_portrait_slices(enemy_bans, enemy_bans_offset, Region.ENEMY_BANS)) return cuts
def __get_ban_portrait_slices(base_image: Any, base_offset: Point, region: Region): cuts = [] h, w = base_image.shape[:2] for idx in range(3): portrait_cut_offset = Point(int(w / 3 * idx), 0) portrait_cut = base_image[portrait_cut_offset.y:h, portrait_cut_offset.x:int(w / 3 * (idx + 1))] current_portrait_offset = utils.add_offset_to_point( base_offset, portrait_cut_offset) cuts.append(ImageCut(portrait_cut, region, current_portrait_offset)) return cuts
def __get_locked_status(portrait_image, draft_image): if draft_image.shape[0] > portrait_image.shape[0]: draft_image = utils.resize(draft_image, height=portrait_image.shape[0]) else: portrait_image = utils.resize(portrait_image, height=draft_image.shape[0]) # Remove the frames and what not, by cutting a smaller square out of the image, stripping 25% of each side. h, w = draft_image.shape[:2] ratio = 4 crop_bounding_box = Rect( Point(int(w / ratio), int(h / ratio)), Point(int((ratio - 1) * w / ratio), int((ratio - 1) * h / ratio))) draft_image_cropped = utils.crop_to_rect(draft_image, crop_bounding_box) portrait_image_cropped = utils.crop_to_rect(portrait_image, crop_bounding_box) if min(*(draft_image_cropped.shape[:2] + portrait_image_cropped.shape[:2])) > 0: draft_image_channel_variance = utils.get_channel_variance( draft_image_cropped, cv2.COLOR_BGR2YCrCb) portrait_channel_variance = utils.get_channel_variance( portrait_image_cropped, cv2.COLOR_BGR2YCrCb) luminosity_ratio = (portrait_channel_variance[0] / draft_image_channel_variance[0]) chromatic_ratio = (((portrait_channel_variance[1] / draft_image_channel_variance[1]) + (portrait_channel_variance[2] / draft_image_channel_variance[2])) / 2) # Not used for now _ = chromatic_ratio return luminosity_ratio < 2.5 return False
def __get_bounding_box(portrait: Portrait, cut_features: Features, matches: List[Any]) -> Optional[Rect]: src_pts = np.float32([ portrait.features.key_points[m.queryIdx].pt for m in matches ]).reshape(-1, 1, 2) dst_pts = np.float32([ cut_features.key_points[m.trainIdx].pt for m in matches ]).reshape(-1, 1, 2) matrix, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) if matrix is None: return None h, w, d = portrait.image.shape pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2) dst = cv2.perspectiveTransform(pts, matrix) top_left = Point(max(int(min(point[0][0] for point in dst)), 0), max(int(min(point[0][1] for point in dst)), 0)) bottom_right = Point(max(int(max(point[0][0] for point in dst)), 0), max(int(max(point[0][1] for point in dst)), 0)) return Rect(top_left, bottom_right)
def __get_pick_portrait_slices(base_image: Any, base_offset: Point, odd_multiplier: Tuple[float, float], even_multiplier: Tuple[float, float], region: Region) -> List[ImageCut]: cuts = [] h, w = base_image.shape[:2] for idx in range(5): # Portraits alternate if idx % 2 == 1: w_start = int(w * odd_multiplier[0]) w_end = int(w * odd_multiplier[1]) else: w_start = int(w * even_multiplier[0]) w_end = int(w * even_multiplier[1]) portrait_cut_offset = Point(w_start, int(h / 5 * idx)) portrait_cut = base_image[portrait_cut_offset.y:int(h / 5 * (idx + 1)), portrait_cut_offset.x:w_end] current_portrait_offset = utils.add_offset_to_point( base_offset, portrait_cut_offset) cuts.append(ImageCut(portrait_cut, region, current_portrait_offset)) return cuts
def add_offset_to_point(point: Point, offset: Point) -> Point: return Point(point.x + offset.x, point.y + offset.y)
def run(self): # run_in_layout_build_mode(canvas) data_provider = DataProvider() detector = Detector(data_provider) suggester = Suggester(data_provider) layouts = [layout.LabelLayout(), layout.DraftSuggestionLayout()] thread_pool = ThreadPoolExecutor(4) keyboard_queue = Queue(100) keyboard.add_hotkey("F8", lambda *a, **k: keyboard_queue.put("F8")) keyboard.add_hotkey("F7", lambda *a, **k: keyboard_queue.put("F7")) visible = False logging.info( "Press F8 to show/hide overlay, F7 to refresh while it's visible") while True: key_pressed = keyboard_queue.get() if key_pressed == "F8" and visible: canvas.clear_paint_commands() visible = False logging.info("Hiding overlay") continue if key_pressed == "F7" and not visible: logging.info("Cannot refresh when overlay not visible") continue # Supposedly something should become visible, if something fails # F8 will be queued up which will make it invisible. visible = True # It's either a refresh with F7 or a show with F8 try: canvas_image = canvas.capture() if canvas_image is None: logging.info("Could not capture image") keyboard_queue.put("F8") continue logging.info("Captured image, processing") draft_state = detector.get_draft_state(canvas_image) logging.info("Processed image") if not draft_state: logging.info("Could not determine the draft") keyboard_queue.put("F8") continue pick_suggestions_future = thread_pool.submit( lambda: suggester.get_draft_suggestions( draft_state.map, draft_state.locked_ally_picks, draft_state.enemy_picks, draft_state.bans)) unlocked_pick_suggestions_future = thread_pool.submit( lambda: suggester.get_draft_suggestions( draft_state.map, draft_state.ally_picks, draft_state. enemy_picks, draft_state.bans)) ban_suggestions_future = thread_pool.submit( lambda: suggester.get_ban_suggestions( draft_state.map, draft_state.locked_ally_picks, draft_state.enemy_picks, draft_state.bans)) unlocked_ban_suggestions_future = thread_pool.submit( lambda: suggester.get_ban_suggestions( draft_state.map, draft_state.ally_picks, draft_state. enemy_picks, draft_state.bans)) logging.info("Submitted suggestion requests") pick_suggestions = pick_suggestions_future.result() unlocked_pick_suggestions = unlocked_pick_suggestions_future.result( ) ban_suggestions = ban_suggestions_future.result() unlocked_ban_suggestions = unlocked_ban_suggestions_future.result( ) logging.info("Suggestions retrieved") annotation = Annotation(draft_state, pick_suggestions, ban_suggestions, unlocked_pick_suggestions, unlocked_ban_suggestions) size = Point(canvas_image.shape[1], canvas_image.shape[0]) paint_commands = [] for current_layout in layouts: paint_commands.extend( current_layout.get_paint_commands(size, annotation)) logging.info("Generated overlay") canvas.execute_paint_commands(paint_commands) except Exception as e: logging.exception("Failed to run: %s", e)