@ -89,11 +89,9 @@ Point3f ocl_getNormalVoxel(
# endif
void integrateHashTsdfVolumeUnit (
const VolumeSettings & settings , const Matx44f & cameraPose , int & lastVolIndex , const int frameId , const int volumeUnitDegree ,
const VolumeSettings & settings , const Matx44f & cameraPose , int & lastVolIndex , const int frameId , const int volumeUnitDegree , bool enableGrowth ,
InputArray _depth , InputArray _pixNorms , InputArray _volUnitsData , VolumeUnitIndexes & volumeUnits )
{
//std::cout << "integrateHashTsdfVolumeUnit()" << std::endl;
CV_TRACE_FUNCTION ( ) ;
CV_Assert ( _depth . type ( ) = = DEPTH_TYPE ) ;
@ -101,10 +99,16 @@ void integrateHashTsdfVolumeUnit(
Mat volUnitsData = _volUnitsData . getMat ( ) ;
Mat pixNorms = _pixNorms . getMat ( ) ;
//! Compute volumes to be allocated
const int depthStride = volumeUnitDegree ;
const float invDepthFactor = 1.f / settings . getDepthFactor ( ) ;
const float truncDist = settings . getTsdfTruncateDistance ( ) ;
Matx44f _pose ;
settings . getVolumePose ( _pose ) ;
const Affine3f pose = Affine3f ( _pose ) ;
const Affine3f cam2vol ( pose . inv ( ) * Affine3f ( cameraPose ) ) ;
Matx33f intr ;
settings . getCameraIntegrateIntrinsics ( intr ) ;
const Intr intrinsics ( intr ) ;
const Intr : : Reprojector reproj ( intrinsics . makeReprojector ( ) ) ;
const float maxDepth = settings . getMaxDepth ( ) ;
const float voxelSize = settings . getVoxelSize ( ) ;
@ -112,89 +116,88 @@ void integrateHashTsdfVolumeUnit(
settings . getVolumeResolution ( resolution ) ;
const float volumeUnitSize = voxelSize * resolution [ 0 ] ;
Matx33f intr ;
settings . getCameraIntegrateIntrinsics ( intr ) ;
const Intr intrinsics ( intr ) ;
const Intr : : Reprojector reproj ( intrinsics . makeReprojector ( ) ) ;
Matx44f _pose ;
settings . getVolumePose ( _pose ) ;
const Affine3f pose = Affine3f ( _pose ) ;
const Affine3f cam2vol ( pose . inv ( ) * Affine3f ( cameraPose ) ) ;
if ( enableGrowth )
{
//! Compute volumes to be allocated
const int depthStride = volumeUnitDegree ;
const float invDepthFactor = 1.f / settings . getDepthFactor ( ) ;
const float truncDist = settings . getTsdfTruncateDistance ( ) ;
const Point3f truncPt ( truncDist , truncDist , truncDist ) ;
VolumeUnitIndexSet newIndices ;
Mutex mutex ;
Range allocateRange ( 0 , depth . rows ) ;
const Point3f truncPt ( truncDist , truncDist , truncDist ) ;
std : : unordered_set < cv : : Vec3i , tsdf_hash > newIndices ;
Mutex mutex ;
Range allocateRange ( 0 , depth . rows ) ;
auto AllocateVolumeUnitsInvoker = [ & ] ( const Range & range ) {
VolumeUnitIndexSet localAccessVolUnits ;
for ( int y = range . start ; y < range . end ; y + = depthStride )
auto AllocateVolumeUnitsInvoker = [ & ] ( const Range & range )
{
const depthType * depthRow = depth [ y ] ;
for ( int x = 0 ; x < depth . cols ; x + = depthStride )
std : : unordered_set < cv : : Vec3i , tsdf_hash > localAccessVolUnits ;
for ( int y = range . start ; y < range . end ; y + = depthStride )
{
depthType z = depthRow [ x ] * invDepthFactor ;
const depthType * depthRow = depth [ y ] ;
for ( int x = 0 ; x < depth . cols ; x + = depthStride )
{
depthType z = depthRow [ x ] * invDepthFactor ;
if ( z < = 0 | | z > maxDepth )
continue ;
if ( z < = 0 | | z > maxDepth )
continue ;
Point3f camPoint = reproj ( Point3f ( ( float ) x , ( float ) y , z ) ) ;
Point3f volPoint = cam2vol * camPoint ;
//! Find accessed TSDF volume unit for valid 3D vertex
Vec3i lower_bound = volumeToVolumeUnitIdx ( volPoint - truncPt , volumeUnitSize ) ;
Vec3i upper_bound = volumeToVolumeUnitIdx ( volPoint + truncPt , volumeUnitSize ) ;
Point3f camPoint = reproj ( Point3f ( ( float ) x , ( float ) y , z ) ) ;
Point3f volPoint = cam2vol * camPoint ;
//! Find accessed TSDF volume unit for valid 3D vertex
Vec3i lower_bound = volumeToVolumeUnitIdx ( volPoint - truncPt , volumeUnitSize ) ;
Vec3i upper_bound = volumeToVolumeUnitIdx ( volPoint + truncPt , volumeUnitSize ) ;
for ( int i = lower_bound [ 0 ] ; i < = upper_bound [ 0 ] ; i + + )
for ( int j = lower_bound [ 1 ] ; j < = upper_bound [ 1 ] ; j + + )
for ( int k = lower_bound [ 2 ] ; k < = upper_bound [ 2 ] ; k + + )
{
const Vec3i tsdf_idx = Vec3i ( i , j , k ) ;
if ( localAccessVolUnits . count ( tsdf_idx ) < = 0 & & volumeUnits . count ( tsdf_idx ) < = 0 )
for ( int i = lower_bound [ 0 ] ; i < = upper_bound [ 0 ] ; i + + )
for ( int j = lower_bound [ 1 ] ; j < = upper_bound [ 1 ] ; j + + )
for ( int k = lower_bound [ 2 ] ; k < = upper_bound [ 2 ] ; k + + )
{
//! This volume unit will definitely be required for current integration
localAccessVolUnits . emplace ( tsdf_idx ) ;
const Vec3i tsdf_idx = Vec3i ( i , j , k ) ;
if ( localAccessVolUnits . count ( tsdf_idx ) < = 0 & & volumeUnits . count ( tsdf_idx ) < = 0 )
{
//! This volume unit will definitely be required for current integration
localAccessVolUnits . emplace ( tsdf_idx ) ;
}
}
}
}
}
}
mutex . lock ( ) ;
for ( const auto & tsdf_idx : localAccessVolUnits )
{
//! If the insert into the global set passes
if ( ! newIndices . count ( tsdf_idx ) )
mutex . lock ( ) ;
for ( const auto & tsdf_idx : localAccessVolUnits )
{
// Volume allocation can be performed outside of the lock
newIndices . emplace ( tsdf_idx ) ;
//! If the insert into the global set passes
if ( ! newIndices . count ( tsdf_idx ) )
{
// Volume allocation can be performed outside of the lock
newIndices . emplace ( tsdf_idx ) ;
}
}
}
mutex . unlock ( ) ;
} ;
parallel_for_ ( allocateRange , AllocateVolumeUnitsInvoker ) ;
//AllocateVolumeUnitsInvoker(allocateRange);
mutex . unlock ( ) ;
} ;
parallel_for_ ( allocateRange , AllocateVolumeUnitsInvoker ) ;
//! Perform the allocation
for ( auto idx : newIndices )
{
VolumeUnit & vu = volumeUnits . emplace ( idx , VolumeUnit ( ) ) . first - > second ;
//! Perform the allocation
for ( auto idx : newIndices )
{
VolumeUnit & vu = volumeUnits . emplace ( idx , VolumeUnit ( ) ) . first - > second ;
Matx44f subvolumePose = pose . translate ( pose . rotation ( ) * volumeUnitIdxToVolume ( idx , volumeUnitSize ) ) . matrix ;
Matx44f subvolumePose = pose . translate ( pose . rotation ( ) * volumeUnitIdxToVolume ( idx , volumeUnitSize ) ) . matrix ;
vu . pose = subvolumePose ;
vu . index = lastVolIndex ; lastVolIndex + + ;
if ( lastVolIndex > int ( volUnitsData . size ( ) . height ) )
{
volUnitsData . resize ( ( lastVolIndex - 1 ) * 2 ) ;
}
volUnitsData . row ( vu . index ) . forEach < VecTsdfVoxel > ( [ ] ( VecTsdfVoxel & vv , const int * /* position */ )
vu . pose = subvolumePose ;
vu . index = lastVolIndex ;
lastVolIndex + + ;
if ( lastVolIndex > int ( volUnitsData . size ( ) . height ) )
{
volUnitsData . resize ( ( lastVolIndex - 1 ) * 2 ) ;
}
volUnitsData . row ( vu . index ) . forEach < VecTsdfVoxel > ( [ ] ( VecTsdfVoxel & vv , const int * /* position */ )
{
TsdfVoxel & v = reinterpret_cast < TsdfVoxel & > ( vv ) ;
v . tsdf = floatToTsdf ( 0.0f ) ; v . weight = 0 ;
} ) ;
//! This volume unit will definitely be required for current integration
vu . lastVisibleIndex = frameId ;
vu . isActive = true ;
//! This volume unit will definitely be required for current integration
vu . lastVisibleIndex = frameId ;
vu . isActive = true ;
}
}
//! Get keys for all the allocated volume Units
@ -206,7 +209,8 @@ void integrateHashTsdfVolumeUnit(
//! Mark volumes in the camera frustum as active
Range inFrustumRange ( 0 , ( int ) volumeUnits . size ( ) ) ;
parallel_for_ ( inFrustumRange , [ & ] ( const Range & range ) {
parallel_for_ ( inFrustumRange , [ & ] ( const Range & range )
{
const Affine3f vol2cam ( Affine3f ( cameraPose . inv ( ) ) * pose ) ;
const Intr : : Projector proj ( intrinsics . makeProjector ( ) ) ;
@ -232,11 +236,12 @@ void integrateHashTsdfVolumeUnit(
it - > second . isActive = true ;
}
}
} ) ;
} ) ;
//! Integrate the correct volumeUnits
parallel_for_ ( Range ( 0 , ( int ) totalVolUnits . size ( ) ) , [ & ] ( const Range & range ) {
parallel_for_ ( Range ( 0 , ( int ) totalVolUnits . size ( ) ) , [ & ] ( const Range & range )
{
for ( int i = range . start ; i < range . end ; i + + )
{
Vec3i tsdf_idx = totalVolUnits [ i ] ;
@ -254,7 +259,7 @@ void integrateHashTsdfVolumeUnit(
volumeUnit . isActive = false ;
}
}
} ) ;
} ) ;
}
@ -474,7 +479,7 @@ void markActive(
void ocl_integrateHashTsdfVolumeUnit (
const VolumeSettings & settings , const Matx44f & cameraPose , int & lastVolIndex , const int frameId , int & bufferSizeDegree , const int volumeUnitDegree ,
const VolumeSettings & settings , const Matx44f & cameraPose , int & lastVolIndex , const int frameId , int & bufferSizeDegree , const int volumeUnitDegree , bool enableGrowth ,
InputArray _depth , InputArray _pixNorms , InputArray _lastVisibleIndices , InputArray _volUnitsDataCopy , InputArray _volUnitsData , CustomHashSet & hashTable , InputArray _isActiveFlags )
{
CV_TRACE_FUNCTION ( ) ;
@ -510,46 +515,49 @@ void ocl_integrateHashTsdfVolumeUnit(
const Affine3f pose = Affine3f ( _pose ) ;
Matx44f vol2camMatrix = ( Affine3f ( cameraPose ) . inv ( ) * pose ) . matrix ;
// Save length to fill new data in ranges
int sizeBefore = hashTable . last ;
allocateVolumeUnits ( depth , depthFactor , pose , cameraPose , intrinsics , hashTable , volumeUnitDegree , truncDist , maxDepth , volumeUnitSize ) ;
int sizeAfter = hashTable . last ;
//! Perform the allocation
// Grow buffers
int buff_lvl = ( int ) ( 1 < < bufferSizeDegree ) ;
if ( sizeAfter > = buff_lvl )
if ( enableGrowth )
{
bufferSizeDegree = ( int ) ( log2 ( sizeAfter ) + 1 ) ; // clz() would be better
int oldBuffSize = buff_lvl ;
buff_lvl = ( int ) pow ( 2 , bufferSizeDegree ) ;
// Save length to fill new data in ranges
int sizeBefore = hashTable . last ;
allocateVolumeUnits ( depth , depthFactor , pose , cameraPose , intrinsics , hashTable , volumeUnitDegree , truncDist , maxDepth , volumeUnitSize ) ;
int sizeAfter = hashTable . last ;
//! Perform the allocation
// Grow buffers
int buff_lvl = ( int ) ( 1 < < bufferSizeDegree ) ;
if ( sizeAfter > = buff_lvl )
{
bufferSizeDegree = ( int ) ( log2 ( sizeAfter ) + 1 ) ; // clz() would be better
int oldBuffSize = buff_lvl ;
buff_lvl = ( int ) pow ( 2 , bufferSizeDegree ) ;
volUnitsDataCopy . resize ( buff_lvl ) ;
volUnitsDataCopy . resize ( buff_lvl ) ;
Range oldr ( 0 , oldBuffSize ) ;
int volCubed = volumeUnitResolution * volumeUnitResolution * volumeUnitResolution ;
UMat newData ( buff_lvl , volCubed , CV_8UC2 ) ;
volUnitsData . copyTo ( newData . rowRange ( oldr ) ) ;
volUnitsData = newData ;
Range oldr ( 0 , oldBuffSize ) ;
int volCubed = volumeUnitResolution * volumeUnitResolution * volumeUnitResolution ;
UMat newData ( buff_lvl , volCubed , CV_8UC2 ) ;
volUnitsData . copyTo ( newData . rowRange ( oldr ) ) ;
volUnitsData = newData ;
UMat newLastVisibleIndices ( buff_lvl , 1 , CV_32S ) ;
lastVisibleIndices . copyTo ( newLastVisibleIndices . rowRange ( oldr ) ) ;
lastVisibleIndices = newLastVisibleIndices ;
UMat newLastVisibleIndices ( buff_lvl , 1 , CV_32S ) ;
lastVisibleIndices . copyTo ( newLastVisibleIndices . rowRange ( oldr ) ) ;
lastVisibleIndices = newLastVisibleIndices ;
UMat newIsActiveFlags ( buff_lvl , 1 , CV_8U ) ;
isActiveFlags . copyTo ( newIsActiveFlags . rowRange ( oldr ) ) ;
isActiveFlags = newIsActiveFlags ;
}
UMat newIsActiveFlags ( buff_lvl , 1 , CV_8U ) ;
isActiveFlags . copyTo ( newIsActiveFlags . rowRange ( oldr ) ) ;
isActiveFlags = newIsActiveFlags ;
}
// Fill data for new volume units
Range r ( sizeBefore , sizeAfter ) ;
if ( r . start < r . end )
{
lastVisibleIndices . rowRange ( r ) = frameId ;
isActiveFlags . rowRange ( r ) = 1 ;
// Fill data for new volume units
Range r ( sizeBefore , sizeAfter ) ;
if ( r . start < r . end )
{
lastVisibleIndices . rowRange ( r ) = frameId ;
isActiveFlags . rowRange ( r ) = 1 ;
TsdfVoxel emptyVoxel ( floatToTsdf ( 0.0f ) , 0 ) ;
volUnitsData . rowRange ( r ) = Vec2b ( ( uchar ) ( emptyVoxel . tsdf ) , ( uchar ) ( emptyVoxel . weight ) ) ;
TsdfVoxel emptyVoxel ( floatToTsdf ( 0.0f ) , 0 ) ;
volUnitsData . rowRange ( r ) = Vec2b ( ( uchar ) ( emptyVoxel . tsdf ) , ( uchar ) ( emptyVoxel . weight ) ) ;
}
}
//! Mark volumes in the camera frustum as active
@ -596,8 +604,6 @@ void ocl_integrateHashTsdfVolumeUnit(
if ( ! k . run ( 3 , globalSize , NULL , true ) )
throw std : : runtime_error ( " Failed to run kernel " ) ;
//std::cout << "ocl_integrateHashTsdfVolumeUnit() end" << std::endl;
}
# endif