Commit 34da2afb authored by Philip A. Chou's avatar Philip A. Chou Committed by David Flynn
Browse files

m42634/raht: added rahtLeafDecimationDepth control

This commit introduces the rahtLeafDecimationDepth parameter to allow
chroma sub-sampling by decimating the coefficients in the bottom n
levels of the tree.

The default value of 3 provides chroma sub-sampling by a factor of 2
in each dimension.
parent 4a6b1a3d
......@@ -154,6 +154,7 @@ int AttributeDecoder::decodeHeader(
transformType = TransformType(transType);
PCCReadFromBuffer<uint8_t>(bitstream.buffer, depthRaht, bitstream.size);
PCCReadFromBuffer<uint8_t>(bitstream.buffer, binaryLevelThresholdRaht, bitstream.size);
PCCReadFromBuffer<uint32_t>(bitstream.buffer, quantizationStepRaht, bitstream.size);
return 0;
}
......@@ -294,8 +295,9 @@ void AttributeDecoder::decodeReflectancesRaht(
// Re-obtain weights at the decoder by calling RAHT without any attributes.
float *weight = new float[voxelCount];
int *binaryLayer = new int[voxelCount];
regionAdaptiveHierarchicalTransform(
mortonCode, nullptr, weight, 0, voxelCount, depthRaht);
mortonCode, nullptr, weight, binaryLayer, 0, voxelCount, depthRaht);
// Sort integerized attributes by weight
std::vector<WeightWithIndex> sortedWeight(voxelCount);
......@@ -336,6 +338,7 @@ void AttributeDecoder::decodeReflectancesRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
......@@ -375,8 +378,9 @@ void AttributeDecoder::decodeColorsRaht(
// Re-obtain weights at the decoder by calling RAHT without any attributes.
float *weight = new float[voxelCount];
int *binaryLayer = new int[voxelCount];
regionAdaptiveHierarchicalTransform(
mortonCode, nullptr, weight, 0, voxelCount, depthRaht);
mortonCode, nullptr, weight, binaryLayer, 0, voxelCount, depthRaht);
// Sort integerized attributes by weight
std::vector<WeightWithIndex> sortedWeight(voxelCount);
......@@ -392,9 +396,15 @@ void AttributeDecoder::decodeColorsRaht(
for (int n = 0; n < voxelCount; ++n) {
const uint32_t attValue0 = decoder.decode0();
sortedIntegerizedAttributes[n] = o3dgc::UIntToInt(attValue0);
for (int d = 1; d < 3; ++d) {
const uint32_t attValue1 = decoder.decode1();
sortedIntegerizedAttributes[voxelCount * d + n] = o3dgc::UIntToInt(attValue1);
if (binaryLayer[sortedWeight[n].index] >= binaryLevelThresholdRaht) {
for (int d = 1; d < 3; ++d) {
const uint32_t attValue1 = decoder.decode1();
sortedIntegerizedAttributes[voxelCount * d + n] = o3dgc::UIntToInt(attValue1);
}
} else {
for (int d = 1; d < 3; d++) {
sortedIntegerizedAttributes[voxelCount * d + n] = 0;
}
}
}
......@@ -432,6 +442,7 @@ void AttributeDecoder::decodeColorsRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
......
......@@ -99,6 +99,7 @@ private:
size_t levelOfDetailCount;
uint32_t quantizationStepRaht;
uint8_t depthRaht;
uint8_t binaryLevelThresholdRaht;
TransformType transformType;
};
......
......@@ -155,6 +155,10 @@ int AttributeEncoder::encodeHeader(
PCCWriteToBuffer<uint8_t>(
uint8_t(attributeParams.depthRaht), bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(
uint8_t(attributeParams.binaryLevelThresholdRaht),
bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint32_t>(
uint32_t(attributeParams.quantizationStepRaht),
bitstream.buffer, bitstream.size);
......@@ -317,6 +321,7 @@ void AttributeEncoder::encodeReflectancesTransformRaht(
int *integerizedAttributes = new int[voxelCount];
int *sortedIntegerizedAttributes = new int[voxelCount];
float *weight = new float[voxelCount];
int *binaryLayer = new int[voxelCount];
// Populate input arrays.
for (int n = 0; n < voxelCount; n++) {
......@@ -326,8 +331,9 @@ void AttributeEncoder::encodeReflectancesTransformRaht(
// Transform.
regionAdaptiveHierarchicalTransform(
mortonCode, attributes, weight,
mortonCode, attributes, weight, binaryLayer,
1, voxelCount, reflectanceParams.depthRaht);
// Quantize.
for (int n = 0; n < voxelCount; n++) {
integerizedAttributes[n] =
......@@ -354,7 +360,9 @@ void AttributeEncoder::encodeReflectancesTransformRaht(
}
// Re-obtain weights at the decoder by calling Raht without any attributes.
regionAdaptiveHierarchicalTransform(
mortonCode, nullptr, weight, 0, voxelCount, reflectanceParams.depthRaht);
mortonCode, nullptr, weight, binaryLayer,
0, voxelCount, reflectanceParams.depthRaht);
// Sort integerized attributes by weight.
for (int n = 0; n < voxelCount; n++) {
sortedWeight[n].weight = weight[n];
......@@ -381,6 +389,7 @@ void AttributeEncoder::encodeReflectancesTransformRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
......@@ -420,6 +429,7 @@ void AttributeEncoder::encodeColorsTransformRaht(
int *integerizedAttributes = new int[attribCount * voxelCount];
int *sortedIntegerizedAttributes = new int[attribCount * voxelCount];
float *weight = new float[voxelCount];
int *binaryLayer = new int[voxelCount];
// Populate input arrays.
for (int n = 0; n < voxelCount; n++) {
......@@ -432,8 +442,9 @@ void AttributeEncoder::encodeColorsTransformRaht(
// Transform.
regionAdaptiveHierarchicalTransform(
mortonCode, attributes, weight,
mortonCode, attributes, weight, binaryLayer,
attribCount, voxelCount, colorParams.depthRaht);
// Quantize.
for (int n = 0; n < voxelCount; n++) {
for (int k = 0; k < attribCount; k++) {
......@@ -463,17 +474,25 @@ void AttributeEncoder::encodeColorsTransformRaht(
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue0 = uint32_t(detail);
encoder.encode0(attValue0);
for (int d = 1; d < 3; ++d) {
const int64_t detail = o3dgc::IntToUInt(sortedIntegerizedAttributes[voxelCount * d + n]);
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue1 = uint32_t(detail);
encoder.encode1(attValue1);
if (binaryLayer[sortedWeight[n].index] >= colorParams.binaryLevelThresholdRaht) {
for (int d = 1; d < 3; ++d) {
const int64_t detail = o3dgc::IntToUInt(sortedIntegerizedAttributes[voxelCount * d + n]);
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue1 = uint32_t(detail);
encoder.encode1(attValue1);
}
} else {
for (int d = 1; d < 3; d++) {
sortedIntegerizedAttributes[voxelCount * d + n] = 0;
}
}
}
// Re-obtain weights at the decoder by calling RAHT without any attributes.
regionAdaptiveHierarchicalTransform(
mortonCode, nullptr, weight, 0, voxelCount, colorParams.depthRaht);
mortonCode, nullptr, weight, binaryLayer,
0, voxelCount, colorParams.depthRaht);
// Sort integerized attributes by weight.
for (int n = 0; n < voxelCount; n++) {
sortedWeight[n].weight = weight[n];
......@@ -510,6 +529,7 @@ void AttributeEncoder::encodeColorsTransformRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
......
......@@ -58,6 +58,7 @@ struct PCCAttributeEncodeParamaters {
size_t searchRange;
int quantizationStepRaht;
int depthRaht;
int binaryLevelThresholdRaht;
TransformType transformType;
std::vector<size_t> dist2;
std::vector<size_t> quantizationSteps;
......
......@@ -61,7 +61,7 @@ namespace pcc {
* sorting or bucketing for entropy coding.
*/
void regionAdaptiveHierarchicalTransform(
long long *mortonCode, float *attributes, float *weight,
long long *mortonCode, float *attributes, float *weight, int *binaryLayer,
int attribCount, int voxelCount, int depth)
{
// Prologue, common to both RAHT and IRAHT:
......@@ -170,7 +170,10 @@ void regionAdaptiveHierarchicalTransform(
float *x1 = new float[attribCount];
// Initialize weights.
for (int n = 0; n < voxelCount; n++) weight[n] = 1.0f;
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1.0f;
binaryLayer[n] = 0;
}
// Process one level at a time, from leaves (b=0) to root (b=3*depth-1).
for (int b = 0; b < 3 * depth; b++) {
......@@ -204,6 +207,8 @@ void regionAdaptiveHierarchicalTransform(
weight[i0] = (w0 + w1);
weight[i1] = (w0 + w1);
binaryLayer[i0] = b + 1;
n++; // skip over right sibling
}
}
......
......@@ -67,7 +67,7 @@ struct MortonCodeWithIndex {
};
void regionAdaptiveHierarchicalTransform(
long long *mortonCode, float *attributes, float *weight,
long long *mortonCode, float *attributes, float *weight, int *binaryLayer,
int attribCount, int voxelCount, int depth);
void regionAdaptiveHierarchicalInverseTransform(
......
......@@ -205,6 +205,11 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
" 0: Nearest neighbour prediction with integer lifting transform\n"
" 1: Region Adaptive Hierarchical Transform (RAHT)")
("rahtLeafDecimationDepth",
params_attr.binaryLevelThresholdRaht, 3,
"Sets coefficients to zero in the bottom n levels of RAHT tree. "
"Used for chroma-subsampling in attribute=color only.")
("rahtQuantizationStep",
params_attr.quantizationStepRaht, 1,
"Quantization step size used in RAHT")
......
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