| """ |
| 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'] |
|
|
| |
| 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 = np.array([junc['coordinate'] for junc in annos['junctions']]) |
| junction_floor = np.where(np.isclose(junctions[:, -1], 0))[0] |
|
|
| |
| 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 |
|
|
| |
| 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 |