|
""" |
|
@date: 2021/8/4 |
|
@description: |
|
""" |
|
import numpy as np |
|
import cv2 |
|
import scipy |
|
|
|
from evaluation.f1_score import f1_score_2d |
|
from loss import GradLoss |
|
from utils.boundary import corners2boundaries, layout2depth |
|
from utils.conversion import depth2xyz, uv2xyz, get_u, depth2uv, xyz2uv, uv2pixel |
|
from utils.height import calc_ceil_ratio |
|
from evaluation.iou import calc_IoU, calc_Iou_height |
|
from visualization.boundary import draw_boundaries |
|
from visualization.floorplan import draw_iou_floorplan |
|
from visualization.grad import show_grad |
|
|
|
|
|
def calc_accuracy(dt, gt, visualization=False, h=512): |
|
visb_iou_2ds = [] |
|
visb_iou_3ds = [] |
|
full_iou_2ds = [] |
|
full_iou_3ds = [] |
|
iou_heights = [] |
|
|
|
visb_iou_floodplans = [] |
|
full_iou_floodplans = [] |
|
pano_bds = [] |
|
|
|
if 'depth' not in dt.keys(): |
|
dt['depth'] = gt['depth'] |
|
|
|
for i in range(len(gt['depth'])): |
|
|
|
dt_xyz = dt['processed_xyz'][i] if 'processed_xyz' in dt else depth2xyz(np.abs(dt['depth'][i])) |
|
visb_gt_xyz = depth2xyz(np.abs(gt['depth'][i])) |
|
corners = gt['corners'][i] |
|
full_gt_corners = corners[corners[..., 0] + corners[..., 1] != 0] |
|
full_gt_xyz = uv2xyz(full_gt_corners) |
|
|
|
dt_xz = dt_xyz[..., ::2] |
|
visb_gt_xz = visb_gt_xyz[..., ::2] |
|
full_gt_xz = full_gt_xyz[..., ::2] |
|
|
|
gt_ratio = gt['ratio'][i][0] |
|
|
|
if 'ratio' not in dt.keys(): |
|
if 'boundary' in dt.keys(): |
|
w = len(dt['boundary'][i]) |
|
boundary = np.clip(dt['boundary'][i], 0.0001, 0.4999) |
|
depth = np.clip(dt['depth'][i], 0.001, 9999) |
|
dt_ceil_boundary = np.concatenate([get_u(w, is_np=True)[..., None], boundary], axis=-1) |
|
dt_floor_boundary = depth2uv(depth) |
|
dt_ratio = calc_ceil_ratio(boundaries=[dt_ceil_boundary, dt_floor_boundary]) |
|
else: |
|
dt_ratio = gt_ratio |
|
else: |
|
dt_ratio = dt['ratio'][i][0] |
|
|
|
visb_iou_2d, visb_iou_3d = calc_IoU(dt_xz, visb_gt_xz, dt_height=1 + dt_ratio, gt_height=1 + gt_ratio) |
|
full_iou_2d, full_iou_3d = calc_IoU(dt_xz, full_gt_xz, dt_height=1 + dt_ratio, gt_height=1 + gt_ratio) |
|
iou_height = calc_Iou_height(dt_height=1 + dt_ratio, gt_height=1 + gt_ratio) |
|
|
|
visb_iou_2ds.append(visb_iou_2d) |
|
visb_iou_3ds.append(visb_iou_3d) |
|
full_iou_2ds.append(full_iou_2d) |
|
full_iou_3ds.append(full_iou_3d) |
|
iou_heights.append(iou_height) |
|
|
|
if visualization: |
|
pano_img = cv2.resize(gt['image'][i].transpose(1, 2, 0), (h*2, h)) |
|
|
|
|
|
visb_iou_floodplans.append(draw_iou_floorplan(dt_xz, visb_gt_xz, side_l=h)) |
|
full_iou_floodplans.append(draw_iou_floorplan(dt_xz, full_gt_xz, side_l=h)) |
|
gt_boundaries = corners2boundaries(gt_ratio, corners_xyz=full_gt_xyz, step=None, length=1024, visible=False) |
|
dt_boundaries = corners2boundaries(dt_ratio, corners_xyz=dt_xyz, step=None, visible=False, |
|
length=1024) |
|
|
|
pano_bd = draw_boundaries(pano_img, boundary_list=gt_boundaries, boundary_color=[0, 0, 1]) |
|
pano_bd = draw_boundaries(pano_bd, boundary_list=dt_boundaries, boundary_color=[0, 1, 0]) |
|
pano_bds.append(pano_bd) |
|
|
|
visb_iou_2d = np.array(visb_iou_2ds).mean() |
|
visb_iou_3d = np.array(visb_iou_3ds).mean() |
|
full_iou_2d = np.array(full_iou_2ds).mean() |
|
full_iou_3d = np.array(full_iou_3ds).mean() |
|
iou_height = np.array(iou_heights).mean() |
|
|
|
if visualization: |
|
visb_iou_floodplans = np.array(visb_iou_floodplans).transpose(0, 3, 1, 2) |
|
full_iou_floodplans = np.array(full_iou_floodplans).transpose(0, 3, 1, 2) |
|
pano_bds = np.array(pano_bds).transpose(0, 3, 1, 2) |
|
return [visb_iou_2d, visb_iou_3d, visb_iou_floodplans],\ |
|
[full_iou_2d, full_iou_3d, full_iou_floodplans], iou_height, pano_bds, full_iou_2ds |
|
|
|
|
|
def calc_ce(dt, gt): |
|
w = 1024 |
|
h = 512 |
|
ce_s = [] |
|
for i in range(len(gt['corners'])): |
|
floor_gt_corners = gt['corners'][i] |
|
|
|
floor_gt_corners = floor_gt_corners[floor_gt_corners[..., 0] + floor_gt_corners[..., 1] != 0] |
|
floor_gt_corners = np.roll(floor_gt_corners, -np.argmin(floor_gt_corners[..., 0]), 0) |
|
gt_ratio = gt['ratio'][i][0] |
|
ceil_gt_corners = corners2boundaries(gt_ratio, corners_uv=floor_gt_corners, step=None)[1] |
|
gt_corners = np.concatenate((floor_gt_corners, ceil_gt_corners)) |
|
gt_corners = uv2pixel(gt_corners, w, h) |
|
|
|
floor_dt_corners = xyz2uv(dt['processed_xyz'][i]) |
|
floor_dt_corners = np.roll(floor_dt_corners, -np.argmin(floor_dt_corners[..., 0]), 0) |
|
dt_ratio = dt['ratio'][i][0] |
|
ceil_dt_corners = corners2boundaries(dt_ratio, corners_uv=floor_dt_corners, step=None)[1] |
|
dt_corners = np.concatenate((floor_dt_corners, ceil_dt_corners)) |
|
dt_corners = uv2pixel(dt_corners, w, h) |
|
|
|
mse = np.sqrt(((gt_corners - dt_corners) ** 2).sum(1)).mean() |
|
ce = 100 * mse / np.sqrt(w ** 2 + h ** 2) |
|
ce_s.append(ce) |
|
|
|
return np.array(ce_s).mean() |
|
|
|
|
|
def calc_pe(dt, gt): |
|
w = 1024 |
|
h = 512 |
|
pe_s = [] |
|
for i in range(len(gt['corners'])): |
|
floor_gt_corners = gt['corners'][i] |
|
|
|
floor_gt_corners = floor_gt_corners[floor_gt_corners[..., 0] + floor_gt_corners[..., 1] != 0] |
|
floor_gt_corners = np.roll(floor_gt_corners, -np.argmin(floor_gt_corners[..., 0]), 0) |
|
gt_ratio = gt['ratio'][i][0] |
|
gt_floor_boundary, gt_ceil_boundary = corners2boundaries(gt_ratio, corners_uv=floor_gt_corners, length=w) |
|
gt_floor_boundary = uv2pixel(gt_floor_boundary, w, h) |
|
gt_ceil_boundary = uv2pixel(gt_ceil_boundary, w, h) |
|
|
|
floor_dt_corners = xyz2uv(dt['processed_xyz'][i]) |
|
floor_dt_corners = np.roll(floor_dt_corners, -np.argmin(floor_dt_corners[..., 0]), 0) |
|
dt_ratio = dt['ratio'][i][0] |
|
dt_floor_boundary, dt_ceil_boundary = corners2boundaries(dt_ratio, corners_uv=floor_dt_corners, length=w) |
|
dt_floor_boundary = uv2pixel(dt_floor_boundary, w, h) |
|
dt_ceil_boundary = uv2pixel(dt_ceil_boundary, w, h) |
|
|
|
gt_surface = np.zeros((h, w), dtype=np.int32) |
|
gt_surface[gt_ceil_boundary[..., 1], np.arange(w)] = 1 |
|
gt_surface[gt_floor_boundary[..., 1], np.arange(w)] = 1 |
|
gt_surface = np.cumsum(gt_surface, axis=0) |
|
|
|
dt_surface = np.zeros((h, w), dtype=np.int32) |
|
dt_surface[dt_ceil_boundary[..., 1], np.arange(w)] = 1 |
|
dt_surface[dt_floor_boundary[..., 1], np.arange(w)] = 1 |
|
dt_surface = np.cumsum(dt_surface, axis=0) |
|
|
|
pe = 100 * (dt_surface != gt_surface).sum() / (h * w) |
|
pe_s.append(pe) |
|
return np.array(pe_s).mean() |
|
|
|
|
|
def calc_rmse_delta_1(dt, gt): |
|
rmse_s = [] |
|
delta_1_s = [] |
|
for i in range(len(gt['depth'])): |
|
gt_boundaries = corners2boundaries(gt['ratio'][i], corners_xyz=depth2xyz(gt['depth'][i]), step=None, |
|
visible=False) |
|
dt_xyz = dt['processed_xyz'][i] if 'processed_xyz' in dt else depth2xyz(np.abs(dt['depth'][i])) |
|
|
|
dt_boundaries = corners2boundaries(dt['ratio'][i], corners_xyz=dt_xyz, step=None, |
|
length=256 if 'processed_xyz' in dt else None, |
|
visible=True if 'processed_xyz' in dt else False) |
|
gt_layout_depth = layout2depth(gt_boundaries, show=False) |
|
dt_layout_depth = layout2depth(dt_boundaries, show=False) |
|
|
|
rmse = ((gt_layout_depth - dt_layout_depth) ** 2).mean() ** 0.5 |
|
threshold = np.maximum(gt_layout_depth / dt_layout_depth, dt_layout_depth / gt_layout_depth) |
|
delta_1 = (threshold < 1.25).mean() |
|
rmse_s.append(rmse) |
|
delta_1_s.append(delta_1) |
|
return np.array(rmse_s).mean(), np.array(delta_1_s).mean() |
|
|
|
|
|
def calc_f1_score(dt, gt, threshold=10): |
|
w = 1024 |
|
h = 512 |
|
f1_s = [] |
|
precision_s = [] |
|
recall_s = [] |
|
for i in range(len(gt['corners'])): |
|
floor_gt_corners = gt['corners'][i] |
|
|
|
floor_gt_corners = floor_gt_corners[floor_gt_corners[..., 0] + floor_gt_corners[..., 1] != 0] |
|
floor_gt_corners = np.roll(floor_gt_corners, -np.argmin(floor_gt_corners[..., 0]), 0) |
|
gt_ratio = gt['ratio'][i][0] |
|
ceil_gt_corners = corners2boundaries(gt_ratio, corners_uv=floor_gt_corners, step=None)[1] |
|
gt_corners = np.concatenate((floor_gt_corners, ceil_gt_corners)) |
|
gt_corners = uv2pixel(gt_corners, w, h) |
|
|
|
floor_dt_corners = xyz2uv(dt['processed_xyz'][i]) |
|
floor_dt_corners = np.roll(floor_dt_corners, -np.argmin(floor_dt_corners[..., 0]), 0) |
|
dt_ratio = dt['ratio'][i][0] |
|
ceil_dt_corners = corners2boundaries(dt_ratio, corners_uv=floor_dt_corners, step=None)[1] |
|
dt_corners = np.concatenate((floor_dt_corners, ceil_dt_corners)) |
|
dt_corners = uv2pixel(dt_corners, w, h) |
|
|
|
Fs, Ps, Rs = f1_score_2d(gt_corners, dt_corners, [threshold]) |
|
f1_s.append(Fs[0]) |
|
precision_s.append(Ps[0]) |
|
recall_s.append(Rs[0]) |
|
|
|
return np.array(f1_s).mean(), np.array(precision_s).mean(), np.array(recall_s).mean() |
|
|
|
|
|
def show_heat_map(dt, gt, vis_w=1024): |
|
dt_heat_map = dt['corner_heat_map'].detach().cpu().numpy() |
|
gt_heat_map = gt['corner_heat_map'].detach().cpu().numpy() |
|
dt_heat_map_imgs = [] |
|
gt_heat_map_imgs = [] |
|
for i in range(len(gt['depth'])): |
|
dt_heat_map_img = dt_heat_map[..., np.newaxis].repeat(3, axis=-1).repeat(20, axis=0) |
|
gt_heat_map_img = gt_heat_map[..., np.newaxis].repeat(3, axis=-1).repeat(20, axis=0) |
|
dt_heat_map_imgs.append(cv2.resize(dt_heat_map_img, (vis_w, dt_heat_map_img.shape[0])).transpose(2, 0, 1)) |
|
gt_heat_map_imgs.append(cv2.resize(gt_heat_map_img, (vis_w, dt_heat_map_img.shape[0])).transpose(2, 0, 1)) |
|
return dt_heat_map_imgs, gt_heat_map_imgs |
|
|
|
|
|
def show_depth_normal_grad(dt, gt, device, vis_w=1024): |
|
grad_conv = GradLoss().to(device).grad_conv |
|
gt_grad_imgs = [] |
|
dt_grad_imgs = [] |
|
|
|
if 'depth' not in dt.keys(): |
|
dt['depth'] = gt['depth'] |
|
|
|
if vis_w == 1024: |
|
h = 5 |
|
else: |
|
h = int(vis_w / (12 * 10)) |
|
|
|
for i in range(len(gt['depth'])): |
|
gt_grad_img = show_grad(gt['depth'][i], grad_conv, h) |
|
dt_grad_img = show_grad(dt['depth'][i], grad_conv, h) |
|
vis_h = dt_grad_img.shape[0] * (vis_w // dt_grad_img.shape[1]) |
|
gt_grad_imgs.append(cv2.resize(gt_grad_img, (vis_w, vis_h), interpolation=cv2.INTER_NEAREST).transpose(2, 0, 1)) |
|
dt_grad_imgs.append(cv2.resize(dt_grad_img, (vis_w, vis_h), interpolation=cv2.INTER_NEAREST).transpose(2, 0, 1)) |
|
|
|
return gt_grad_imgs, dt_grad_imgs |
|
|