point-cloud-libraryraytracingvoxelocclusion

Occlusion estimation in pointcloud using pcl voxelgridOcclusionEstimation


I need to find out which points of a pointcloud are visible from a RGBD sensor located at origin(0,0,0). I tried to use the voxelgridOcclusionEstimation class of pcl to determine the visible region in the cloud as seen by the sensor. It uses ray tracing technique.

As an experiment,I tried to get the visible region in a sphere whose center satisfies one of the following:

  1. center is along x
  2. center is along y
  3. center is along z
  4. center is along xz plane
  5. center is along y z plane
  6. center is along x y plane.

The sensor is at the origin with zero rotation in all cases.

voxelgridOcclusionEstimation yeilds wierd results. The green region denotes visible region, while the red represents the occluded region.

sphere along x axis

sphere along z axis

sphere along y axis

sphere along xy plane

sphere along yz plane

My code is:

int main(int argc, char * argv[])
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_occluded(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_visible(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::io::loadPCDFile(argv[1],*cloud_in);

    Eigen::Quaternionf quat(1,0,0,0); 
    cloud_in->sensor_origin_  = Eigen::Vector4f(0,0,0,0); 

    cloud_in->sensor_orientation_= quat; 
    pcl::VoxelGridOcclusionEstimation<pcl::PointXYZ> voxelFilter; 
    voxelFilter.setInputCloud (cloud_in); 

    float leaf_size=atof(argv[2]); 
    voxelFilter.setLeafSize (leaf_size, leaf_size, leaf_size); 
    voxelFilter.initializeVoxelGrid(); 

    std::vector<Eigen::Vector3i, 
    Eigen::aligned_allocator&lt;Eigen::Vector3i> > occluded_voxels; 

    for (size_t i=0;i<cloud_in->size();i++) 
    { 

        PointT pt=cloud_in->points[i]; 

        Eigen::Vector3i grid_cordinates=voxelFilter.getGridCoordinates (pt.x, pt.y, pt.z); 

        int grid_state; 

        int ret=voxelFilter.occlusionEstimation( grid_state, grid_cordinates ); 

        if (grid_state==1) 
        { 
            cloud_occluded->push_back(cloud_in->points[i]); 
        } 
        else 
        { 
            cloud_visible->push_back(cloud_in->points[i]); 
        } 

    }
    pcl::io::savePCDFile(argv[3],*cloud_occluded);
    pcl::io::savePCDFile(argv[4],*cloud_visible);

    return 0;
}

Solution

  • The voxelgridOcclusionEstimation class works but the grid width is very important. If we make it very small then there will be unoccupied voxels in the Foreground, which will let the casted rays to pass to pass to Background. If they are set very big, then the surface will not be correctly represented. This is more difficult if the model does not have uniform point density as in the case of data captured by RGBD sensors