Commit a7db40cc authored by Toshiyasu Sugio's avatar Toshiyasu Sugio Committed by David Flynn
Browse files

attr/m46107: intra-lod neighbour selection for pred transform

This commit introduces prediction by previously coded points within
the same level of detail using the predicting attribute coder.
The feature is controlled using --intraLodPredictionEnabled=0|1.
parent 153c449e
......@@ -41,6 +41,7 @@ categories:
- levelOfDetailCount: 0
- positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2}
- intraLodPredictionEnabled: 1
##
# attribute coding -- reflectance
......
......@@ -37,6 +37,7 @@ categories:
- levelOfDetailCount: 0
- positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2}
- intraLodPredictionEnabled: 1
##
# attribute coding -- reflectance
......
......@@ -262,6 +262,10 @@ Controls the level-of-detail generation method:
| 0 | Euclidean distance thresholding |
| 1 | Decimation by 1:3 |
### `--intraLodPredictionEnabled=0|1`
Part of LoD attribute coding. Permits (1) points to be predicted from
previously reconstructed points within the same LoD.
### `--levelOfDetailCount=INT-VALUE`
Attribute's number of levels of detail.
......
......@@ -276,9 +276,10 @@ AttributeDecoder::decodeReflectancesPred(
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
}
const int64_t maxReflectance = (1ll << desc.attr_bitdepth) - 1;
int zero_cnt = decoder.decodeZeroCnt(pointCount);
......@@ -364,9 +365,10 @@ AttributeDecoder::decodeColorsPred(
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
}
uint32_t values[3];
int zero_cnt = decoder.decodeZeroCnt(pointCount);
......@@ -559,9 +561,10 @@ AttributeDecoder::decodeColorsLift(
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......@@ -635,9 +638,10 @@ AttributeDecoder::decodeReflectancesLift(
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......
......@@ -481,9 +481,10 @@ AttributeEncoder::encodeReflectancesPred(
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
}
const int64_t clipMax = (1ll << desc.attr_bitdepth) - 1;
PCCResidualsEntropyEstimator context;
......@@ -670,9 +671,10 @@ AttributeEncoder::encodeColorsPred(
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
}
const int64_t clipMax = (1ll << desc.attr_bitdepth) - 1;
uint32_t values[3];
......@@ -952,9 +954,10 @@ AttributeEncoder::encodeColorsLift(
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......@@ -1050,9 +1053,10 @@ AttributeEncoder::encodeReflectancesLift(
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
pointCloud, aps.lod_decimation_enabled_flag,
aps.intra_lod_prediction_enabled_flag, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......
......@@ -499,7 +499,8 @@ computeNearestNeighbors(
std::vector<PCCPredictor>& predictors,
std::vector<uint32_t>& pointIndexToPredictorIndex,
int32_t& predIndex,
std::vector<Box3<double>>& bBoxes)
std::vector<Box3<double>>& bBoxes,
const bool intraLodPredictionEnabled)
{
const int32_t retainedSize = retained.size();
const int32_t bucketSize = 8;
......@@ -517,6 +518,24 @@ computeNearestNeighbors(
}
}
std::vector<Box3<double>> bBoxesI;
const int32_t indexesSize = endIndex - startIndex;
if (intraLodPredictionEnabled) {
bBoxesI.resize((indexesSize + bucketSize - 1) / bucketSize);
for (int32_t i = startIndex, b = 0; i < endIndex; ++b) {
auto& bBox = bBoxesI[b];
bBox.min = bBox.max = pointCloud[packedVoxel[indexes[i++]].index];
for (int32_t k = 1; k < bucketSize && i < endIndex; ++k, ++i) {
const int32_t pointIndex = packedVoxel[indexes[i]].index;
const auto& point = pointCloud[pointIndex];
for (int32_t p = 0; p < 3; ++p) {
bBox.min[p] = std::min(bBox.min[p], point[p]);
bBox.max[p] = std::max(bBox.max[p], point[p]);
}
}
}
}
const int32_t index0 = numberOfNearestNeighborsInPrediction - 1;
for (int32_t i = startIndex, j = 0; i < endIndex; ++i) {
......@@ -572,6 +591,45 @@ computeNearestNeighbors(
}
}
}
if (intraLodPredictionEnabled) {
const int32_t i0 = i - startIndex;
const int32_t j1 = std::min(indexesSize, i0 + searchRange + 1);
const int32_t bucketIndex0 = i0 / bucketSize;
int32_t k0 = i0 + 1;
int32_t k1 = std::min((bucketIndex0 + 1) * bucketSize, j1);
for (int32_t k = k0; k < k1; ++k) {
const int32_t pointIndex1 = packedVoxel[indexes[startIndex + k]].index;
const auto& point1 = pointCloud[pointIndex1];
predictor.insertNeighbor(
pointIndex1, (point - point1).getNorm2(),
numberOfNearestNeighborsInPrediction);
}
for (int32_t s0 = 1, sr = (1 + searchRange / bucketSize); s0 < sr;
++s0) {
const int32_t bucketIndex1 = bucketIndex0 + s0;
if (bucketIndex1 >= bBoxesI.size())
continue;
if (
predictor.neighborCount < numberOfNearestNeighborsInPrediction
|| bBoxesI[bucketIndex1].getDist2(point)
< predictor.neighbors[index0].weight) {
const int32_t k0 = bucketIndex1 * bucketSize;
const int32_t k1 = std::min((bucketIndex1 + 1) * bucketSize, j1);
for (int32_t k = k0; k < k1; ++k) {
const int32_t pointIndex1 =
packedVoxel[indexes[startIndex + k]].index;
const auto& point1 = pointCloud[pointIndex1];
predictor.insertNeighbor(
pointIndex1, (point - point1).getNorm2(),
numberOfNearestNeighborsInPrediction);
}
}
}
}
assert(predictor.neighborCount <= numberOfNearestNeighborsInPrediction);
}
}
......@@ -695,6 +753,7 @@ inline void
buildPredictorsFast(
const PCCPointSet3& pointCloud,
bool lod_decimation_enabled_flag,
bool intraLodPredictionEnabled,
const std::vector<int64_t>& dist2,
const int32_t levelOfDetailCount,
const int32_t numberOfNearestNeighborsInPrediction,
......@@ -759,7 +818,8 @@ buildPredictorsFast(
computeNearestNeighbors(
pointCloud, packedVoxel, retained, startIndex, endIndex, searchRange2,
numberOfNearestNeighborsInPrediction, indexes, predictors,
pointIndexToPredictorIndex, predIndex, bBoxes);
pointIndexToPredictorIndex, predIndex, bBoxes,
intraLodPredictionEnabled);
}
numberOfPointsPerLevelOfDetail.push_back(retained.size());
......
......@@ -444,6 +444,10 @@ ParseParameters(int argc, char* argv[], Parameters& params)
"Attribute's list of squared distances, or initial value for automatic"
"derivation")
("intraLodPredictionEnabled",
params_attr.aps.intra_lod_prediction_enabled_flag, false,
"Permits referring to points in same LoD")
("qp",
params_attr.aps.init_qp, 4,
"Attribute's luma quantisation parameter")
......@@ -543,6 +547,7 @@ ParseParameters(int argc, char* argv[], Parameters& params)
if (attr_aps.attr_encoding == AttributeEncoding::kLiftingTransform) {
attr_aps.adaptive_prediction_threshold = 0;
attr_aps.intra_lod_prediction_enabled_flag = false;
}
// For RAHT, ensure that the unused lod count = 0 (prevents mishaps)
......
......@@ -237,6 +237,7 @@ struct AttributeParameterSet {
int max_num_direct_predictors;
int adaptive_prediction_threshold;
int search_range;
bool intra_lod_prediction_enabled_flag;
// NB: derived from num_detail_levels_minus1
int num_detail_levels;
......
......@@ -273,6 +273,7 @@ write(const AttributeParameterSet& aps)
if (aps.attr_encoding == AttributeEncoding::kPredictingTransform) {
bs.writeUe(aps.adaptive_prediction_threshold);
bs.write(aps.intra_lod_prediction_enabled_flag);
}
if (aps.attr_encoding == AttributeEncoding::kRAHTransform) {
......@@ -320,8 +321,10 @@ parseAps(const PayloadBuffer& buf)
}
}
aps.intra_lod_prediction_enabled_flag = false;
if (aps.attr_encoding == AttributeEncoding::kPredictingTransform) {
bs.readUe(&aps.adaptive_prediction_threshold);
bs.read(&aps.intra_lod_prediction_enabled_flag);
}
if (aps.attr_encoding == AttributeEncoding::kRAHTransform) {
......
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