Spaces:
Sleeping
Sleeping
from detectron2.structures.boxes import Boxes | |
from ProposalNetwork.proposals.proposals import propose | |
from ProposalNetwork.utils.spaces import Cubes | |
from ProposalNetwork.utils.conversions import cube_to_box, cubes_to_box, normalised_space_to_pixel | |
from ProposalNetwork.utils.utils import iou_3d | |
from ProposalNetwork.scoring.scorefunction import score_segmentation, score_dimensions, score_iou, score_angles | |
from ProposalNetwork.utils.utils import show_mask | |
import matplotlib.pyplot as plt | |
import torch | |
import os | |
import pickle | |
import numpy as np | |
from cubercnn import util, vis | |
from detectron2.data.detection_utils import convert_image_to_rgb | |
from detectron2.utils.visualizer import Visualizer | |
from math import atan2, cos, sin, sqrt, pi | |
from skimage.transform import resize | |
import cv2 | |
from sklearn.decomposition import PCA | |
from cubercnn.data.generate_ground_segmentations import init_segmentation | |
def drawAxis(img, p_, q_, color, scale): | |
p = list(p_) | |
q = list(q_) | |
## [visualization1] | |
angle = atan2(p[1] - q[1], p[0] - q[0]) # angle in radians | |
hypotenuse = sqrt((p[1] - q[1]) * (p[1] - q[1]) + (p[0] - q[0]) * (p[0] - q[0])) | |
# Here we lengthen the arrow by a factor of scale | |
q[0] = p[0] - scale * hypotenuse * cos(angle) | |
q[1] = p[1] - scale * hypotenuse * sin(angle) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
# create the arrow hooks | |
p[0] = q[0] + 9 * cos(angle + pi / 4) | |
p[1] = q[1] + 9 * sin(angle + pi / 4) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
p[0] = q[0] + 9 * cos(angle - pi / 4) | |
p[1] = q[1] + 9 * sin(angle - pi / 4) | |
cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv2.LINE_AA) | |
## [visualization1] | |
#torch.manual_seed(1) | |
# Get image and scale intrinsics | |
with open('ProposalNetwork/proposals/network_out2.pkl', 'rb') as f: | |
batched_inputs, images, proposals, Ks, gt_instances, im_scales_ratio, instances = pickle.load(f) | |
image = 1 | |
gt_obj = 1 | |
# Necessary Ground Truths | |
# 2D | |
gt_box = gt_instances[image].gt_boxes[gt_obj] | |
# 3D | |
gt____whlxyz = gt_instances[image].gt_boxes3D[gt_obj] | |
gt_R = gt_instances[image].gt_poses[gt_obj] | |
gt_cube_ = Cubes(torch.cat([gt____whlxyz[6:],gt____whlxyz[3:6],gt_R.flatten()])) | |
gt_cube = gt_cube_.get_cubes() | |
gt_z = gt_cube_.centers.squeeze()[2] | |
#print('GT',gt____whlxyz,util.mat2euler(gt_R)) | |
#print(gt_R - util.euler2mat(util.mat2euler(gt_R))) | |
# image | |
input_format = 'BGR' | |
img = batched_inputs[image]['image'] | |
img = convert_image_to_rgb(img.permute(1, 2, 0), input_format) | |
input = batched_inputs[image] | |
K = torch.tensor(input['K']) | |
scale = input['height']/img.shape[0] | |
K_scaled = torch.tensor( | |
[[1/scale, 0 , 0], [0, 1/scale, 0], [0, 0, 1.0]], | |
dtype=torch.float32) @ K | |
reference_box = proposals[image].proposal_boxes[0] | |
# Get depth info | |
depth_image = np.load(f"datasets/depth_maps/{batched_inputs[image]['image_id']}.npz")['depth'] | |
depth_image = torch.as_tensor(resize(depth_image,(img.shape[0],img.shape[1]))) | |
# depth_patch = depth_image[int(reference_box.tensor[0,0]):int(reference_box.tensor[0,2]),int(reference_box.tensor[0,1]):int(reference_box.tensor[0,3])] | |
#################################################################################################################################################################################################################################################################################### | |
# Get Proposals | |
x_points = [1]#, 10, 100]#, 1000, 10000]#, 100000] | |
number_of_proposals = 1000 | |
with open('tools/priors.pkl', 'rb') as f: | |
priors, Metadatacatalog = pickle.load(f) | |
category = gt_instances[image].gt_classes[gt_obj] | |
priors_propose = torch.as_tensor(priors['priors_dims_per_cat'][category]).split(1, dim=0) | |
pred_cubes, _, _ = propose(reference_box, depth_image, priors_propose, img.shape[:2][::-1], K, number_of_proposals=number_of_proposals, gt_cube=gt_cube_) | |
proposed_box = cubes_to_box(pred_cubes,K_scaled) | |
# OB IoU3D | |
IoU3D = np.array(iou_3d(gt_cube_,pred_cubes)) | |
print('Percentage of cubes with no intersection:',int(np.count_nonzero(IoU3D == 0.0)/IoU3D.size*100)) | |
idx_scores_iou3d = np.argsort(IoU3D)[::-1] | |
sorted_iou3d_IoU = [IoU3D[i] for i in idx_scores_iou3d] | |
print('Highest possible IoU3D score',sorted_iou3d_IoU[0]) | |
# OB IoU2D | |
IoU2D = score_iou(gt_box, proposed_box[0]).numpy() | |
idx_scores_iou2d = np.argsort(IoU2D)[::-1] | |
sorted_iou2d_IoU = [IoU3D[i] for i in idx_scores_iou2d] | |
iou2d_ious = [np.max(sorted_iou2d_IoU[:n]) for n in x_points] | |
print('IoU3D of best IoU2D score',sorted_iou2d_IoU[0]) | |
# Segment Score | |
if os.path.exists('ProposalNetwork/mask'+str(image)+'.pkl'): | |
# load | |
with open('ProposalNetwork/mask'+str(image)+'.pkl', 'rb') as f: | |
masks = pickle.load(f) | |
else: | |
predictor = init_segmentation() | |
predictor.set_image(img) | |
input_box = np.array([reference_box.tensor[0,0],reference_box.tensor[0,2],reference_box.tensor[0,1],reference_box.tensor[0,3]]) | |
masks, _, _ = predictor.predict( | |
point_coords=None, | |
point_labels=None, | |
box=input_box[None, :], | |
multimask_output=False, | |
) | |
# dump | |
with open('ProposalNetwork/mask'+str(image)+'.pkl', 'wb') as f: | |
pickle.dump(masks, f) | |
seg_mask = torch.as_tensor(masks[0]) | |
bube_corners = pred_cubes.get_bube_corners(K_scaled) | |
segment_scores = score_segmentation(seg_mask, bube_corners).numpy() | |
idx_scores_segment = np.argsort(segment_scores)[::-1] | |
sorted_segment_IoU = [IoU3D[i] for i in idx_scores_segment] | |
segment_ious = [np.max(sorted_segment_IoU[:n]) for n in x_points] | |
print('IoU3D of best segment score',sorted_segment_IoU[0]) | |
# # OB Dimensions | |
# dimensions = [np.array(pred_cubes[i].dimensions) for i in range(len(pred_cubes))] | |
# dim_scores = score_dimensions(priors_propose, dimensions) | |
# idx_scores_dim = np.argsort(dim_scores)[::-1] | |
# sorted_dim_IoU = [IoU3D[i] for i in idx_scores_dim] | |
# dim_ious = [np.max(sorted_dim_IoU[:n]) for n in x_points] | |
# print('IoU3D of best dim score',sorted_dim_IoU[0]) | |
# # Angles | |
# angles = [np.array(util.mat2euler(pred_cubes[i].rotation)) for i in range(len(pred_cubes))] | |
# angle_scores = score_angles(util.mat2euler(gt_R),angles) | |
# idx_scores_angles = np.argsort(angle_scores)[::-1] | |
# sorted_angles_IoU = [IoU3D[i] for i in idx_scores_angles] | |
# angle_ious = [np.max(sorted_angles_IoU[:n]) for n in x_points] | |
# print('IoU3D of best angle score',sorted_angles_IoU[0]) | |
# 2D Contour | |
seg_mask_uint8 = np.array(seg_mask).astype(np.uint8) * 255 | |
ret, thresh = cv2.threshold(seg_mask_uint8, 0.5, 1, 0) | |
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
contour_x = [] | |
contour_y = [] | |
for i in range(len(contours)): | |
for j in range(len(contours[i])): | |
contour_x.append(contours[i][j][0][0]) | |
contour_y.append(contours[i][j][0][1]) | |
# 3rd dimension | |
contour_z = np.zeros(len(contour_x)) | |
for i in range(len(contour_x)): | |
contour_z[i] = depth_image[contour_x[i],contour_y[i]] | |
min_val = np.min(contour_x) | |
max_val = np.max(contour_x) | |
scaled_contour_x = (contour_x - min_val) / (max_val - min_val) | |
min_val = np.min(contour_y) | |
max_val = np.max(contour_y) | |
scaled_contour_y = (contour_y - min_val) / (max_val - min_val) | |
min_val = np.min(contour_z) | |
max_val = np.max(contour_z) | |
scaled_contour_z = (contour_z - min_val) / (max_val - min_val) | |
contours3D = np.array([scaled_contour_x, scaled_contour_y, scaled_contour_z]).T | |
# PCA | |
pca = PCA(n_components=3) | |
pca.fit(contours3D) | |
orientations = pca.components_ | |
def gram_schmidt(n): | |
# Choose an arbitrary vector | |
v1 = np.array([1.0, 0.0, 0.0]) # Choose a simple starting vector | |
# Normalize the first vector | |
v1 /= np.linalg.norm(v1) | |
# Calculate the second vector using Gram-Schmidt process | |
v2 = n - np.dot(n, v1) * v1 | |
v2 /= np.linalg.norm(v2) | |
# Calculate the third vector as the cross product of v1 and v2 | |
v3 = np.cross(v1, v2) | |
return np.array([v1, v2, v3]) | |
basis = orientations | |
euler_angles = np.arctan2(basis[2, 1], basis[2, 2]), np.arcsin(-basis[2, 0]), np.arctan2(basis[1, 0], basis[0, 0]) | |
print(basis.T) | |
print('found angles',np.array(euler_angles) % (pi / 2)) | |
print('gt angles',util.mat2euler(gt_R) % (pi / 2)) | |
def vectors_from_rotation_matrix(rotation_matrix): | |
# Extract vectors from rotation matrix | |
v1 = rotation_matrix[:, 0] | |
v2 = rotation_matrix[:, 1] | |
v3 = rotation_matrix[:, 2] | |
return np.array([v1, v2, v3]) | |
#orientations = vectors_from_rotation_matrix(np.array(gt_R)) #gt rotation | |
points_2d_homogeneous = np.dot(K_scaled, orientations.T).T | |
# Convert homogeneous coordinates to Cartesian coordinates | |
points_2d = points_2d_homogeneous[:, :2] / points_2d_homogeneous[:, 2:] | |
# Plotting | |
# plt.figure() | |
# plt.plot(x_points, dim_ious, marker='o', linestyle='-',c='green',label='dim') | |
# plt.plot(x_points, segment_ious, marker='o', linestyle='-',c='purple',label='segment') | |
# plt.plot(x_points, iou2d_ious, marker='o', linestyle='-',c='orange',label='2d IoU') | |
# plt.plot(x_points, angle_ious, marker='o', linestyle='-',c='darkslategrey',label='angles') | |
# plt.grid(True) | |
# plt.xscale('log') | |
# plt.xlabel('Number of Proposals') | |
# plt.ylabel('3D IoU') | |
# plt.title('IoU vs Number of Proposals') | |
# plt.legend() | |
# plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'BO.png'),dpi=300, bbox_inches='tight') | |
# combined_score = np.array(segment_scores)*np.array(IoU2D)*np.array(dim_scores)*np.array(angle_scores) | |
# plt.figure() | |
# plt.hexbin(combined_score, IoU3D, gridsize=10) | |
# plt.axis([combined_score.min(), combined_score.max(), IoU3D.min(), IoU3D.max()]) | |
# plt.xlabel('score') | |
# plt.ylabel('3DIoU') | |
# plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'combined_scores.png'),dpi=300, bbox_inches='tight') | |
""" Makes only sense when better results | |
fig, ax = plt.subplots() | |
ax.scatter(combined_score,IoU3D, alpha=0.3) | |
heatmap, xedges, yedges = np.histogram2d(combined_score,IoU3D, bins=10) | |
extent = [xedges[0], xedges[-1]+0.05, yedges[0], yedges[-1]+0.05] | |
cax = ax.imshow(heatmap.T, extent=extent, origin='lower') | |
cbar = fig.colorbar(cax) | |
fig.savefig(os.path.join('ProposalNetwork/output/AMOB', 'combined_scores.png'),dpi=300, bbox_inches='tight') | |
""" | |
#################################################################################################################################################################################################################################################################################### | |
# Plot | |
# Get 2 proposal boxes | |
box_size = min(len(proposals[image].proposal_boxes), 1) | |
v_pred = Visualizer(img, None) | |
v_pred = v_pred.overlay_instances( | |
boxes=proposals[image].proposal_boxes[0:box_size].tensor.cpu().numpy() | |
) | |
# Take box with highest iou | |
# pred_meshes = [pred_cubes[idx_scores_iou3d[0]].get_cube().__getitem__(0).detach()] | |
#print(pred_cubes[idx_scores_iou3d[0]].__repr__) | |
# Add 3D GT | |
# meshes_text = ['proposal cube' for _ in range(len(pred_meshes))] | |
# meshes_text.append('gt cube') | |
# pred_meshes.append(gt_cube.__getitem__(0).detach()) | |
# fig = plt.figure() | |
# prop_img = v_pred.get_image() | |
# ax = fig.add_subplot(111) | |
# img_3DPR, img_novel, _ = vis.draw_scene_view(prop_img, K_scaled.cpu().numpy(), pred_meshes,text=meshes_text, blend_weight=0.5, blend_weight_overlay=0.85,scale = img.shape[0]) | |
# im_concat = np.concatenate((img_3DPR, img_novel), axis=1) | |
# vis_img_3d = img_3DPR.astype(np.uint8) | |
# ax.imshow(vis_img_3d) | |
# ax.plot(torch.cat((gt_box.get_all_corners()[:,0],gt_box.get_all_corners()[0,0].reshape(1))),torch.cat((gt_box.get_all_corners()[:,1],gt_box.get_all_corners()[0,1].reshape(1))),color='purple') | |
# ax.scatter(gt____whlxyz[0],gt____whlxyz[1],color='r') | |
# plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'box_with_highest_iou.png'),dpi=300, bbox_inches='tight') | |
distances = np.linalg.norm(points_2d, axis=1) | |
# Normalize points by dividing each coordinate by its distance from the origin | |
points_2d = points_2d / np.max(distances) | |
#points_2d = points_2d / distances[:, np.newaxis] | |
prop_img = v_pred.get_image() | |
# Contour Plot | |
cntr = np.array(gt____whlxyz[:2]) | |
p1 = (cntr[0] + points_2d[0][0], cntr[1] + points_2d[0][1]) | |
p2 = (cntr[0] + points_2d[1][0], cntr[1] + points_2d[1][1]) | |
p3 = (cntr[0] + points_2d[2][0], cntr[1] + points_2d[2][1]) | |
fig = plt.figure(figsize=(15,5)) | |
ax = fig.add_subplot(121) | |
drawAxis(prop_img, cntr, p1, (255, 255, 0), 150) | |
drawAxis(prop_img, cntr, p2, (0, 0, 255), 150) | |
drawAxis(prop_img, cntr, p3, (0, 255, 255), 150) | |
ax.imshow(prop_img) | |
ax.axis('off') | |
ax.set_title('Estimated axes') | |
# show_mask(seg_mask,ax) | |
#ax.scatter(contour_x, contour_y, c='r', s=1) | |
ax2 = fig.add_subplot(122, projection='3d') | |
ax2.view_init(elev=-89, azim=-92, roll=0) | |
ax2.scatter(contours3D[:, 0], contours3D[:, 1], contours3D[:, 2], c='r', s=1) | |
ax2.set_xlabel('x'); ax2.set_ylabel('y'); ax2.set_zlabel('z') | |
ax2.set_title('3D contour') | |
plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'contour.png'),dpi=300, bbox_inches='tight') | |
#################################################################################################################################################################################################################################################################################### | |
exit() | |
# convert from BGR to RGB | |
im_concat = im_concat[..., ::-1] | |
util.imwrite(im_concat, os.path.join('ProposalNetwork/output/AMOB', 'vis_result.jpg')) | |
# Take box with highest segment | |
pred_meshes = [pred_cubes[idx_scores_segment[0]].get_cube().__getitem__(0).detach()] | |
# Add 3D GT | |
meshes_text = ['highest segment'] | |
meshes_text.append('gt cube') | |
pred_meshes.append(gt_cube.__getitem__(0).detach()) | |
img_3DPR, _, _ = vis.draw_scene_view(prop_img, K_scaled.cpu().numpy(), pred_meshes,text=meshes_text, blend_weight=0.5, blend_weight_overlay=0.85,scale = img.shape[0]) | |
vis_img_3d = img_3DPR.astype(np.uint8) | |
fig = plt.figure() | |
ax = fig.add_subplot(111) | |
ax.imshow(vis_img_3d) | |
ax.plot(torch.cat((gt_box.get_all_corners()[:,0],gt_box.get_all_corners()[0,0].reshape(1))),torch.cat((gt_box.get_all_corners()[:,1],gt_box.get_all_corners()[0,1].reshape(1))),color='purple') | |
show_mask(masks,ax) | |
plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'box_with_highest_segment.png'),dpi=300, bbox_inches='tight') | |
# tmp | |
for i in range(len(IoU3D)): | |
if IoU3D[i] == 0.0: | |
idx = i | |
break | |
else: | |
idx = -1 | |
pred_meshes = [pred_cubes[idx].get_cube().__getitem__(0).detach()] | |
meshes_text = ['box with 0 3diou'] | |
meshes_text.append('gt cube') | |
pred_meshes.append(gt_cube.__getitem__(0).detach()) | |
fig = plt.figure() | |
ax = fig.add_subplot(111) | |
prop_img = v_pred.get_image() | |
img_3DPR, img_novel, _ = vis.draw_scene_view(prop_img, K_scaled.cpu().numpy(), pred_meshes,text=meshes_text, blend_weight=0.5, blend_weight_overlay=0.85,scale = img.shape[0]) | |
im_concat = np.concatenate((img_3DPR, img_novel), axis=1) | |
im_concat = im_concat[..., ::-1] | |
util.imwrite(im_concat, os.path.join('ProposalNetwork/output/AMOB', 'tmp.jpg')) | |
center = normalised_space_to_pixel(np.array(pred_cubes[idx].center)[:2],img.shape[:2][::-1]) | |
fig = plt.figure() | |
ax = fig.add_subplot(111) | |
vis_img_3d = img_3DPR.astype(np.uint8) | |
ax.imshow(vis_img_3d) | |
ax.scatter([135.45,135.45,259.76,259.76],[121.6,236.29,121.6,236.29],color='b') | |
ax.scatter(center[0],center[1],color='r') | |
plt.savefig(os.path.join('ProposalNetwork/output/AMOB', 'tmp2.png'),dpi=300, bbox_inches='tight') |