Filters segmented point clouds by depth and masks
Browse filesImproves the extraction of segmented point clouds by adding filtering based on depth and masks for apex and eave end points. This reduces noise and inaccuracies in the point cloud data. Additionally, switches the training loop to use the validation set.
- predict.py +97 -2
- train.py +1 -1
predict.py
CHANGED
|
@@ -595,16 +595,111 @@ def extract_segmented_pcloud(gest_seg_np, colmap_rec, img_id_substring, ade_seg,
|
|
| 595 |
# Filter points that fall within the apex or eave_end masks
|
| 596 |
filtered_points_xyz = []
|
| 597 |
filtered_point_idxs = []
|
|
|
|
| 598 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 599 |
for i, (u, v) in enumerate(uv):
|
| 600 |
# Check if this projected point falls within the combined maskvalid_indices
|
| 601 |
if combined_mask[v, u] > 0 and house_mask[v, u] > 0:
|
| 602 |
original_idx = valid_indices[i] # Get original index
|
| 603 |
filtered_points_xyz.append(points_xyz_world[original_idx])
|
| 604 |
filtered_point_idxs.append(points_idxs[original_idx])
|
| 605 |
-
|
| 606 |
filtered_points_xyz = np.array(filtered_points_xyz) if filtered_points_xyz else np.empty((0, 3))
|
| 607 |
filtered_point_idxs = np.array(filtered_point_idxs) if filtered_point_idxs else np.empty((0,))
|
|
|
|
| 608 |
|
| 609 |
'''
|
| 610 |
depth_fitted, depth_sparse, _, col_img = get_fitted_dense_depth(depth, colmap_rec, img_id_substring, ade_seg, K, R, t)
|
|
@@ -663,7 +758,7 @@ def extract_segmented_pcloud(gest_seg_np, colmap_rec, img_id_substring, ade_seg,
|
|
| 663 |
# Filtered COLMAP points in red
|
| 664 |
if len(filtered_points_xyz) > 0:
|
| 665 |
pcd_filtered.points = o3d.utility.Vector3dVector(filtered_points_xyz)
|
| 666 |
-
pcd_filtered.colors = o3d.utility.Vector3dVector(np.
|
| 667 |
|
| 668 |
# Segmented depth points in blue
|
| 669 |
if len(segmented_points_3d) > 0:
|
|
|
|
| 595 |
# Filter points that fall within the apex or eave_end masks
|
| 596 |
filtered_points_xyz = []
|
| 597 |
filtered_point_idxs = []
|
| 598 |
+
filtered_points_color = []
|
| 599 |
|
| 600 |
+
# Apex
|
| 601 |
+
apex_color = np.array(gestalt_color_mapping['apex'])
|
| 602 |
+
apex_mask = cv2.inRange(gest_seg_np, apex_color-10., apex_color+10.)
|
| 603 |
+
if apex_mask.sum() > 0:
|
| 604 |
+
output = cv2.connectedComponentsWithStats(apex_mask, 8, cv2.CV_32S)
|
| 605 |
+
(numLabels, labels, stats, centroids) = output
|
| 606 |
+
stats, centroids = stats[1:], centroids[1:]
|
| 607 |
+
for i in range(1, numLabels):
|
| 608 |
+
cur_mask = labels == i
|
| 609 |
+
# Dilate the current mask to make it slightly larger
|
| 610 |
+
kernel = np.ones((5, 5), np.uint8)
|
| 611 |
+
cur_mask = cv2.dilate(cur_mask.astype(np.uint8), kernel, iterations=2).astype(bool)
|
| 612 |
+
color = np.random.rand(3)
|
| 613 |
+
# Create boolean mask for points in current apex mask and house mask
|
| 614 |
+
valid_points_mask = cur_mask[uv[:, 1], uv[:, 0]] & house_mask[uv[:, 1], uv[:, 0]]
|
| 615 |
+
|
| 616 |
+
for z in range(5):
|
| 617 |
+
if np.sum(valid_points_mask) < 5:
|
| 618 |
+
cur_mask = cv2.dilate(cur_mask.astype(np.uint8), kernel, iterations=1).astype(bool)
|
| 619 |
+
valid_points_mask = cur_mask[uv[:, 1], uv[:, 0]] & house_mask[uv[:, 1], uv[:, 0]]
|
| 620 |
+
else:
|
| 621 |
+
break
|
| 622 |
+
#
|
| 623 |
+
if np.any(valid_points_mask):
|
| 624 |
+
# Get indices of valid points
|
| 625 |
+
valid_point_indices = valid_indices[valid_points_mask]
|
| 626 |
+
|
| 627 |
+
# Get 3D points in camera coordinates for depth filtering
|
| 628 |
+
valid_world_points = points_xyz_world[valid_point_indices]
|
| 629 |
+
valid_cam_points = points_cam[valid_point_indices]
|
| 630 |
+
|
| 631 |
+
# Compute depths (Z coordinates in camera space)
|
| 632 |
+
depths = valid_cam_points[:, 2]
|
| 633 |
+
|
| 634 |
+
# Find minimum depth and filter points within min_depth + 2 meters
|
| 635 |
+
if len(depths) > 0:
|
| 636 |
+
min_depth = np.min(depths)
|
| 637 |
+
depth_filter = depths <= (min_depth + 2.0)
|
| 638 |
+
|
| 639 |
+
# Apply depth filter
|
| 640 |
+
final_valid_indices = valid_point_indices[depth_filter]
|
| 641 |
+
|
| 642 |
+
# Add corresponding points to filtered lists
|
| 643 |
+
filtered_points_xyz.extend(points_xyz_world[final_valid_indices])
|
| 644 |
+
filtered_point_idxs.extend(points_idxs[final_valid_indices])
|
| 645 |
+
filtered_points_color.extend([color] * np.sum(depth_filter))
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
# Eave end
|
| 649 |
+
eave_end_color = np.array(gestalt_color_mapping['eave_end_point'])
|
| 650 |
+
eave_end_mask = cv2.inRange(gest_seg_np, eave_end_color-10, eave_end_color+10)
|
| 651 |
+
if eave_end_mask.sum() > 0:
|
| 652 |
+
output = cv2.connectedComponentsWithStats(eave_end_mask, 8, cv2.CV_32S)
|
| 653 |
+
(numLabels, labels, stats, centroids) = output
|
| 654 |
+
stats, centroids = stats[1:], centroids[1:]
|
| 655 |
+
for i in range(1, numLabels):
|
| 656 |
+
cur_mask = labels == i
|
| 657 |
+
kernel = np.ones((5,5), np.uint8)
|
| 658 |
+
cur_mask = cv2.dilate(cur_mask.astype(np.uint8), kernel, iterations=2).astype(bool)
|
| 659 |
+
color = np.random.rand(3)
|
| 660 |
+
valid_points_mask = cur_mask[uv[:, 1], uv[:, 0]] & house_mask[uv[:, 1], uv[:, 0]]
|
| 661 |
+
|
| 662 |
+
for z in range(5):
|
| 663 |
+
if np.sum(valid_points_mask) < 5:
|
| 664 |
+
cur_mask = cv2.dilate(cur_mask.astype(np.uint8), kernel, iterations=1).astype(bool)
|
| 665 |
+
valid_points_mask = cur_mask[uv[:, 1], uv[:, 0]] & house_mask[uv[:, 1], uv[:, 0]]
|
| 666 |
+
else:
|
| 667 |
+
break
|
| 668 |
+
if np.any(valid_points_mask):
|
| 669 |
+
# Get indices of valid points
|
| 670 |
+
valid_point_indices = valid_indices[valid_points_mask]
|
| 671 |
+
|
| 672 |
+
# Get 3D points in camera coordinates for depth filtering
|
| 673 |
+
valid_world_points = points_xyz_world[valid_point_indices]
|
| 674 |
+
valid_cam_points = points_cam[valid_point_indices]
|
| 675 |
+
|
| 676 |
+
# Compute depths (Z coordinates in camera space)
|
| 677 |
+
depths = valid_cam_points[:, 2]
|
| 678 |
+
|
| 679 |
+
# Find minimum depth and filter points within min_depth + 2 meters
|
| 680 |
+
if len(depths) > 0:
|
| 681 |
+
min_depth = np.min(depths)
|
| 682 |
+
depth_filter = depths <= (min_depth + 2.0)
|
| 683 |
+
|
| 684 |
+
# Apply depth filter
|
| 685 |
+
final_valid_indices = valid_point_indices[depth_filter]
|
| 686 |
+
|
| 687 |
+
# Add corresponding points to filtered lists
|
| 688 |
+
filtered_points_xyz.extend(points_xyz_world[final_valid_indices])
|
| 689 |
+
filtered_point_idxs.extend(points_idxs[final_valid_indices])
|
| 690 |
+
filtered_points_color.extend([color] * np.sum(depth_filter))
|
| 691 |
+
|
| 692 |
+
'''
|
| 693 |
for i, (u, v) in enumerate(uv):
|
| 694 |
# Check if this projected point falls within the combined maskvalid_indices
|
| 695 |
if combined_mask[v, u] > 0 and house_mask[v, u] > 0:
|
| 696 |
original_idx = valid_indices[i] # Get original index
|
| 697 |
filtered_points_xyz.append(points_xyz_world[original_idx])
|
| 698 |
filtered_point_idxs.append(points_idxs[original_idx])
|
| 699 |
+
'''
|
| 700 |
filtered_points_xyz = np.array(filtered_points_xyz) if filtered_points_xyz else np.empty((0, 3))
|
| 701 |
filtered_point_idxs = np.array(filtered_point_idxs) if filtered_point_idxs else np.empty((0,))
|
| 702 |
+
filtered_points_color = np.array(filtered_points_color) if filtered_points_color else np.empty((0, 3))
|
| 703 |
|
| 704 |
'''
|
| 705 |
depth_fitted, depth_sparse, _, col_img = get_fitted_dense_depth(depth, colmap_rec, img_id_substring, ade_seg, K, R, t)
|
|
|
|
| 758 |
# Filtered COLMAP points in red
|
| 759 |
if len(filtered_points_xyz) > 0:
|
| 760 |
pcd_filtered.points = o3d.utility.Vector3dVector(filtered_points_xyz)
|
| 761 |
+
pcd_filtered.colors = o3d.utility.Vector3dVector(np.array(filtered_points_color))
|
| 762 |
|
| 763 |
# Segmented depth points in blue
|
| 764 |
if len(segmented_points_3d) > 0:
|
train.py
CHANGED
|
@@ -22,7 +22,7 @@ scores_iou = []
|
|
| 22 |
show_visu = False
|
| 23 |
|
| 24 |
idx = 0
|
| 25 |
-
for a in ds['
|
| 26 |
#plot_all_modalities(a)
|
| 27 |
#pred_vertices, pred_edges = predict_wireframe(a)
|
| 28 |
try:
|
|
|
|
| 22 |
show_visu = False
|
| 23 |
|
| 24 |
idx = 0
|
| 25 |
+
for a in ds['validation']:
|
| 26 |
#plot_all_modalities(a)
|
| 27 |
#pred_vertices, pred_edges = predict_wireframe(a)
|
| 28 |
try:
|