class CompoHTML: def __init__(self, compo_id, html_tag, compo_df=None, html_id=None, html_class_name=None, children=None, parent=None): self.compo_df = compo_df self.compo_id = compo_id self.children = children if children is not None else [ ] # CompoHTML objs self.parent = parent # CompoHTML obj self.html_id = html_id self.html_class_name = html_class_name self.html_tag = html_tag self.html_tag_map = {'Compo': 'div', 'Text': 'div', 'Block': 'div'} self.html = None # HTML obj self.html_script = '' # sting self.css = [ ] # CSS objs, a compo may have multiple css styles through linking to multiple css classes self.init_html() def init_html(self): self.html = HTML(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) if type(self.children) is not list: self.children = [self.children] for child in self.children: self.html.add_child(child.html_script) self.html_script = self.html.html_script def add_child(self, child): ''' :param child: CompoHTML object ''' self.children.append(child) self.html.add_child(child.html_script) self.html_script = self.html.html_script
class Block: def __init__(self, id, compos, slice_sub_block_direction='h', html_tag=None, html_id=None, html_class_name=None, css=None): self.block_id = id self.compos = compos # list of CompoHTML objs self.sub_blocks = [] # list of Block objs self.children = [] # compos + sub_blocks self.type = 'block' self.top = None self.left = None self.bottom = None self.right = None self.width = None self.height = None # html info self.html = None # HTML obj self.html_tag = 'div' if html_tag is None else html_tag self.html_id = html_id self.html_class_name = html_class_name self.html_script = '' # sting self.react = None # React obj self.react_html_script = '' # string self.css = css # dictionary: {'css-name': CSS obj} self.css_script = '' # string # slice sub-block comprising multiple compos self.sub_blk_alignment = slice_sub_block_direction self.slice_sub_blocks() self.sort_compos_and_sub_blks() # print(self.html_id, slice_sub_block_direction) self.init_boundary() self.init_html() self.init_css() self.init_children_css() self.init_react() def init_boundary(self): self.top = int(min(self.compos + self.sub_blocks, key=lambda x: x.top).top) self.bottom = int(max(self.compos + self.sub_blocks, key=lambda x: x.bottom).bottom) self.left = int(min(self.compos + self.sub_blocks, key=lambda x: x.left).left) self.right = int(max(self.compos + self.sub_blocks, key=lambda x: x.right).right) self.height = int(self.bottom - self.top) self.width = int(self.right - self.left) def init_html(self): self.html = HTML(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) for child in self.children: self.html.add_child(child.html_script) self.html_script = self.html.html_script def init_react(self): self.react = React(tag=self.html_tag, react_compo_name='Block' + str(self.block_id), id=self.html_id, class_name=self.html_class_name) for child in self.children: self.react.add_child(child.react_html_script) self.react_html_script = self.react.react_html_script def init_css(self): for sub_block in self.sub_blocks: self.css.update(sub_block.css) for compo in self.compos: self.css.update(compo.css) self.css_script = self.css self.assembly_css() def assembly_css(self): self.css_script = '' for i in self.css: self.css_script += self.css[i].css_script def update_css(self, css_name, **attrs): if css_name in self.css: self.css[css_name].add_attrs(**attrs) else: self.css[css_name] = CSS(css_name, **attrs) self.assembly_css() ''' ****************************** ********** Children ********** ****************************** ''' def slice_sub_blocks(self): ''' slice the block into sub-blocks ''' self.sub_blocks, self.compos = slice_blocks(self.compos, direction=self.sub_blk_alignment) def sort_compos_and_sub_blks(self): ''' combine comps and sub_blocks w.r.t the slicing direction :param direction: slicing direction: 'v': from top to bottom; 'h': from left to right :return: children: sorted sub-blocks and compos ''' if self.sub_blk_alignment == 'v': self.children = sorted(self.compos + self.sub_blocks, key=lambda x: x.top) elif self.sub_blk_alignment == 'h': self.children = sorted(self.compos + self.sub_blocks, key=lambda x: x.left) def init_children_css(self): if self.sub_blk_alignment == 'v': for i in range(1, len(self.children)): child = self.children[i] # if child.type == 'block': continue css_name = '#' + child.html_id gap = child.top - self.children[i - 1].bottom if child.html_tag == 'ul': child.update_css(css_name, padding_top=str(gap) + 'px') else: child.update_css(css_name, margin_top=str(gap) + 'px') self.css.update(child.css) elif self.sub_blk_alignment == 'h': for i in range(len(self.children)): child = self.children[i] # if child.type == 'block': continue css_name = '#' + child.html_id child.update_css(css_name, float='left') if i > 0: gap = child.left - self.children[i - 1].right # for nested compos, cancel float and move upper if gap < 0: self.children[i - 1].update_css('#' + self.children[i - 1].html_id, float='none') gap = child.top - self.children[i - 1].bottom child.update_css(css_name, float='none', margin_top=str(gap) + 'px') continue if child.html_tag == 'ul': child.update_css(css_name, padding_left=str(gap) + 'px', clear='none') else: child.update_css(css_name, margin_left=str(gap) + 'px') self.css.update(child.css) self.assembly_css() ''' ****************************** ******** Visualization ******* ****************************** ''' def visualize_block(self, img, flag='line', show=False, color=(0, 255, 0)): fill_type = {'line': 2, 'block': -1} board = img.copy() board = cv2.rectangle(board, (self.left, self.top), (self.right, self.bottom), color, fill_type[flag]) if show: cv2.imshow('compo', board) cv2.waitKey() cv2.destroyWindow('compo') return board def visualize_compos(self, img, flag='line', show=False, color=(0, 255, 0)): board = img.copy() for compo in self.compos: board = compo.visualize(board, flag, color=color) if show: cv2.imshow('blk_compos', board) cv2.waitKey() cv2.destroyWindow('blk_compos') return board def visualize_sub_blocks(self, img, flag='line', show=False, color=(0, 255, 0)): board = img.copy() for sub_block in self.sub_blocks: board = sub_block.visualize_block(board, flag, color=color) if show: cv2.imshow('blk_compos', board) cv2.waitKey() cv2.destroyWindow('blk_compos') return board def visualize_sub_blocks_and_compos(self, img, recursive=False, show=True): board = img.copy() board = self.visualize_block(board) board = self.visualize_compos(board, color=(0,0,200)) for sub_block in self.sub_blocks: board = sub_block.visualize_block(board, color=(200,200,0)) if show: print('Num of sub_block:%i; Num of element: %i' % (len(self.sub_blocks), len(self.compos))) cv2.imshow('sub_blocks', board) cv2.waitKey() cv2.destroyWindow('sub_blocks') if recursive: board = img.copy() for sub_block in self.sub_blocks: board = sub_block.visualize_sub_blocks_and_compos(board, recursive) return board def put_info(self): info = {'class':'block', 'column_min': self.left, 'column_max': self.right, 'row_min':self.top, 'row_max':self.bottom, 'height': self.height, 'width':self.width} if self.html_id is not None: info['html_id'] = self.html_id if self.html_class_name is not None: info['html_class_name'] = self.html_class_name return info
class Block: def __init__(self, id, compos, is_slice_sub_block=True, html_tag=None, html_id=None, html_class_name=None, css=None): self.block_id = id self.compos = compos # list of CompoHTML objs self.block_obj = None # CompoHTML obj self.block_img = None self.sub_blocks = [] # list of Block objs self.top = None self.left = None self.bottom = None self.right = None self.width = None self.height = None # html info self.html = None # HTML obj self.html_tag = 'div' if html_tag is None else html_tag self.html_id = html_id self.html_class_name = html_class_name self.html_script = '' # sting self.css = css # CSS objs self.css_script = '' # string # only slice sub-block once if is_slice_sub_block: self.slice_sub_blocks() if css is not None: self.init_css() self.init_boundary() self.init_html() def init_boundary(self): self.top = min(self.compos, key=lambda x: x.top).top self.bottom = max(self.compos, key=lambda x: x.bottom).bottom self.left = min(self.compos, key=lambda x: x.left).left self.right = max(self.compos, key=lambda x: x.right).right def init_html(self): self.html = HTML(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) if len(self.sub_blocks) > 1: # add compos of sub blocks for sub_block in self.sub_blocks: self.html.add_child(sub_block.html_script) else: for compo in self.compos: self.html.add_child(compo.html_script) self.html_script = self.html.html_script def init_css(self): if len(self.sub_blocks) > 1: for sub_block in self.sub_blocks: self.css.update(sub_block.css) else: for compo in self.compos: self.css.update(compo.css) self.css_script = self.css self.assembly_css() def assembly_css(self): self.css_script = '' for i in self.css: self.css_script += self.css[i].css_script # self.block_obj.css = self.css def slice_sub_blocks(self): ''' Horizontally slice the block into sub-blocks ''' self.sub_blocks = slice_blocks(self.compos, 'h', is_slice_sub_block=False) def clip_block_img(self, org, show=False): self.block_img = org[self.top:self.bottom, self.left:self.right] if show: self.show_block_img() def show_block_img(self): cv2.imshow('block', self.block_img) cv2.waitKey() cv2.destroyWindow('block') def visualize(self, img=None, img_shape=None, flag='line', show=True): fill_type = {'line': 2, 'block': -1} img_shape = img_shape board = cv2.resize(img, img_shape) board = cv2.rectangle(board, (self.left, self.top), (self.right, self.bottom), (0, 255, 0), fill_type[flag]) if show: cv2.imshow('compo', board) cv2.waitKey() cv2.destroyWindow('compo') return board
class CompoHTML: def __init__(self, compo_id, html_tag, compo_df=None, html_id=None, html_class_name=None, children=None, parent=None, img=None, img_shape=None, css=None): self.compo_df = compo_df self.compo_id = compo_id self.children = children if children is not None else [ ] # CompoHTML objs self.parent = parent # CompoHTML obj # compo boundary self.top = None self.left = None self.bottom = None self.right = None self.width = None self.height = None # html info self.html = None # HTML obj self.html_id = html_id self.html_class_name = html_class_name self.html_tag = html_tag self.html_tag_map = {'Compo': 'div', 'Text': 'div', 'Block': 'div'} self.html_script = '' # sting self.css = {} if css is None else css # directory of CSS objs, {'.class'/'#id' : CSS obj} self.img = img self.img_shape = img_shape self.init_html() self.init_boundary() def init_html(self): self.html = HTML(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) if type(self.children) is not list: self.children = [self.children] for child in self.children: self.html.add_child(child.html_script) self.html_script = self.html.html_script def init_boundary(self): compo = self.compo_df self.top = compo['row_min'].min() self.left = compo['column_min'].min() self.bottom = compo['row_max'].max() self.right = compo['column_max'].max() self.width = self.right - self.left self.height = self.bottom - self.top def put_boundary(self): return { 'top': self.top, 'left': self.left, 'bottom': self.bottom, 'right': self.right, 'width': self.width, 'height': self.height } def add_child(self, child): ''' :param child: CompoHTML object ''' self.children.append(child) self.html.add_child(child.html_script) self.html_script = self.html.html_script self.compo_df.append(child.compo_df) self.init_boundary() def update_css(self, css_name, **attrs): if css_name in self.css: self.css[css_name].add_attrs(**attrs) else: self.css[css_name] = CSS(css_name, **attrs) def visualize(self, img=None, flag='line', show=False, color=(0, 255, 0)): fill_type = {'line': 2, 'block': -1} img = self.img if img is None else img board = img.copy() board = cv2.rectangle(board, (self.left, self.top), (self.right, self.bottom), color, fill_type[flag]) if show: cv2.imshow('compo', board) cv2.waitKey() cv2.destroyWindow('compo') return board
class CompoHTML: def __init__(self, compo_id, html_tag, compo_class, compo_df=None, html_id=None, html_class_name=None, children=None, parent=None, img=None, img_shape=None, css=None): self.compo_df = compo_df self.compo_id = compo_id self.compo_class = compo_class # get the clip for single element self.compo_clip = compo_df['clip_path'].replace('data/output\clips\\', '') \ if compo_df is not None and children is None and 'clip_path' in compo_df.index else None self.children = children if children is not None else [] # CompoHTML objs self.parent = parent # CompoHTML obj self.type = 'compo' # compo boundary self.top = None self.left = None self.bottom = None self.right = None self.width = None self.height = None # html info self.html = None # HTML obj self.html_id = html_id self.html_class_name = html_class_name self.html_tag = html_tag self.html_tag_map = {'Compo': 'div', 'Text': 'div', 'Block': 'div'} self.html_script = '' # string self.react = None # React self.react_html_script = '' # string self.css = {} if css is None else css # directory of CSS objs, {'.class'/'#id' : CSS obj} self.img = img self.img_shape = img_shape self.init_html() self.init_react() self.init_boundary() def init_html(self): self.html = HTML(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) if self.compo_clip is not None: clip_img = '<img src="' + self.compo_clip + '" class="clip_img">\n' self.html.add_child(clip_img) if type(self.children) is not list: self.children = [self.children] for child in self.children: self.html.add_child(child.html_script) self.html_script = self.html.html_script def init_react(self): self.react = React(tag=self.html_tag, id=self.html_id, class_name=self.html_class_name) for child in self.children: self.react.add_child(child.react_html_script) self.react_html_script = self.react.react_html_script def init_boundary(self): compo = self.compo_df self.top = int(compo['row_min'].min()) self.left = int(compo['column_min'].min()) self.bottom = int(compo['row_max'].max()) self.right = int(compo['column_max'].max()) self.width = int(self.right - self.left) self.height = int(self.bottom - self.top) def put_info(self): info = {'class': self.compo_class, 'column_min': self.left, 'column_max': self.right, 'row_min': self.top, 'row_max': self.bottom, 'height': self.height, 'width': self.width} if self.html_id is not None: info['html_id'] = self.html_id if self.html_class_name is not None: info['html_class_name'] = self.html_class_name return info def add_child(self, child): ''' :param child: CompoHTML object ''' self.children.append(child) self.html.add_child(child.html_script) self.html_script = self.html.html_script self.compo_df.append(child.compo_df) self.init_boundary() def update_css(self, css_name, **attrs): if css_name in self.css: self.css[css_name].add_attrs(**attrs) else: self.css[css_name] = CSS(css_name, **attrs) def visualize(self, img=None, flag='line', show=False, color=(0,255,0)): fill_type = {'line':2, 'block':-1} img = self.img if img is None else img board = img.copy() board = cv2.rectangle(board, (self.left, self.top), (self.right, self.bottom), color, fill_type[flag]) if show: cv2.imshow('compo', board) cv2.waitKey() cv2.destroyWindow('compo') return board