Skip to content

Commit

Permalink
boxClipper3D tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
patcmorneau committed Jul 14, 2023
1 parent b268d07 commit d7da661
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 0 deletions.
62 changes: 62 additions & 0 deletions doc/tutorials/content/boxClipper3D_example.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.. _BoxClipper3D:

Extracting points inside a box
------------------------------------

In this tutorial we will learn how to use the BoxClipper3D filter to extract a subset of
points from a point cloud. In this example we will create a point cloud and some points will be inside the box and some on the outside. The way the BoxClipper3D works is counter intuitive. Instead of having to put the box somewhere and have the right inclination to fit the points we want to extract, we have to do the reverse operation on the cloud so the points we want to extract move inside the box. We will se how this works in this example.

The code
--------


Then, create a file, let's say, ``extract_points.cpp`` in your favorite
editor, and place the following inside it:

.. literalinclude:: sources/boxClipper3D/boxClipper3D_example.cpp
:language: cpp
:linenos:


The explanation
---------------

Here we define our simple point cloud with its inliers and outliers and we rotate the cloud 45 degree on its Z axis;

.. literalinclude:: sources/boxClipper3D/boxClipper3D_example.cpp
:language: cpp
:lines: 133-145

Now lets look at the magic.

.. literalinclude:: sources/boxClipper3D/boxClipper3D_example.cpp
:language: cpp
:lines: 23-46

We have to define three transformation: a translation, a rotation and a scaling factor;
.. literalinclude:: sources/boxClipper3D/boxClipper3D_example.cpp
:language: cpp
:lines: 27-31

If we think about the intuitive way: We have a point cloud that is rotated 45 degree on its Z axis.
Lets picture our self creating a box starting at (0,0,0). Then, we want to fit our inliers inside the box. So we have to translate the box by a vector of (1,1,1) and then rotate it of 45 degree on its Z axis and than scale the box to only fit the points we want.

But as mentioned earlier the way the boxClipper3D works is the opposite. Therefore, we have to translate the cloud by a vector of (-1,-1,-1) and then rotate it of -45 degree on its Z axis so the points we want to extract fits inside the box. The box is 2x2x2 and it starts at (-1,-1,-1) and it ends at (1,1,1).

Compiling and running the program
---------------------------------

Add the following lines to your CMakeLists.txt file:

.. literalinclude:: sources/boxClipper3D/CMakeLists.txt
:language: cmake
:linenos:

After you have made the executable, you can run it. Simply do::

$ ./extract_points

You will see something similar to::

nb inliers: 3

13 changes: 13 additions & 0 deletions doc/tutorials/content/sources/boxClipper3D/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(boxClipper3D_example)

add_definitions(-std=c++17 -Wall -g)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
find_package(PCL 1.10 REQUIRED)

include_directories( ${PCL_INCLUDE_DIRS} )
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable(extract_points example_boxClipper3D.cpp)
target_link_libraries(extract_points ${PCL_LIBRARIES})
146 changes: 146 additions & 0 deletions doc/tutorials/content/sources/boxClipper3D/example_boxClipper3D.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*!
* \Author: Patrick Charron-Morneau
* \Interdisciplinary Centre for the Development of Ocean Mapping (CIDCO)
*/

#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/box_clipper3D.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/common/transforms.h>


class pointExtractor{

public:
pointExtractor(){
this->cloud = pcl::PointCloud<pcl::PointXYZRGB>::Ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
}

~pointExtractor(){}


void extractPoints(pcl::Indices & windowPoints){

this->inliers = pcl::PointCloud<pcl::PointXYZRGB>::Ptr (new pcl::PointCloud<pcl::PointXYZRGB>);

Eigen::Vector3f rodrigues(0, 0, -0.7853982); // Eigen::Vector3f rodrigues(x,y,z) in radians
Eigen::Vector3f translation(-1 ,-1 ,-1);
Eigen::Vector3f box_size (1/1, 1/1, 1/1);

pcl::BoxClipper3D<pcl::PointXYZRGB> boxClipper(rodrigues, translation, box_size);
boxClipper.clipPointCloud3D (*this->cloud, windowPoints);
std::cerr<<"nb inliers: " << windowPoints.size()<<"\n";

pcl::IndicesPtr idxPtr = std::make_shared<pcl::Indices>(windowPoints);

pcl::ExtractIndices<pcl::PointXYZRGB> extract;
extract.setInputCloud (this->cloud);
extract.setIndices (idxPtr);
extract.setNegative (false);
extract.filter (*this->inliers);

//showPointCloud(this->inliers, "box clipper");
}

void setInlier(){
pcl::PointXYZRGB pt;
uint8_t r = 0, g = 255, b = 0;
uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
pt.x = 1.1;
pt.y = 1.1;
pt.z = 1.1;
pt.rgba = rgb;
this->cloud->push_back(pt);

pcl::PointXYZRGB pt1;
pt1.x = 1.4;
pt1.y = 1.4;
pt1.z = 1.4;
pt1.rgba = rgb;
this->cloud->push_back(pt1);

pcl::PointXYZRGB pt8;
pt8.x = 0.1;
pt8.y = 0.1;
pt8.z = 0.1;
pt8.rgba = rgb;
this->cloud->push_back(pt8);
}

void setOutlier(){
pcl::PointXYZRGB pt;
uint8_t r = 255, g = 0, b = 0;
uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
pt.x = 2.1;
pt.y = 2.1;
pt.z = 2.1;
pt.rgba = rgb;
this->cloud->push_back(pt);

pcl::PointXYZRGB pt9;
pt9.x = 2.5;
pt9.y = 2.5;
pt9.z = 2.5;
pt9.rgba = rgb;
this->cloud->push_back(pt9);

pcl::PointXYZRGB pt11;
pt11.x = -2.7;
pt11.y = -2.7;
pt11.z = -2.7;
pt11.rgba = rgb;
this->cloud->push_back(pt11);
}

void rotateCloud(){
Eigen::Affine3f transform = Eigen::Affine3f::Identity();

// 45 deg
transform.rotate (Eigen::AngleAxisf (0.7853982, Eigen::Vector3f::UnitZ()));

// Executing the transformation
this->transformed_cloud = pcl::PointCloud<pcl::PointXYZRGB>::Ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::transformPointCloud (*this->cloud, *transformed_cloud, transform);

//showPointCloud(this->cloud, "original cloud");
this->cloud->swap(*transformed_cloud);
//showPointCloud(this->cloud, "rotated cloud");
}


void showPointCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloud, std::string windowName){
pcl::visualization::CloudViewer viewer (windowName);

viewer.showCloud (pointCloud);

while (!viewer.wasStopped ()){

}
}

private:

pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr inliers;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed_cloud;

};


int main(int argc,char** argv){

pointExtractor pe;

pe.setInlier();

pe.setOutlier();

pe.rotateCloud();

pcl::Indices indexes;

pe.extractPoints(indexes);
}

0 comments on commit d7da661

Please sign in to comment.