import itertools from itertools import compress from itertools import starmap from operator import __and__ import cv2 import numpy as np from cv_analysis.utils.connect_rects import connect_related_rects from cv_analysis.utils.display import show_image_mpl from cv_analysis.utils.draw import draw_rectangles from cv_analysis.utils.label_rects import label_rects from cv_analysis.utils.structures import Rectangle from cv_analysis.utils.postprocessing import ( remove_overlapping, remove_included, has_no_parent, ) from cv_analysis.utils.visual_logging import vizlogger #could be dynamic parameter is the scan is noisy def is_likely_segment(rect, min_area=100): return cv2.contourArea(rect, False) > min_area def find_segments(image): contours, hierarchies = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) mask1 = map(is_likely_segment, contours) mask2 = map(has_no_parent, hierarchies[0]) mask = starmap(__and__, zip(mask1, mask2)) contours = compress(contours, mask) rectangles = (cv2.boundingRect(c) for c in contours) return rectangles def dilate_page_components(image): #if text is detected in words make kernel bigger image = cv2.GaussianBlur(image, (7, 7), 0) thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) return cv2.dilate(thresh, kernel, iterations=4) def fill_in_component_area(image, rect): x, y, w, h = rect cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 0), -1) cv2.rectangle(image, (x, y), (x + w, y + h), (255, 255, 255), 7) _, image = cv2.threshold(image, 254, 255, cv2.THRESH_BINARY) return ~image def parse_layout(image: np.array): image = image.copy() image_ = image.copy() #show_image_mpl(image) if len(image_.shape) > 2: image_ = cv2.cvtColor(image_, cv2.COLOR_BGR2GRAY) dilate = dilate_page_components(image_) # show_mpl(dilate) rects = list(find_segments(dilate)) # -> Run meta detection on the previous detections TODO: refactor for rect in rects: x, y, w, h = rect cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 0), -1) cv2.rectangle(image, (x, y), (x + w, y + h), (255, 255, 255), 7) # show_mpl(image) _, image = cv2.threshold(image, 254, 255, cv2.THRESH_BINARY) image = ~image # show_mpl(image) if len(image.shape) > 2: image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) rects = find_segments(image) # <- End of meta detection rects = list(map(Rectangle.from_xywh, rects)) rects = remove_included(rects) rects = map(lambda r: r.xywh(), rects) rects = connect_related_rects(rects) rects = list(map(Rectangle.from_xywh, rects)) # rects = remove_included(rects) return rects