def complete_local(self, text, line, *ignored): m = re.match(r'local +([0-9a-z-]+) +', line) if m: name = m.group(1) eps = utils.get_local_episodes(name)[name] return [utils.compress_range(utils.extract_range(eps))] return self.complete_listlocal(text, line, *ignored)
def anime_updates(anime_name=''): """Check and display the updates on the tracked anime list.""" if anime_name == '': anime_list = utils.read_log(logfile=config.ongoingfile) else: anime_list = { anime_name: utils.read_log(anime_name=anime_name, logfile=config.ongoingfile) } updates = {} for anime, episodes in anime_list.items(): new_episodes = gogoanime.get_episodes_range( gogoanime.get_anime_url(anime)) new = set(utils.extract_range(new_episodes)).difference( set(utils.extract_range(episodes))) if len(new) > 0: updates[anime] = new return updates
def anime_updates(anime_name=""): """Check and display the updates on the tracked anime list.""" if anime_name == "": anime_list = utils.read_log(logfile=config.ongoingfile) else: anime_list = { anime_name: utils.read_log(anime_name=anime_name, logfile=config.ongoingfile) } updates = {} for anime, log in anime_list.items(): episodes = log.split()[1] new_episodes = anime_source_module.get_episodes_range( anime_source_module.get_anime_url(anime)) new = set(utils.extract_range(new_episodes)).difference( set(utils.extract_range(episodes))) if len(new) > 0: updates[anime] = new return updates
def list_episodes(args): name = read_args(args, episodes=False) available_rng = gogoanime.get_episodes_range(gogoanime.get_anime_url(name)) if len(args) == 2: _, episodes = read_args(args) eps = set(episodes) avl_eps = set(utils.extract_range(available_rng)) res = eps.intersection(avl_eps) available_rng = utils.compress_range(res) outputs.prompt_val(f'Available episodes', available_rng) outputs.prompt_val(f'Watched episodes', utils.read_log(name), 'success') utils.write_cache(name)
def read_args(args, episodes=True, verbose=True): if len(args) == 0: name = utils.read_cache() elif len(args) == 1 and args[0].isnumeric(): name = utils.read_cache(int(args[0])) if verbose: outputs.prompt_val("Name", name) elif "/" in args[0]: name = args[0].strip("/").split("/")[-1] else: name = anime_source_module.process_anime_name(args[0].strip('"')) if not anime_source_module.verify_anime_exists(name): outputs.prompt_val("Anime with the name doesn't exist", args[0], "error") raise SystemExit if not name: outputs.error_info("Numbers choice invalid, or invalid context.") raise SystemExit if len(args) <= 1: if episodes: if verbose: outputs.warning_info("Episodes range not given defaulting to all") available_rng = anime_source_module.get_episodes_range( anime_source_module.get_anime_url(name)) if verbose: outputs.prompt_val("Available episodes", available_rng) eps = utils.extract_range(available_rng) else: eps = None elif len(args) == 2: eps = utils.extract_range(args[1]) else: outputs.error_info("Too many arguments.\n") outputs.normal_info(__doc__) raise SystemExit return name, eps
def list_episodes(args): name, _ = read_args(args, episodes=False) available_rng = anime_source_module.get_episodes_range(anime_source_module.get_anime_url(name)) if len(args) == 2: _, episodes = read_args(args) eps = set(episodes) avl_eps = set(utils.extract_range(available_rng)) res = eps.intersection(avl_eps) available_rng = utils.compress_range(res) outputs.prompt_val("Available episodes", available_rng) log = utils.Log(utils.read_log(name)) outputs.prompt_val("Watched episodes", log.eps, "success", end=' ') outputs.normal_info(log.last_updated_fmt) utils.write_cache(name)
def read_args(args, episodes=True, verbose=True): if len(args) == 0: name = utils.read_cache() elif args[0].isnumeric(): name = utils.read_cache(int(args[0])) if verbose: outputs.prompt_val('Name', name) elif '/' in args[0]: name = args[0].strip('/').split('/')[-1] else: name = gogoanime.process_anime_name(args[0]) if not gogoanime.verify_anime_exists(name): outputs.prompt_val(f'Anime with the name doesn\'t exist', args[0], 'error') raise SystemExit if not name: outputs.error_info('Numbers choice invalid, or invalid context.') raise SystemExit if not episodes: return name if len(args) <= 1: if verbose: outputs.warning_info('Episodes range not given defaulting to all') available_rng = gogoanime.get_episodes_range( gogoanime.get_anime_url(name)) if verbose: outputs.prompt_val('Available episodes', available_rng) episodes = utils.extract_range(available_rng) elif len(args) == 2: episodes = utils.extract_range(args[1]) else: outputs.error_info('Too many arguments.\n') outputs.normal_info(__doc__) raise SystemExit return name, episodes
def get_episodes_range(anime_url): soup = utils.get_soup(anime_url) if not soup: return [] rngs_obj = soup.find_all('a', ep_end=True, ep_start=True) total_rng = [] for r in rngs_obj: rng = r.text rngs = rng.split('-') if rngs[0] == '0': rngs[0] = '1' total_rng.append('-'.join(rngs)) text = ','.join(total_rng) parsed_rng = utils.compress_range(utils.extract_range(text)) return parsed_rng
def save_anime(args): """Put the anime into watch later list.""" anime_name, eps = read_args(args) watched = utils.read_log(anime_name) if watched: watched_eps = utils.extract_range(utils.Log(watched).eps) else: watched_eps = [] save_eps = set(eps).difference(set(watched_eps)) if not save_eps: outputs.warning_info('Already watched the provided episodes.') return utils.write_log(anime_name, utils.compress_range(save_eps), append=True, logfile=config.watchlaterfile)
def list_local_episodes(args): in_dict = utils.get_local_episodes(*args) out_dict = dict() for anime, eps in in_dict.items(): new_eps = utils.compress_range(utils.extract_range(eps)) if new_eps != "": out_dict[anime] = new_eps empties = set(in_dict).difference(set(out_dict)) if len(out_dict) == 0: outputs.warning_info("No local entries found.") else: outputs.bold_info("Episodes\tAnime Name") for k, v in out_dict.items(): outputs.normal_info(f"{v}\t\t{k}") if len(empties) > 0: outputs.warning_info("Directories without Episodes:") outputs.warning_info(", ".join(empties))
def continue_play(args, play_func=play_anime): name, _ = read_args(args, episodes=False) log = utils.Log(utils.read_log().get(name)) watch_later = utils.read_log(name, logfile=config.watchlaterfile) if watch_later: episodes = utils.extract_range(utils.Log(watch_later).eps) else: _, episodes = read_args(args) outputs.prompt_val("Watched", log._eps, "success", end='\t') outputs.normal_info(log.last_updated_fmt) if not log.eps: last = 0 else: last = int(re.split('-|,', log.eps)[-1]) to_play = utils.compress_range(filter(lambda e: e > last, episodes)) if to_play.strip(): play_func([name, to_play]) else: unsave_anime(name)
def generate(general_struct, filter_chain_list, class_id_to_name_dict, img_name_to_class_id_dict, yolo_version, draw_bounding_boxes=False, no_yolo_output=False): """ Generate images with given settings in general struct and filter chain list. With the assignment of each object image to an object class this method also creates output files for YOLO. :param general_struct: object containing general settings :param filter_chain_list: list of filter_chain objects containing all settings for every set filter :param class_id_to_name_dict: dict assigning object class IDs to its corresponding class name :param img_name_to_class_id_dict: dict assigning each image to its object class ID :param yolo_version: number of YOLO version for which the YOLO output files should be created :param draw_bounding_boxes: boolean value specifying whether bounding boxes should be drawn around object :param no_yolo_output: boolean value specifying whether no YOLO output files should be created :return: """ # get destination resolution dest_res_x = general_struct.output_width dest_res_y = general_struct.output_height # collect input images objects_path = general_struct.object_path obj_img_filename_list = utils.list_directory(objects_path, [".jpg", ".png"]) # setup yolo object yolo_generator = YoloGenerator(yolo_version=yolo_version) # set counter for filename of stored images img_counter = 1 # list of all objects obj_list = [] # do operations for every object for filter_chain in filter_chain_list: for obj_img_filename in obj_img_filename_list: # TODO: following outprint should be in the next upper loop and here should be "Generate image x" or smth logging.info("Process filter chain number %d:" % img_counter) output_filename = str(img_counter) obj_list.clear() # list of all objects # get number of objects which should be placed onto each generated image num_obj_per_img_min, num_obj_per_img_max = utils.extract_range( filter_chain.num_obj_per_img) if num_obj_per_img_min == num_obj_per_img_max: num_obj_per_img = int(num_obj_per_img_min) else: num_obj_per_img = random.randint(num_obj_per_img_min, num_obj_per_img_max) logging.info( " => %s objects get placed onto each generated image" % num_obj_per_img) ############################################################# # BACKGROUND FILTERS # get resolution out of resolution filter if filter_chain.resolution: res_x, res_y = apply_resolution_filter(filter_chain.resolution) else: res_x = dest_res_x res_y = dest_res_y # apply all filters aiming on background bg_img = apply_filters_on_background( general_struct.background_path, filter_chain, res_x, res_y) ############################################################# # OBJECTS FILTERS # read in main object image obj_img_path = os.path.abspath( os.path.join(general_struct.object_path, obj_img_filename)) category_number = img_name_to_class_id_dict[obj_img_filename] main_obj = Object(filename=obj_img_filename, image=img_processing.import_image(obj_img_path), category=category_number) obj_list.append(main_obj) logging.info(" => object image path \'%s\'" % obj_img_filename) # read in other randomly selected object images including their labels for x in range(num_obj_per_img - 1): random_idx = random.randint(0, len(obj_img_filename_list) - 1) obj_img_path = os.path.abspath( os.path.join(general_struct.object_path, obj_img_filename_list[random_idx])) category_number = img_name_to_class_id_dict[ obj_img_filename_list[random_idx]] obj = Object(filename=obj_img_filename_list[random_idx], image=img_processing.import_image(obj_img_path), category=category_number) logging.info(" => random object image path \'%s\'" % obj_img_path) obj_list.append(obj) # apply all object filters on the generated objects merged_img, obj_list = apply_filters_on_objects( obj_list, filter_chain, bg_img, res_x, res_y) ############################################################# # OBJECT AND BACKGROUND FILTERS # before applying all other filters, insert additional objects in front of objects for obj in obj_list: # overlap filter applied onto fore- and background if filter_chain.overlap: if filter_chain.overlap.type == 1: # type 1: in front of objects merged_img = apply_overlap_filter( filter_chain.overlap, obj, merged_img) elif filter_chain.overlap.type != 0: logging.error( "ERROR: Unknown overlap filter type (%s)" % filter_chain.overlap.type) sys.exit(-1) # apply all filters aiming for object and background merged_img = apply_filters_on_objects_and_background( merged_img, filter_chain) ############################################################# # draw bounding box if draw_bounding_boxes: for obj in obj_list: img_processing.draw_bounding_box(merged_img, obj.bbox) # save result image img_processing.save_image(merged_img, general_struct.output_path, output_filename + '.jpg') # create YOLO information for every generated image with category numbers and bounding boxes of objects yolo_generator.generate_yolo_output(obj_list, merged_img.shape[:2], general_struct.output_path, output_filename) logging.info("... done processing filter chain number %s\n" % img_counter) img_counter += 1 # create text files 'train.txt', 'obj.names' and 'obj.data' for YOLO inside the output directory if not no_yolo_output: yolo_generator.generate_train_data_file(general_struct.output_path) yolo_generator.generate_obj_names_file(general_struct.output_path, class_id_to_name_dict) yolo_generator.generate_obj_data_file( general_struct.output_path, len(class_id_to_name_dict.keys())) yolo_generator.generate_yolo_obj_cfg(general_struct.output_path, len(class_id_to_name_dict.keys())) return