Skip to content
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

RemoveBeyond option for the maxQuantileDistance filter #452

Merged
merged 2 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions doc/DataFilters.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ No example available.

### Description

Points are filtered according to where they lie on a distribution of their positions along a given axis. The entire distance range is divided into quantiles which lie between 0 and 1. One can specify the distance quantile above which points are rejected by the filter.
Points are filtered according to where they lie on a distribution of their positions along a given axis. The entire distance range is divided into quantiles which lie between 0 and 1. One can specify the distance quantile above or beneath which points are rejected by the filter.

__Required descriptors:__ none
__Output descriptor:__ none
Expand All @@ -240,15 +240,15 @@ __Impact on the number of points:__ reduces number of points
|Parameter |Description |Default value |Allowable range|
|--------- |:---------|:----------------|:--------------|
|dim | Dimension over which the distance (from the center) is thresholded | 0 | x:0 y:1 z:2 |
|ratio |Quantile threshold. Points whose distance exceed this threshold are rejected by the filter | 0.5 | min: 0.0000001, max: 0.9999999 |

|ratio |Quantile threshold. The threshold at which the points are rejected by the filter | 0.5 | min: 0.0000001, max: 0.9999999 |
|removeBeyond |If 1 the points beyond the quantile threshold are rejected, else (0) the points under the quantile threshold are rejected | 1 | 1 or 0 |
### Example

In the following example, maximum quantile filtering is performed over the x-axis with a quantile threshold of 0.5. Therefore, points which have an x-value which exceeds the 50% quantile are rejected. The output of the filter is displayed in white and overlaid with the input point cloud in the image below. A sampling region centered at the origin and extending in both directions of the x-axis is clearly visible.
In the following example, maximum quantile filtering is performed over the x-axis with a quantile threshold of 0.5 and with the option to removeBeyond set to 1. Therefore, points which have an x-value which exceeds the 50% quantile are removed. The output of the filter is displayed in white and overlaid with the input point cloud in the image below. A sampling region centered at the origin and extending in both directions of the x-axis is clearly visible.

|Figure: Maximum quantile on axis filter in the x-direction with a maximum quantile <br>of 0.5. | Parameters used |
|Figure: Maximum quantile on axis filter in the x-direction with a maximum quantile <br>of 0.5 and removeBeyond set to 1. | Parameters used |
|---|:---|
|![max quant after](images/max_quant.png "After applying maximum quantile on axis filter in the x-direction with a maximum quantile of 0.5") | dim : 0 <br> ratio : 0.5 |
|![max quant after](images/max_quant.png "After applying maximum quantile on axis filter in the x-direction with a maximum quantile of 0.5 and removeByond set to 1") | dim : 0 <br> ratio : 0.5 <br> removeBeyond : 1 |

## Random Sampling Filter <a name="randomsamplinghead"></a>

Expand Down
78 changes: 55 additions & 23 deletions pointmatcher/DataPointsFilters/MaxQuantileOnAxis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ MaxQuantileOnAxisDataPointsFilter<T>::MaxQuantileOnAxisDataPointsFilter(
PointMatcher<T>::DataPointsFilter("MaxQuantileOnAxisDataPointsFilter",
MaxQuantileOnAxisDataPointsFilter::availableParameters(), params),
dim(Parametrizable::get<unsigned>("dim")),
ratio(Parametrizable::get<T>("ratio"))
ratio(Parametrizable::get<T>("ratio")),
removeBeyond(Parametrizable::get<bool>("removeBeyond"))
{
}

Expand All @@ -68,33 +69,64 @@ void MaxQuantileOnAxisDataPointsFilter<T>::inPlaceFilter(DataPoints& cloud)
throw InvalidParameter((boost::format("MaxQuantileOnAxisDataPointsFilter: Error, filtering on dimension number %1%, larger than feature dimensionality %2%") % dim % cloud.features.rows()).str());

const int nbPointsIn = cloud.features.cols();
const int nbPointsOut = nbPointsIn * ratio;

// build array
std::vector<T> values;
values.reserve(nbPointsIn);
for (int x = 0; x < nbPointsIn; ++x)
values.push_back(cloud.features(dim, x));

// get quartiles value
std::nth_element(values.begin(), values.begin() + (values.size() * ratio), values.end());
const T limit = values[nbPointsOut];

// copy towards beginning the elements we keep
int j = 0;
for (int i = 0; i < nbPointsIn; ++i)
{
if (cloud.features(dim, i) < limit)

if (removeBeyond) {
const int nbPointsOut = nbPointsIn * ratio;

// build array
std::vector<T> values;
values.reserve(nbPointsIn);
for (int x = 0; x < nbPointsIn; ++x)
values.push_back(cloud.features(dim, x));

// get quartiles value
std::nth_element(values.begin(), values.begin() + (values.size() * ratio), values.end());
const T limit = values[nbPointsOut];

// copy towards beginning the elements we keep
int j = 0;
for (int i = 0; i < nbPointsIn; ++i)
{
assert(j <= i);
cloud.setColFrom(j, cloud, i);
++j;
if (cloud.features(dim, i) < limit)
{
assert(j <= i);
cloud.setColFrom(j, cloud, i);
++j;
}
}
assert(j <= nbPointsOut);

cloud.conservativeResize(j);
}
assert(j <= nbPointsOut);
else {
const int nbPointsOut = nbPointsIn * (1 - ratio);

// build array
std::vector<T> values;
values.reserve(nbPointsIn);
for (int x = 0; x < nbPointsIn; ++x)
values.push_back(cloud.features(dim, x));

cloud.conservativeResize(j);
// get quartiles value
std::nth_element(values.begin(), values.begin() + (values.size() * ratio), values.end());

const T limit = values[nbPointsIn-nbPointsOut];

// copy towards beginning the elements we keep
int j = 0;
for (int i = 0; i < nbPointsIn; ++i)
{
if (cloud.features(dim, i) > limit)
{
assert(j <= i);
cloud.setColFrom(j, cloud, i);
++j;
}
}
assert(j <= nbPointsOut);

cloud.conservativeResize(j);
}
}

template struct MaxQuantileOnAxisDataPointsFilter<float>;
Expand Down
6 changes: 4 additions & 2 deletions pointmatcher/DataPointsFilters/MaxQuantileOnAxis.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,20 @@ struct MaxQuantileOnAxisDataPointsFilter: public PointMatcher<T>::DataPointsFilt

inline static const std::string description()
{
return "Subsampling. Filter points beyond a maximum quantile measured on a specific axis.";
return "Subsampling. Filter points under or beyond a maximum quantile measured on a specific axis.";
}
inline static const ParametersDoc availableParameters()
{
return {
{"dim", "dimension on which the filter will be applied. x=0, y=1, z=2", "0", "0", "2", &P::Comp<unsigned>},
{"ratio", "maximum quantile authorized. All points beyond that will be filtered.", "0.5", "0.0000001", "0.9999999", &P::Comp<T>}
{"ratio", "maximum quantile authorized. All points beyond that will be filtered.", "0.5", "0.0000001", "0.9999999", &P::Comp<T>},
{"removeBeyond", "If set to true (1), remove points beyond the quantile ratio; else (0), remove points under the quantile ratio", "1", "0", "1", P::Comp<bool>}
};
}

const unsigned dim;
const T ratio;
const bool removeBeyond;

//! Constructor, uses parameter interface
MaxQuantileOnAxisDataPointsFilter(const Parameters& params = Parameters());
Expand Down