Commit 81b3c8b8 authored by Jungsun Kim's avatar Jungsun Kim Committed by David Flynn
Browse files

attr/m44899: add attribute prediction without LoD

This simplified attribute prediction scheme avoids computing the
LoD structure in order to reduce the computational complexity of
both the encoder and the decoder.  It is activated by setting
levelOfDetailCount=0.

NB: this is only configured for lossless/near-lossless predictive
attribute coding of cat3 sequences.
parent 2e60eef8
......@@ -36,6 +36,9 @@ categories:
- transformType: 0
- numberOfNearestNeighborsInPrediction: 3
- levelOfDetailCount: ${seq_lod}
-
- !conditional '"${group}" =~ m{^cat3}'
- levelOfDetailCount: 0
- positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2}
......
......@@ -32,6 +32,9 @@ categories:
- transformType: 0
- numberOfNearestNeighborsInPrediction: 3
- levelOfDetailCount: ${seq_lod}
-
- !conditional '"${group}" =~ m{^cat3}'
- levelOfDetailCount: 0
- positionQuantizationScaleAdjustsDist2: 1
- dist2: ${seq_dist2}
......
......@@ -238,10 +238,16 @@ AttributeDecoder::decodeReflectancesPred(
std::vector<PCCPredictor> predictors;
std::vector<uint32_t> numberOfPointsPerLOD;
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
if (aps.num_detail_levels <= 1) {
buildPredictorsFastNoLod(
pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, 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;
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......@@ -310,10 +316,16 @@ AttributeDecoder::decodeColorsPred(
std::vector<PCCPredictor> predictors;
std::vector<uint32_t> numberOfPointsPerLOD;
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
if (aps.num_detail_levels <= 1) {
buildPredictorsFastNoLod(
pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
}
uint32_t values[3];
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
......
......@@ -429,11 +429,16 @@ AttributeEncoder::encodeReflectancesPred(
std::vector<PCCPredictor> predictors;
std::vector<uint32_t> numberOfPointsPerLOD;
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
if (aps.num_detail_levels <= 1) {
buildPredictorsFastNoLod(
pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, 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;
for (size_t predictorIndex = 0; predictorIndex < pointCount;
......@@ -572,10 +577,16 @@ AttributeEncoder::encodeColorsPred(
std::vector<PCCPredictor> predictors;
std::vector<uint32_t> numberOfPointsPerLOD;
std::vector<uint32_t> indexesLOD;
buildPredictorsFast(
pointCloud, aps.dist2, aps.num_detail_levels,
aps.num_pred_nearest_neighbours, aps.search_range, aps.search_range,
predictors, numberOfPointsPerLOD, indexesLOD);
if (aps.num_detail_levels <= 1) {
buildPredictorsFastNoLod(
pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
predictors, indexesLOD);
} else {
buildPredictorsFast(
pointCloud, 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];
PCCResidualsEntropyEstimator context;
......
......@@ -98,7 +98,7 @@ struct PCCNeighborInfo {
//---------------------------------------------------------------------------
struct PCCPredictor {
size_t neighborCount;
uint32_t neighborCount;
PCCNeighborInfo neighbors[kAttributePredictionMaxNeighbourCount];
int8_t predMode;
......@@ -668,6 +668,57 @@ buildPredictorsFast(
//---------------------------------------------------------------------------
inline void
buildPredictorsFastNoLod(
const PCCPointSet3& pointCloud,
const int32_t numberOfNearestNeighborsInPrediction,
const int32_t searchRange,
std::vector<PCCPredictor>& predictors,
std::vector<uint32_t>& indexes)
{
const int32_t pointCount = int32_t(pointCloud.getPointCount());
assert(pointCount);
indexes.resize(pointCount);
// re-order points
{
std::vector<MortonCodeWithIndex> packedVoxel;
computeMortonCodes(pointCloud, packedVoxel);
for (int32_t i = 0; i < pointCount; ++i) {
indexes[i] = packedVoxel[i].index;
}
}
predictors.resize(pointCount);
for (int32_t i = 0; i < pointCount; ++i) {
const int32_t index = indexes[i];
const auto& point = pointCloud[index];
auto& predictor = predictors[i];
predictor.init();
const int32_t k0 = std::max(0, i - searchRange);
const int32_t k1 = i - 1;
for (int32_t k = k1; k >= k0; --k) {
const int32_t index1 = indexes[k];
const auto& point1 = pointCloud[index1];
predictor.insertNeighbor(
k, (point - point1).getNorm2(), numberOfNearestNeighborsInPrediction);
}
assert(predictor.neighborCount <= numberOfNearestNeighborsInPrediction);
if (predictor.neighborCount < 2) {
predictor.neighbors[0].weight = 1.0;
} else if (predictor.neighbors[0].weight == 0.0) {
predictor.neighborCount = 1;
predictor.neighbors[0].weight = 1.0;
} else {
for (int32_t k = 0; k < predictor.neighborCount; ++k) {
auto& weight = predictor.neighbors[k].weight;
weight = 1.0 / weight;
}
}
}
}
//---------------------------------------------------------------------------
} // namespace pcc
#endif /* PCCTMC3Common_h */
......@@ -457,18 +457,23 @@ ParseParameters(int argc, char* argv[], Parameters& params)
|| attr_aps.attr_encoding == AttributeEncoding::kLiftingTransform;
// derive the dist2 values based on an initial value
if (isLifting && !attr_aps.dist2.empty()) {
if (attr_aps.dist2.size() < attr_aps.num_detail_levels) {
if (isLifting) {
if (attr_aps.dist2.size() > attr_aps.num_detail_levels) {
attr_aps.dist2.resize(attr_aps.num_detail_levels);
const double distRatio = 4.0;
uint64_t d2 = attr_aps.dist2[0];
for (int i = 0; i < attr_aps.num_detail_levels; ++i) {
attr_aps.dist2[i] = d2;
d2 = uint64_t(std::round(distRatio * d2));
} else if (
attr_aps.dist2.size() < attr_aps.num_detail_levels
&& !attr_aps.dist2.empty()) {
if (attr_aps.dist2.size() < attr_aps.num_detail_levels) {
attr_aps.dist2.resize(attr_aps.num_detail_levels);
const double distRatio = 4.0;
uint64_t d2 = attr_aps.dist2[0];
for (int i = 0; i < attr_aps.num_detail_levels; ++i) {
attr_aps.dist2[i] = d2;
d2 = uint64_t(std::round(distRatio * d2));
}
}
}
}
// In order to simplify specification of dist2 values, which are
// depending on the scale of the coded point cloud, the following
// adjust the dist2 values according to PQS. The user need only
......@@ -528,10 +533,9 @@ ParseParameters(int argc, char* argv[], Parameters& params)
if (isLifting) {
int lod = attr_aps.num_detail_levels;
if (lod > 255 || lod < 1) {
if (lod > 255 || lod < 0) {
err.error() << it.first
<< ".levelOfDetailCount must be in the range [1,255]\n";
<< ".levelOfDetailCount must be in the range [0,255]\n";
}
if (attr_aps.dist2.size() != lod) {
err.error() << it.first << ".dist2 does not have " << lod
......
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