def _pause(self) -> None: """Toggles the pause mode of the game.""" if self._paused: self._game.ui.pop_menu() Timer.unpause_timers() else: buttons = [{ 'action': self._pause, 'text': 'Resume', 'size': 16, 'color': cfg.WHITE }, { 'action': self.enter, 'text': 'Restart', 'size': 16, 'color': cfg.WHITE }, { 'action': self._main_menu, 'text': 'Main Menu', 'size': 16, 'color': cfg.WHITE }] self._game.ui.make_menu("Game Paused", 24, cfg.WHITE, buttons) Timer.pause_timers() self._paused = not self._paused
def update(self, dt: float) -> None: """Updates the state of the game world and determines if game is over. :param dt: Time since last frame. :return: None """ if not self._paused: self._level.update(dt) # If game is over, show game-over menu. if self._is_game_over(): if self._level.is_player_alive(): title = "Victory!" else: title = "Defeat" buttons = [{ 'action': self.enter, 'text': 'Play Again', 'size': 16, 'color': cfg.WHITE }, { 'action': self._main_menu, 'text': 'Main Menu', 'size': 16, 'color': cfg.WHITE }, { 'action': sys.exit, 'text': 'Exit', 'size': 16, 'color': cfg.WHITE }] self._game.ui.make_menu(title, 24, cfg.WHITE, buttons) Timer.pause_timers() self._paused = True
def analyze(self, orig_img): x = Variable(self.val_trainsform(orig_img).unsqueeze(0), volatile=True) _t = {'im_detect': Timer(), 'misc': Timer()} _t['im_detect'].tic() arm_loc, arm_conf, odm_loc, odm_conf = self.net(x=x, test=True) boxes, scores = self.detector.forward((odm_loc, odm_conf), self.priors, (arm_loc, arm_conf)) detect_time = _t['im_detect'].toc() print("forward time: %fs" % (detect_time)) boxes = boxes[0] scores=scores[0] boxes = boxes.cpu().numpy() scores = scores.cpu().numpy() # scale each detection back up to the image scale = torch.Tensor([orig_img.shape[1], orig_img.shape[0], orig_img.shape[1], orig_img.shape[0]]).cpu().numpy() boxes *= scale all_boxes = [[] for _ in range(num_classes)] for class_id in range(1, num_classes): inds = np.where(scores[:, class_id] > 0.95)[0] c_scores = scores[inds, class_id] c_bboxes = boxes[inds] c_dets = np.hstack((c_bboxes, c_scores[:, np.newaxis])).astype(np.float32, copy=False) keep = nms(c_dets, 0.45, force_cpu=True) all_boxes[class_id] = c_dets[keep, :] for class_id in range(1, num_classes): for det in all_boxes[class_id]: left, top, right, bottom, score = det orig_img = cv2.rectangle(orig_img, (left, top), (right, bottom), (255, 255, 0), 1) orig_img = cv2.putText(orig_img, '%d:%.3f'%(class_id, score), (int(left), int(top)+30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1) # cv2.imwrite("./test_3.png", img_det) return orig_img
def __init__(self, level_file: str): """Creates a map and creates all of the sprites in it. :param level_file: Filename of level file to load from the configuration file's map folder. """ # Create the tiled map surface. map_loader = TiledMapLoader(level_file) self.image = map_loader.make_map() self.rect = self.image.get_rect() self._groups = { 'all': pg.sprite.LayeredUpdates(), 'tanks': pg.sprite.Group(), 'damageable': pg.sprite.Group(), 'bullets': pg.sprite.Group(), 'obstacles': pg.sprite.Group(), 'items': pg.sprite.Group(), 'item_boxes': pg.sprite.Group() } self._player = None self._camera = None self._ai_mobs = [] self._item_spawn_positions = [] self._item_spawn_timer = Timer() # Initialize all sprites in game world. self._init_sprites(map_loader.tiled_map.objects)
def enter(self) -> None: """Creates the game world.""" # Clear the UI. self._game.ui.clear() Timer.clear_timers() self._level = Level('level_1.tmx') self._paused = False
class Item(BaseSprite, metaclass=abc.ABCMeta): """An abstract base class for sprites that represent in-game items.""" # Number of pixels up and down that item will bob. BOB_RANGE = 15 BOB_SPEED = 0.2 def __init__(self, x: float, y: float, image: str, sound: str, groups: typing.Dict[str, pg.sprite.Group]): BaseSprite.__init__(self, image, groups, groups['all'], groups['items']) self.rect.center = (x, y) self._sfx = sound self._spawn_pos = pg.math.Vector2(x, y) self._effect_timer = Timer() # Default duration is 0. self._duration = 0 # Tween function maps integer steps to values between 0 and 1. self._tween = tween.easeInOutSine self._step = 0 self._direction = 1 @property def spawn_pos(self) -> pg.math.Vector2: return self._spawn_pos def update(self, dt: float) -> None: """Floating animation for an item that has spawned. Credits to Chris Bradfield from KidsCanCode.""" # Shift bobbing y offset to bob about item's original center. offset = Item.BOB_RANGE * (self._tween(self._step / Item.BOB_RANGE) - 0.5) self.rect.centery = self._spawn_pos.y + offset * self._direction self._step += Item.BOB_SPEED # Reverse bobbing direction when item returns to center. if self._step > Item.BOB_RANGE: self._step = 0 self._direction *= -1 def activate(self, sprite: pg.sprite.Sprite) -> None: """Applies the item's effect upon pickup and causes it to be stop being drawn.""" self._apply_effect(sprite) self._effect_timer.restart() # Applies to items with non-zero duration. sfx_loader.play(self._sfx) # Make sure it doesn't get drawn anymore after the effect has been applied. super().kill() def effect_subsided(self) -> bool: """Checks if the item's effect should subside.""" return self._effect_timer.elapsed() > self._duration @abc.abstractmethod def _apply_effect(self, sprite) -> None: """Effect that is applied on item as long as the timer has not subsided.""" pass def remove_effect(self, sprite) -> None: """Causes an item with a non-zero duration to have its effect removed from a sprite at the end.""" pass
def __init__(self, x: float, y: float, rot: float, all_groups): """Aligns the MuzzleFlash so that it starts at the tip of the Barrel nozzle.""" self._layer = cfg.EFFECTS_LAYER BaseSprite.__init__(self, MuzzleFlash.IMAGE, all_groups, all_groups['all']) RotateMixin.__init__(self) self.rect.center = (x, y) self.rot = rot self.rotate() self._spawn_timer = Timer()
def __init__(self, x: float, y: float, angle: float, color: str, category: str, owner, all_groups: typing.Dict[str, pg.sprite.Group]): """Creates a bullet object, rotating it to face the correct direction.""" self._layer = cfg.ITEM_LAYER BaseSprite.__init__(self, _IMAGES[category][color], all_groups, all_groups['all'], all_groups['bullets']) MoveMixin.__init__(self, x, y) self.vel = pg.math.Vector2(_STATS[category]["speed"], 0).rotate(-angle) self._damage = _STATS[category]["damage"] self._lifetime = _STATS[category]["lifetime"] self._spawn_timer = Timer() self._owner = owner RotateMixin.rotate_image(self, self.image, angle - Bullet.IMAGE_ROT)
def text_detect(text_detector, im): im_small, f, im_height, im_width = resize_im(im, Config.SCALE, Config.MAX_SCALE) timer = Timer() timer.tic() text_lines = text_detector.detect(im_small) text_lines = draw_boxes(im_small, text_lines, f, im_height, im_width) print "Number of the detected text lines: %s" % len(text_lines) print "Detection Time: %f" % timer.toc() print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" return text_lines
def __init__(self, x: float, y: float, image: str, sound: str, groups: typing.Dict[str, pg.sprite.Group]): BaseSprite.__init__(self, image, groups, groups['all'], groups['items']) self.rect.center = (x, y) self._sfx = sound self._spawn_pos = pg.math.Vector2(x, y) self._effect_timer = Timer() # Default duration is 0. self._duration = 0 # Tween function maps integer steps to values between 0 and 1. self._tween = tween.easeInOutSine self._step = 0 self._direction = 1
def __init__(self, tank, offset: pg.math.Vector2, image: str, color: str, category: str, all_groups: typing.Dict[str, pg.sprite.Group]): """Fills up the Barrel's ammo and centers its position on its parent.""" self._layer = cfg.BARREL_LAYER BaseSprite.__init__(self, image, all_groups, all_groups['all']) RotateMixin.__init__(self) # Bullet parameters. self._category = category self._color = color self._ammo_count = _STATS[self._category]["max_ammo"] # Parameters used for barrel position. self._parent = tank self.rect.center = tank.rect.center self._offset = offset self._fire_delay = _STATS[self._category]["fire_delay"] self._fire_timer = Timer()
def __init__(self, x: float, y: float, img: str, all_groups: typing.Dict[str, pg.sprite.Group]): """Initializes the tank's sprite with no barrels to shoot from. :param x: x coordinate for centering the sprite's position. :param y: y coordinate for centering the sprite's position. :param img: filename for the sprite's tank image. :param all_groups: A dictionary of all of the game world's sprite groups. """ self._layer = cfg.TANK_LAYER BaseSprite.__init__(self, img, all_groups, all_groups['all'], all_groups['tanks'], all_groups['damageable']) MoveNonlinearMixin.__init__(self, x, y) RotateMixin.__init__(self) DamageMixin.__init__(self, self.hit_rect) self.rect.center = (x, y) self.MAX_ACCELERATION = 768 self._barrels = [] self._items = [] self._track_timer = Timer()
def text_detect(text_detector, im, img_type): if img_type == "others": return [], 0 im_small, f = resize_im(im, Config.SCALE, Config.MAX_SCALE) timer = Timer() timer.tic() text_lines = text_detector.detect(im_small) text_lines = text_lines / f # project back to size of original image text_lines = refine_boxes(im, text_lines, expand_pixel_len = Config.DILATE_PIXEL, pixel_blank = Config.BREATH_PIXEL, binary_thresh=Config.BINARY_THRESH) text_area_ratio = calc_area_ratio(text_lines, im.shape) print "Number of the detected text lines: %s" % len(text_lines) print "Detection Time: %f" % timer.toc() print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" if Config.DEBUG_SAVE_BOX_IMG: im_with_text_lines = draw_boxes(im, text_lines, is_display=False, caption=image_path, wait=False) if im_with_text_lines is not None: cv2.imwrite(image_path+'_boxes.jpg', im_with_text_lines) return text_lines, text_area_ratio
def wrapper(self, *args, **kwargs): timer = Timer() # before the method call timer.start() # the actual method call result = method(self, *args, **kwargs) # after the method call timer.stop(method.__name__) return result
class AIReloadState(AITurretCtrlState): """ State class for AITankCtrl for reloading the AI's turret.""" _RELOAD_TIME = 10000 def __init__(self, ai): AITurretCtrlState.__init__(self, ai) self._reload_timer = None def enter(self) -> None: """Initiates the reload timer for the AI's turret.""" self._reload_timer = Timer() def update(self, dt: float) -> None: """Switches back to attack state once it's time to reload.""" if self._reload_timer.elapsed() > AIReloadState._RELOAD_TIME: self._ai.turret.barrel.reload() self._ai.state = self._ai.attack_state
class MuzzleFlash(BaseSprite, RotateMixin): """Sprite that models the flash (or explosion) at the barrel's nozzle upon firing a bullet.""" FLASH_DURATION = 25 IMAGE = 'shotLarge.png' def __init__(self, x: float, y: float, rot: float, all_groups): """Aligns the MuzzleFlash so that it starts at the tip of the Barrel nozzle.""" self._layer = cfg.EFFECTS_LAYER BaseSprite.__init__(self, MuzzleFlash.IMAGE, all_groups, all_groups['all']) RotateMixin.__init__(self) self.rect.center = (x, y) self.rot = rot self.rotate() self._spawn_timer = Timer() def update(self, dt: float) -> None: """Remove the flash from screen after a short duration.""" if self._spawn_timer.elapsed() > MuzzleFlash.FLASH_DURATION: self.kill()
class Bullet(BaseSprite, MoveMixin): """Sprite class that models a Bullet object.""" IMAGE_ROT = 90 # See sprite sheet. def __init__(self, x: float, y: float, angle: float, color: str, category: str, owner, all_groups: typing.Dict[str, pg.sprite.Group]): """Creates a bullet object, rotating it to face the correct direction.""" self._layer = cfg.ITEM_LAYER BaseSprite.__init__(self, _IMAGES[category][color], all_groups, all_groups['all'], all_groups['bullets']) MoveMixin.__init__(self, x, y) self.vel = pg.math.Vector2(_STATS[category]["speed"], 0).rotate(-angle) self._damage = _STATS[category]["damage"] self._lifetime = _STATS[category]["lifetime"] self._spawn_timer = Timer() self._owner = owner RotateMixin.rotate_image(self, self.image, angle - Bullet.IMAGE_ROT) @property def owner(self): """Returns the owner sprite that triggered the creation of this bullet, i.e., a Tank object. :return: A sprite that triggered the firing of this bullet. """ return self._owner @classmethod def range(cls, category: str) -> float: """Returns the range that this bullet can travel before it vanishes.""" return _STATS[category]["speed"] * (_STATS[category]["lifetime"] / 1000) @property def damage(self) -> int: """Returns the damage that this bullet can cause upon collision.""" return self._damage def update(self, dt) -> None: """Moves the bullet until it's time for it to disappear.""" if self._spawn_timer.elapsed() > self._lifetime: self.kill() else: self.move(dt)
def train_epoch(self, scaler, epoch, model, dataset, dataloader, optimizer, prefix="train"): model.train() _timer = Timer() lossLogger = LossLogger() performanceLogger = build_evaluator(self.cfg, dataset) num_iters = len(dataloader) for i, sample in enumerate(dataloader): self.n_iters_elapsed += 1 _timer.tic() self.run_step(scaler, model, sample, optimizer, lossLogger, performanceLogger, prefix) torch.cuda.synchronize() _timer.toc() if (i + 1) % self.cfg.N_ITERS_TO_DISPLAY_STATUS == 0: if self.cfg.local_rank == 0: template = "[epoch {}/{}, iter {}/{}, lr {}] Total train loss: {:.4f} " "(ips = {:.2f})\n" "{}" logger.info( template.format( epoch, self.cfg.N_MAX_EPOCHS - 1, i, num_iters - 1, round(get_current_lr(optimizer), 6), lossLogger.meters["loss"].value, self.batch_size * self.cfg.N_ITERS_TO_DISPLAY_STATUS / _timer.diff, "\n".join( ["{}: {:.4f}".format(n, l.value) for n, l in lossLogger.meters.items() if n != "loss"]), ) ) if self.cfg.TENSORBOARD and self.cfg.local_rank == 0: # Logging train losses [self.tb_writer.add_scalar(f"loss/{prefix}_{n}", l.global_avg, epoch) for n, l in lossLogger.meters.items()] performances = performanceLogger.evaluate() if performances is not None and len(performances): [self.tb_writer.add_scalar(f"performance/{prefix}_{k}", v, epoch) for k, v in performances.items()] if self.cfg.TENSORBOARD_WEIGHT and False: for name, param in model.named_parameters(): layer, attr = os.path.splitext(name) attr = attr[1:] self.tb_writer.add_histogram("{}/{}".format(layer, attr), param, epoch)
def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, multi_scales=False, flip=False, **kwargs): np.set_printoptions(precision=5, suppress=True) num_classes = cfg.DATASET.NUM_CLASSES base_size = cfg.TEST.BASE_SIZE crop_size = cfg.TEST.CROP_SIZE startup_prog = fluid.Program() test_prog = fluid.Program() dataset = build_dataset(cfg.DATASET.DATASET_NAME, file_list=cfg.DATASET.VAL_FILE_LIST, mode=ModelPhase.EVAL, data_dir=cfg.DATASET.DATA_DIR) def data_generator(): #TODO: check is batch reader compatitable with Windows if use_mpio: data_gen = dataset.multiprocess_generator( num_processes=cfg.DATALOADER.NUM_WORKERS, max_queue_size=cfg.DATALOADER.BUF_SIZE) else: data_gen = dataset.generator() for b in data_gen: yield b[0], b[1], b[2] py_reader, avg_loss, out, grts, masks = build_model(test_prog, startup_prog, phase=ModelPhase.EVAL) py_reader.decorate_sample_generator(data_generator, drop_last=False, batch_size=cfg.EVAL_BATCH_SIZE, places=fluid.cuda_places()) # Get device environment places = fluid.cuda_places() if use_gpu else fluid.cpu_places() place = places[0] dev_count = len(places) print("#Device count: {}".format(dev_count)) exe = fluid.Executor(place) exe.run(startup_prog) test_prog = test_prog.clone(for_test=True) ckpt_dir = cfg.TEST.TEST_MODEL if not ckpt_dir else ckpt_dir if ckpt_dir is not None: filename = '{}_{}_{}_epoch_{}.pdparams'.format( str(cfg.MODEL.MODEL_NAME), str(cfg.MODEL.BACKBONE), str(cfg.DATASET.DATASET_NAME), cfg.SOLVER.NUM_EPOCHS) print("loading testing model file: {}/{}".format(ckpt_dir, filename)) fluid.io.load_params(exe, ckpt_dir, main_program=test_prog, filename=filename) # Use streaming confusion matrix to calculate mean_iou np.set_printoptions(precision=4, suppress=True, linewidth=160, floatmode="fixed") conf_mat = ConfusionMatrix(cfg.DATASET.NUM_CLASSES, streaming=True) #fetch_list: return of the model fetch_list = [avg_loss.name, out.name] num_images = 0 step = 0 all_step = cfg.DATASET.VAL_TOTAL_IMAGES // cfg.EVAL_BATCH_SIZE timer = Timer() timer.start() for data in py_reader(): mask = np.array(data[0]['mask']) label = np.array(data[0]['label']) image_org = np.array(data[0]['image']) image = np.transpose(image_org, (0, 2, 3, 1)) # BCHW->BHWC image = np.squeeze(image) if cfg.TEST.SLIDE_WINDOW: if not multi_scales: scales = [1.0] else: scales = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25 ] if cfg.DATASET.DATASET_NAME == 'cityscapes' else [ 0.5, 0.75, 1.0, 1.25, 1.5, 1.75 ] #scales = [0.75, 1.0, 1.25] # fast multi-scale testing #strides stride = int(crop_size * 1.0 / 3) # 1/3 > 2/3 > 1/2 for input_size: 769 x 769 h, w = image.shape[0:2] scores = np.zeros(shape=[num_classes, h, w], dtype='float32') for scale in scales: long_size = int(math.ceil(base_size * scale)) if h > w: height = long_size width = int(1.0 * w * long_size / h + 0.5) short_size = width else: width = long_size height = int(1.0 * h * long_size / w + 0.5) short_size = height # print('org_img_size: {}x{}, rescale_img_size: {}x{}'.format(h, w, height, width)) cur_img = image_resize(image, height, width) # pading if long_size <= crop_size: pad_img = pad_single_image(cur_img, crop_size) label_feed, mask_feed = get_feed(pad_img) pad_img = mapper_image(pad_img) loss, pred1 = exe.run(test_prog, feed={ 'image': pad_img, 'label': label_feed, 'mask': mask_feed }, fetch_list=fetch_list, return_numpy=True) pred1 = np.array(pred1) outputs = pred1[:, :, :height, :width] if flip: pad_img_flip = flip_left_right_image(cur_img) pad_img_flip = pad_single_image( pad_img_flip, crop_size) label_feed, mask_feed = get_feed(pad_img_flip) pad_img_flip = mapper_image(pad_img_flip) loss, pred1 = exe.run(test_prog, feed={ 'image': pad_img_flip, 'label': label_feed, 'mask': mask_feed }, fetch_list=fetch_list, return_numpy=True) pred1 = np.flip(pred1, 3) outputs += pred1[:, :, :height, :width] else: if short_size < crop_size: pad_img = pad_single_image(cur_img, crop_size) else: pad_img = cur_img ph, pw = pad_img.shape[0:2] #slid window h_grids = int(math.ceil(1.0 * (ph - crop_size) / stride)) + 1 w_grids = int(math.ceil(1.0 * (pw - crop_size) / stride)) + 1 outputs = np.zeros(shape=[1, num_classes, ph, pw], dtype='float32') count_norm = np.zeros(shape=[1, 1, ph, pw], dtype='int32') for idh in range(h_grids): for idw in range(w_grids): h0 = idh * stride w0 = idw * stride h1 = min(h0 + crop_size, ph) w1 = min(w0 + crop_size, pw) #print('(h0,w0,h1,w1):({},{},{},{})'.format(h0, w0, h1, w1)) crop_img = crop_image(pad_img, h0, w0, h1, w1) pad_crop_img = pad_single_image( crop_img, crop_size) label_feed, mask_feed = get_feed(pad_crop_img) pad_crop_img = mapper_image(pad_crop_img) loss, pred1 = exe.run(test_prog, feed={ 'image': pad_crop_img, 'label': label_feed, 'mask': mask_feed }, fetch_list=fetch_list, return_numpy=True) pred1 = np.array(pred1) outputs[:, :, h0:h1, w0:w1] += pred1[:, :, 0:h1 - h0, 0:w1 - w0] count_norm[:, :, h0:h1, w0:w1] += 1 if flip: pad_img_flip = flip_left_right_image(crop_img) pad_img_flip = pad_single_image( pad_img_flip, crop_size) label_feed, mask_feed = get_feed(pad_img_flip) pad_img_flip = mapper_image(pad_img_flip) loss, pred1 = exe.run(test_prog, feed={ 'image': pad_img_flip, 'label': label_feed, 'mask': mask_feed }, fetch_list=fetch_list, return_numpy=True) pred1 = np.flip(pred1, 3) outputs[:, :, h0:h1, w0:w1] += pred1[:, :, 0:h1 - h0, 0:w1 - w0] count_norm[:, :, h0:h1, w0:w1] += 1 outputs = 1.0 * outputs / count_norm outputs = outputs[:, :, :height, :width] with fluid.dygraph.guard(): outputs = fluid.dygraph.to_variable(outputs) outputs = fluid.layers.resize_bilinear(outputs, out_shape=[h, w]) score = outputs.numpy()[0] scores += score else: # taking the original image as the model input loss, pred = exe.run(test_prog, feed={ 'image': image_org, 'label': label, 'mask': mask }, fetch_list=fetch_list, return_numpy=True) scores = pred[0] # computing IoU with all scale result pred = np.argmax(scores, axis=0).astype('int64') pred = pred[np.newaxis, :, :, np.newaxis] step += 1 num_images += pred.shape[0] conf_mat.calculate(pred, label, mask) _, iou = conf_mat.mean_iou() _, acc = conf_mat.accuracy() print("[EVAL] step={}/{} acc={:.4f} IoU={:.4f}".format( step, all_step, acc, iou)) category_iou, avg_iou = conf_mat.mean_iou() category_acc, avg_acc = conf_mat.accuracy() print("[EVAL] #image={} acc={:.4f} IoU={:.4f}".format( num_images, avg_acc, avg_iou)) print("[EVAL] Category IoU:", category_iou) print("[EVAL] Category Acc:", category_acc) print("[EVAL] Kappa:{:.4f}".format(conf_mat.kappa())) print("flip = ", flip) print("scales = ", scales) return category_iou, avg_iou, category_acc, avg_acc
class Tank(BaseSprite, MoveNonlinearMixin, RotateMixin, DamageMixin): """Sprite class that models a Tank object.""" KNOCK_BACK = 100 _SPEED_CUTOFF = 100 _TRACK_DELAY = 100 BIG = "big" LARGE = "large" HUGE = "huge" def __init__(self, x: float, y: float, img: str, all_groups: typing.Dict[str, pg.sprite.Group]): """Initializes the tank's sprite with no barrels to shoot from. :param x: x coordinate for centering the sprite's position. :param y: y coordinate for centering the sprite's position. :param img: filename for the sprite's tank image. :param all_groups: A dictionary of all of the game world's sprite groups. """ self._layer = cfg.TANK_LAYER BaseSprite.__init__(self, img, all_groups, all_groups['all'], all_groups['tanks'], all_groups['damageable']) MoveNonlinearMixin.__init__(self, x, y) RotateMixin.__init__(self) DamageMixin.__init__(self, self.hit_rect) self.rect.center = (x, y) self.MAX_ACCELERATION = 768 self._barrels = [] self._items = [] self._track_timer = Timer() def update(self, dt: float) -> None: """Rotates, moves, and handles any active in-game items that have some effect. :param dt: Time elapsed since the tank's last update. :return: None """ self.rotate(dt) self.move(dt) for item in self._items: if item.effect_subsided(): item.remove_effect(self) self._items.remove(item) if self.vel.length_squared( ) > Tank._SPEED_CUTOFF and self._track_timer.elapsed( ) > Tank._TRACK_DELAY: self._spawn_tracks() @property def range(self) -> float: """The shooting distance of the tank, as given by the tank's barrels.""" return self._barrels[0].range @property def color(self) -> str: """Returns a string representing the color of one of the tank's barrels.""" return self._barrels[0].color def pickup(self, item) -> None: """Activates an item that this Tank object has picked up (collided with) and saves it. :param item: Item sprite that can be used to apply an effect on the Tank object. :return: None """ item.activate(self) self._items.append(item) def equip_barrel(self, barrel: Barrel) -> None: """Equips a new barrel to this tank.""" self._barrels.append(barrel) def _spawn_tracks(self) -> None: """Spawns track sprites as the tank object moves around the map.""" Tracks(*self.pos, self.hit_rect.height, self.hit_rect.height, self.rot, self.all_groups) self._track_timer.restart() def rotate_barrel(self, aim_direction: float): """Rotates the all of the tank's barrels in a direction indicated by aim_direction.""" for barrel in self._barrels: barrel.rot = aim_direction barrel.rotate() def ammo_count(self) -> int: """Returns the ammo count of the tank's barrels.""" return self._barrels[0].ammo_count def fire(self) -> None: """Fires a bullet from the Tank's barrels.""" for barrel in self._barrels: barrel.fire() def reload(self) -> None: """Reloads bullets for each of the bullets.""" for barrel in self._barrels: barrel.reload() def kill(self) -> None: """Removes this sprite and its barrels from all sprite groups.""" for barrel in self._barrels: barrel.kill() for item in self._items: item.kill() super().kill() @classmethod def color_tank(cls, x: float, y: float, color: str, category: str, groups: typing.Dict[str, pg.sprite.Group]): """Factory method for creating Tank objects.""" tank = cls(x, y, f"tankBody_{color}_outline.png", groups) offset = pg.math.Vector2(tank.hit_rect.height // 3, 0) barrel = Barrel.create_color_barrel(tank, offset, color.capitalize(), category, groups) tank.equip_barrel(barrel) return tank @classmethod def enemy(cls, x: float, y: float, size: str, groups: typing.Dict[str, pg.sprite.Group]) -> 'Tank': """Returns a enemy tank class depending on the size parameter.""" if size == cls.BIG: return cls.big_tank(x, y, groups) elif size == cls.LARGE: return cls.large_tank(x, y, groups) elif size == cls.HUGE: return cls.huge_tank(x, y, groups) raise ValueError(f"Invalid size attribute: {size}") @classmethod def big_tank(cls, x: float, y: float, groups: typing.Dict[str, pg.sprite.Group]) -> 'Tank': """Returns the a 'big' enemy tank.""" tank = cls(x, y, "tankBody_bigRed.png", groups) for y_offset in (-10, 10): barrel = Barrel.create_special(tank, pg.math.Vector2(0, y_offset), "Dark", groups, special=1) tank.equip_barrel(barrel) return tank @classmethod def large_tank(cls, x: float, y: float, groups: typing.Dict[str, pg.sprite.Group]) -> 'Tank': """Returns the a 'large' enemy tank.""" tank = cls(x, y, "tankBody_darkLarge.png", groups) tank.MAX_ACCELERATION *= 0.9 for y_offset in (-10, 10): barrel = Barrel.create_special(tank, pg.math.Vector2(0, y_offset), "Dark", groups, special=4) tank.equip_barrel(barrel) return tank @classmethod def huge_tank(cls, x: float, y: float, groups: typing.Dict[str, pg.sprite.Group]) -> 'Tank': """Returns the a 'huge' enemy tank.""" tank = cls(x, y, "tankBody_huge_outline.png", groups) tank.MAX_ACCELERATION *= 0.8 for y_offset in (-10, 10): barrel = Barrel.create_special(tank, pg.math.Vector2(20, y_offset), "Dark", groups, special=4) tank.equip_barrel(barrel) barrel = Barrel.create_special(tank, pg.math.Vector2(-10, 0), "Dark", groups, special=1) tank.equip_barrel(barrel) return tank
def train(cfg): startup_prog = fluid.Program() train_prog = fluid.Program() drop_last = True dataset = build_dataset(cfg.DATASET.DATASET_NAME, file_list=cfg.DATASET.TRAIN_FILE_LIST, mode=ModelPhase.TRAIN, shuffle=True, data_dir=cfg.DATASET.DATA_DIR, base_size= cfg.DATAAUG.BASE_SIZE, crop_size= cfg.DATAAUG.CROP_SIZE, rand_scale=True) def data_generator(): if args.use_mpio: data_gen = dataset.multiprocess_generator( num_processes=cfg.DATALOADER.NUM_WORKERS, max_queue_size=cfg.DATALOADER.BUF_SIZE) else: data_gen = dataset.generator() batch_data = [] for b in data_gen: batch_data.append(b) if len(batch_data) == (cfg.TRAIN_BATCH_SIZE // cfg.NUM_TRAINERS): for item in batch_data: yield item[0], item[1], item[2] batch_data = [] # If use sync batch norm strategy, drop last batch if number of samples # in batch_data is less then cfg.BATCH_SIZE to avoid NCCL hang issues if not cfg.TRAIN.SYNC_BATCH_NORM: for item in batch_data: yield item[0], item[1], item[2] # Get device environment gpu_id = int(os.environ.get('FLAGS_selected_gpus', 0)) place = fluid.CUDAPlace(gpu_id) if args.use_gpu else fluid.CPUPlace() places = fluid.cuda_places() if args.use_gpu else fluid.cpu_places() # Get number of GPU dev_count = cfg.NUM_TRAINERS if cfg.NUM_TRAINERS > 1 else len(places) print_info("#device count: {}".format(dev_count)) cfg.TRAIN_BATCH_SIZE = dev_count * int(cfg.TRAIN_BATCH_SIZE_PER_GPU) print_info("#train_batch_size: {}".format(cfg.TRAIN_BATCH_SIZE)) print_info("#batch_size_per_dev: {}".format(cfg.TRAIN_BATCH_SIZE_PER_GPU)) py_reader, avg_loss, lr, pred, grts, masks = build_model( train_prog, startup_prog, phase=ModelPhase.TRAIN) py_reader.decorate_sample_generator( data_generator, batch_size=cfg.TRAIN_BATCH_SIZE_PER_GPU, drop_last=drop_last) exe = fluid.Executor(place) exe.run(startup_prog) exec_strategy = fluid.ExecutionStrategy() # Clear temporary variables every 100 iteration if args.use_gpu: exec_strategy.num_threads = fluid.core.get_cuda_device_count() exec_strategy.num_iteration_per_drop_scope = 100 build_strategy = fluid.BuildStrategy() if cfg.NUM_TRAINERS > 1 and args.use_gpu: dist_utils.prepare_for_multi_process(exe, build_strategy, train_prog) exec_strategy.num_threads = 1 if cfg.TRAIN.SYNC_BATCH_NORM and args.use_gpu: if dev_count > 1: # Apply sync batch norm strategy print_info("Sync BatchNorm strategy is effective.") build_strategy.sync_batch_norm = True else: print_info( "Sync BatchNorm strategy will not be effective if GPU device" " count <= 1") compiled_train_prog = fluid.CompiledProgram(train_prog).with_data_parallel( loss_name=avg_loss.name, exec_strategy=exec_strategy, build_strategy=build_strategy) # Resume training begin_epoch = cfg.SOLVER.BEGIN_EPOCH if cfg.TRAIN.RESUME_MODEL_DIR: begin_epoch = load_checkpoint(exe, train_prog) # Load pretrained model elif os.path.exists(cfg.TRAIN.PRETRAINED_MODEL_DIR): print_info('Pretrained model dir: ', cfg.TRAIN.PRETRAINED_MODEL_DIR) load_vars = [] load_fail_vars = [] def var_shape_matched(var, shape): """ Check whehter persitable variable shape is match with current network """ var_exist = os.path.exists( os.path.join(cfg.TRAIN.PRETRAINED_MODEL_DIR, var.name)) if var_exist: var_shape = parse_shape_from_file( os.path.join(cfg.TRAIN.PRETRAINED_MODEL_DIR, var.name)) return var_shape == shape return False for x in train_prog.list_vars(): if isinstance(x, fluid.framework.Parameter): shape = tuple(fluid.global_scope().find_var( x.name).get_tensor().shape()) if var_shape_matched(x, shape): load_vars.append(x) else: load_fail_vars.append(x) fluid.io.load_vars( exe, dirname=cfg.TRAIN.PRETRAINED_MODEL_DIR, vars=load_vars) for var in load_vars: print_info("Parameter[{}] loaded sucessfully!".format(var.name)) for var in load_fail_vars: print_info( "Parameter[{}] don't exist or shape does not match current network, skip" " to load it.".format(var.name)) print_info("{}/{} pretrained parameters loaded successfully!".format( len(load_vars), len(load_vars) + len(load_fail_vars))) else: print_info( 'Pretrained model dir {} not exists, training from scratch...'. format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) fetch_list = [avg_loss.name, lr.name] if args.debug: # Fetch more variable info and use streaming confusion matrix to # calculate IoU results if in debug mode np.set_printoptions( precision=4, suppress=True, linewidth=160, floatmode="fixed") fetch_list.extend([pred.name, grts.name, masks.name]) cm = ConfusionMatrix(cfg.DATASET.NUM_CLASSES, streaming=True) if args.use_vdl: if not args.vdl_log_dir: print_info("Please specify the log directory by --vdl_log_dir.") exit(1) from visualdl import LogWriter log_writer = LogWriter(args.vdl_log_dir) # trainer_id = int(os.getenv("PADDLE_TRAINER_ID", 0)) # num_trainers = int(os.environ.get('PADDLE_TRAINERS_NUM', 1)) step = 0 all_step = cfg.DATASET.TRAIN_TOTAL_IMAGES // cfg.TRAIN_BATCH_SIZE if cfg.DATASET.TRAIN_TOTAL_IMAGES % cfg.TRAIN_BATCH_SIZE and drop_last != True: all_step += 1 all_step *= (cfg.SOLVER.NUM_EPOCHS - begin_epoch + 1) avg_loss = 0.0 timer = Timer() timer.start() if begin_epoch > cfg.SOLVER.NUM_EPOCHS: raise ValueError( ("begin epoch[{}] is larger than cfg.SOLVER.NUM_EPOCHS[{}]").format( begin_epoch, cfg.SOLVER.NUM_EPOCHS)) if args.use_mpio: print_info("Use multiprocess reader") else: print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): py_reader.start() while True: try: if args.debug: # Print category IoU and accuracy to check whether the # traning process is corresponed to expectation loss, lr, pred, grts, masks = exe.run( program=compiled_train_prog, fetch_list=fetch_list, return_numpy=True) cm.calculate(pred, grts, masks) avg_loss += np.mean(np.array(loss)) step += 1 if step % args.log_steps == 0: speed = args.log_steps / timer.elapsed_time() avg_loss /= args.log_steps category_acc, mean_acc = cm.accuracy() category_iou, mean_iou = cm.mean_iou() print_info(( "epoch={}/{} step={}/{} lr={:.5f} loss={:.4f} acc={:.5f} mIoU={:.5f} step/sec={:.3f} | ETA {}" ).format(epoch, cfg.SOLVER.NUM_EPOCHS, step, all_step, lr[0], avg_loss, mean_acc, mean_iou, speed, calculate_eta(all_step - step, speed))) print_info("Category IoU: ", category_iou) print_info("Category Acc: ", category_acc) if args.use_vdl: log_writer.add_scalar('Train/mean_iou', mean_iou, step) log_writer.add_scalar('Train/mean_acc', mean_acc, step) log_writer.add_scalar('Train/loss', avg_loss, step) log_writer.add_scalar('Train/lr', lr[0], step) log_writer.add_scalar('Train/step/sec', speed, step) sys.stdout.flush() avg_loss = 0.0 cm.zero_matrix() timer.restart() else: # If not in debug mode, avoid unnessary log and calculate loss, lr = exe.run( program=compiled_train_prog, fetch_list=fetch_list, return_numpy=True) avg_loss += np.mean(np.array(loss)) step += 1 if step % args.log_steps == 0 and cfg.TRAINER_ID == 0: avg_loss /= args.log_steps speed = args.log_steps / timer.elapsed_time() print(( "epoch={}/{} step={}/{} lr={:.5f} loss={:.4f} step/sec={:.3f} | ETA {}" ).format(epoch, cfg.SOLVER.NUM_EPOCHS, global_step, all_step, lr[0], avg_loss, speed, calculate_eta(all_step - global_step, speed))) if args.use_vdl: log_writer.add_scalar('Train/loss', avg_loss, step) log_writer.add_scalar('Train/lr', lr[0], step) log_writer.add_scalar('Train/speed', speed, step) sys.stdout.flush() avg_loss = 0.0 timer.restart() except fluid.core.EOFException: py_reader.reset() break except Exception as e: print(e) if epoch % cfg.TRAIN.SNAPSHOT_EPOCH == 0 and cfg.TRAINER_ID == 0: ckpt_dir = save_checkpoint(exe, train_prog, epoch) if args.do_eval: print("Evaluation start") _, mean_iou, _, mean_acc = evaluate( cfg=cfg, ckpt_dir=ckpt_dir, use_gpu=args.use_gpu, use_mpio=args.use_mpio) if args.use_vdl: log_writer.add_scalar('Evaluate/mean_iou', mean_iou, step) log_writer.add_scalar('Evaluate/mean_acc', mean_acc, step) # Use VisualDL to visualize results if args.use_vdl and cfg.DATASET.VIS_FILE_LIST is not None: visualize( cfg=cfg, use_gpu=args.use_gpu, vis_file_list=cfg.DATASET.VIS_FILE_LIST, vis_dir="visual", ckpt_dir=ckpt_dir, log_writer=log_writer) # save final model if cfg.TRAINER_ID == 0: save_checkpoint(exe, train_prog, 'final') if args.use_vdl: log_writer.close()
NET_DEF_FILE = "models/deploy.prototxt" MODEL_FILE = "models/ctpn_trained_model.caffemodel" if len(sys.argv) > 1 and sys.argv[1] == "--no-gpu": caffe.set_mode_cpu() else: caffe.set_mode_gpu() caffe.set_device(cfg.TEST_GPU_ID) # initialize the detectors text_proposals_detector = TextProposalDetector( CaffeModel(NET_DEF_FILE, MODEL_FILE)) text_detector = TextDetector(text_proposals_detector) demo_imnames = os.listdir(DEMO_IMAGE_DIR) timer = Timer() for im_name in demo_imnames: print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "Image: %s" % im_name im_file = osp.join(DEMO_IMAGE_DIR, im_name) im = cv2.imread(im_file) timer.tic() im, f = resize_im(im, cfg.SCALE, cfg.MAX_SCALE) text_lines = text_detector.detect(im) print "Number of the detected text lines: %s" % len(text_lines) print "Time: %f" % timer.toc()
def train_epoch(self, scaler, epoch, model, dataloader, optimizer, prefix="train"): model.train() _timer = Timer() lossLogger = LossLogger() performanceLogger = MetricLogger(self.dictionary, self.cfg) for i, sample in enumerate(dataloader): imgs, targets = sample['image'], sample['target'] _timer.tic() # zero the parameter gradients optimizer.zero_grad() imgs = list( img.cuda() for img in imgs) if isinstance(imgs, list) else imgs.cuda() if isinstance(targets, list): if isinstance(targets[0], torch.Tensor): targets = [t.cuda() for t in targets] else: targets = [{k: v.cuda() for k, v in t.items()} for t in targets] else: targets = targets.cuda() # Autocast with amp.autocast(enabled=True): out = model(imgs, targets, prefix) if not isinstance(out, tuple): losses, predicts = out, None else: losses, predicts = out self.n_iters_elapsed += 1 # Scales loss. Calls backward() on scaled loss to create scaled gradients. # Backward passes under autocast are not recommended. # Backward ops run in the same dtype autocast chose for corresponding forward ops. scaler.scale(losses["loss"]).backward() # scaler.step() first unscales the gradients of the optimizer's assigned params. # If these gradients do not contain infs or NaNs, optimizer.step() is then called, # otherwise, optimizer.step() is skipped. scaler.step(optimizer) # Updates the scale for next iteration. scaler.update() # torch.cuda.synchronize() _timer.toc() if (i + 1) % self.cfg.N_ITERS_TO_DISPLAY_STATUS == 0: if self.cfg.distributed: # reduce losses over all GPUs for logging purposes loss_dict_reduced = reduce_dict(losses) lossLogger.update(**loss_dict_reduced) del loss_dict_reduced else: lossLogger.update(**losses) if predicts is not None: if self.cfg.distributed: # reduce performances over all GPUs for logging purposes predicts_dict_reduced = reduce_dict(predicts) performanceLogger.update(targets, predicts_dict_reduced) del predicts_dict_reduced else: performanceLogger.update(**predicts) del predicts if self.cfg.local_rank == 0: template = "[epoch {}/{}, iter {}, lr {}] Total train loss: {:.4f} " "(ips = {:.2f})\n" "{}" logger.info( template.format( epoch, self.cfg.N_MAX_EPOCHS, i, round(get_current_lr(optimizer), 6), lossLogger.meters["loss"].value, self.batch_size * self.cfg.N_ITERS_TO_DISPLAY_STATUS / _timer.diff, "\n".join([ "{}: {:.4f}".format(n, l.value) for n, l in lossLogger.meters.items() if n != "loss" ]), )) del imgs, targets, losses if self.cfg.TENSORBOARD and self.cfg.local_rank == 0: # Logging train losses [ self.tb_writer.add_scalar(f"loss/{prefix}_{n}", l.global_avg, epoch) for n, l in lossLogger.meters.items() ] performances = performanceLogger.compute() if len(performances): [ self.tb_writer.add_scalar(f"performance/{prefix}_{k}", v, epoch) for k, v in performances.items() ] if self.cfg.TENSORBOARD_WEIGHT and False: for name, param in model.named_parameters(): layer, attr = os.path.splitext(name) attr = attr[1:] self.tb_writer.add_histogram("{}/{}".format(layer, attr), param, epoch)
def train_epoch(self, epoch, model, dataloader, optimizer, lr_scheduler, grad_normalizer=None, prefix="train"): model.train() _timer = Timer() lossMeter = LossMeter() perfMeter = PerfMeter() for i, (imgs, labels) in enumerate(dataloader): _timer.tic() # zero the parameter gradients optimizer.zero_grad() if self.cfg.HALF: imgs = imgs.half() if len(self.device) > 1: out = data_parallel(model, (imgs, labels, prefix), device_ids=self.device, output_device=self.device[0]) else: imgs = imgs.cuda() labels = [label.cuda() for label in labels] if isinstance( labels, list) else labels.cuda() out = model(imgs, labels, prefix) if not isinstance(out, tuple): losses, performances = out, None else: losses, performances = out if losses["all_loss"].sum().requires_grad: if self.cfg.GRADNORM is not None: grad_normalizer.adjust_losses(losses) grad_normalizer.adjust_grad(model, losses) else: losses["all_loss"].sum().backward() optimizer.step() self.n_iters_elapsed += 1 _timer.toc() lossMeter.__add__(losses) if performances is not None and all(performances): perfMeter.put(performances) if (i + 1) % self.cfg.N_ITERS_TO_DISPLAY_STATUS == 0: avg_losses = lossMeter.average() template = "[epoch {}/{}, iter {}, lr {}] Total train loss: {:.4f} " "(ips = {:.2f} )\n" "{}" self.logger.info( template.format( epoch, self.cfg.N_MAX_EPOCHS, i, round(get_current_lr(optimizer), 6), avg_losses["all_loss"], self.batch_size * self.cfg.N_ITERS_TO_DISPLAY_STATUS / _timer.total_time, "\n".join([ "{}: {:.4f}".format(n, l) for n, l in avg_losses.items() if n != "all_loss" ]), )) if self.cfg.TENSORBOARD: tb_step = int((epoch * self.n_steps_per_epoch + i) / self.cfg.N_ITERS_TO_DISPLAY_STATUS) # Logging train losses [ self.tb_writer.add_scalar(f"loss/{prefix}_{n}", l, tb_step) for n, l in avg_losses.items() ] lossMeter.clear() del imgs, labels, losses, performances lr_scheduler.step() if self.cfg.TENSORBOARD and len(perfMeter): avg_perf = perfMeter.average() [ self.tb_writer.add_scalar(f"performance/{prefix}_{k}", v, epoch) for k, v in avg_perf.items() ] if self.cfg.TENSORBOARD_WEIGHT and False: for name, param in model.named_parameters(): layer, attr = os.path.splitext(name) attr = attr[1:] self.tb_writer.add_histogram("{}/{}".format(layer, attr), param, epoch)
def hit_remove(self, json_body, secret_access=None): self.headers['X-Secret-Access'] = secret_access with Timer('/remove'): response = requests.post(self.endpoint, data=json_body, headers=self.headers, timeout=self.timeout) return response
class Barrel(BaseSprite, RotateMixin): """Sprite class that models a Barrel object.""" _FIRE_SFX = 'shoot.wav' def __init__(self, tank, offset: pg.math.Vector2, image: str, color: str, category: str, all_groups: typing.Dict[str, pg.sprite.Group]): """Fills up the Barrel's ammo and centers its position on its parent.""" self._layer = cfg.BARREL_LAYER BaseSprite.__init__(self, image, all_groups, all_groups['all']) RotateMixin.__init__(self) # Bullet parameters. self._category = category self._color = color self._ammo_count = _STATS[self._category]["max_ammo"] # Parameters used for barrel position. self._parent = tank self.rect.center = tank.rect.center self._offset = offset self._fire_delay = _STATS[self._category]["fire_delay"] self._fire_timer = Timer() @property def color(self) -> str: """Returns a string representing the barrel's color.""" return self._color @property def ammo_count(self) -> int: """Returns the current ammo count for this barrel.""" return self._ammo_count @property def range(self) -> float: """Returns the fire range of the barrel.""" return Bullet.range(self._category) @property def fire_delay(self) -> float: """Returns the number of milliseconds until barrel can fire again.""" return self._fire_delay def update(self, dt: float) -> None: """Updates the barrel's position by centering on the parent's position (accounting for the offset).""" vec = self._offset.rotate(-self.rot) self.rect.centerx = self._parent.rect.centerx + vec.x self.rect.centery = self._parent.rect.centery + vec.y def fire(self) -> None: """Fires a Bullet if enough time has passed and if there's ammo.""" if self._ammo_count > 0 and self._fire_timer.elapsed() > self._fire_delay: self._spawn_bullet() sfx_loader.play(Barrel._FIRE_SFX) self._fire_timer.restart() def _spawn_bullet(self) -> None: """Spawns a Bullet object from the Barrel's nozzle.""" fire_pos = pg.math.Vector2(self.hit_rect.height, 0).rotate(-self.rot) fire_pos.xy += self.rect.center Bullet(fire_pos.x, fire_pos.y, self.rot, self._color, self._category, self._parent, self.all_groups) MuzzleFlash(*fire_pos, self.rot, self.all_groups) self._ammo_count -= 1 def reload(self) -> None: """Reloads the Barrel to have maximum ammo""" self._ammo_count = _STATS[self._category]["max_ammo"] def kill(self) -> None: self._parent = None super().kill() @classmethod def create_color_barrel(cls, tank, offset: pg.math.Vector2, color: str, category: str, groups: typing.Dict[str, pg.sprite.Group]) -> 'Barrel': """Creates a color barrel object.""" return cls(tank, offset, f"tank{color.capitalize()}_barrel{cfg.CATEGORY[category]}.png", color, category, groups) @classmethod def create_special(cls, tank, offset: pg.math.Vector2, color: str, all_groups: typing.Dict[str, pg.sprite.Group], special) -> 'Barrel': """Creates a special barrel object.""" barrel = cls(tank, offset, f"specialBarrel{special}.png", color, "standard", all_groups) helpers.flip(barrel, orig_image=barrel.image, x_reflect=True, y_reflect=False) return barrel
def enter(self) -> None: """Initiates the reload timer for the AI's turret.""" self._reload_timer = Timer()
class Level: """Class that creates, draws, and updates the game world, including the map and all sprites.""" _ITEM_RESPAWN_TIME = 30000 # 1 minute. def __init__(self, level_file: str): """Creates a map and creates all of the sprites in it. :param level_file: Filename of level file to load from the configuration file's map folder. """ # Create the tiled map surface. map_loader = TiledMapLoader(level_file) self.image = map_loader.make_map() self.rect = self.image.get_rect() self._groups = { 'all': pg.sprite.LayeredUpdates(), 'tanks': pg.sprite.Group(), 'damageable': pg.sprite.Group(), 'bullets': pg.sprite.Group(), 'obstacles': pg.sprite.Group(), 'items': pg.sprite.Group(), 'item_boxes': pg.sprite.Group() } self._player = None self._camera = None self._ai_mobs = [] self._item_spawn_positions = [] self._item_spawn_timer = Timer() # Initialize all sprites in game world. self._init_sprites(map_loader.tiled_map.objects) def _init_sprites(self, objects: pytmx.TiledObjectGroup) -> None: """Initializes all of the pygame sprites in this level's map. :param objects: Iterator for accessing the properties of all game objects to be created. :return: None Expects to find a single 'player' and 'enemy_tank' object, and possible more than one of any other object. A sprite is created out of each object and added to the appropriate group. A boundary for the game world is also created to keep the sprites constrained. """ game_objects = {} for t_obj in objects: # Expect single enemy tank and multiple of other objects. if t_obj.name == 'enemy_tank' or t_obj.name == "player": game_objects[t_obj.name] = t_obj else: game_objects.setdefault(t_obj.name, []).append(t_obj) # Create the player and world camera. p = game_objects.get('player') tank = Tank.color_tank(p.x, p.y, p.color, p.category, self._groups) # Make a tank factory. self._player = PlayerCtrl(tank) self._camera = Camera(self.rect.width, self.rect.height, self._player.tank) # Spawn single enemy tank. t = game_objects.get('enemy_tank') tank = Tank.enemy(t.x, t.y, t.size, self._groups) # Make a tank factory. ai_patrol_points = game_objects.get('ai_patrol_point') ai_boss = AITankCtrl(tank, ai_patrol_points, self._player.tank) self._ai_mobs.append(ai_boss) # Spawn turrets. for t in game_objects.get('turret'): turret = Turret(t.x, t.y, t.category, t.special, self._groups) self._ai_mobs.append( AITurretCtrl(turret, ai_boss, self._player.tank)) # Spawn obstacles that one can collide with. for tree in game_objects.get('small_tree'): Tree(tree.x, tree.y, self._groups) # Spawn items boxes that can be destroyed to get an item. for box in game_objects.get('box_spawn'): self._item_spawn_positions.append((box.x, box.y)) ItemBox.spawn(box.x, box.y, self._groups) # Creates the boundaries of the game world. BoundaryWall(x=0, y=0, width=self.rect.width, height=1, all_groups=self._groups) # Top BoundaryWall(x=0, y=self.rect.height, width=self.rect.width, height=1, all_groups=self._groups) # Bottom BoundaryWall(x=0, y=0, width=1, height=self.rect.height, all_groups=self._groups) # Left BoundaryWall(x=self.rect.width, y=0, width=1, height=self.rect.height, all_groups=self._groups) # Right def _can_spawn_item(self) -> bool: """"Checks if a new item can be spawned.""" return self._item_spawn_timer.elapsed() > Level._ITEM_RESPAWN_TIME and \ len(self._groups['items']) + len(self._groups['item_boxes']) < len(self._item_spawn_positions) def is_player_alive(self) -> bool: """Checks if the player's tank has been defeated.""" return self._player.tank.alive() def mob_count(self) -> int: """Checks if all the AI mobs have been defeated.""" return len(self._ai_mobs) def process_inputs(self) -> None: """Handles keys and clicks that affect the game world.""" self._player.handle_keys() # Convert mouse coordinates to world coordinates. mouse_x, mouse_y = pg.mouse.get_pos() mouse_world_pos = pg.math.Vector2(mouse_x + self._camera.rect.x, mouse_y + self._camera.rect.y) self._player.handle_mouse(mouse_world_pos) def update(self, dt: float) -> None: """Updates the game world's AI, sprites, camera, and resolves collisions. :param dt: time elapsed since the last update of the game world. :return: None """ for ai in self._ai_mobs: ai.update(dt) self._groups['all'].update(dt) # Update list of ai mobs. self._camera.update() game_items_count = len(self._groups['items']) collision_handler.handle_collisions(self._groups) if game_items_count > 0 and len( self._groups['items']) < game_items_count: self._item_spawn_timer.restart() # See if it's time to spawn a new item. if self._can_spawn_item(): available_positions = self._item_spawn_positions.copy() for x, y in self._item_spawn_positions: for sprite in self._groups['items']: if sprite.spawn_pos.x == x and sprite.spawn_pos == y and ( x, y) in available_positions: available_positions.remove((x, y)) for sprite in self._groups['item_boxes']: if sprite.rect.center == (x, y) and ( x, y) in available_positions: available_positions.remove((x, y)) if available_positions: x, y, = random.choice(available_positions) ItemBox.spawn(x, y, self._groups) # Filter out any AIs that have been defeated. self._ai_mobs = [ai for ai in self._ai_mobs if ai.sprite.alive()] def draw(self, screen: pg.Surface) -> None: """Draws every sprite in the game world, as well as heads-up display elements. :param screen: The screen surface that the world's elements will be drawn to. :return: None """ # Draw the map. screen.blit(self.image, self._camera.apply(self.rect)) # Draw all sprites. for sprite in self._groups['all']: screen.blit(sprite.image, self._camera.apply(sprite.rect)) # pg.draw.rect(screen, (255, 255, 255), self._camera.apply(sprite.hit_rect), 1) # Draw HUD. for ai in self._ai_mobs: ai.sprite.draw_health(screen, self._camera) self._player.draw_hud(screen, self._camera)
def eval_model(model, classes, bm, last_epoch=True, verbose=False, xls_sheet=None): print('Start evaluation...') since = time.time() device = next(model.parameters()).device was_training = model.training model.eval() dataloaders = [] for cls in classes: image_dataset = GMDataset(cfg.DATASET_FULL_NAME, bm, cfg.EVAL.SAMPLES, cfg.PROBLEM.TEST_ALL_GRAPHS, cls, cfg.PROBLEM.TYPE) torch.manual_seed(cfg.RANDOM_SEED ) # Fix fetched data in test-set to prevent variance dataloader = get_dataloader(image_dataset, shuffle=True) dataloaders.append(dataloader) recalls = [] precisions = [] f1s = [] coverages = [] pred_time = [] objs = torch.zeros(len(classes), device=device) cluster_acc = [] cluster_purity = [] cluster_ri = [] timer = Timer() prediction = [] for i, cls in enumerate(classes): if verbose: print('Evaluating class {}: {}/{}'.format(cls, i, len(classes))) running_since = time.time() iter_num = 0 pred_time_list = [] obj_total_num = torch.zeros(1, device=device) cluster_acc_list = [] cluster_purity_list = [] cluster_ri_list = [] prediction_cls = [] for inputs in dataloaders[i]: if iter_num >= cfg.EVAL.SAMPLES / inputs['batch_size']: break if model.module.device != torch.device('cpu'): inputs = data_to_cuda(inputs) batch_num = inputs['batch_size'] iter_num = iter_num + 1 with torch.set_grad_enabled(False): timer.tick() outputs = model(inputs) pred_time_list.append( torch.full((batch_num, ), timer.toc() / batch_num)) # Evaluate matching accuracy if cfg.PROBLEM.TYPE == '2GM': assert 'perm_mat' in outputs for b in range(outputs['perm_mat'].shape[0]): perm_mat = outputs['perm_mat'][ b, :outputs['ns'][0][b], :outputs['ns'][1][b]].cpu() perm_mat = perm_mat.numpy() eval_dict = dict() id_pair = inputs['id_list'][0][b], inputs['id_list'][1][b] eval_dict['ids'] = id_pair eval_dict['cls'] = cls eval_dict['perm_mat'] = perm_mat prediction.append(eval_dict) prediction_cls.append(eval_dict) if 'aff_mat' in outputs: pred_obj_score = objective_score(outputs['perm_mat'], outputs['aff_mat']) gt_obj_score = objective_score(outputs['gt_perm_mat'], outputs['aff_mat']) objs[i] += torch.sum(pred_obj_score / gt_obj_score) obj_total_num += batch_num elif cfg.PROBLEM.TYPE in ['MGM', 'MGM3']: assert 'graph_indices' in outputs assert 'perm_mat_list' in outputs ns = outputs['ns'] idx = -1 for x_pred, (idx_src, idx_tgt) in \ zip(outputs['perm_mat_list'], outputs['graph_indices']): idx += 1 for b in range(x_pred.shape[0]): perm_mat = x_pred[ b, :ns[idx_src][b], :ns[idx_tgt][b]].cpu() perm_mat = perm_mat.numpy() eval_dict = dict() id_pair = inputs['id_list'][idx_src][b], inputs[ 'id_list'][idx_tgt][b] eval_dict['ids'] = id_pair if cfg.PROBLEM.TYPE == 'MGM3': eval_dict['cls'] = bm.data_dict[id_pair[0]]['cls'] else: eval_dict['cls'] = cls eval_dict['perm_mat'] = perm_mat prediction.append(eval_dict) prediction_cls.append(eval_dict) else: raise ValueError('Unknown problem type {}'.format( cfg.PROBLEM.TYPE)) # Evaluate clustering accuracy if cfg.PROBLEM.TYPE == 'MGM3': assert 'pred_cluster' in outputs assert 'cls' in outputs pred_cluster = outputs['pred_cluster'] cls_gt_transpose = [[] for _ in range(batch_num)] for batched_cls in outputs['cls']: for b, _cls in enumerate(batched_cls): cls_gt_transpose[b].append(_cls) cluster_acc_list.append( clustering_accuracy(pred_cluster, cls_gt_transpose)) cluster_purity_list.append( clustering_purity(pred_cluster, cls_gt_transpose)) cluster_ri_list.append( rand_index(pred_cluster, cls_gt_transpose)) if iter_num % cfg.STATISTIC_STEP == 0 and verbose: running_speed = cfg.STATISTIC_STEP * batch_num / ( time.time() - running_since) print('Class {:<8} Iteration {:<4} {:>4.2f}sample/s'.format( cls, iter_num, running_speed)) running_since = time.time() objs[i] = objs[i] / obj_total_num pred_time.append(torch.cat(pred_time_list)) if cfg.PROBLEM.TYPE == 'MGM3': cluster_acc.append(torch.cat(cluster_acc_list)) cluster_purity.append(torch.cat(cluster_purity_list)) cluster_ri.append(torch.cat(cluster_ri_list)) if verbose: if cfg.PROBLEM.TYPE != 'MGM3': bm.eval_cls(prediction_cls, cls, verbose=verbose) print('Class {} norm obj score = {:.4f}'.format(cls, objs[i])) print('Class {} pred time = {}s'.format( cls, format_metric(pred_time[i]))) if cfg.PROBLEM.TYPE == 'MGM3': print('Class {} cluster acc={}'.format( cls, format_metric(cluster_acc[i]))) print('Class {} cluster purity={}'.format( cls, format_metric(cluster_purity[i]))) print('Class {} cluster rand index={}'.format( cls, format_metric(cluster_ri[i]))) if cfg.PROBLEM.TYPE == 'MGM3': result = bm.eval(prediction, classes[0], verbose=True) for cls in classes[0]: precision = result[cls]['precision'] recall = result[cls]['recall'] f1 = result[cls]['f1'] coverage = result[cls]['coverage'] recalls.append(recall) precisions.append(precision) f1s.append(f1) coverages.append(coverage) else: result = bm.eval(prediction, classes, verbose=True) for cls in classes: precision = result[cls]['precision'] recall = result[cls]['recall'] f1 = result[cls]['f1'] coverage = result[cls]['coverage'] recalls.append(recall) precisions.append(precision) f1s.append(f1) coverages.append(coverage) time_elapsed = time.time() - since print('Evaluation complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) model.train(mode=was_training) if xls_sheet: for idx, cls in enumerate(classes): xls_sheet.write(0, idx + 1, cls) xls_sheet.write(0, idx + 2, 'mean') xls_row = 1 # show result if xls_sheet: xls_sheet.write(xls_row, 0, 'precision') xls_sheet.write(xls_row + 1, 0, 'recall') xls_sheet.write(xls_row + 2, 0, 'f1') xls_sheet.write(xls_row + 3, 0, 'coverage') for idx, (cls, cls_p, cls_r, cls_f1, cls_cvg) in enumerate( zip(classes, precisions, recalls, f1s, coverages)): if xls_sheet: xls_sheet.write( xls_row, idx + 1, '{:.4f}'.format(cls_p)) #'{:.4f}'.format(torch.mean(cls_p))) xls_sheet.write( xls_row + 1, idx + 1, '{:.4f}'.format(cls_r)) #'{:.4f}'.format(torch.mean(cls_r))) xls_sheet.write( xls_row + 2, idx + 1, '{:.4f}'.format(cls_f1)) #'{:.4f}'.format(torch.mean(cls_f1))) xls_sheet.write(xls_row + 3, idx + 1, '{:.4f}'.format(cls_cvg)) if xls_sheet: xls_sheet.write(xls_row, idx + 2, '{:.4f}'.format(result['mean']['precision']) ) #'{:.4f}'.format(torch.mean(torch.cat(precisions)))) xls_sheet.write(xls_row + 1, idx + 2, '{:.4f}'.format( result['mean'] ['recall'])) #'{:.4f}'.format(torch.mean(torch.cat(recalls)))) xls_sheet.write(xls_row + 2, idx + 2, '{:.4f}'.format( result['mean'] ['f1'])) #'{:.4f}'.format(torch.mean(torch.cat(f1s)))) xls_row += 4 if not torch.any(torch.isnan(objs)): print('Normalized objective score') if xls_sheet: xls_sheet.write(xls_row, 0, 'norm objscore') for idx, (cls, cls_obj) in enumerate(zip(classes, objs)): print('{} = {:.4f}'.format(cls, cls_obj)) if xls_sheet: xls_sheet.write(xls_row, idx + 1, cls_obj.item()) #'{:.4f}'.format(cls_obj)) print('average objscore = {:.4f}'.format(torch.mean(objs))) if xls_sheet: xls_sheet.write( xls_row, idx + 2, torch.mean(objs).item()) #'{:.4f}'.format(torch.mean(objs))) xls_row += 1 if cfg.PROBLEM.TYPE == 'MGM3': print('Clustering accuracy') if xls_sheet: xls_sheet.write(xls_row, 0, 'cluster acc') for idx, (cls, cls_acc) in enumerate(zip(classes, cluster_acc)): print('{} = {}'.format(cls, format_metric(cls_acc))) if xls_sheet: xls_sheet.write(xls_row, idx + 1, torch.mean(cls_acc).item() ) #'{:.4f}'.format(torch.mean(cls_acc))) print('average clustering accuracy = {}'.format( format_metric(torch.cat(cluster_acc)))) if xls_sheet: xls_sheet.write( xls_row, idx + 2, torch.mean(torch.cat(cluster_acc)).item( )) #'{:.4f}'.format(torch.mean(torch.cat(cluster_acc)))) xls_row += 1 print('Clustering purity') if xls_sheet: xls_sheet.write(xls_row, 0, 'cluster purity') for idx, (cls, cls_acc) in enumerate(zip(classes, cluster_purity)): print('{} = {}'.format(cls, format_metric(cls_acc))) if xls_sheet: xls_sheet.write(xls_row, idx + 1, torch.mean(cls_acc).item() ) #'{:.4f}'.format(torch.mean(cls_acc))) print('average clustering purity = {}'.format( format_metric(torch.cat(cluster_purity)))) if xls_sheet: xls_sheet.write( xls_row, idx + 2, torch.mean(torch.cat(cluster_purity)).item( )) #'{:.4f}'.format(torch.mean(torch.cat(cluster_purity)))) xls_row += 1 print('Clustering rand index') if xls_sheet: xls_sheet.write(xls_row, 0, 'rand index') for idx, (cls, cls_acc) in enumerate(zip(classes, cluster_ri)): print('{} = {}'.format(cls, format_metric(cls_acc))) if xls_sheet: xls_sheet.write(xls_row, idx + 1, torch.mean(cls_acc).item() ) #'{:.4f}'.format(torch.mean(cls_acc))) print('average rand index = {}'.format( format_metric(torch.cat(cluster_ri)))) if xls_sheet: xls_sheet.write( xls_row, idx + 2, torch.mean(torch.cat(cluster_ri)).item( )) #'{:.4f}'.format(torch.mean(torch.cat(cluster_ri)))) xls_row += 1 print('Predict time') if xls_sheet: xls_sheet.write(xls_row, 0, 'time') for idx, (cls, cls_time) in enumerate(zip(classes, pred_time)): print('{} = {}'.format(cls, format_metric(cls_time))) if xls_sheet: xls_sheet.write( xls_row, idx + 1, torch.mean( cls_time).item()) #'{:.4f}'.format(torch.mean(cls_time))) print('average time = {}'.format(format_metric(torch.cat(pred_time)))) if xls_sheet: xls_sheet.write(xls_row, idx + 2, torch.mean(torch.cat(pred_time)).item() ) #'{:.4f}'.format(torch.mean(torch.cat(pred_time)))) xls_row += 1 bm.rm_gt_cache(last_epoch=last_epoch) return torch.Tensor(recalls)
def post(): """ Main function for /remove endpoint. :return: JSON response. """ correlation_id = str(uuid.uuid4()) image_path = output_image_path = None try: body = request.form with Timer('Validate input data'): if request.headers.get( 'X-Secret-Access') != env.get_secret_access(): return make_response(correlation_id, True, error_id='003') if bool('image_url' in body) == bool('image_base64' in body): return make_response(correlation_id, True, error_id='003') output_format = body.get('output_format', 'url') to_remove = body.get('to_remove', 'background') color_removal = body.get('color_removal', 'transparent') with Timer('Download image'): if 'image_url' in body: image_path = image.download(correlation_id, body['image_url']) elif 'image_base64' in body: image_path = image.decode(correlation_id, body['image_base64']) else: image_path = None if not image_path: return make_response(correlation_id, True, error_id='002') with Timer('Hit inference module'): json_body = dict(img=image_path, to_remove=to_remove, color_removal=color_removal, secret_access=env.get_secret_access()) request_headers = dict(Host='inference') for attempt in range(3): try: response = requests.post('http://traefik/predict', json=json_body, headers=request_headers) if response.ok: response = response.json() if not response.get('error'): output_image_path = response.get('img') break else: log.error( 'Error hitting inference module: [{}]'.format( response.get('message'))) raise ValueError else: log.error( 'Error hitting inference module: Status code [{}]'. format(response.status_code)) raise ValueError except ValueError: time.sleep(attempt + 1) if attempt >= 2: return make_response(correlation_id, True, error_id='001') with Timer('Prepare response'): image_url = image_base64 = None if output_format == 'url': image_url = image.upload(correlation_id, output_image_path) else: image_base64 = image.encode(output_image_path) if not any([image_url, image_base64]): return make_response(correlation_id, True, error_id='001') return make_response(correlation_id, False, image_url=image_url, image_base64=image_base64) except Exception as e: log.error('Generic error: [{}]'.format(e)) log.exception(e) return make_response(correlation_id, True, '001') finally: with Timer('Remove input and output images'): if image_path and os.path.exists(image_path): os.remove(image_path) if output_image_path and os.path.exists(output_image_path): os.remove(output_image_path)