Spaces:
Runtime error
Runtime error
import torch | |
import scipy.io as sio | |
import numpy as np | |
import cv2 | |
import copy | |
from .utils import * | |
class FloorPlan(): | |
def __init__(self, data, train=False, rot=None): | |
self.data = copy.deepcopy(data) | |
self._get_rot() | |
if rot is not None: | |
if train: | |
boxes = self.data.box[:, :4][:, [1, 0, 3, 2]] | |
boxes = align_box(boxes, self.rot, rot)[:, [1, 0, 3, 2]] | |
self.data.box[:, :4] = boxes | |
points = self.data.boundary[:, :2][:, [1, 0]] | |
points = align_points(points, self.rot, rot)[:, [1, 0]] | |
self.data.boundary[:, :2] = points | |
self._get_rot() | |
def _get_rot(self): | |
door_line = self.data.boundary[:2, :2] # [:,[1,0]] | |
c = door_line.mean(0) - np.array([127.5,127.5]) | |
theta = np.arctan2(c[1], c[0]) + np.pi # [-pi,pi] | |
self.rot = theta | |
def get_input_boundary(self, tensor=True): | |
external = self.data.boundary[:, :2] | |
door = self.data.boundary[:2, :2] | |
boundary = np.zeros((128, 128), dtype=float) | |
inside = np.zeros((128, 128), dtype=float) | |
front = np.zeros((128, 128), dtype=float) | |
pts = np.concatenate([external, external[:1]]) // 2 | |
pts_door = door // 2 | |
cv2.fillPoly(inside, pts.reshape(1, -1, 2), 1.0) | |
cv2.polylines(boundary, pts.reshape(1, -1, 2), True, 1.0, 3) | |
cv2.polylines(boundary, pts_door.reshape(1, -1, 2), True, 0.5, 3) | |
cv2.polylines(front, pts_door.reshape(1, -1, 2), True, 1.0, 3) | |
input_image = np.stack([inside, boundary, front], -1) | |
if tensor: input_image = torch.tensor(input_image).permute((2, 0, 1)).float() | |
return input_image | |
def get_inside_box(self, tensor=True): | |
external = self.data.boundary[:, :2] | |
X, Y = np.linspace(0, 1, 256), np.linspace(0, 1, 256) | |
x0, x1 = np.min(external[:, 0]), np.max(external[:, 0]) | |
y0, y1 = np.min(external[:, 1]), np.max(external[:, 1]) | |
box = np.array([[X[x0], Y[y0], X[x1], Y[y1]]]) | |
if tensor: box = torch.tensor(box).float() | |
return box | |
def get_rooms(self, tensor=True): | |
rooms = self.data.box[:, -1] | |
if tensor: rooms = torch.tensor(rooms).long() | |
return rooms | |
def get_attributes(self, gsize=5, alevel=10, relative=True, tensor=True): | |
boxes = self.data.box[:, :4][:, [1, 0, 3, 2]] | |
external = self.data.boundary | |
h, w = 256, 256 | |
if relative: | |
external = np.asarray(external) | |
x0, x1 = np.min(external[:, 0]), np.max(external[:, 0]) | |
y0, y1 = np.min(external[:, 1]), np.max(external[:, 1]) | |
h, w = y1 - y0, x1 - x0 | |
boxes = boxes - np.array([y0, x0, y0, x0], dtype=float) | |
boxes /= np.array([h, w, h, w]) | |
boxes[:, 2:] -= boxes[:, :2] # y1,x1->h,w | |
boxes[:, :2] += boxes[:, 2:] / 2 # y0,x0->yc,xc | |
l = len(boxes) | |
gbins = np.linspace(0,1,gsize+1) # [1,gsize] | |
gbins[0],gbins[-1]=-np.inf,np.inf | |
abins = np.linspace(0,1,alevel+1) # [1,gsize] | |
abins[0],abins[-1]=-np.inf,np.inf | |
attributes = np.zeros((l,gsize*gsize+alevel)) | |
# pos: xc*gsize+yc*gsize*gsize | |
attributes[range(l),(np.digitize(boxes[:,0],gbins)-1)*gsize+np.digitize(boxes[:,1],gbins)-1]=1 | |
# area:(w*h) | |
attributes[range(l),gsize*gsize+np.digitize(boxes[:,2:].prod(1),abins)-1]=1 | |
if tensor: attributes = torch.tensor(attributes).float() | |
return attributes | |
def get_triples(self, random=False, tensor=True): | |
boxes = self.data.box[:, :4][:, [1, 0, 3, 2]] | |
triples = [] | |
# add edge relation | |
for u, v, _ in self.data.edge: | |
uy0, ux0, uy1, ux1 = boxes[u] | |
vy0, vx0, vy1, vx1 = boxes[v] | |
uc = (uy0 + uy1) / 2, (ux0 + ux1) / 2 | |
vc = (vy0 + vy1) / 2, (vx0 + vx1) / 2 | |
# surrounding/inside -> X four quadrants | |
if ux0 < vx0 and ux1 > vx1 and uy0 < vy0 and uy1 > vy1: | |
relation = 'surrounding' | |
elif ux0 >= vx0 and ux1 <= vx1 and uy0 >= vy0 and uy1 <= vy1: | |
relation = 'inside' | |
else: | |
relation = point_box_relation(uc, boxes[v]) | |
triples.append([u, vocab['pred_name_to_idx'][relation], v]) | |
triples = np.array(triples, dtype=int) | |
if tensor: triples = torch.tensor(triples).long() | |
return triples | |
def vis_box(self): | |
h, w = 128, 128 | |
image = np.full((h, w, 4), 0, dtype=np.uint8) | |
boxes = self.data.box[:, :4] // 2 | |
objs = self.data.box[:, -1] | |
for i, obj in enumerate(objs): | |
if obj == 14: continue | |
color = colormap_255[obj] | |
box = boxes[i] | |
cv2.rectangle(image, (box[0], box[1]), (box[2], box[3]), (color[0], color[1], color[2], 255), 3) | |
return image | |
def get_test_data(self, tensor=True): | |
boundary = self.get_input_boundary(tensor=tensor) | |
inside_box = self.get_inside_box(tensor=tensor) | |
rooms = self.get_rooms(tensor=tensor) | |
attrs = self.get_attributes(tensor=tensor) | |
triples = self.get_triples(random=False, tensor=tensor) | |
return boundary, inside_box, rooms, attrs, triples | |
def adapt_graph(self, fp_graph): | |
fp = FloorPlan(fp_graph.data, train=True, rot=self.rot) | |
g_external = fp.data.boundary[:, :2] | |
gx0, gx1 = np.min(g_external[:, 0]), np.max(g_external[:, 0]) | |
gy0, gy1 = np.min(g_external[:, 1]), np.max(g_external[:, 1]) | |
gw, gh = gx1 - gx0, gy1 - gy0 | |
fp.data.boundary = self.data.boundary | |
b_external = self.data.boundary[:, :2] | |
bx0, bx1 = np.min(b_external[:, 0]), np.max(b_external[:, 0]) | |
by0, by1 = np.min(b_external[:, 1]), np.max(b_external[:, 1]) | |
bh, bw = by1 - by0, bx1 - bx0 | |
box_adapter = lambda box: (((box - np.array([gx0, gy0, gx0, gy0])) * np.array([bw, bh, bw, bh])) / np.array( | |
[gw, gh, gw, gh]) + np.array([bx0, by0, bx0, by0])).astype(int) | |
fp.data.box[:, :4] = np.apply_along_axis(box_adapter, 1, fp.data.box[:, :4]) | |
return fp | |
def adjust_graph(self): | |
external = self.data.boundary[:, :2] | |
bx0, bx1 = np.min(external[:, 0]), np.max(external[:, 0]) | |
by0, by1 = np.min(external[:, 1]), np.max(external[:, 1]) | |
hw_b = np.array([by1 - by0, bx1 - bx0]) | |
step = hw_b / 10 | |
pts = np.concatenate([external, external[:1]]) | |
mask = np.zeros((256, 256), dtype=np.uint8) | |
cv2.fillPoly(mask, pts.reshape(1, -1, 2), 255) | |
# plt.imshow(mask) | |
# plt.show() | |
mask = cv2.resize(mask[by0:by1 + 1, bx0:bx1 + 1], (10, 10)) | |
# plt.imshow(mask) | |
# plt.show() | |
mask[mask > 0] = 255 | |
outside_rooms = [] | |
for i in range(len(self.data.box)): | |
box = self.data.box[i][:4][[1, 0, 3, 2]] | |
center = (box[:2] + box[2:]) / 2 | |
center55 = ((center - np.array([by0, bx0])) * 10 / hw_b).astype(int) | |
if not mask[center55[0], center55[1]]: | |
outside_rooms.append([i, center55]) | |
candicate_coords55 = {} | |
for i, coords55 in outside_rooms: | |
row, col = coords55 | |
# left/right/up/down | |
candicate_coords55[i] = np.array([ | |
next((col-c for c in range(col,-1,-1) if mask[row,c]==255),255), | |
next((c-col for c in range(col+1,5) if mask[row,c]==255),255), | |
next((row-r for r in range(row,-1,-1) if mask[r,col]==255),255), | |
next((r-row for r in range(row+1,5) if mask[r,col]==255),255)]) | |
signs = np.array([ | |
[0, -1, 0, -1], | |
[0, 1, 0, 1], | |
[-1, 0, -1, 0], | |
[1, 0, 1, 0] | |
]) | |
for i, coords55 in outside_rooms: | |
deltas = candicate_coords55[i] | |
idx = np.argmin(deltas) | |
self.data.box[i, :4] += (signs[idx] * deltas[idx] * np.tile(step, 2)).astype(int)[[1, 0, 3, 2]] | |
if __name__ == "__main__": | |
pass | |