def __init__(self, manga109_root_dir, year=2020, version="", book_limit=None, page_limit=None, add_manga109_info=False, add_coco_info=True): """ Parameters ---------- add_manga109_info : bool include additional information out of original COCO format. add_coco_info : bool include information in original COCO format, but out of Manga109 Dataset. if set to False, COCO compatibility breaks. """ self.book_limit = book_limit self.page_limit = page_limit self.add_manga109_info = add_manga109_info self.add_coco_info = add_coco_info self.parser = manga109api.Parser(root_dir=manga109_root_dir) self.init_coco_format_info(year=year, version=version) self.reset_converter()
def get_faces_for_yolo(): manga109_root_dir = "Data" p = manga109api.Parser(root_dir=manga109_root_dir) j = 0 for book_title in p.books: annotation = p.get_annotation(book=book_title) for i in range(0, len(annotation['page'])): img = Image.open(p.img_path(book=book_title, index=i)) for annotation_type in ["face"]: j += 1 rois = annotation["page"][i][annotation_type] f = open(f"Yolo_dataset/{j}.txt", "w+") for roi in rois: w = (roi["@xmax"] - roi["@xmin"]) h = (roi["@ymax"] - roi["@ymin"]) x = roi['@xmin'] + ((roi["@xmax"] - roi["@xmin"]) / 2) y = roi["@ymin"] + ((roi["@ymax"] - roi["@ymin"]) / 2) x = round(x / img.size[0], 6) y = round(y / img.size[1], 6) w = round(w / img.size[0], 6) h = round(h / img.size[1], 6) f.write(f"1 {x} {y} {w} {h}\n") f.close() img.save(f"Yolo_dataset/{j}.jpg")
def test_img_path(): manga109_root_dir = "tests/data_dummy/" p = manga109api.Parser(root_dir=manga109_root_dir) img1 = Path(p.img_path(book="TitleA", index=0)).absolute() img2 = Path("tests/data_dummy/images/TitleA/000.jpg").absolute() assert (img1 == img2)
def test_data_type(): manga109_root_dir = "tests/data_dummy/" p = manga109api.Parser(root_dir=manga109_root_dir) for book in p.books: annotation = p.get_annotation(book=book) # title assert isinstance(annotation["title"], str) # character assert isinstance(annotation["character"], list) for character in annotation["character"]: assert isinstance(character["@id"], str) assert isinstance(character["@name"], str) # page assert isinstance(annotation["page"], list) for page in annotation["page"]: assert isinstance(page["@index"], int) assert isinstance(page["@width"], int) assert isinstance(page["@height"], int) for obj_type in {"body", "face", "frame", "text"}: assert isinstance(page[obj_type], list) for obj in page[obj_type]: assert isinstance(obj["@id"], str) assert isinstance(obj["@xmin"], int) assert isinstance(obj["@xmax"], int) assert isinstance(obj["@ymin"], int) assert isinstance(obj["@ymax"], int) if obj_type == "text": assert isinstance(obj["#text"], str)
def test_data_type_separated(): manga109_root_dir = "tests/data_dummy/" p = manga109api.Parser(root_dir=manga109_root_dir) for book in p.books: annotation = p.get_annotation(book=book, separate_by_tag=True) # title assert isinstance(annotation["title"], str) # character assert isinstance(annotation["character"], list) for character in annotation["character"]: assert isinstance(character["@id"], str) assert isinstance(character["@name"], str) # page assert isinstance(annotation["page"], list) for page in annotation["page"]: assert isinstance(page["@index"], int) assert isinstance(page["@width"], int) assert isinstance(page["@height"], int) for obj_type in page.keys(): if obj_type in {"body", "face", "frame", "text"}: assert isinstance(page[obj_type], list) for obj in page[obj_type]: assert isinstance(obj["@id"], str) assert isinstance(obj["@xmin"], int) assert isinstance(obj["@xmax"], int) assert isinstance(obj["@ymin"], int) assert isinstance(obj["@ymax"], int) assert obj["type"] == obj_type if obj_type == "text": assert isinstance(obj["#text"], str) # custom tag test elif obj_type not in {"@index", "@width", "@height"}: for obj in page[obj_type]: assert isinstance(obj["@id"], str) assert isinstance(obj["@attr_num"], int) assert isinstance(obj["@attr_str"], str) assert isinstance(obj["@attr_mix"], str) assert obj["type"] == obj_type for key in (obj.keys() - { "@id", "@attr_num", "@attr_str", "@attr_mix", "type" }): assert isinstance(obj[key], (int, str)) if "#text" in obj.keys(): assert isinstance(obj["#text"], str)
def load(cls, path, **kwargs): os.makedirs('cache/manga', exist_ok=True) try: with open('cache/manga/data.json', 'r') as f: data = json.load(f) except: data = manga109api.Parser(root_dir=str(path)) data = {'books': data.books, 'annotations': data.annotations} with open('cache/manga/data.json', 'w') as f: json.dump(data, f) try: with open('cache/manga/pages.json', 'r') as f: pages = json.load(f) except: pages = [] for book in data['books']: for page in data['annotations'][book]['book']['pages']['page']: pagedata = { 'text': [], 'path': str(path / 'images' / book / (str(page['@index']).zfill(3) + ".jpg")) } if 'text' in page: for txt in page['text'] if isinstance( page['text'], list) else [page['text']]: pagedata['text'].append({ 'xmin': txt['@xmin'], 'xmax': txt['@xmax'], 'ymin': txt['@ymin'], 'ymax': txt['@ymax'], 'text': txt['#text'] }) pages.append(pagedata) with open('cache/manga/pages.json', 'w') as f: json.dump(pages, f) return Manga109ImageList( list(filter(lambda x: len(x['text']) > 0, pages)), **kwargs)
def __init__( self, manga109_root: str, titles, data_root: str = "dataset", exclude_others: bool = True, threshold: int = 0, transform=None, ) -> None: self.root = manga109_root self.data_root = data_root self.titles = titles self.transform = transform chara_others = set() with open(os.path.join(self.data_root, "others_ids.txt")) as f: for line in f: chara_others.add(line.rstrip()) # obtain list of character ids and file paths chara_ids = list() self.paths = list() self.manga109_parser = manga109api.Parser(self.root) for title in self.titles: # We used the old version. annot = self.manga109_parser.get_annotation( title, annotation_type="annotations.v2018.05.31") for chara in annot["character"]: if exclude_others and chara["@id"] in chara_others: continue chara_path = os.path.join(self.data_root, "images", chara["@id"]) if not os.path.exists(chara_path): continue paths = os.listdir(chara_path) if len(paths) < threshold: continue self.paths += paths chara_ids += [chara["@id"]] * len(paths) self.classes = sorted(set(chara_ids)) self.labels = [self.classes.index(id) for id in chara_ids] assert len(self.labels) == len(self.paths)
def main(): arg_parser = argparse.ArgumentParser() arg_parser.add_argument("manga109dir") arg_parser.add_argument("--out", default="dataset/images", type=Path) args = arg_parser.parse_args() parser = manga109api.Parser(root_dir=args.manga109dir) books = list() for split in {"train", "val", "test"}: with open("dataset/{}_titles.txt".format(split)) as f: for line in f: books.append(line.rstrip()) for book in tqdm.tqdm(books): annotation = parser.get_annotation( book=book, annotation_type="annotations.v2018.05.31") for page in annotation["page"]: name = "{:03d}.jpg".format(page["@index"]) path = parser.root_dir / "images" / annotation["title"] / name # H, W, C page_img = cv2.imread(path.as_posix()) for face in page["face"]: (args.out / face["@character"]).mkdir(exist_ok=True, parents=True) # small face images are excluded. if (face["@xmax"] - face["@xmin"]) <= 30: continue if (face["@ymax"] - face["@ymin"]) <= 30: continue attrs = ("@xmin", "@ymin", "@xmax", "@ymax") bbox = [face[attr] for attr in attrs] bbox = expand_bbox(bbox, page["@width"], page["@height"]) img = page_img[bbox[1]:bbox[3], bbox[0]:bbox[2], :] # NOTE: ".png" should be used save_path = args.out / face["@character"] / (face["@id"] + ".jpg") cv2.imwrite(save_path.as_posix(), img)
import manga109api from pprint import pprint import cv2 import time import os from dotenv import load_dotenv import numpy as np load_dotenv() TEST_RATIO = 0.1 manga109_root_dir = os.getenv('MANGA109_ROOT_DIR') p = manga109api.Parser(root_dir=manga109_root_dir) book_cnt = 0 os.system('rm -r face body') os.mkdir('face/') os.mkdir('body/') face_train = open("face_training_set.txt", "w") face_test = open("face_test_set.txt", "w") for book in p.books: book_cnt += 1 face_cnt = 0 body_cnt = 0 os.mkdir('face/' + str(book_cnt)) os.mkdir('body/' + str(book_cnt)) for page in p.annotations[book]["book"]["pages"]["page"]: img = cv2.imread(p.img_path(book=book, index=page["@index"])) if "face" in page.keys() and type(page["face"]) is list:
if __name__ == "__main__": ap = args_parser() manga109_root_dir = "manga109extracted" if not os.path.exists(manga109_root_dir): os.makedirs(manga109_root_dir) book = ap.book page_count = ap.pages file_count = [ glob.glob(os.path.join(manga109_root_dir, '**', '*.*'), recursive=True) ] count = len(file_count[0]) for page_index in range(page_count): tracker = 0 p = manga109api.Parser(root_dir="Manga109s_data") annotation = p.get_annotation(book=book) img = Image.open(p.img_path(book=book, index=page_index)) for annotation_type in [ap.annotation]: rois = annotation["page"][page_index][annotation_type] for roi in rois: cropped = img.crop( (roi["@xmin"], roi["@ymin"], roi["@xmax"], roi["@ymax"])) image_x_dim, image_y_dim = cropped.size if ap.preprocess: cropped = cropped.resize((ap.size, ap.size), Image.ANTIALIAS) if image_x_dim >= (ap.size / 2) and image_y_dim >= (ap.size / 2): cropped.save("manga109extracted/%s_%d.jpg" % (ap.book, count))
import argparse import manga109api arg_parser = argparse.ArgumentParser() arg_parser.add_argument("root", help="/path/to/Manga109_20xx_xx_xx") args = arg_parser.parse_args() others_names = ["Others", "Other", "the other", "Other", "other", "Ohter"] # for Buraritessen others_names += ["Other(スリ)", "Other(赤穂浪士)", "Other(役人)", "Other(大吉屋の手下)"] others_ids = list() parser = manga109api.Parser(args.root) for book in parser.books: annot = parser.get_annotation(book, annotation_type="annotations.v2018.05.31") for chara in annot["character"]: if chara["@name"] in others_names: others_ids.append(chara["@id"]) with open("dataset/others_ids.txt", "w") as f: for id in others_ids: f.write(id + "\n")
def get_annotation_dict( annotation_type='face', threshold_num=70, dict_len=200, manga109_dir='/Users/patrick/Documents/datasets/Manga109_2017_09_28', return_list=False): """ :param annotation_type: face/body :param threshold_num: minimum number of this annotation type appears in a book :param dict_len: the length of return dict :param manga109_dir: the dir of manga109 dataset :param return_list: whether the type of return value is a list :return: the annotation ordered dict in this format { 'id_of_the_element': { '@count': int, '@book': book_name, 'elements': [ { '@page': int, '@xmax': int, '@xmin': int, '@ymax': int, '@ymin': int }, ... ] }, ... } """ p = manga109api.Parser(root_dir=manga109_dir) books = p.books all_characters = {} for book_name in books: book = p.annotations[book_name]['book'] characters = book['characters']['character'] # print(characters) characters_count = {} for char in characters: characters_count[char['@id']] = { '@count': 0, '@book': book_name, 'elements': [] } pages = book['pages']['page'] for i in range(len(pages)): page = pages[i] if annotation_type not in page: continue # 不止有一个 face if type(page[annotation_type]) is type([]): for face in page[annotation_type]: temp_dict = dict() temp_dict['@page'] = i temp_dict['@xmax'] = face['@xmax'] temp_dict['@xmin'] = face['@xmin'] temp_dict['@ymax'] = face['@ymax'] temp_dict['@ymin'] = face['@ymin'] characters_count[face['@character']]['elements'].append( temp_dict) characters_count[face['@character']]['@count'] += 1 else: temp_dict = dict() temp_dict['@page'] = i temp_dict['@xmax'] = page[annotation_type]['@xmax'] temp_dict['@xmin'] = page[annotation_type]['@xmin'] temp_dict['@ymax'] = page[annotation_type]['@ymax'] temp_dict['@ymin'] = page[annotation_type]['@ymin'] characters_count[page[annotation_type] ['@character']]['elements'].append(temp_dict) characters_count[page[annotation_type] ['@character']]['@count'] += 1 for key, val in characters_count.items(): if val['@count'] >= threshold_num: all_characters[key] = val ordered_characters = OrderedDict() for key, val in all_characters.items(): ordered_characters[key] = val ordered_characters = sorted(list(ordered_characters.items()), key=lambda x: x[1]['@count'], reverse=True) if return_list: return ordered_characters[:dict_len] return OrderedDict(ordered_characters[:dict_len])
def get_frame_dict( manga109_dir='/Users/patrick/Documents/datasets/Manga109_2017_09_28'): p = manga109api.Parser(root_dir=manga109_dir) books = p.books all_frames = {} frame_without_face = 0 frame_without_body = 0 for book_name in books: book = p.annotations[book_name]['book'] pages = book['pages']['page'] for i in range(len(pages)): page = pages[i] frame_list = [] face_list = [] body_list = [] if 'frame' not in page: continue # 统一为 list,方便后面的处理 if type(page['frame']) is type([]): frame_list.extend(page['frame']) else: frame_list.append(page['frame']) if 'face' in page: if type(page['face']) is type([]): face_list.extend(page['face']) else: face_list.append(page['face']) if 'body' in page: if type(page['body']) is type([]): body_list.extend(page['body']) else: body_list.append(page['body']) for frame in frame_list: # 初始化每个 frame frame_dict = dict() frame_dict['@book'] = book_name frame_dict['@page'] = i frame_dict['@xmax'] = frame['@xmax'] frame_dict['@xmin'] = frame['@xmin'] frame_dict['@ymax'] = frame['@ymax'] frame_dict['@ymin'] = frame['@ymin'] frame_dict['@body_count'] = 0 frame_dict['@face_count'] = 0 frame_dict['body'] = [] frame_dict['face'] = [] # 添加到返回的结果中 all_frames[frame['@id']] = frame_dict # 把 face 和 body 添加到对应的 frame 之中 for frame in frame_list: # 将 face 添加到对应的 frame 中 for face in face_list: if is_element_in_frame(frame, face): all_frames[frame['@id']]['@face_count'] += 1 all_frames[frame['@id']]['face'].append(face) # 将 body 添加到对应的 frame 中 for body in body_list: if is_element_in_frame(frame, body): all_frames[frame['@id']]['@body_count'] += 1 all_frames[frame['@id']]['body'].append(face) for frame in frame_list: if all_frames[frame['@id']]['@face_count'] == 0: frame_without_face += 1 if all_frames[frame['@id']]['@body_count'] == 0: frame_without_body += 1 print('all frames count:', len(all_frames)) print('frames without face count:', frame_without_face) print('frames without body count:', frame_without_body) return all_frames
def crop_save(folder): try: os.makedirs(folder + 'train/B/') os.makedirs(folder + 'test/B/') os.makedirs(folder + 'train/A/') os.makedirs(folder + 'test/A/') except: pass counter = 0 print('start prasing...') p = manga109api.Parser(root_dir=manga109_root_dir) print('end') for m in range(0, len(p.books)): print(p.books[m]) for index in range( 1, len(p.annotations[p.books[m]]['book']['pages']['page']) - 1): #print(p.books[m], index) try: imgright = Image.open( p.img_path(book=p.books[m], index=2 * index)) imgleft = Image.open( p.img_path(book=p.books[m], index=2 * index + 1)) except: continue width = imgleft.size[0] total_width = imgleft.size[0] + imgright.size[0] max_height = imgleft.size[1] new_im = Image.new('RGB', (total_width, max_height)) new_im.paste(imgleft, (0, 0)) new_im.paste(imgright, (width, 0)) annotation_type = "frame" try: rois = p.annotations[p.books[m]]["book"]["pages"]["page"][ index][annotation_type] except: continue #print(rois) if type(rois) is not list: rois = [rois] for roi in rois: #print(roi) xmin = roi["@xmin"] ymin = roi["@ymin"] xmax = roi["@xmax"] ymax = roi["@ymax"] width = (xmax - xmin) height = (ymax - ymin) ratio = width / height #print(width, height, ratio) if width < 768 and width > 256 and height > 256 and height < 768 and ( 0.8 < ratio and ratio < 1.25): #draw_rectangle(new_im,xmin,ymin,xmax,ymax, annotation_type) #new_im.show() counter += 1 box = (xmin + 10, ymin + 10, xmax - 20, ymax - 20) cropped_image = new_im.crop(box) #cropped_image.show() if width < height: cropped_image = cropped_image.resize( (256, int(256 * height / width))) else: cropped_image = cropped_image.resize( (int(256 * width / height), 256)) if counter % 10 == 0: outf = folder + 'test/B/' else: outf = folder + 'train/B/' result = np.array(cropped_image) cv2.imwrite(outf + "{:05d}.jpg".format(counter), result)