Skip to content

(Discussion) Initial refactor resampleCloudSpatially for multi-threading #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions include/CloudSamplingTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ namespace CCCoreLib
DgmOctree* octree = nullptr,
GenericProgressCallback* progressCb = nullptr);

//! Resamples a point cloud (process based on inter point distance)
/** The cloud is resampled so that there is no point nearer than a given distance to other points
It works by picking a reference point, removing all points which are to close to this point, and repeating these two steps until the result is reached
\param cloud the point cloud to resample
\param minDistance the distance under which a point in the resulting cloud cannot have any neighbour
\param modParams parameters of the subsampling behavior modulation with a scalar field (optional)
\param octree associated octree if available
\param markers per-point marker for filtered-in points (required to be size of cloud)
\param progressCb the client application can get some notification of the process progress through this callback mechanism (see GenericProgressCallback)
\return a reference cloud corresponding to the resampling 'selection'
**/
static size_t resampleCloudSpatially( GenericIndexedCloudPersist* cloud,
PointCoordinateType minDistance,
const SFModulationParams& modParams,
char* markers,
DgmOctree* octree = nullptr,
GenericProgressCallback* progressCb = nullptr);

//! Statistical Outliers Removal (SOR) filter
/** This filter removes points based on their mean distance to their distance (by comparing it to the average distance of all points to their neighbors).
It is equivalent to PCL StatisticalOutlierRemoval filter (see http://pointclouds.org/documentation/tutorials/statistical_outlier.php)
Expand Down
102 changes: 52 additions & 50 deletions src/CloudSamplingTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,40 +245,65 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe
assert(inputCloud);
unsigned cloudSize = inputCloud->size();

DgmOctree* octree = inputOctree;
if (!octree)
std::vector<char> markers; //DGM: upgraded from vector, as this can be quite huge!
try
{
octree = new DgmOctree(inputCloud);
if (octree->build() < static_cast<int>(cloudSize))
{
delete octree;
return nullptr;
}
markers.resize(cloudSize, 1); //true by default
}
assert(octree && octree->associatedCloud() == inputCloud);

//output cloud
ReferenceCloud* sampledCloud = new ReferenceCloud(inputCloud);
const unsigned c_reserveStep = 65536;
if (!sampledCloud->reserve(std::min(cloudSize, c_reserveStep)))
catch (const std::bad_alloc&)
{
if (!inputOctree)
delete octree;
return nullptr;
}

std::vector<char> markers; //DGM: upgraded from vector, as this can be quite huge!
try
size_t filtered = resampleCloudSpatially(inputCloud, minDistance, modParams, &markers[0], inputOctree, progressCb);
if (filtered)
{
markers.resize(cloudSize, 1); //true by default
//output cloud
ReferenceCloud* sampledCloud = new ReferenceCloud(inputCloud);
if (!sampledCloud->reserve(filtered))
{
delete sampledCloud;
return nullptr;
}

for (unsigned i = 0; i < cloudSize; i++)
{
if (markers[i])
{
if (!sampledCloud->addPointIndex(i))
{
delete sampledCloud;
return nullptr;
}
}
}
return sampledCloud;
}
catch (const std::bad_alloc&)
return nullptr;
}

/* Return 0 for error */
size_t CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPersist* inputCloud,
PointCoordinateType minDistance,
const SFModulationParams& modParams,
char* markers,
DgmOctree* inputOctree/*=0*/,
GenericProgressCallback* progressCb/*=0*/)
{
assert(inputCloud);
unsigned cloudSize = inputCloud->size();

DgmOctree* octree = inputOctree;
if (!octree)
{
if (!inputOctree)
octree = new DgmOctree(inputCloud);
if (octree->build() < static_cast<int>(cloudSize))
{
delete octree;
delete sampledCloud;
return nullptr;
return 0;
}
}
assert(octree && octree->associatedCloud() == inputCloud);

//best octree level (there may be several of them if we use parameter modulation)
std::vector<unsigned char> bestOctreeLevel;
Expand Down Expand Up @@ -336,8 +361,7 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe
{
delete octree;
}
delete sampledCloud;
return nullptr;
return 0;
}

//progress notification
Expand All @@ -361,6 +385,7 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe
//default octree level
assert(!bestOctreeLevel.empty());
unsigned char octreeLevel = bestOctreeLevel.front();
size_t filtered = 0;
//default distance between points
PointCoordinateType minDistBetweenPoints = minDistance;
for (unsigned i = 0; i < cloudSize; i++)
Expand Down Expand Up @@ -403,18 +428,7 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe

//At this stage, the ith point is the only one marked in a radius of <minDistance>.
//Therefore it will necessarily be in the final cloud!
if (sampledCloud->size() == sampledCloud->capacity() && !sampledCloud->reserve(sampledCloud->capacity() + c_reserveStep))
{
//not enough memory
error = true;
break;
}
if (!sampledCloud->addPointIndex(i))
{
//not enough memory
error = true;
break;
}
++filtered;
}

//progress indicator
Expand All @@ -426,18 +440,6 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe
}
}

//remove unnecessarily allocated memory
if (!error)
{
if (sampledCloud->capacity() > sampledCloud->size())
sampledCloud->resize(sampledCloud->size());
}
else
{
delete sampledCloud;
sampledCloud = nullptr;
}

if (progressCb)
{
progressCb->stop();
Expand All @@ -450,7 +452,7 @@ ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPe
octree = nullptr;
}

return sampledCloud;
return error ? 0 : filtered;
}

ReferenceCloud* CloudSamplingTools::sorFilter( GenericIndexedCloudPersist* inputCloud,
Expand Down