import cv2 import numpy as np from random import randint as rint import time import detect_compo.lib_ip.ip_preprocessing as pre import detect_compo.lib_ip.ip_detection as det import detect_compo.lib_ip.ip_draw as draw import detect_compo.lib_ip.ip_segment as seg from detect_compo.lib_ip.Block import Block from config.CONFIG_UIED import Config C = Config() def block_hierarchy(blocks): for i in range(len(blocks) - 1): for j in range(i + 1, len(blocks)): relation = blocks[i].compo_relation(blocks[j]) if relation == -1: blocks[j].children.append(i) if relation == 1: blocks[i].children.append(j) return def block_bin_erase_all_blk(binary, blocks, pad=0, show=False): ''' erase the block parts from the binary map :param binary: binary map of original image :param blocks_corner: corners of detected layout block :param show: show or not :param pad: expand the bounding boxes of blocks :return: binary map without block parts ''' bin_org = binary.copy() for block in blocks: block.block_erase_from_bin(binary, pad) if show: cv2.imshow('before', bin_org) cv2.imshow('after', binary) cv2.waitKey() def block_division(grey, org, grad_thresh, show=False, write_path=None, step_h=10, step_v=10, line_thickness=C.THRESHOLD_LINE_THICKNESS, min_rec_evenness=C.THRESHOLD_REC_MIN_EVENNESS, max_dent_ratio=C.THRESHOLD_REC_MAX_DENT_RATIO, min_block_height_ratio=C.THRESHOLD_BLOCK_MIN_HEIGHT): ''' :param grey: grey-scale of original image :return: corners: list of [(top_left, bottom_right)] -> top_left: (column_min, row_min) -> bottom_right: (column_max, row_max) ''' blocks = [] mask = np.zeros((grey.shape[0]+2, grey.shape[1]+2), dtype=np.uint8) broad = np.zeros((grey.shape[0], grey.shape[1], 3), dtype=np.uint8) broad_all = broad.copy() row, column = grey.shape[0], grey.shape[1] for x in range(0, row, step_h): for y in range(0, column, step_v): if mask[x, y] == 0: # region = flood_fill_bfs(grey, x, y, mask) # flood fill algorithm to get background (layout block) mask_copy = mask.copy() ff = cv2.floodFill(grey, mask, (y, x), None, grad_thresh, grad_thresh, cv2.FLOODFILL_MASK_ONLY) # ignore small regions if ff[0] < 500: continue mask_copy = mask - mask_copy region = np.reshape(cv2.findNonZero(mask_copy[1:-1, 1:-1]), (-1, 2)) region = [(p[1], p[0]) for p in region] block = Block(region, grey.shape) # draw.draw_region(region, broad_all) # if block.height < 40 and block.width < 40: # continue if block.height < 30: continue # print(block.area / (row * column)) if block.area / (row * column) > 0.9: continue elif block.area / (row * column) > 0.7: block.redundant = True # get the boundary of this region # ignore lines if block.compo_is_line(line_thickness): continue # ignore non-rectangle as blocks must be rectangular if not block.compo_is_rectangle(min_rec_evenness, max_dent_ratio): continue # if block.height/row < min_block_height_ratio: # continue blocks.append(block) # draw.draw_region(region, broad) if show: cv2.imshow('flood-fill all', broad_all) cv2.imshow('block', broad) cv2.waitKey() if write_path is not None: cv2.imwrite(write_path, broad) return blocks