def process(self, frame: Frame) -> bool: y = frame.image_yuv[:, :, 0] champions_eliminated = self.REGIONS[ "champions_eliminated"].extract_one(y) t, thresh = cv2.threshold(champions_eliminated, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # cv2.imshow('thresh', thresh) match, key = imageops.match_templates(thresh, self.TEMPLATES, cv2.TM_CCORR_NORMED, self.REQUIRED_MATCH) frame.apex.squad_summary_match = round(match, 4) if match > self.REQUIRED_MATCH: champions = key in ["champions_of_the_arena"] duos_empty_area = self.REGIONS["duos_empty_area"].extract_one( frame.image_yuv[:, :, 0]) duos_sum = np.sum(duos_empty_area > 100) duos = duos_sum < 100 logger.debug(f"Got duos_sum={duos_sum} => duos={duos}") shunt = 0 if duos: duos_shunt_area = self.REGIONS["duos_shunt_area"].extract_one( frame.image_yuv[:, :, 0]) duos_shunt_sum = np.sum(duos_shunt_area > 100) duos_shunt = duos_shunt_sum < 100 logger.debug( f"Got duos_shunt_sum={duos_shunt_sum} => duos_shunt={duos_shunt}" ) if duos_shunt: shunt = 270 frame.apex.squad_summary = SquadSummary( champions=champions, placed=self._process_yellowtext( self.REGIONS["placed"].extract_one(frame.image)), squad_kills=self._process_yellowtext( self.REGIONS["squad_kills"].extract_one(frame.image)), player_stats=self._process_player_stats(y, duos, shunt), elite=False, mode="duos" if duos else None, image=lazy_upload( "squad_summary", self.REGIONS.blank_out(frame.image), frame.timestamp, selection="last", ), ) self.REGIONS.draw(frame.debug_image) _draw_squad_summary(frame.debug_image, frame.apex.squad_summary) return True return False
def process(self, frame: Frame) -> bool: y = frame.image_yuv[:, :, 0] tank_region = np.max(self.REGIONS["tank_region"].extract_one(frame.image), axis=2) _, thresh = cv2.threshold(tank_region, 100, 255, cv2.THRESH_BINARY) # cv2.imshow('thresh1', thresh) tank_match_sm = cv2.matchTemplate(thresh, self.TANK_TEMPLATE, cv2.TM_CCORR_NORMED) _, match_sm, _, mxloc_sm = cv2.minMaxLoc(tank_match_sm) tank_match_lg = cv2.matchTemplate(thresh, self.TANK_LARGE_TEMPLATE, cv2.TM_CCORR_NORMED) _, match_lg, _, mxloc_lg = cv2.minMaxLoc(tank_match_lg) lock_match = cv2.matchTemplate(thresh, self.LOCK_TEMPLATE, cv2.TM_CCORR_NORMED) _, match_lock, _, mxloc_lock = cv2.minMaxLoc(lock_match) matched_i = arrayops.argmax([match_sm, match_lg, match_lock]) # print([match_sm, match_lg, match_lock]) match = [match_sm, match_lg, match_lock][matched_i] matched = ["tank", "tank_lg", "lock"][matched_i] best_match_pos = [mxloc_sm, mxloc_lg, mxloc_lock][matched_i] match_x = best_match_pos[0] # print(matched, match_x) frame.overwatch.role_select_match = round(match, 2) if match > self.REQUIRED_MATCH: grouped = match_x < 150 logger.debug( f"Found match for {matched!r} with match={match:0.3f} ({match_sm:.2f}, {match_lg:.2f}, {match_lock:.2f}), x={match_x} => grouped={grouped}" ) suffix = "_group" if grouped else "_solo" frame.overwatch.role_select = RoleSelect( placement_text=imageops.tesser_ocr_all( self.REGIONS["placements" + suffix].extract(y), whitelist=string.digits + "/-" ), sr_text=big_noodle.ocr_all(self.REGIONS["srs" + suffix].extract(y), height=23, invert=True), account_name=imageops.tesser_ocr( self.REGIONS["account_name"].extract_one(y), engine=imageops.tesseract_lstm ), grouped=grouped, image=lazy_upload( "role_select", self.REGIONS.blank_out(frame.image), frame.timestamp, selection="last" ), ) if frame.debug_image is not None: self.REGIONS.draw(frame.debug_image) _draw_role_select(frame.debug_image, frame.overwatch.role_select) return True return False
def process(self, frame: Frame) -> bool: y = frame.image_yuv[:, :, 0] im = self.REGIONS["competitive_points"].extract_one(y) _, thresh = cv2.threshold(im, 50, 255, cv2.THRESH_BINARY) match = np.max(cv2.matchTemplate(thresh, self.COMPETITIVE_POINTS_TEMPLATE, cv2.TM_CCORR_NORMED)) frame.overwatch.endgame_sr_match = round(float(match), 5) if match > self.COMPETITIVE_POINTS_THRESH: sr_image = self.REGIONS["sr"].extract_one(y) sr = big_noodle.ocr_int(sr_image) if sr is None: logger.warning(f"Unable to parse SR") else: frame.overwatch.endgame_sr = EndgameSR( sr, image=lazy_upload("end_sr", self.REGIONS.blank_out(frame.image), frame.timestamp) ) return True return False
def process(self, frame: Frame) -> bool: result_y = self.REGIONS["result"].extract_one(frame.image_yuv[:, :, 0]) _, result_thresh = cv2.threshold(result_y, 220, 255, cv2.THRESH_BINARY) match, result = imageops.match_templates( result_thresh, self.RESULTS, cv2.TM_CCORR_NORMED, required_match=self.RESULT_TEMPLATE_REQUIRED_MATCH, previous_match_context=(self.__class__.__name__, "result"), ) if match > self.RESULT_TEMPLATE_REQUIRED_MATCH: logger.debug(f"Round result is {result} with match={match}") score_ims = self.REGIONS["scores"].extract(frame.image) score_gray = [ imageops.normalise(np.max(im, axis=2)) for im in score_ims ] scores = imageops.tesser_ocr_all( score_gray, expected_type=int, engine=din_next_regular_digits, invert=True, ) logger.debug(f"Round score is {scores}") frame.valorant.postgame = Postgame( victory=result == "victory", score=(scores[0], scores[1]), map=imageops.ocr_region(frame, self.REGIONS, "map"), game_mode=imageops.ocr_region(frame, self.REGIONS, "game_mode"), image=lazy_upload("postgame", self.REGIONS.blank_out(frame.image), frame.timestamp), ) draw_postgame(frame.debug_image, frame.valorant.postgame) sort_mode_gray = np.min( self.SCOREBOARD_REGIONS["scoreboard_sort_mode"].extract_one( frame.image), axis=2) sort_mode_filt = 255 - imageops.normalise(sort_mode_gray, bottom=75) # cv2.imshow('sort_mode_gray', sort_mode_gray) sort_mode = imageops.tesser_ocr(sort_mode_filt, engine=imageops.tesseract_lstm) sort_mode_match = max([ levenshtein.ratio( textops.strip_string(sort_mode).upper(), expected) for expected in self.SCOREBOARD_SORT_MODES ]) logger.debug( f"Got scoreboard sort mode: {sort_mode!r} match={sort_mode_match:.2f}" ) if sort_mode_match > 0.75: frame.valorant.scoreboard = self._parse_scoreboard(frame) draw_scoreboard(frame.debug_image, frame.valorant.scoreboard) return True return False
def _parse_scoreboard(self, frame: Frame) -> Scoreboard: agent_images = self.SCOREBOARD_REGIONS["agents"].extract(frame.image) name_images = self.SCOREBOARD_REGIONS["names"].extract(frame.image) stat_images = self.SCOREBOARD_REGIONS["stats"].extract(frame.image) stat_images_filt = [ self._filter_statrow_image(im) for im in stat_images ] stat_image_rows = [ stat_images_filt[r * 8:(r + 1) * 8] for r in range(10) ] # cv2.imshow( # 'stats', # np.vstack([ # np.hstack([self._filter_statrow_image(n)] + r) # for n, r in zip(name_images, stat_image_rows) # ]) # ) stats = [] for i, (agent_im, name_im, stat_row) in enumerate( zip(agent_images, name_images, stat_image_rows)): agent_match, agent = imageops.match_templates( agent_im, self.AGENT_TEMPLATES, method=cv2.TM_SQDIFF, required_match=self.AGENT_TEMPLATE_REQUIRED_MATCH, use_masks=True, previous_match_context=(self.__class__.__name__, "scoreboard", "agent", i), ) if agent_match > self.AGENT_TEMPLATE_REQUIRED_MATCH: agent = None row_bg = name_im[np.max(name_im, axis=2) < 200] row_color = np.median(row_bg, axis=0).astype(np.int) # cv2.imshow('name', self._filter_statrow_image(name_im)) # cv2.waitKey(0) stat = PlayerStats( agent, imageops.tesser_ocr( self._filter_statrow_image(name_im), engine=imageops.tesseract_lstm, ), row_color[0] > row_color[2], *imageops.tesser_ocr_all( stat_row, expected_type=int, engine=din_next_regular_digits, ), ) stats.append(stat) logger.debug( f"Got player stats: {stat} - agent match={agent_match:.2f}, row colour={tuple(row_color)}" ) return Scoreboard( stats, image=lazy_upload("scoreboard", self.SCOREBOARD_REGIONS.blank_out(frame.image), frame.timestamp), )
def process(self, frame: Frame): y = frame.image_yuv[:, :, 0] your_squad_image = self.REGIONS["your_squad"].extract_one(y) t, thresh = cv2.threshold(your_squad_image, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) match, key = imageops.match_templates(thresh, self.TEMPLATES, cv2.TM_CCORR_NORMED, self.REQUIRED_MATCH) frame.apex.your_squad_match = round(match, 4) if match < self.REQUIRED_MATCH: return False name1_trios = np.min(self.REGIONS["names"].extract_one(frame.image), axis=2) name1_duos = np.min(self.REGIONS["names_duos"].extract_one(frame.image), axis=2) # name1_thresh_value = max(np.max(name1_duos), np.max(name1_trios)) * 0.95 name1_thresh_value = 240 # logger.debug(f"Name thresh: {name1_thresh_value}") name1_trios_score = int(np.sum(name1_trios > name1_thresh_value)) name1_duos_score = int(np.sum(name1_duos > name1_thresh_value)) logger.debug(f"Trios name score: {name1_trios_score} vs duos name score: {name1_duos_score}") # self.duos = name1_duos_score and name1_duos_score > name1_trios_score self.duos = name1_trios_score < 100 logger.info(f"Using duos={self.duos}") if key == "your_squad": names_region_name = "names_duos" if self.duos else "names" names = imageops.tesser_ocr_all( self.REGIONS[names_region_name].extract(y), engine=imageops.tesseract_lstm, invert=True, ) frame.apex.your_squad = YourSquad( tuple(self._to_name(n) for n in names), mode="duos" if self.duos else None, images=lazy_upload( "your_squad", np.hstack(self.REGIONS[names_region_name].extract(frame.image)), frame.timestamp, ), ) self.REGIONS.draw(frame.debug_image) _draw_squad(frame.debug_image, frame.apex.your_squad) elif key == "your_selection": frame.apex.your_selection = YourSelection( name=self._to_name( imageops.tesser_ocr( self.REGIONS["names"].extract(y)[1], engine=imageops.tesseract_lstm, invert=True, ) ), image=lazy_upload( "your_selection", self.REGIONS["names"].extract(frame.image)[1], frame.timestamp, ), ) self.REGIONS.draw(frame.debug_image) _draw_squad(frame.debug_image, frame.apex.your_selection) elif key == "champion_squad": names_region_name = "names_duos" if self.duos else "names" names = imageops.tesser_ocr_all( self.REGIONS[names_region_name].extract(y), engine=imageops.tesseract_lstm, invert=True, ) frame.apex.champion_squad = ChampionSquad( tuple(self._to_name(n) for n in names), mode="duos" if self.duos else None, images=lazy_upload( "champion_squad", np.hstack(self.REGIONS[names_region_name].extract(frame.image)), frame.timestamp, ), ) self.REGIONS.draw(frame.debug_image) _draw_squad(frame.debug_image, frame.apex.champion_squad) return True
def process(self, frame: Frame) -> bool: agent_name_yuv = self.REGIONS["agent_name"].extract_one( frame.image_yuv) agent_name_thresh = cv2.inRange(agent_name_yuv, (200, 85, 120), (255, 115, 150)) # if hasattr(frame, 'source_image'): # cv2.imshow('agent_name_yuv', agent_name_yuv) # cv2.imshow('agent_name_thresh', agent_name_thresh) # cv2.imwrite( # os.path.join(os.path.dirname(__file__), 'data', 'agent_names', os.path.basename(frame.source_image)), # agent_name_thresh # ) match, best_match = imageops.match_templates( agent_name_thresh, self.AGENT_NAME_TEMPLATES, method=cv2.TM_CCORR_NORMED, required_match=0.95, # verbose=True, ) # self.REGIONS.draw(frame.debug_image) if match > self.AGENT_TEMPLATE_REQUIRED_MATCH: selected_agent_ims = self.REGIONS["selected_agents"].extract( frame.image) selected_agent_ims_gray = [ 255 - imageops.normalise(np.max(im, axis=2), bottom=50) for im in selected_agent_ims ] selected_agent_texts = imageops.tesser_ocr_all( selected_agent_ims_gray, engine=imageops.tesseract_lstm, ) logger.info(f"Got selected_agent_texts={selected_agent_texts}") picking = True for i, text in enumerate(selected_agent_texts): for word in textops.strip_string(text, string.ascii_letters + " .").split(" "): match = levenshtein.ratio(word, best_match) logger.debug( f"Player {i}: Got match {match:.2f} for {word!r} = {best_match!r}" ) if match > 0.7: logger.info( f"Found matching locked in agent {text!r} for selecting agent {best_match!r} - selection locked" ) picking = False game_mode = imageops.ocr_region(frame, self.REGIONS, "game_mode") ranks = [] for i, im in enumerate(self.REGIONS["player_ranks"].extract( frame.image)): match, matched_rank = imageops.match_templates( im, self.RANK_TEMPLATES, method=cv2.TM_SQDIFF, use_masks=True, required_match=15, previous_match_context=("player_ranks", i), ) ranks.append((matched_rank, round(match, 3))) player_name_ims = self.REGIONS["player_names"].extract(frame.image) player_name_gray = [ 255 - imageops.normalise(np.max(im, axis=2), bottom=50) for im in player_name_ims ] player_names = imageops.tesser_ocr_all( player_name_gray, engine=imageops.tesseract_lstm) frame.valorant.agent_select = AgentSelect( best_match, locked_in=not picking, map=imageops.ocr_region(frame, self.REGIONS, "map"), game_mode=game_mode, player_names=player_names, agents=selected_agent_texts, ranks=ranks, image=lazy_upload("agent_select", self.REGIONS.blank_out(frame.image), frame.timestamp, selection="last"), ) draw_agent_select(frame.debug_image, frame.valorant.agent_select) return True return False
def process(self, frame: Frame) -> bool: y = frame.image_yuv[:, :, 0] your_squad_image = self.REGIONS["match_summary"].extract_one(y) t, thresh = cv2.threshold(your_squad_image, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) match = np.max( cv2.matchTemplate(thresh, self.MATCH_SUMMARY_TEMPLATE, cv2.TM_CCORR_NORMED)) frame.apex.match_summary_match = round(float(match), 5) if match >= self.REQUIRED_MATCH: self.REGIONS.draw(frame.debug_image) placed = self._get_placed(frame) image_title = "match_summary" xp_stats, score_report = None, None xp_breakdown_title_image = self.REGIONS[ "xp_breakdown"].extract_one(y) _, xp_breakdown_title_thresh = cv2.threshold( xp_breakdown_title_image, 150, 255, cv2.THRESH_BINARY) xp_breakdown_title_match = np.max( cv2.matchTemplate( xp_breakdown_title_thresh, self.XP_BREAKDOWN_TEMPLATE, cv2.TM_CCORR_NORMED, )) if xp_breakdown_title_match > self.REQUIRED_MATCH: xp_stats = self._parse_xp_breakdown(y) image_title += "_xp_breakdown" else: score_report_title_image = self.REGIONS[ "score_report"].extract_one(y) _, score_report_title_thresh = cv2.threshold( score_report_title_image, 150, 255, cv2.THRESH_BINARY) score_report_title_match = np.max( cv2.matchTemplate( score_report_title_thresh, self.SCORE_REPORT_TEMPLATE, cv2.TM_CCORR_NORMED, )) if score_report_title_match > self.REQUIRED_MATCH: score_report = self._parse_score_report(y) image_title += "_score_report" if placed is not None: frame.apex.match_summary = MatchSummary( placed=placed, xp_stats=xp_stats, score_report=score_report, image=lazy_upload( image_title, self.REGIONS.blank_out(frame.image), frame.timestamp, selection="last", ), ) _draw_match_summary(frame.debug_image, frame.apex.match_summary) return True return False