Commit 3c9e671c authored by Valery Valentin's avatar Valery Valentin Committed by David Flynn
Browse files

attr/m46188: decimation based LoD generation

This LoD generation (subsampling) method uses the Morton-based ordering
of points that is used to determine prediction neighbours.  Each LoD
level comprises 3/4 of the points of the previous.
parent 05526a18
...@@ -33,9 +33,10 @@ categories: ...@@ -33,9 +33,10 @@ categories:
- positionQuantizationScaleAdjustsDist2: 1 - positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2} - dist2: ${seq_dist2}
- lodBinaryTree: 0 - lodBinaryTree: 0
- lodDecimation: 0
- -
- !conditional '"${group}" =~ m{^cat3}' - !conditional '"${group}" =~ m{^cat3}'
- lodBinaryTree: 1 - lodDecimation: 1
## ##
# attribute coding -- reflectance # attribute coding -- reflectance
......
...@@ -42,9 +42,10 @@ categories: ...@@ -42,9 +42,10 @@ categories:
- positionQuantizationScaleAdjustsDist2: 1 - positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2} - dist2: ${seq_dist2}
- lodBinaryTree: 0 - lodBinaryTree: 0
- lodDecimation: 0
- -
- !conditional '"${group}" =~ m{^cat3}' - !conditional '"${group}" =~ m{^cat3}'
- lodBinaryTree: 1 - lodDecimation: 1
## ##
# attribute coding -- reflectance # attribute coding -- reflectance
......
...@@ -33,9 +33,10 @@ categories: ...@@ -33,9 +33,10 @@ categories:
- numberOfNearestNeighborsInPrediction: 3 - numberOfNearestNeighborsInPrediction: 3
- levelOfDetailCount: ${seq_lod} - levelOfDetailCount: ${seq_lod}
- lodBinaryTree: 0 - lodBinaryTree: 0
- lodDecimation: 0
- -
- !conditional '"${group}" =~ m{^cat3}' - !conditional '"${group}" =~ m{^cat3}'
- lodBinaryTree: 1 - lodDecimation: 1
- positionQuantizationScaleAdjustsDist2: 1 - positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2} - dist2: ${seq_dist2}
......
...@@ -254,6 +254,14 @@ Range for nearest neighbour search. ...@@ -254,6 +254,14 @@ Range for nearest neighbour search.
Maximum number of nearest neighbour candidates used in direct Maximum number of nearest neighbour candidates used in direct
attribute prediction. attribute prediction.
### `--lodDecimation=0|1`
Controls the level-of-detail generation method:
| Value | Description |
|:-----:| ------------------------------- |
| 0 | Euclidean distance thresholding |
| 1 | Decimation by 1:3 |
### `--levelOfDetailCount=INT-VALUE` ### `--levelOfDetailCount=INT-VALUE`
Attribute's number of levels of detail. Attribute's number of levels of detail.
......
...@@ -277,9 +277,10 @@ AttributeDecoder::decodeReflectancesPred( ...@@ -277,9 +277,10 @@ AttributeDecoder::decodeReflectancesPred(
predictors, indexesLOD); predictors, indexesLOD);
} else { } else {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
indexesLOD);
} }
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
...@@ -373,9 +374,10 @@ AttributeDecoder::decodeColorsPred( ...@@ -373,9 +374,10 @@ AttributeDecoder::decodeColorsPred(
predictors, indexesLOD); predictors, indexesLOD);
} else { } else {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
indexesLOD);
} }
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
...@@ -576,9 +578,9 @@ AttributeDecoder::decodeColorsLift( ...@@ -576,9 +578,9 @@ AttributeDecoder::decodeColorsLift(
if (!aps.lod_binary_tree_enabled_flag) { if (!aps.lod_binary_tree_enabled_flag) {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
computePredictors( computePredictors(
...@@ -659,9 +661,9 @@ AttributeDecoder::decodeReflectancesLift( ...@@ -659,9 +661,9 @@ AttributeDecoder::decodeReflectancesLift(
if (!aps.lod_binary_tree_enabled_flag) { if (!aps.lod_binary_tree_enabled_flag) {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
computePredictors( computePredictors(
......
...@@ -482,9 +482,10 @@ AttributeEncoder::encodeReflectancesPred( ...@@ -482,9 +482,10 @@ AttributeEncoder::encodeReflectancesPred(
predictors, indexesLOD); predictors, indexesLOD);
} else { } else {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
indexesLOD);
} }
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
...@@ -679,9 +680,10 @@ AttributeEncoder::encodeColorsPred( ...@@ -679,9 +680,10 @@ AttributeEncoder::encodeColorsPred(
predictors, indexesLOD); predictors, indexesLOD);
} else { } else {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
indexesLOD);
} }
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
...@@ -969,9 +971,9 @@ AttributeEncoder::encodeColorsLift( ...@@ -969,9 +971,9 @@ AttributeEncoder::encodeColorsLift(
if (!aps.lod_binary_tree_enabled_flag) { if (!aps.lod_binary_tree_enabled_flag) {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
computePredictors( computePredictors(
...@@ -1074,9 +1076,9 @@ AttributeEncoder::encodeReflectancesLift( ...@@ -1074,9 +1076,9 @@ AttributeEncoder::encodeReflectancesLift(
if (!aps.lod_binary_tree_enabled_flag) { if (!aps.lod_binary_tree_enabled_flag) {
buildPredictorsFast( buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels, pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range, aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD); aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
} else { } else {
buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD); buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
computePredictors( computePredictors(
......
...@@ -579,7 +579,7 @@ computeNearestNeighbors( ...@@ -579,7 +579,7 @@ computeNearestNeighbors(
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
inline void inline void
subsample( subsampleByDistance(
const PCCPointSet3& pointCloud, const PCCPointSet3& pointCloud,
const std::vector<MortonCodeWithIndex>& packedVoxel, const std::vector<MortonCodeWithIndex>& packedVoxel,
const std::vector<uint32_t>& input, const std::vector<uint32_t>& input,
...@@ -613,6 +613,44 @@ subsample( ...@@ -613,6 +613,44 @@ subsample(
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
inline void
subsampleByDecimation(
const std::vector<uint32_t>& input,
std::vector<uint32_t>& retained,
std::vector<uint32_t>& indexes)
{
static const int kLodUniformQuant = 4;
const int indexCount = int(input.size());
for (int i = 0; i < indexCount; ++i) {
if (i % kLodUniformQuant == 0)
retained.push_back(input[i]);
else
indexes.push_back(input[i]);
}
}
//---------------------------------------------------------------------------
inline void
subsample(
bool useDecimation,
const PCCPointSet3& pointCloud,
const std::vector<MortonCodeWithIndex>& packedVoxel,
const std::vector<uint32_t>& input,
const double radius2,
const int32_t searchRange,
std::vector<uint32_t>& retained,
std::vector<uint32_t>& indexes)
{
if (useDecimation)
subsampleByDecimation(input, retained, indexes);
else
subsampleByDistance(
pointCloud, packedVoxel, input, radius2, searchRange, retained, indexes);
}
//---------------------------------------------------------------------------
inline void inline void
computeMortonCodes( computeMortonCodes(
const PCCPointSet3& pointCloud, const PCCPointSet3& pointCloud,
...@@ -799,6 +837,7 @@ computePredictors( ...@@ -799,6 +837,7 @@ computePredictors(
inline void inline void
buildPredictorsFast( buildPredictorsFast(
const PCCPointSet3& pointCloud, const PCCPointSet3& pointCloud,
bool lod_decimation_enabled_flag,
const std::vector<int64_t>& dist2, const std::vector<int64_t>& dist2,
const int32_t levelOfDetailCount, const int32_t levelOfDetailCount,
const int32_t numberOfNearestNeighborsInPrediction, const int32_t numberOfNearestNeighborsInPrediction,
...@@ -843,8 +882,8 @@ buildPredictorsFast( ...@@ -843,8 +882,8 @@ buildPredictorsFast(
} else { } else {
const double radius2 = dist2[lodIndex]; const double radius2 = dist2[lodIndex];
subsample( subsample(
pointCloud, packedVoxel, input, radius2, searchRange1, retained, lod_decimation_enabled_flag, pointCloud, packedVoxel, input, radius2,
indexes); searchRange1, retained, indexes);
} }
const int32_t endIndex = indexes.size(); const int32_t endIndex = indexes.size();
......
...@@ -430,6 +430,12 @@ ParseParameters(int argc, char* argv[], Parameters& params) ...@@ -430,6 +430,12 @@ ParseParameters(int argc, char* argv[], Parameters& params)
" 0: distance based subsampling\n" " 0: distance based subsampling\n"
" 1: binary tree") " 1: binary tree")
("lodDecimation",
params_attr.aps.lod_decimation_enabled_flag, false,
"Controls LoD generation method:\n"
" 0: distance based subsampling\n"
" 1: decimation by 1:3")
("max_num_direct_predictors", ("max_num_direct_predictors",
params_attr.aps.max_num_direct_predictors, 3, params_attr.aps.max_num_direct_predictors, 3,
"Maximum number of nearest neighbour candidates used in direct" "Maximum number of nearest neighbour candidates used in direct"
......
...@@ -233,6 +233,7 @@ struct AttributeParameterSet { ...@@ -233,6 +233,7 @@ struct AttributeParameterSet {
//--- lifting/predicting transform parameters //--- lifting/predicting transform parameters
bool lod_binary_tree_enabled_flag; bool lod_binary_tree_enabled_flag;
bool lod_decimation_enabled_flag;
int num_pred_nearest_neighbours; int num_pred_nearest_neighbours;
int max_num_direct_predictors; int max_num_direct_predictors;
int adaptive_prediction_threshold; int adaptive_prediction_threshold;
......
...@@ -262,6 +262,7 @@ write(const AttributeParameterSet& aps) ...@@ -262,6 +262,7 @@ write(const AttributeParameterSet& aps)
bs.writeUe(aps.num_pred_nearest_neighbours); bs.writeUe(aps.num_pred_nearest_neighbours);
bs.writeUe(aps.max_num_direct_predictors); bs.writeUe(aps.max_num_direct_predictors);
bs.writeUe(aps.search_range); bs.writeUe(aps.search_range);
bs.write(aps.lod_decimation_enabled_flag);
bs.write(aps.lod_binary_tree_enabled_flag); bs.write(aps.lod_binary_tree_enabled_flag);
bs.writeUe(aps.num_detail_levels); bs.writeUe(aps.num_detail_levels);
...@@ -311,6 +312,7 @@ parseAps(const PayloadBuffer& buf) ...@@ -311,6 +312,7 @@ parseAps(const PayloadBuffer& buf)
bs.readUe(&aps.num_pred_nearest_neighbours); bs.readUe(&aps.num_pred_nearest_neighbours);
bs.readUe(&aps.max_num_direct_predictors); bs.readUe(&aps.max_num_direct_predictors);
bs.readUe(&aps.search_range); bs.readUe(&aps.search_range);
bs.read(&aps.lod_decimation_enabled_flag);
bs.read(&aps.lod_binary_tree_enabled_flag); bs.read(&aps.lod_binary_tree_enabled_flag);
aps.num_detail_levels = int(bs.readUe()); aps.num_detail_levels = int(bs.readUe());
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment