Commit 89fae502 authored by David Flynn's avatar David Flynn
Browse files

geom/m43600: intra geometry occupancy prediction

This commit provides a method to predict the child occupancy bits of a
node based on the node's 26 neighbours.  The prediction is used to
contextualise coding of each occupancy bit.

This tool requires the use of the occupancyAtlas for neighbour lookup.
NB: a restriction in the current implementation requires that the
atlas size is at most 8³.

intra_pred_max_node_size_log2: 6
parent 90e8646a
......@@ -12,7 +12,8 @@ categories:
- geometryCodec: 1
- mergeDuplicatedPoints: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- positionQuantizationScale: 1
####
......
......@@ -11,7 +11,8 @@ categories:
- geometryCodec: 1
- mergeDuplicatedPoints: 1
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- positionQuantizationScale:
r01: '$eval{ $rp = 5; $gp = ${src-geometry-precision}; $p_min = max(gp - 9, 7); $start = min(1, $gp - ($p_min + 6)); $step = max(1, (min($gp - 1, $p_min + 7) - $p_min) / 5); $y = $start + round($rp * $step); $div = 1 << (abs($y) + 1); ((1 - 2*signbit($y)) % $div) / $div }'
r02: '$eval{ $rp = 4; $gp = ${src-geometry-precision}; $p_min = max(gp - 9, 7); $start = min(1, $gp - ($p_min + 6)); $step = max(1, (min($gp - 1, $p_min + 7) - $p_min) / 5); $y = $start + round($rp * $step); $div = 1 << (abs($y) + 1); ((1 - 2*signbit($y)) % $div) / $div }'
......
......@@ -13,8 +13,9 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- neighbourAvailBoundaryLog2: 9
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
####
# attribute coding (common options -- relies on option ordering)
......
......@@ -13,8 +13,9 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- neighbourAvailBoundaryLog2: 9
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
####
# attribute coding (common options -- relies on option ordering)
......
......@@ -12,7 +12,8 @@ categories:
- geometryCodec: 1
- mergeDuplicatedPoints: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- positionQuantizationScale: 1
####
......
......@@ -11,7 +11,8 @@ categories:
- geometryCodec: 1
- mergeDuplicatedPoints: 1
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- positionQuantizationScale:
r01: '$eval{ $rp = 5; $gp = ${src-geometry-precision}; $p_min = max(gp - 9, 7); $start = min(1, $gp - ($p_min + 6)); $step = max(1, (min($gp - 1, $p_min + 7) - $p_min) / 5); $y = $start + round($rp * $step); $div = 1 << (abs($y) + 1); ((1 - 2*signbit($y)) % $div) / $div }'
r02: '$eval{ $rp = 4; $gp = ${src-geometry-precision}; $p_min = max(gp - 9, 7); $start = min(1, $gp - ($p_min + 6)); $step = max(1, (min($gp - 1, $p_min + 7) - $p_min) / 5); $y = $start + round($rp * $step); $div = 1 << (abs($y) + 1); ((1 - 2*signbit($y)) % $div) / $div }'
......
......@@ -11,7 +11,8 @@ categories:
# geometry parameters (trisoup)
- geometryCodec: 2
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- inferredDirectCodingMode: 0
- triSoupDepth: ${test-depth}
- triSoupIntToOrigScale: '$eval{ 1 << ( ${src-geometry-precision} - ${test-depth} ) }'
......
......@@ -11,7 +11,8 @@ categories:
# geometry parameters (trisoup)
- geometryCodec: 2
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 9
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- inferredDirectCodingMode: 0
- triSoupDepth: ${test-depth}
- triSoupIntToOrigScale: '$eval{ 1 << ( ${src-geometry-precision} - ${test-depth} ) }'
......
......@@ -73,6 +73,7 @@ file(GLOB PROJECT_INC_FILES
"TMC3.h"
"constants.h"
"geometry.h"
"geometry_intra_pred.h"
"geometry_octree.h"
"geometry_trisoup.h"
"hls.h"
......@@ -98,6 +99,7 @@ file(GLOB PROJECT_CPP_FILES
"TMC3.cpp"
"decoder.cpp"
"encoder.cpp"
"geometry_intra_pred.cpp"
"geometry_octree.cpp"
"geometry_octree_decoder.cpp"
"geometry_octree_encoder.cpp"
......
......@@ -323,6 +323,10 @@ ParseParameters(int argc, char* argv[], Parameters& params)
params.encoder.gps.inferred_direct_coding_mode_enabled_flag, true,
"Permits early termination of the geometry octree for isolated points")
("intra_pred_max_node_size_log2",
params.encoder.gps.intra_pred_max_node_size_log2, 0,
"octree nodesizes eligible for occupancy intra prediction")
("ctxOccupancyReductionFactor",
params.encoder.gps.geom_occupancy_ctx_reduction_factor, 3,
"Adjusts the number of contexts used in occupancy coding")
......@@ -520,6 +524,12 @@ ParseParameters(int argc, char* argv[], Parameters& params)
}
// sanity checks
if (params.encoder.gps.intra_pred_max_node_size_log2)
if (!params.encoder.gps.neighbour_avail_boundary_log2)
err.error() << "Geometry intra prediction requires finite"
"neighbour_avail_boundary_log2\n";
for (const auto& it : params.encoder.attributeIdxMap) {
const auto& attr_sps = params.encoder.sps.attributeSets[it.second];
const auto& attr_aps = params.encoder.aps[it.second];
......
/* The copyright in this software is being made available under the BSD
* Licence, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such
* rights are granted under this licence.
*
* Copyright (c) 2017-2018, ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the ISO/IEC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "geometry_intra_pred.h"
namespace pcc {
//============================================================================
static const int8_t LUT_dist[26][8] = {
{2, 4, 4, 6, 4, 6, 6, 7}, {1, 1, 3, 3, 3, 3, 5, 5}, {4, 2, 6, 4, 6, 4, 7, 6},
{1, 3, 1, 3, 3, 5, 3, 5}, {0, 0, 0, 0, 2, 2, 2, 2}, {3, 1, 3, 1, 5, 3, 5, 3},
{4, 6, 2, 4, 6, 7, 4, 6}, {3, 3, 1, 1, 5, 5, 3, 3}, {6, 4, 4, 2, 7, 6, 6, 4},
{1, 3, 3, 5, 1, 3, 3, 5}, {0, 0, 2, 2, 0, 0, 2, 2}, {3, 1, 5, 3, 3, 1, 5, 3},
{0, 2, 0, 2, 0, 2, 0, 2}, {2, 0, 2, 0, 2, 0, 2, 0}, {3, 5, 1, 3, 3, 5, 1, 3},
{2, 2, 0, 0, 2, 2, 0, 0}, {5, 3, 3, 1, 5, 3, 3, 1}, {4, 6, 6, 7, 2, 4, 4, 6},
{3, 3, 5, 5, 1, 1, 3, 3}, {6, 4, 7, 6, 4, 2, 6, 4}, {3, 5, 3, 5, 1, 3, 1, 3},
{2, 2, 2, 2, 0, 0, 0, 0}, {5, 3, 5, 3, 3, 1, 3, 1}, {6, 7, 4, 6, 4, 6, 2, 4},
{5, 5, 3, 3, 3, 3, 1, 1}, {7, 6, 6, 4, 6, 4, 4, 2}};
//----------------------------------------------------------------------------
static const int LUT1[8] = {27, 39, 20, 8, 18, 4, 11, 18};
static const int LUT0[8] = {-1, -6, 12, 20, 14, 28, 22, 12};
static const int LUT_th0[5] = {62, 60, 61, 59, 59};
static const int LUT_th1[5] = {67, 66, 65, 66, 64};
//============================================================================
void
predictGeometryOccupancyIntra(
const MortonMap3D& occupancyAtlas,
PCCVector3<uint32_t> pos,
int nodeSizeLog2,
int* occupancyIsPredicted,
int* occupancyPrediction)
{
uint32_t mask = occupancyAtlas.cubeSize() - 1;
int32_t x = (pos[0] >> nodeSizeLog2) & mask;
int32_t y = (pos[1] >> nodeSizeLog2) & mask;
int32_t z = (pos[2] >> nodeSizeLog2) & mask;
int score[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int numOccupied = 0;
const int8_t* p = &LUT_dist[0][0];
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
for (int dz = -1; dz <= 1; dz++) {
if (dz == 0 && dy == 0 && dx == 0)
continue;
// todo(df): remove unnecessary checks
bool occupied = occupancyAtlas.getWithCheck(x + dx, y + dy, z + dz);
if (occupied) {
for (int i = 0; i < 8; i++)
score[i] += LUT1[p[i]];
numOccupied++;
} else {
for (int i = 0; i < 8; i++)
score[i] += LUT0[p[i]];
}
// next pattern
p += 8;
}
}
}
if (numOccupied <= 8) {
*occupancyIsPredicted = 0;
*occupancyPrediction = 0;
return;
}
numOccupied -= 9;
if (numOccupied >= 4)
numOccupied = 4;
int th0 = LUT_th0[numOccupied] * 26;
int th1 = LUT_th1[numOccupied] * 26;
int occIsPredicted = 0;
int occPrediction = 0;
for (int i = 0; i < 8; i++) {
int score_i = score[i] << 2;
if (score_i <= th0) {
occIsPredicted |= 1 << i;
} else if (score_i >= th1) {
occIsPredicted |= 1 << i;
occPrediction |= 1 << i;
}
}
*occupancyIsPredicted = occIsPredicted;
*occupancyPrediction = occPrediction;
}
//============================================================================
} // namespace pcc
/* The copyright in this software is being made available under the BSD
* Licence, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such
* rights are granted under this licence.
*
* Copyright (c) 2017-2018, ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the ISO/IEC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <cstdint>
#include "OctreeNeighMap.h"
#include "PCCMath.h"
namespace pcc {
//============================================================================
void predictGeometryOccupancyIntra(
const MortonMap3D& occupancyAtlas,
PCCVector3<uint32_t> pos,
int nodeSizeLog2,
int* occupacyIsPredIntra,
int* occupacyPredIntra);
//============================================================================
} // namespace pcc
......@@ -38,6 +38,7 @@
#include "DualLutCoder.h"
#include "OctreeNeighMap.h"
#include "geometry_octree.h"
#include "geometry_intra_pred.h"
#include "io_hls.h"
#include "tables.h"
......@@ -413,6 +414,13 @@ decodeGeometryOctree(
int occupancyIsPredicted = 0;
int occupancyPrediction = 0;
// generate intra prediction
if (nodeSizeLog2 < gps.intra_pred_max_node_size_log2) {
predictGeometryOccupancyIntra(
occupancyAtlas, node0.pos, nodeSizeLog2, &occupancyIsPredicted,
&occupancyPrediction);
}
// decode occupancy pattern
uint8_t occupancy = decoder.decodeOccupancy(
node0.neighPattern, occupancyIsPredicted, occupancyPrediction);
......
......@@ -38,6 +38,7 @@
#include "DualLutCoder.h"
#include "OctreeNeighMap.h"
#include "geometry_octree.h"
#include "geometry_intra_pred.h"
#include "io_hls.h"
#include "tables.h"
......@@ -452,6 +453,13 @@ encodeGeometryOctree(
int occupancyIsPredicted = 0;
int occupancyPrediction = 0;
// generate intra prediction
if (nodeSizeLog2 < gps.intra_pred_max_node_size_log2) {
predictGeometryOccupancyIntra(
occupancyAtlas, node0.pos, nodeSizeLog2, &occupancyIsPredicted,
&occupancyPrediction);
}
// encode child occupancy map
assert(occupancy > 0);
encoder.encodeOccupancy(
......
......@@ -211,6 +211,9 @@ struct GeometryParameterSet {
// for occupancy coding.
int geom_occupancy_ctx_reduction_factor;
// Maximum node size where intra prediction is enabled
int intra_pred_max_node_size_log2;
// depth of voxels (reconstructed points) in trisoup geometry
int trisoup_depth;
......
......@@ -195,6 +195,7 @@ write(const GeometryParameterSet& gps)
bs.write(gps.bitwise_occupancy_coding_flag);
bs.writeUe(gps.geom_occupancy_ctx_reduction_factor);
bs.writeUe(gps.neighbour_avail_boundary_log2);
bs.writeUe(gps.intra_pred_max_node_size_log2);
if (gps.geom_codec_type == GeometryCodecType::kTriSoup) {
bs.writeUe(gps.trisoup_depth);
......@@ -227,6 +228,7 @@ parseGps(const PayloadBuffer& buf)
bs.read(&gps.bitwise_occupancy_coding_flag);
bs.readUe(&gps.geom_occupancy_ctx_reduction_factor);
bs.readUe(&gps.neighbour_avail_boundary_log2);
bs.readUe(&gps.intra_pred_max_node_size_log2);
if (gps.geom_codec_type == GeometryCodecType::kTriSoup) {
bs.readUe(&gps.trisoup_depth);
......
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