""" This code is an adaptation that uses Structured 3D for the code base. Reference: https://github.com/bertjiazheng/Structured3D """ import numpy as np import cv2 from shapely.geometry import Polygon import random def parse_floor_plan_polys(annos): planes = [] for semantic in annos['semantics']: for planeID in semantic['planeID']: if annos['planes'][planeID]['type'] == 'floor': planes.append({'planeID': planeID, 'type': semantic['type']}) if semantic['type'] == 'outwall': outerwall_planes = semantic['planeID'] # extract hole vertices lines_holes = [] for semantic in annos['semantics']: if semantic['type'] in ['window', 'door']: for planeID in semantic['planeID']: lines_holes.extend(np.where(np.array(annos['planeLineMatrix'][planeID]))[0].tolist()) lines_holes = np.unique(lines_holes) # junctions on the floor junctions = np.array([junc['coordinate'] for junc in annos['junctions']]) junction_floor = np.where(np.isclose(junctions[:, -1], 0))[0] # construct each polygon polygons = [] for plane in planes: lineIDs = np.where(np.array(annos['planeLineMatrix'][plane['planeID']]))[0].tolist() junction_pairs = [np.where(np.array(annos['lineJunctionMatrix'][lineID]))[0].tolist() for lineID in lineIDs] polygon = convert_lines_to_vertices(junction_pairs) polygons.append([polygon[0], plane['type']]) outerwall_floor = [] for planeID in outerwall_planes: lineIDs = np.where(np.array(annos['planeLineMatrix'][planeID]))[0].tolist() lineIDs = np.setdiff1d(lineIDs, lines_holes) junction_pairs = [np.where(np.array(annos['lineJunctionMatrix'][lineID]))[0].tolist() for lineID in lineIDs] for start, end in junction_pairs: if start in junction_floor and end in junction_floor: outerwall_floor.append([start, end]) outerwall_polygon = convert_lines_to_vertices(outerwall_floor) polygons.append([outerwall_polygon[0], 'outwall']) return polygons def convert_lines_to_vertices(lines): """ convert line representation to polygon vertices """ polygons = [] lines = np.array(lines) polygon = None while len(lines) != 0: if polygon is None: polygon = lines[0].tolist() lines = np.delete(lines, 0, 0) lineID, juncID = np.where(lines == polygon[-1]) vertex = lines[lineID[0], 1 - juncID[0]] lines = np.delete(lines, lineID, 0) if vertex in polygon: polygons.append(polygon) polygon = None else: polygon.append(vertex) return polygons def generate_floorplan(annos, polygons, height, width, ignore_types, include_types=None, fillpoly=True, constant_color=False, shuffle=False): """ plot floorplan """ floor_map = np.zeros((height, width)) junctions = np.array([junc['coordinate'][:2] for junc in annos['junctions']]) room_ind = 0 if shuffle: room_ind = np.random.randint(0, 2) polygons_list = [] for poly_ind, (polygon, poly_type) in enumerate(polygons): if poly_type in ignore_types: continue if include_types is not None and poly_type not in include_types: continue polygon = junctions[np.array(polygon)].astype(np.int32) poly_shapely = Polygon(polygon) area = poly_shapely.area # assert area > 10 if area < 100: continue polygons_list.append(polygon) if shuffle: random.shuffle(polygons_list) for poly_ind, polygon in enumerate(polygons_list): if shuffle: room_ind += np.random.randint(1, 2) else: room_ind += 1 if fillpoly: if constant_color: clr = 1. else: clr = room_ind cv2.fillPoly(floor_map, [polygon], color=clr) else: assert constant_color cv2.polylines(floor_map, [polygon], isClosed=True, color=1., thickness=3) return floor_map, polygons_list