def mask_page(title: str, page_no: int) -> Optional[np.ndarray]: data = annotations(title, page_no) img = cv2.imread( op.join(root, "manga109", "images", title, f"{page_no:03d}.jpg")) mask = np.full((img.shape[0], img.shape[1]), 255, dtype=np.uint8) if "text" not in data: return text_boxes = data["text"] if isinstance(text_boxes, list): for box in text_boxes: x1 = box["@xmin"] y1 = box["@ymin"] x2 = box["@xmax"] y2 = box["@ymax"] points = np.array([[x1, y1], [x1, y2], [x2, y2], [x2, y1]], dtype=np.int32) cv2.fillPoly(mask, [points], (0, 0, 0)) else: x1 = text_boxes["@xmin"] y1 = text_boxes["@ymin"] x2 = text_boxes["@xmax"] y2 = text_boxes["@ymax"] points = np.array([[x1, y1], [x1, y2], [x2, y2], [x2, y1]], dtype=np.int32) cv2.fillPoly(mask, [points], (0, 0, 0)) fg = cv2.bitwise_or(img, img, mask=mask) background = np.full(img.shape, 255, dtype=np.uint8) mask = cv2.bitwise_not(mask) bk = cv2.bitwise_or(background, background, mask=mask) final = cv2.bitwise_or(fg, bk) return final
def page_annotations_visual(title: str, page_no: int) -> Optional[np.ndarray]: data = annotations(title, page_no) img = cv2.imread( op.join(root, "manga109", "images", title, f"{page_no:03d}.jpg")) if "text" not in data and "frame" not in data: return frames = data["frame"] text_boxes = data["text"] if not isinstance(text_boxes, list): text_boxes = [text_boxes] for box in text_boxes: x1 = int(box["@xmin"]) y1 = int(box["@ymin"]) x2 = int(box["@xmax"]) y2 = int(box["@ymax"]) cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2) if not isinstance(frames, list): frames = [frames] for box in frames: x1 = int(box["@xmin"]) y1 = int(box["@ymin"]) x2 = int(box["@xmax"]) y2 = int(box["@ymax"]) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) mid = img.shape[1] // 2 cv2.rectangle(img, (mid - 100, 0), (mid + 100, img.shape[0]), (0, 0, 225)) return img
def text_in_frames(title, page_no) -> Dict[str, List[Dict[str, Any]]]: data = annotations(title, page_no) texts = data["text"] if not isinstance(texts, list): texts = [texts] if "frame" not in data: return {"-1": [text for text in texts]} frames = data["frame"] if not isinstance(frames, list): frames = [frames] for i in range(len(frames)): frames[i]["boxtopleft"] = (int(frames[i]["@xmin"]), int(frames[i]["@ymin"])) frames[i]["boxbotright"] = (int(frames[i]["@xmax"]), int(frames[i]["@ymax"])) frames_to_text = {frame["@id"]: [] for frame in frames} for text in texts: text_topleft = (int(text["@xmin"]), int(text["@ymin"])) text_botright = (int(text["@xmax"]), int(text["@ymax"])) areas = {frame["@id"]: 0 for frame in frames} for frame in frames: frame_topleft = frame["boxtopleft"] frame_botright = frame["boxbotright"] SI = max(0, min(text_botright[0], frame_botright[0]) - max(text_topleft[0], frame_topleft[0])) * \ max(0, min(text_botright[1], frame_botright[1]) - max(text_topleft[1], frame_topleft[1])) areas[frame["@id"]] = SI best_frame = max(areas.items(), key=operator.itemgetter(1))[0] if areas[best_frame] == 0: continue frames_to_text[best_frame].append(text) return frames_to_text
def frame_order(title, page_no) -> List[str]: data = annotations(title, page_no) text = text_in_frames(title, page_no) if "frame" not in data: return ["-1"] frames = data["frame"] if not isinstance(frames, list): frames = [frames] if title in yonkoma: return _frame_order_yonkoma(frames) frames = [f for f in frames if len(text[f["@id"]]) > 0] if len(frames) == 0: return ["-1"] if frame_crosses_middle(title, page_no): return _frame_order(frames) midpoint = find_midpoint(title, page_no) right_page_frames = [] left_page_frames = [] for frame in frames: topright_x = int(frame["@xmax"]) # Have a small buffer to fix pixel errors if topright_x > midpoint + 50: right_page_frames.append(frame) else: left_page_frames.append(frame) return _frame_order(right_page_frames) + _frame_order(left_page_frames)
def frame_crosses_middle(title, page_no) -> Optional[bool]: data = annotations(title) img = cv2.imread( op.join(root, "manga109", "images", title, f"{page_no:03d}.jpg")) mid = img.shape[1] / 2 if "frame" not in data["book"]["pages"]["page"][page_no]: return frames = data["book"]["pages"]["page"][page_no]["frame"] if not isinstance(frames, list): frames = [frames] for box in frames: x1 = int(box["@xmin"]) x2 = int(box["@xmax"]) if x1 < mid - 75 < mid + 75 < x2: return True return False
def get_pages(with_text: bool = False, exclude: Optional[List[str]] = None, include: Optional[List[str]] = None) -> \ List[Tuple[str, int]]: assert exclude is None or include is None if exclude is None: exclude = [] result = [] books = get_books() if include is None else include for book in books: if book in exclude: continue data = annotations(book) num_pages = len(data["book"]["pages"]["page"]) for i in range(num_pages): if with_text: if "text" not in data["book"]["pages"]["page"][i]: continue if (book, i) in degeneracies: continue result.append((book, i)) return result