def _edit_major_cv_image(self, major_cv_image): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera Returns: Image: Edited main camera image """ # # TODO: Currently dont have the gradient image for the training. So not using any gradient overlay on image # major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_img, self.gradient_alpha) # if self._current_training_phase: # Add the label that lets the user know the training phase major_cv_image = utils.write_text_on_image( image=major_cv_image, text=self._current_training_phase, loc=XYPixelLoc.TRAINING_PHASE_LOC.value, font=self.training_phase_font, font_color=None, font_shadow_color=RaceCarColorToRGB.Black.value) return major_cv_image
def _edit_major_cv_image(self, major_cv_image, cur_training_phase): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera Returns: Image: Edited main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha) # Add the label that lets the user know the training phase major_cv_image = utils.write_text_on_image( image=major_cv_image, text=cur_training_phase, loc=XYPixelLoc.TRAINING_PHASE_LOC.value, font=self.training_phase_font, font_color=None, font_shadow_color=RaceCarColorToRGB.Black.value) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA) return major_cv_image
def _edit_major_cv_image(self, major_cv_image): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera Returns: Image: Edited main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_img, self.gradient_alpha) # Subscribing to the agent metrics mp4_video_metrics_info = list() for racecar_info, mp4_video_metrics_srv in zip( self.racecars_info, self.mp4_video_metrics_srv_list): mp4_video_metrics = mp4_video_metrics_srv(VideoMetricsSrvRequest()) mp4_video_metrics_info.append(mp4_video_metrics) # Adding display name to the image agents_speed = 0 agent_done = False for i, racecar_info in enumerate(self.racecars_info): loc_x, loc_y = XYPixelLoc.MULTI_AGENT_DISPLAY_NAME_LOC.value[i][ 0], XYPixelLoc.MULTI_AGENT_DISPLAY_NAME_LOC.value[i][1] # Display name (Racer name/Model name) display_name = racecar_info['display_name'] display_name_txt = display_name if len( display_name) < 15 else "{}...".format(display_name[:15]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(loc_x, loc_y), font=self.amazon_ember_regular_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Lap Counter loc_y += 30 total_laps = rospy.get_param("NUMBER_OF_TRIALS", 0) current_lap = int(mp4_video_metrics_info[i].lap_counter) + 1 lap_counter_text = "{}/{}".format(current_lap, total_laps) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_heavy_30px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset counter loc_y += 45 reset_counter_text = "Reset | {}".format( mp4_video_metrics_info[i].reset_counter) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=reset_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) if self.racecar_name == racecar_info['name']: agents_speed = mp4_video_metrics_info[i].throttle # The race is complete when total lap is same as current lap and done flag is set agent_done = agent_done or (mp4_video_metrics_info[i].done and (current_lap == int(total_laps))) # Speed loc_x, loc_y = XYPixelLoc.SPEED_EVAL_LOC.value if self.is_league_leaderboard: loc_x, loc_y = XYPixelLoc.SPEED_LEADERBOARD_LOC.value speed_text = "{} m/s".format( utils.get_speed_formatted_str(agents_speed)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=speed_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Leaderboard name if self.is_league_leaderboard: major_cv_image = utils.write_text_on_image( image=major_cv_image, text=self.leaderboard_name, loc=XYPixelLoc.LEADERBOARD_NAME_LOC.value, font=self.amazon_ember_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Evaluation type loc_x, loc_y = XYPixelLoc.RACE_TYPE_EVAL_LOC.value if self.is_league_leaderboard: loc_x, loc_y = XYPixelLoc.RACE_TYPE_RACE_LOC.value race_text = "race" if self.is_racing else "evaluation" evaluation_type_txt = "{} {}".format( RACE_TYPE_TO_VIDEO_TEXT_MAPPING[self.race_type], race_text) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=evaluation_type_txt, loc=(loc_x, loc_y), font=self.amazon_ember_light_italic_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # total_evaluation_time (Race time) loc_x, loc_y = XYPixelLoc.MULTI_AGENT_EVAL_TIME.value total_eval_milli_seconds = mp4_video_metrics_info[ 0].total_evaluation_time time_delta = datetime.timedelta(milliseconds=total_eval_milli_seconds) total_eval_time_text = "Race | {}".format( utils.milliseconds_to_timeformat(time_delta)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=total_eval_time_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # AWS Deepracer logo at the bottom for the community leaderboard if self.is_league_leaderboard: major_cv_image = utils.write_text_on_image( image=major_cv_image, text=AWS_DEEPRACER_WATER_MARK, loc=XYPixelLoc.AWS_DEEPRACER_WATER_MARK_LOC.value, font=self.amazon_ember_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Check if the done flag is set and set the banner appropriately if agent_done: # When the cv2 text is written, it automatically drops the alpha value of the image rel_y_offset = XYPixelLoc.TRACK_IMG_WITH_OFFSET_LOC.value[ 1] if self.is_league_leaderboard else 0 major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2RGBA) racecomplete_image = utils.get_image( TrackAssetsIconographicPngs.RACE_COMPLETE_OVERLAY_PNG.value, IconographicImageSize.RACE_COMPLETE_IMAGE_SIZE.value) x_offset = major_cv_image.shape[ 1] - racecomplete_image.shape[1] // 2 y_offset = major_cv_image.shape[ 0] - RACE_COMPLETE_Y_OFFSET - rel_y_offset - racecomplete_image.shape[ 0] // 2 major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, racecomplete_image, (x_offset, y_offset)) return major_cv_image
def _edit_top_camera_image_util(self, top_camera_image, rank_name_gap_time, mp4_video_metrics_info): """ Showing stats on the top view camera image Arguments: major_cv_image (Image): Main camera image for the racecar rank_name_gap_time (list): Sorted list based on the ranking along with rank, name, gap time, racer_number mp4_video_metrics_info (list): All the racers metric information Returns: major_cv_image (Image): Edited Main camera image """ # Applying gradient to whole major image and then writing text top_camera_image = utils.apply_gradient( top_camera_image, self.gradient_top_camera_alpha_rgb_mul, self.one_minus_gradient_top_camera_alpha) top_camera_image = cv2.cvtColor(top_camera_image, cv2.COLOR_BGR2RGBA) # LAP Title loc_x, loc_y = XYPixelLoc.F1_TOP_CAMERA_LAP_TEXT_LOC.value lap_txt = "LAP" top_camera_image = utils.write_text_on_image( image=top_camera_image, text=lap_txt, loc=(loc_x, loc_y), font=self.formula1_display_wide_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # LAP counter loc_x, loc_y = XYPixelLoc.F1_TOP_CAMERA_LAP_COUNTER_LOC.value # For Top view, lap counter should be based on leader's lap count. leader_index = rank_name_gap_time[0][3] current_lap = min( int(mp4_video_metrics_info[leader_index].lap_counter) + 1, int(self.total_laps)) lap_counter_text = "{} / {}".format(current_lap, int(self.total_laps)) top_camera_image = utils.write_text_on_image( image=top_camera_image, text=lap_counter_text, loc=(loc_x, loc_y), font=self.formula1_display_bold_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Each racers ranking, name and gap time rank_loc_x, rank_loc_y = XYPixelLoc.F1_TOP_CAMERA_LEADER_RANK_LOC.value color_code_loc_x, color_code_loc_y = XYPixelLoc.F1_TOP_CAMERA_LEADER_COLOR_CODE_LOC.value display_name_loc_x, display_name_loc_y = XYPixelLoc.F1_TOP_CAMERA_LEADER_DISPLAY_NAME_LOC.value gap_loc_x, gap_loc_y = XYPixelLoc.F1_TOP_CAMERA_LEADER_GAP_LOC.value for row in range(4): for col in range(3): if (row + 4 * col) >= len(rank_name_gap_time): continue rank, display_name, gap_time, racer_number = rank_name_gap_time[ row + 4 * col] # Rank loc_x, loc_y = rank_loc_x + (col * 185), rank_loc_y + (row * 20) racer_rank = "{}".format(rank) top_camera_image = utils.write_text_on_image( image=top_camera_image, text=racer_rank, loc=(loc_x, loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Draw racer color code icon loc_x, loc_y = color_code_loc_x + ( col * 185), color_code_loc_y + (row * 20) top_camera_image = utils.plot_rectangular_image_on_main_image( top_camera_image, self._racer_color_code_rect_img[racer_number], (loc_x, loc_y)) # Adding display name to the table loc_x, loc_y = display_name_loc_x + ( col * 185), display_name_loc_y + (row * 20) display_name_txt = display_name if len( display_name) <= 6 else "{}".format(display_name[:6]) top_camera_image = utils.write_text_on_image( image=top_camera_image, text=display_name_txt, loc=(loc_x, loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Adding gap to the table if row != 0 or col != 0: loc_x, loc_y = gap_loc_x + (col * 180), gap_loc_y + (row * 20) # The gradient box images are not equally placed for gaps if col == 2: loc_x, loc_y = gap_loc_x + (col * 182), gap_loc_y + ( row * 20) gap_time_text = "+{:.3f}".format(gap_time) top_camera_image = utils.write_text_on_image( image=top_camera_image, text=gap_time_text, loc=(loc_x, loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) return top_camera_image
def _race_finish_display(self, major_cv_image, rank_name_gap_time): """ This displays the stats of all the racers who have finished the lap. When the car finishes the lap the finisher racers get added into this list. Arguments: major_cv_image (Image): Main camera image for the racecar rank_name_gap_time (list): Sorted list based on the ranking along with rank, name, gap time, racer_number Returns: major_cv_image (Image): Edited Main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient( major_cv_image, self.gradient_finisher_alpha_rgb_mul, self.one_minus_gradient_finisher_alpha) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_BGR2RGBA) # F1 logo # loc_x, loc_y = XYPixelLoc.F1_LOGO_LOC.value # f1_logo_image = utils.get_image(TrackAssetsIconographicPngs.F1_LOGO_PNG.value, # IconographicImageSize.F1_LOGO_IMAGE_SIZE.value, # is_rgb=True) # major_cv_image = utils.plot_rectangular_image_on_main_image(major_cv_image, f1_logo_image, (loc_x, loc_y)) # Finish Title loc_x, loc_y = XYPixelLoc.F1_FINISHED_TITLE_LOC.value finisher_txt = "Finishers" major_cv_image = utils.write_text_on_image( image=major_cv_image, text=finisher_txt, loc=(loc_x, loc_y), font=self.formula1_display_bold_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) rank_loc_x, rank_loc_y = XYPixelLoc.F1_FINISHED_RANK_LOC.value color_code_loc_x, color_code_loc_y = XYPixelLoc.F1_FINISHED_COLOR_CODE_LOC.value display_name_loc_x, display_name_loc_y = XYPixelLoc.F1_FINISHED_DISPLAY_NAME_LOC.value for rank, display_name, _, racer_number in rank_name_gap_time: if racer_number not in self._finished_lap_time: continue # All racers name and gap racer_rank = "{}".format(rank) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=racer_rank, loc=(rank_loc_x, rank_loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Draw racer color code icon major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, self._racer_color_code_rect_img[racer_number], (color_code_loc_x, color_code_loc_y)) # Adding display name to the table display_name_txt = display_name if len( display_name) <= 6 else "{}".format(display_name[:6]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(display_name_loc_x, display_name_loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) rank_loc_y += 20 color_code_loc_y += 20 display_name_loc_y += 20 return cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA)
def _midway_racers_progress_display(self, major_cv_image, rank_name_gap_time, mp4_video_metrics_info): """ Half way of the track we show the stats of the racers with there ranks and gap time Arguments: major_cv_image (Image): Main camera image for the racecar rank_name_gap_time (list): Sorted list based on the ranking along with rank, name, gap time, racer_number mp4_video_metrics_info (list): All the racers metric information Returns: major_cv_image (Image): Edited Main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient( major_cv_image, self.gradient_midway_alpha_rgb_mul, self.one_minus_gradient_midway_alpha) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_BGR2RGBA) # LAP Title loc_x, loc_y = XYPixelLoc.F1_MIDWAY_LAP_TEXT_LOC.value lap_txt = "LAP" major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_txt, loc=(loc_x, loc_y), font=self.formula1_display_wide_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # LAP counter loc_x, loc_y = XYPixelLoc.F1_MIDWAY_LAP_COUNTER_LOC.value current_lap = min( int(mp4_video_metrics_info[self.racecar_index].lap_counter) + 1, int(self.total_laps)) lap_counter_text = "{} / {}".format(current_lap, int(self.total_laps)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_counter_text, loc=(loc_x, loc_y), font=self.formula1_display_bold_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Each racers ranking, name and gap time rank_loc_x, rank_loc_y = XYPixelLoc.F1_MIDWAY_LEADER_RANK_LOC.value color_code_loc_x, color_code_loc_y = XYPixelLoc.F1_MIDWAY_LEADER_COLOR_CODE_LOC.value display_name_loc_x, display_name_loc_y = XYPixelLoc.F1_MIDWAY_LEADER_DISPLAY_NAME_LOC.value gap_loc_x, gap_loc_y = XYPixelLoc.F1_MIDWAY_LEADER_GAP_LOC.value # All the other racers name and gap for i, val in enumerate(rank_name_gap_time): rank, display_name, gap_time, racer_number = val # Rank racer_rank = "{}".format(rank) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=racer_rank, loc=(rank_loc_x, rank_loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Draw racer color code icon major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, self._racer_color_code_rect_img[racer_number], (color_code_loc_x, color_code_loc_y)) # Adding display name to the table display_name_txt = display_name if len( display_name) <= 6 else "{}".format(display_name[:6]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(display_name_loc_x, display_name_loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Adding gap to the table (Do not write gap for leader) if i: gap_time_text = "+{:.3f}".format(gap_time) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=gap_time_text, loc=(gap_loc_x, gap_loc_y), font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) rank_loc_y += 20 color_code_loc_y += 20 display_name_loc_y += 20 gap_loc_y += 20 return cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA)
def _basic_racer_info_display(self, major_cv_image, racers_ranking, cur_racer_metrics_info, show_racer_name=True): """ Basic display editting of the main camera following the car. All the information at the bottom left of the MP4 is edited here. Arguments: major_cv_image (Image): Main camera image for the racecar racers_ranking (OrderedDict): Sorted ordered dict with racer_number and progress percentage along with lap cur_racer_metrics_info (dict): Given racers metric information Keyword Arguments: show_racer_name (bool): All the other states call this. But the finisher state does not have enough space to show the display name.(default: {True}) Returns: major_cv_image (Image): Edited Main camera image """ if show_racer_name: # Adding display name to the image loc_x, loc_y = XYPixelLoc.F1_DISPLAY_NAME_LOC.value display_name = self.racecars_info[ self.racecar_index]['display_name'] display_name_txt = display_name if len( display_name) <= 6 else "{}".format(display_name[:6]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(loc_x, loc_y), font=self.formula1_display_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Racers ranking loc_x, loc_y = XYPixelLoc.F1_RANKING_LOC.value cur_rank = self._get_racecar_ranking(racers_ranking, self.racecar_index) rank_txt = "Rank {}/{}".format(cur_rank, len(self.racecars_info)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=rank_txt, loc=(loc_x, loc_y), font=self.formula1_display_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Lap Counter|Total eval|gap time # Lap counter calculation loc_x, loc_y = XYPixelLoc.F1_LAP_EVAL_GAP_LOC.value current_lap = min( int(cur_racer_metrics_info.lap_counter) + 1, int(self.total_laps)) lap_counter_text = "Lap {:2d} / {:2d}".format(current_lap, int(self.total_laps)) # Total eval time if self.racecar_index in self._finished_lap_time: # If the racer finished the race then lock the total evaluation time to finished lap time. total_eval_milli_seconds = self._finished_lap_time[ self.racecar_index] else: total_eval_milli_seconds = cur_racer_metrics_info.total_evaluation_time time_delta = datetime.timedelta(milliseconds=total_eval_milli_seconds) total_eval_time_text = "{}".format( utils.milliseconds_to_timeformat(time_delta)) # Writing to the frame (Lap Counter|Total eval|gap time) lap_elapsed_gap_time = "{} | {} | Gap ".format(lap_counter_text, total_eval_time_text) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_elapsed_gap_time, loc=(loc_x, loc_y), font=self.formula1_display_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Gap (In orange color) loc_x, loc_y = XYPixelLoc.F1_LAP_EVAL_GAP_VAL_LOC.value # For the racer ranking 0, we see small floating number for the gap. Hence making it zero if cur_rank == 1: gap_time = 0 gap_time = self._get_gap_time(racers_ranking, self.racecar_index, cur_racer_metrics_info) gap_time_text = "+{:.3f}".format(gap_time) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=gap_time_text, loc=(loc_x, loc_y), font=self.formula1_display_regular_16px, font_color=RaceCarColorToRGB.Orange.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Leaderboard name f1_water_mark_text = "{}".format(self.leaderboard_name) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=f1_water_mark_text, loc=XYPixelLoc.F1_LEADERBOARD_NAME_LOC.value, font=self.formula1_display_regular_12px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Do all plotting of images at the end if show_racer_name: # Draw racer color code loc_x, loc_y = XYPixelLoc.F1_DISPLAY_NAME_SLASH_LOC.value major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, self._racer_color_code_slash_img[self.racecar_index], (loc_x, loc_y)) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA) return major_cv_image
def _edit_major_cv_image(self, major_cv_image, mp4_video_metrics_info): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera Returns: Image: Edited main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha) # Top left location of the picture loc_x, loc_y = XYPixelLoc.SINGLE_AGENT_DISPLAY_NAME_LOC.value # Display name (Racer name/Model name) display_name = self.racecar_info[self.racecar_index]['display_name'] display_name_txt = display_name if len( display_name) < 15 else "{}...".format(display_name[:15]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(loc_x, loc_y), font=self.amazon_ember_regular_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Lap Counter loc_y += 30 total_laps = rospy.get_param("NUMBER_OF_TRIALS", 0) current_lap = min( int(mp4_video_metrics_info[self.racecar_index].lap_counter) + 1, total_laps) lap_counter_text = "{}/{}".format(current_lap, total_laps) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_heavy_30px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # total_evaluation_time (Race time) loc_y += 45 total_eval_milli_seconds = mp4_video_metrics_info[ self.racecar_index].total_evaluation_time time_delta = datetime.timedelta(milliseconds=total_eval_milli_seconds) total_eval_time_text = "Race | {}".format( utils.milliseconds_to_timeformat(time_delta)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=total_eval_time_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset counter loc_y += 25 reset_counter_text = "Reset | {}".format( mp4_video_metrics_info[self.racecar_index].reset_counter) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=reset_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Speed loc_x, loc_y = XYPixelLoc.SPEED_EVAL_LOC.value if self.is_league_leaderboard: loc_x, loc_y = XYPixelLoc.SPEED_LEADERBOARD_LOC.value speed_text = "{} m/s".format( utils.get_speed_formatted_str( mp4_video_metrics_info[self.racecar_index].throttle)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=speed_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Leaderboard name if self.is_league_leaderboard: loc_x, loc_y = XYPixelLoc.LEADERBOARD_NAME_LOC.value major_cv_image = utils.write_text_on_image( image=major_cv_image, text=self.leaderboard_name, loc=(loc_x, loc_y), font=self.amazon_ember_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Evaluation type loc_x, loc_y = XYPixelLoc.RACE_TYPE_EVAL_LOC.value if self.is_league_leaderboard: loc_x, loc_y = XYPixelLoc.RACE_TYPE_RACE_LOC.value race_text = "race" if self.is_racing else "evaluation" evaluation_type_txt = "{} {}".format( RACE_TYPE_TO_VIDEO_TEXT_MAPPING[self.race_type], race_text) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=evaluation_type_txt, loc=(loc_x, loc_y), font=self.amazon_ember_light_italic_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # AWS Deepracer logo at the bottom for the community leaderboard if self.is_league_leaderboard: major_cv_image = utils.write_text_on_image( image=major_cv_image, text=AWS_DEEPRACER_WATER_MARK, loc=XYPixelLoc.AWS_DEEPRACER_WATER_MARK_LOC.value, font=self.amazon_ember_regular_16px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Check if the done flag is set and set the banner appropriately if mp4_video_metrics_info[self.racecar_index].done and ( int(total_laps) >= current_lap): # When the cv2 text is written, it automatically drops the alpha value of the image rel_y_offset = XYPixelLoc.TRACK_IMG_WITH_OFFSET_LOC.value[ 1] if self.is_league_leaderboard else 0 racecomplete_image = utils.get_image( TrackAssetsIconographicPngs.RACE_COMPLETE_OVERLAY_PNG.value, IconographicImageSize.RACE_COMPLETE_IMAGE_SIZE.value) x_offset = major_cv_image.shape[ 1] - racecomplete_image.shape[1] // 2 y_offset = major_cv_image.shape[ 0] - RACE_COMPLETE_Y_OFFSET - rel_y_offset - racecomplete_image.shape[ 0] // 2 major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, racecomplete_image, (x_offset, y_offset)) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA) return major_cv_image
def __init__(self, racecar_name, racecar_info, race_type): """ Initializing the required data for the head to bot, time-trail. This is used for single agent Arguments: racecar_name (str): racecar name in string racecars_info (list): list of dict having information of the agent race_type (str): Since this class is reused for all the different race_type """ # race duration in milliseconds self._world_name = rospy.get_param("WORLD_NAME") self.num_sectors = int(rospy.get_param("NUM_SECTORS", "3")) self.race_duration = int( rospy.get_param("RACE_DURATION", DEFAULT_RACE_DURATION)) * 1000 self.racecar_info = racecar_info self.race_type = race_type racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 # Store the font which we will use to write the phase with self.amazon_ember_regular_28px = utils.get_font( 'AmazonEmber-Regular', 28) self.amazon_ember_regular_14px = utils.get_font( 'AmazonEmber-Regular', 14) # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = VirtualEventXYPixelLoc.TRACK_IMG_VIRTUAL_EVENT_LOC.value self._track_x_min = None self._track_x_max = None self._track_y_min = None self._track_y_max = None # Gradient overlay image with track and virtual event mock gradient_img_path = VirtualEventIconographicPngs.OVERLAY_PNG.value self.gradient_img = self._plot_track_on_gradient(gradient_img_path) # Time remaining text loc_x, loc_y = VirtualEventXYPixelLoc.TIME_REMAINING_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="TIME REMAINING", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Speed text loc_x, loc_y = VirtualEventXYPixelLoc.SPEED_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="m/s", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset text loc_x, loc_y = VirtualEventXYPixelLoc.RESET_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="RESET", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # current lap time text loc_x, loc_y = VirtualEventXYPixelLoc.CURRENT_LAP_TIME_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="CURRENT LAP TIME", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # best lap time text loc_x, loc_y = VirtualEventXYPixelLoc.BEST_LAP_TIME_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="BEST LAP TIME", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # apply graident self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha = utils.get_gradient_values( self.gradient_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecar_info, is_virtual_event=True) # virtual event image editting state machine self._image_edit_fsm = FSM(initial_state=VirtualEventWaitState()) # if best sector time download from s3 failed. Then, initialize best sector time as None # and not display sector color self._sector_times = {} # declare sector images self._sectors_img_dict = {} for idx in range(self.num_sectors): sector = SECTOR_X_FORMAT.format(idx + 1) sector_color_img_dict = utils.init_sector_img_dict( world_name=self._world_name, sector=sector) self._sectors_img_dict[sector] = sector_color_img_dict # use the s3 bucket and prefix for yaml file stored as environment variable because # here is SimApp use only. For virtual event there is no s3 bucket and prefix past # through yaml file. All are past through sqs. For simplicity, reuse the yaml s3 bucket # and prefix environment variable. self._virtual_event_best_sector_time = VirtualEventBestSectorTime( bucket=os.environ.get("YAML_S3_BUCKET", ''), s3_key=get_s3_key(os.environ.get("YAML_S3_PREFIX", ''), SECTOR_TIME_S3_POSTFIX), region_name=os.environ.get("APP_REGION", "us-east-1"), local_path=SECTOR_TIME_LOCAL_PATH) self._sector_times.update( self._virtual_event_best_sector_time.get_sector_time( num_sectors=self.num_sectors)) # declare default best personal and current persoanl time to inf for idx in range(self.num_sectors): sector = SECTOR_X_FORMAT.format(idx + 1) self._sector_times[SECTOR_TIME_FORMAT_DICT[ TrackSectorTime.BEST_PERSONAL].format(sector)] = float("inf") self._sector_times[SECTOR_TIME_FORMAT_DICT[ TrackSectorTime.CURRENT_PERSONAL].format(sector)] = float( "inf") self._curr_lap_time = 0 self._last_eval_time = 0 self._curr_progress = 0 self._last_progress = 0 self._current_lap = 1 # Initializing the fader behaviour to pre-compute the gradient values final_fading_image = utils.get_image( VirtualEventIconographicPngs.FINAL_FADING_IMAGE_50ALPHA.value, IconographicImageSize.FULL_IMAGE_SIZE.value) final_fading_image = cv2.cvtColor(final_fading_image, cv2.COLOR_RGBA2BGRA) self._fader_obj = Fader( final_fading_image, fading_min_percent=VirtualEventFader.FADING_MIN_PERCENT.value, fading_max_percent=VirtualEventFader.FADING_MAX_PERCENT.value, num_frames=VirtualEventFader.NUM_FRAMES.value)
def _edit_major_cv_image(self, major_cv_image, mp4_video_metrics_info): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera mp4_video_metrics_info (dict): rest image editting info Returns: Image: Edited main camera image """ major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha) ######################### # update display params # ######################### episode_status = mp4_video_metrics_info[ self.racecar_index].episode_status # Display name (Racer name/Model name) display_name = self.racecar_info[self.racecar_index]['display_name'] # total_evaluation_time (Race time) total_eval_milli_seconds = mp4_video_metrics_info[ self.racecar_index].total_evaluation_time # Reset counter reset_counter = mp4_video_metrics_info[ self.racecar_index].reset_counter # Speed speed = mp4_video_metrics_info[self.racecar_index].throttle # Current progress current_progress = mp4_video_metrics_info[ self.racecar_index].completion_percentage # Prepare a dict for finite state machine on event call info_dict = { VirtualEventMP4Params.COUNTDOWN_TIMER.value: mp4_video_metrics_info[self.racecar_index].pause_duration, VirtualEventMP4Params.MAJOR_CV_IMAGE.value: major_cv_image, VirtualEventMP4Params.CURRENT_LAP.value: self._current_lap, VirtualEventMP4Params.TOTAL_EVAL_SECONDS.value: total_eval_milli_seconds, VirtualEventMP4Params.RESET_COUNTER.value: reset_counter, VirtualEventMP4Params.SPEED.value: speed, VirtualEventMP4Params.CURR_PROGRESS.value: current_progress, VirtualEventMP4Params.LAST_EVAL_SECONDS.value: self._last_eval_time, VirtualEventMP4Params.X_MIN.value: self._track_x_min, VirtualEventMP4Params.X_MAX.value: self._track_x_max, VirtualEventMP4Params.Y_MIN.value: self._track_y_min, VirtualEventMP4Params.Y_MAX.value: self._track_y_max, VirtualEventMP4Params.SECTOR_TIMES.value: self._sector_times, VirtualEventMP4Params.CURR_LAP_TIME.value: self._curr_lap_time, VirtualEventMP4Params.SECTOR_IMAGES.value: self._sectors_img_dict, VirtualEventMP4Params.FADER_OBJ.value: self._fader_obj } ##################### # run state machine # ##################### # virtual event image edit finite state machine on event info_dict = self._image_edit_fsm.execute(input_val={ 'event': episode_status, 'info_dict': info_dict }) # update display param from the finite state machine return value major_cv_image = info_dict[VirtualEventMP4Params.MAJOR_CV_IMAGE.value] total_eval_milli_seconds = info_dict[ VirtualEventMP4Params.TOTAL_EVAL_SECONDS.value] reset_counter = info_dict[VirtualEventMP4Params.RESET_COUNTER.value] speed = info_dict[VirtualEventMP4Params.SPEED.value] self._current_lap = info_dict[VirtualEventMP4Params.CURRENT_LAP.value] self._last_eval_time = info_dict[ VirtualEventMP4Params.LAST_EVAL_SECONDS.value] self._sector_times = info_dict[ VirtualEventMP4Params.SECTOR_TIMES.value] self._curr_lap_time = info_dict[ VirtualEventMP4Params.CURR_LAP_TIME.value] # Time remaining digit loc_x, loc_y = VirtualEventXYPixelLoc.TIME_REMAINING_DIGIT.value time_remaining = self.race_duration - total_eval_milli_seconds time_remaining = time_remaining if time_remaining > 0.0 else 0.0 time_remaining = datetime.timedelta(milliseconds=time_remaining) time_remaining = utils.milliseconds_to_timeformat(time_remaining) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=time_remaining, loc=(loc_x, loc_y), font=self.amazon_ember_regular_28px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Speed digit loc_x, loc_y = VirtualEventXYPixelLoc.SPEED_DIGIT.value speed_text = utils.get_speed_formatted_str(speed) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=speed_text, loc=(loc_x, loc_y), font=self.amazon_ember_regular_28px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset digit loc_x, loc_y = VirtualEventXYPixelLoc.RESET_DIGIT.value reset_counter_text = "{}".format(reset_counter) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=reset_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_regular_28px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # curent lap time digit loc_x, loc_y = VirtualEventXYPixelLoc.CURRENT_LAP_TIME_DIGIT.value curr_lap_time = utils.milliseconds_to_timeformat( datetime.timedelta(milliseconds=self._curr_lap_time)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=curr_lap_time, loc=(loc_x, loc_y), font=self.amazon_ember_regular_28px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # best lap time digit loc_x, loc_y = VirtualEventXYPixelLoc.BEST_LAP_TIME_DIGIT.value best_lap_time = mp4_video_metrics_info[ self.racecar_index].best_lap_time # The initial default best_lap_time from s3_metrics.py is inf # If the ros service in s3_metrics.py has not come up yet, best_lap_time is 0 best_lap_time = utils.milliseconds_to_timeformat( datetime.timedelta(milliseconds=best_lap_time)) \ if best_lap_time != float("inf") and best_lap_time != 0 else "--:--.---" major_cv_image = utils.write_text_on_image( image=major_cv_image, text=best_lap_time, loc=(loc_x, loc_y), font=self.amazon_ember_regular_28px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2BGRA) return major_cv_image
def _edit_major_cv_image(self, major_cv_image): """ Apply all the editing for the Major 45degree camera image Args: major_cv_image (Image): Image straight from the camera Returns: Image: Edited main camera image """ # Applying gradient to whole major image and then writing text major_cv_image = utils.apply_gradient(major_cv_image, self.gradient_img, self.gradient_alpha) # Subscribing to the agent metrics mp4_video_metrics_info = list() for racecar_info, mp4_video_metrics_srv in zip( self.racecars_info, self.mp4_video_metrics_srv_list): mp4_video_metrics = mp4_video_metrics_srv(VideoMetricsSrvRequest()) mp4_video_metrics_info.append(mp4_video_metrics) # Adding display name to the image display_name_loc = [(10, 10), (450, 10)] agents_speed = 0 agent_done = False for i, racecar_info in enumerate(self.racecars_info): loc_x, loc_y = display_name_loc[i][0], display_name_loc[i][1] # Display name (Racer name/Model name) display_name = racecar_info['display_name'] display_name_txt = display_name if len( display_name) < 15 else "{}...".format(display_name[:15]) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=display_name_txt, loc=(loc_x, loc_y), font=self.amazon_ember_regular_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Lap Counter loc_y += 30 total_laps = rospy.get_param("NUMBER_OF_TRIALS", 0) lap_counter_text = "{}/{}".format( int(mp4_video_metrics_info[i].lap_counter), total_laps) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=lap_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_heavy_30px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset counter loc_y += 45 reset_counter_text = "Reset | {}".format( mp4_video_metrics_info[i].reset_counter) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=reset_counter_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) if self.racecar_name == racecar_info['name']: agents_speed = mp4_video_metrics_info[i].throttle agent_done = agent_done or mp4_video_metrics_info[i].done # Speed loc_x, loc_y = 10, 420 speed_text = "{} m/s".format( utils.get_speed_formatted_str(agents_speed)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=speed_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Evaluation type loc_y += 25 # TODO - Show text based on whether its a race or customer run evaluation race_text = "race" evaluation_type_txt = "{} {}".format( RACE_TYPE_TO_VIDEO_TEXT_MAPPING[self.race_type], race_text) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=evaluation_type_txt, loc=(loc_x, loc_y), font=self.amazon_ember_light_italic_20px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # total_evaluation_time (Race time) loc_x, loc_y = 240, 10 total_eval_milli_seconds = mp4_video_metrics_info[ 0].total_evaluation_time time_delta = datetime.timedelta(milliseconds=total_eval_milli_seconds) total_eval_time_text = "Race | {}".format( utils.milliseconds_to_timeformat(time_delta)) major_cv_image = utils.write_text_on_image( image=major_cv_image, text=total_eval_time_text, loc=(loc_x, loc_y), font=self.amazon_ember_light_18px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Check if the done flag is set and set the banner appropriately if agent_done: # When the cv2 text is written, it automatically drops the alpha value of the image major_cv_image = cv2.cvtColor(major_cv_image, cv2.COLOR_RGB2RGBA) racecomplete_image = utils.get_image( TrackAssetsIconographicPngs.RACE_COMPLETE_OVERLAY_PNG.value, IconographicImageSize.RACE_COMPLETE_IMAGE_SIZE.value) x_offset = major_cv_image.shape[ 1] - racecomplete_image.shape[1] // 2 y_offset = major_cv_image.shape[ 0] - 180 - racecomplete_image.shape[0] // 2 major_cv_image = utils.plot_rectangular_image_on_main_image( major_cv_image, racecomplete_image, (x_offset, y_offset)) return major_cv_image