1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00
Files
opencv/modules/3d/src/rgbd/sparse_block_matrix.hpp
T
Rostislav Vasilikhin bae9cef0b5 Merge pull request #20013 from savuor:rgbd_to_3d
Moving RGBD parts to 3d

* files moved from rgbd module in contrib repo

* header paths fixed

* perf file added

* lapack compilation fixed

* Rodrigues fixed in tests

* rgbd namespace removed

* headers fixed

* initial: rgbd files moved to 3d module

* rgbd updated from latest contrib master; less file duplication

* "std::" for sin(), cos(), etc.

* KinFu family -> back to contrib

* paths & namespaces

* removed duplicates, file version updated

* namespace kinfu removed from 3d module

* forgot to move test_colored_kinfu.cpp to contrib

* tests fixed: Params removed

* kinfu namespace removed

* it works without objc bindings

* include headers fixed

* tests: data paths fixed

* headers moved to/from public API

* Intr -> Matx33f in public API

* from kinfu_frame.hpp to utils.hpp

* submap: Intr -> Matx33f, HashTSDFVolume -> Volume; no extra headers

* no RgbdFrame class, no Mat fields & arg -> InputArray & pImpl

* get/setPyramidAt() instead of lots of methods

* Mat -> InputArray, TMat

* prepareFrameCache: refactored

* FastICPOdometry: +truncate threshold, +depthFactor; Mat/UMat choose

* Mat/UMat choose

* minor stuff related to headers

* (un)signed int warnings; compilation minor issues

* minors: submap: pyramids -> OdometryFrame; tests fix; FastICP minor; CV_EXPORTS_W for kinfu_frame.hpp

* FastICPOdometry: caching, rgbCameraMatrix

* OdometryFrame: pyramid%s% -> pyramids[]

* drop: rgbCameraMatrix from FastICP, RGB cache mode, makeColoredFrameFrom depth and all color-functions it calls

* makeFrameFromDepth, buildPyramidPointsNormals -> from public to internal utils.hpp

* minors

* FastICPOdometry: caching updated, init fields

* OdometryFrameImpl<UMat> fixed

* matrix building fixed; minors

* returning linemode back to contrib

* params.pose is Mat now

* precomp headers reorganized

* minor fixes, header paths, extra header removed

* minors: intrinsics -> utils.hpp; whitespaces; empty namespace; warning fixed

* moving declarations from/to headers

* internal headers reorganized (once again)

* fix include

* extra var fix

* fix include, fix (un)singed warning

* calibration.cpp: reverting back

* headers fix

* workaround to fix bindings

* temporary removed wrappers

* VolumeType -> VolumeParams

* (temporarily) removing wrappers for Volume and VolumeParams

* pyopencv_linemod -> contrib

* try to fix test_rgbd.py

* headers fixed

* fixing wrappers for rgbd

* fixing docs

* fixing rgbdPlane

* RgbdNormals wrapped

* wrap Volume and VolumeParams, VolumeType from enum to int

* DepthCleaner wrapped

* header folder "rgbd" -> "3d"

* fixing header path

* VolumeParams referenced by Ptr to support Python wrappers

* render...() fixed

* Ptr<VolumeParams> fixed

* makeVolume(... resolution -> [X, Y, Z])

* fixing static declaration

* try to fix ios objc bindings

* OdometryFrame::release...() removed

* fix for Odometry algos not supporting UMats: prepareFrameCache<>()

* preparePyramidMask(): fix to compile with TMat = UMat

* fixing debug guards

* removing references back; adding makeOdometryFrame() instead

* fixing OpenCL ICP hanging (some threads exit before reaching the barrier -> the rest threads hang)

* try to fix objc wrapper warnings; rerun builders

* VolumeType -> VolumeKind

* try to fix OCL bug

* prints removed

* indentation fixed

* headers fixed

* license fix

* WillowGarage licence notion removed, since it's in OpenCV's COPYRIGHT already

* KinFu license notion shortened

* debugging code removed

* include guards fixed

* KinFu license left in contrib module

* isValidDepth() moved to private header

* indentation fix

* indentation fix in src files

* RgbdNormals rewritten to pImpl

* minor

* DepthCleaner removed due to low code quality, no depthScale provided, no depth images found to be successfully filtered; can be replaced by bilateral filtering

* minors, indentation

* no "private" in public headers

* depthTo3d test moved from separate file

* Normals: setDepth() is useless, removing it

* RgbdPlane => findPlanes()

* rescaleDepth(): minor

* warpFrame: minor

* minor TODO

* all Odometries (except base abstract class) rewritten to pImpl

* FastICPOdometry now supports maxRotation and maxTranslation

* minor

* Odometry's children: now checks are done in setters

* get rid of protected members in Odometry class

* get/set cameraMatrix, transformType, maxRot/Trans, iters, minGradients -> OdometryImpl

* cameraMatrix: from double to float

* matrix exponentiation: Eigen -> dual quaternions

* Odometry evaluation fixed to reuse existing code

* "small" macro fixed by undef

* pixNorm is calculated on CPU only now (and then uploads on GPU)

* test registration: no cvtest classes

* test RgbdNormals and findPlanes(): no cvtest classes

* test_rgbd.py: minor fix

* tests for Odometry: no cvtest classes; UMat tests; logging fixed

* more CV_OVERRIDE to overriden functions

* fixing nondependent names to dependent

* more to prev commit

* forgotten fixes: overriden functions, (non)dependent names

* FastICPOdometry: fix UMat support when OpenCL is off

* try to fix compilation: missing namespaces

* Odometry: static const-mimicking functions to internal constants

* forgotten change to prev commit

* more forgotten fixes

* do not expose "submap.hpp" by default

* in-class enums: give names, CamelCase, int=>enums; minors

* namespaces, underscores, String

* std::map is used by pose graph, adding it

* compute()'s signature fixed, computeImpl()'s too

* RgbdNormals: Mat -> InputArray

* depth.hpp: Mat -> InputArray

* cameraMatrix: Matx33f -> InputArray + default value + checks

* "details" headers are not visible by default

* TSDF tests: rearranging checks

* cameraMatrix: no (realistic) default value

* renderPointsNormals*(): no wrappers for them

* debug: assert on empty frame in TSDF tests

* debugging code for TSDF GPU

* debug from integrate to raycast

* no (non-zero) default camera matrix anymore

* drop debugging code (does not help)

* try to fix TSDF GPU: constant -> global const ptr
2021-08-22 13:18:45 +00:00

198 lines
5.8 KiB
C++

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_3D_SPARSE_BLOCK_MATRIX_HPP
#define OPENCV_3D_SPARSE_BLOCK_MATRIX_HPP
#include "../precomp.hpp"
#if defined(HAVE_EIGEN)
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include "opencv2/core/eigen.hpp"
#endif
namespace cv
{
/*!
* \class BlockSparseMat
* Naive implementation of Sparse Block Matrix
*/
template<typename _Tp, size_t blockM, size_t blockN>
struct BlockSparseMat
{
struct Point2iHash
{
size_t operator()(const cv::Point2i& point) const noexcept
{
size_t seed = 0;
constexpr uint32_t GOLDEN_RATIO = 0x9e3779b9;
seed ^= std::hash<int>()(point.x) + GOLDEN_RATIO + (seed << 6) + (seed >> 2);
seed ^= std::hash<int>()(point.y) + GOLDEN_RATIO + (seed << 6) + (seed >> 2);
return seed;
}
};
typedef Matx<_Tp, blockM, blockN> MatType;
typedef std::unordered_map<Point2i, MatType, Point2iHash> IDtoBlockValueMap;
BlockSparseMat(size_t _nBlocks) : nBlocks(_nBlocks), ijValue() {}
void clear()
{
ijValue.clear();
}
inline MatType& refBlock(size_t i, size_t j)
{
Point2i p((int)i, (int)j);
auto it = ijValue.find(p);
if (it == ijValue.end())
{
it = ijValue.insert({ p, MatType::zeros() }).first;
}
return it->second;
}
inline _Tp& refElem(size_t i, size_t j)
{
Point2i ib((int)(i / blockM), (int)(j / blockN));
Point2i iv((int)(i % blockM), (int)(j % blockN));
return refBlock(ib.x, ib.y)(iv.x, iv.y);
}
inline MatType valBlock(size_t i, size_t j) const
{
Point2i p((int)i, (int)j);
auto it = ijValue.find(p);
if (it == ijValue.end())
return MatType::zeros();
else
return it->second;
}
inline _Tp valElem(size_t i, size_t j) const
{
Point2i ib((int)(i / blockM), (int)(j / blockN));
Point2i iv((int)(i % blockM), (int)(j % blockN));
return valBlock(ib.x, ib.y)(iv.x, iv.y);
}
Mat diagonal() const
{
// Diagonal max length is the number of columns in the sparse matrix
int diagLength = blockN * nBlocks;
cv::Mat diag = cv::Mat::zeros(diagLength, 1, cv::DataType<_Tp>::type);
for (int i = 0; i < diagLength; i++)
{
diag.at<_Tp>(i, 0) = valElem(i, i);
}
return diag;
}
#if defined(HAVE_EIGEN)
Eigen::SparseMatrix<_Tp> toEigen() const
{
std::vector<Eigen::Triplet<_Tp>> tripletList;
tripletList.reserve(ijValue.size() * blockM * blockN);
for (const auto& ijv : ijValue)
{
int xb = ijv.first.x, yb = ijv.first.y;
MatType vblock = ijv.second;
for (size_t i = 0; i < blockM; i++)
{
for (size_t j = 0; j < blockN; j++)
{
_Tp val = vblock((int)i, (int)j);
if (abs(val) >= NON_ZERO_VAL_THRESHOLD)
{
tripletList.push_back(Eigen::Triplet<_Tp>((int)(blockM * xb + i), (int)(blockN * yb + j), val));
}
}
}
}
Eigen::SparseMatrix<_Tp> EigenMat(blockM * nBlocks, blockN * nBlocks);
EigenMat.setFromTriplets(tripletList.begin(), tripletList.end());
EigenMat.makeCompressed();
return EigenMat;
}
#endif
inline size_t nonZeroBlocks() const { return ijValue.size(); }
BlockSparseMat<_Tp, blockM, blockN>& operator+=(const BlockSparseMat<_Tp, blockM, blockN>& other)
{
for (const auto& oijv : other.ijValue)
{
Point2i p = oijv.first;
MatType vblock = oijv.second;
this->refBlock(p.x, p.y) += vblock;
}
return *this;
}
#if defined(HAVE_EIGEN)
//! Function to solve a sparse linear system of equations HX = B
//! Requires Eigen
bool sparseSolve(InputArray B, OutputArray X, bool checkSymmetry = true, OutputArray predB = cv::noArray()) const
{
Eigen::SparseMatrix<_Tp> bigA = toEigen();
Mat mb = B.getMat().t();
Eigen::Matrix<_Tp, -1, 1> bigB;
cv2eigen(mb, bigB);
Eigen::SparseMatrix<_Tp> bigAtranspose = bigA.transpose();
if(checkSymmetry && !bigA.isApprox(bigAtranspose))
{
CV_Error(Error::StsBadArg, "H matrix is not symmetrical");
return false;
}
Eigen::SimplicialLDLT<Eigen::SparseMatrix<_Tp>> solver;
solver.compute(bigA);
if (solver.info() != Eigen::Success)
{
CV_LOG_INFO(NULL, "Failed to eigen-decompose");
return false;
}
else
{
Eigen::Matrix<_Tp, -1, 1> solutionX = solver.solve(bigB);
if (solver.info() != Eigen::Success)
{
CV_LOG_INFO(NULL, "Failed to eigen-solve");
return false;
}
else
{
eigen2cv(solutionX, X);
if (predB.needed())
{
Eigen::Matrix<_Tp, -1, 1> predBEigen = bigA * solutionX;
eigen2cv(predBEigen, predB);
}
return true;
}
}
}
#else
bool sparseSolve(InputArray /*B*/, OutputArray /*X*/, bool /*checkSymmetry*/ = true, OutputArray /*predB*/ = cv::noArray()) const
{
CV_Error(Error::StsNotImplemented, "Eigen library required for matrix solve, dense solver is not implemented");
}
#endif
static constexpr _Tp NON_ZERO_VAL_THRESHOLD = _Tp(0.0001);
size_t nBlocks;
IDtoBlockValueMap ijValue;
};
} // namespace cv
#endif // include guard