最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Aligning a point cloud of 2D Mask that was generated from depth camera in ZED - Stack Overflow

programmeradmin0浏览0评论

I'm trying a MVP sample that aligns a 2D Mask that is generating by converting it to point cloud using the depth map generated by ZED Stereo camera.

I'm trying to align a 3D Object file to that point cloud using C# and Unity but for now I'm testing it using python. The 3D Model and the PCD file is here They are size of 2MB~ I want to align this

with

This is the result, and here is my attempt

The mask is generated from that scene

Here is my attempt:

import open3d as o3d
import numpy as np

def load_point_clouds(obj_file, pcd_file, num_points=10000):
    source = o3d.io.read_triangle_mesh(obj_file)
    source_pcd = source.sample_points_uniformly(number_of_points=num_points)
    target = o3d.io.read_point_cloud(pcd_file)
    return source_pcd, target

def filter_points_above_level(pcd, z_level):
    points = np.asarray(pcd.points)
    filtered_points = points[points[:, 1] <= z_level]  # Filter based on z-axis
    filtered_pcd = o3d.geometry.PointCloud()
    filtered_pcd.points = o3d.utility.Vector3dVector(filtered_points)
    return filtered_pcd

def find_dense_region(pcd, voxel_size=0.05):
    # Get points array
    points = np.asarray(pcd.points)
    
    # Find bounding box
    min_point = np.min(points, axis=0)
    max_point = np.max(points, axis=0)
    
    # Create voxel grid dimensions
    dims = ((max_point - min_point) / voxel_size).astype(int) + 1
    voxel_grid = np.zeros(dims)
    
    # Assign points to voxels
    indices = ((points - min_point) / voxel_size).astype(int)
    for idx in indices:
        voxel_grid[tuple(idx)] += 1
        
    # Find densest region
    dense_mask = voxel_grid > np.mean(voxel_grid[voxel_grid > 0])
    if not np.any(dense_mask):
        return None, None
        
    dense_indices = np.argwhere(dense_mask)
    dense_min = dense_indices.min(axis=0) * voxel_size + min_point
    dense_max = dense_indices.max(axis=0) * voxel_size + min_point
    
    return dense_min, dense_max

def extract_and_align(source, target, min_bound, max_bound):
    # Extract region
    target_points = np.asarray(target.points)
    mask = np.all((target_points >= min_bound) & (target_points <= max_bound), axis=1)
    roi = o3d.geometry.PointCloud()
    roi.points = o3d.utility.Vector3dVector(target_points[mask])
    
    # Scale source
    source_scale = np.linalg.norm(np.asarray(source.points), axis=1).mean()
    target_scale = np.linalg.norm(np.asarray(roi.points), axis=1).mean()
    scale = target_scale / source_scale * 0.5  # Reduced scale factor
    
    source_points = np.asarray(source.points) * scale
    source.points = o3d.utility.Vector3dVector(source_points)
    
    # Align centers
    source.translate(roi.get_center() - source.get_center())
    
    # ICP
    reg = o3d.pipelines.registration.registration_icp(
        source, roi, 0.05, np.eye(4),
        o3d.pipelines.registration.TransformationEstimationPointToPoint(),
        o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=200)
    )
    source.transform(reg.transformation)
    return source

def main():
    source, target = load_point_clouds("untitled.obj", "ahmed.pcd")
    source.paint_uniform_color([1, 0, 0])
    target.paint_uniform_color([0, 1, 0])
    target = filter_points_above_level(target, 10)
    o3d.visualization.draw_geometries([target])
    min_bound, max_bound = find_dense_region(target)
    if min_bound is not None:
        aligned_source = extract_and_align(source, target, min_bound, max_bound)
        o3d.visualization.draw_geometries([aligned_source, target])
    else:
        print("Could not find suitable region")

if __name__ == "__main__":
    main()
发布评论

评论列表(0)

  1. 暂无评论