1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge pull request #22598 from savuor:icp_oframe_readonly

Complement PR: #3366@contrib
Changes

    OdometryFrame losts its getters: a user can provide data at construction stage only, pyramids and other generated data is read-only now
    OdometryFrame is based on UMats: no TMat templates inside, CPU operations are done with UMat::getMat() method, chaining issues are solved ad-hoc
    No more Odometry::createOdometryFrame() method, frames are compatible with all odometry algorithms
    Normals computer is cached inside Odometry and exposed to API as well as its settings
    Volume::raycast() won't return the result in OdometryFrame anymore
    Added test for Odometry::prepareFrame*() & other test fixes
    Minor code improvements

TODOs:

    fix TODOs in code
    lower acceptable accuracy errors
This commit is contained in:
Rostislav Vasilikhin
2022-10-24 15:34:01 +02:00
committed by GitHub
parent 8358efaca1
commit 8b7e586faa
24 changed files with 994 additions and 1857 deletions
+4 -3
View File
@@ -104,13 +104,14 @@ CV_EXPORTS_W void registerDepth(InputArray unregisteredCameraMatrix, InputArray
*/
CV_EXPORTS_W void depthTo3dSparse(InputArray depth, InputArray in_K, InputArray in_points, OutputArray points3d);
/** Converts a depth image to an organized set of 3d points.
/** Converts a depth image to 3d points. If the mask is empty then the resulting array has the same dimensions as `depth`,
* otherwise it is 1d vector containing mask-enabled values only.
* The coordinate system is x pointing left, y down and z away from the camera
* @param depth the depth image (if given as short int CV_U, it is assumed to be the depth in millimeters
* (as done with the Microsoft Kinect), otherwise, if given as CV_32F or CV_64F, it is assumed in meters)
* @param K The calibration matrix
* @param points3d the resulting 3d points (point is represented by 4 chanels value [x, y, z, 0]). They are of depth the same as `depth` if it is CV_32F or CV_64F, and the
* depth of `K` if `depth` is of depth CV_U
* @param points3d the resulting 3d points (point is represented by 4 channels value [x, y, z, 0]). They are of the same depth as `depth` if it is CV_32F or CV_64F, and the
* depth of `K` if `depth` is of depth CV_16U or CV_16S
* @param mask the mask of the points to consider (can be empty)
*/
CV_EXPORTS_W void depthTo3d(InputArray depth, InputArray K, OutputArray points3d, InputArray mask = noArray());
@@ -52,7 +52,7 @@ public:
virtual ~Submap() = default;
virtual void integrate(InputArray _depth, const int currframeId);
virtual void raycast(const Odometry& icp, const cv::Affine3f& cameraPose, cv::Size frameSize,
virtual void raycast(const cv::Affine3f& cameraPose, cv::Size frameSize,
OutputArray points = noArray(), OutputArray normals = noArray());
virtual int getTotalAllocatedBlocks() const { return int(volume.getTotalVolumeUnits()); };
@@ -112,25 +112,21 @@ void Submap<MatType>::integrate(InputArray _depth, const int currFrameId)
}
template<typename MatType>
void Submap<MatType>::raycast(const Odometry& icp, const cv::Affine3f& _cameraPose, cv::Size frameSize,
void Submap<MatType>::raycast(const cv::Affine3f& _cameraPose, cv::Size frameSize,
OutputArray points, OutputArray normals)
{
if (!points.needed() && !normals.needed())
{
MatType pts, nrm;
frame.getPyramidAt(pts, OdometryFramePyramidType::PYR_CLOUD, 0);
frame.getPyramidAt(nrm, OdometryFramePyramidType::PYR_NORM, 0);
//TODO: get depth instead of pts from raycast
volume.raycast(_cameraPose.matrix, frameSize.height, frameSize.height, pts, nrm);
frame.setPyramidAt(pts, OdometryFramePyramidType::PYR_CLOUD, 0);
frame.setPyramidAt(nrm, OdometryFramePyramidType::PYR_NORM, 0);
std::vector<MatType> pch(3);
split(pts, pch);
renderFrame = frame;
Mat depth;
frame.getScaledDepth(depth);
frame = icp.createOdometryFrame();
frame.setDepth(depth);
frame = OdometryFrame(noArray(), pch[2]);
}
else
{
+8 -12
View File
@@ -43,24 +43,16 @@ public:
Odometry(OdometryType otype, const OdometrySettings settings, OdometryAlgoType algtype);
~Odometry();
/** Create new odometry frame
* The Type (Mat or UMat) depends on odometry type
*/
OdometryFrame createOdometryFrame() const;
// Deprecated
OdometryFrame createOdometryFrame(OdometryFrameStoreType matType) const;
/** Prepare frame for odometry calculation
* @param frame odometry prepare this frame as src frame and dst frame simultaneously
*/
void prepareFrame(OdometryFrame& frame);
void prepareFrame(OdometryFrame& frame) const;
/** Prepare frame for odometry calculation
* @param srcFrame frame will be prepared as src frame ("original" image)
* @param dstFrame frame will be prepared as dsr frame ("rotated" image)
*/
void prepareFrames(OdometryFrame& srcFrame, OdometryFrame& dstFrame);
void prepareFrames(OdometryFrame& srcFrame, OdometryFrame& dstFrame) const;
/** Compute Rigid Transformation between two frames so that Rt * src = dst
* @param srcFrame src frame ("original" image)
@@ -71,11 +63,15 @@ public:
* R_31 R_32 R_33 t_3
* 0 0 0 1 }
*/
bool compute(const OdometryFrame& srcFrame, const OdometryFrame& dstFrame, OutputArray Rt);
bool compute(const OdometryFrame& srcFrame, const OdometryFrame& dstFrame, OutputArray Rt) const;
CV_WRAP bool compute(InputArray srcFrame, InputArray dstFrame, OutputArray Rt) const;
CV_WRAP bool compute(InputArray srcDepthFrame, InputArray dstDepthFrame, OutputArray Rt) const;
CV_WRAP bool compute(InputArray srcDepthFrame, InputArray srcRGBFrame, InputArray dstDepthFrame, InputArray dstRGBFrame, OutputArray Rt) const;
//TODO: document it
//requires frame size, initialized at prepareFrame stage()
Ptr<RgbdNormals> getNormalsComputer() const;
class Impl;
private:
Ptr<Impl> impl;
@@ -9,62 +9,45 @@
namespace cv
{
/** Indicates what pyramid is to access using get/setPyramid... methods:
* @param PYR_IMAGE The pyramid of RGB images
* @param PYR_DEPTH The pyramid of depth images
* @param PYR_MASK The pyramid of masks
* @param PYR_CLOUD The pyramid of point clouds, produced from the pyramid of depths
* @param PYR_DIX The pyramid of dI/dx derivative images
* @param PYR_DIY The pyramid of dI/dy derivative images
* @param PYR_TEXMASK The pyramid of textured masks
* @param PYR_NORM The pyramid of normals
* @param PYR_NORMMASK The pyramid of normals masks
/** Indicates what pyramid is to access using getPyramidAt() method:
*/
enum OdometryFramePyramidType
{
PYR_IMAGE = 0,
PYR_DEPTH = 1,
PYR_MASK = 2,
PYR_CLOUD = 3,
PYR_DIX = 4,
PYR_DIY = 5,
PYR_TEXMASK = 6,
PYR_NORM = 7,
PYR_NORMMASK = 8,
PYR_IMAGE = 0, //!< The pyramid of grayscale images
PYR_DEPTH = 1, //!< The pyramid of depth images
PYR_MASK = 2, //!< The pyramid of masks
PYR_CLOUD = 3, //!< The pyramid of point clouds, produced from the pyramid of depths
PYR_DIX = 4, //!< The pyramid of dI/dx derivative images
PYR_DIY = 5, //!< The pyramid of dI/dy derivative images
PYR_TEXMASK = 6, //!< The pyramid of "textured" masks (i.e. additional masks for normals or grayscale images)
PYR_NORM = 7, //!< The pyramid of normals
PYR_NORMMASK = 8, //!< The pyramid of normals masks
N_PYRAMIDS
};
enum class OdometryFrameStoreType
{
MAT = 0,
UMAT = 1
};
class CV_EXPORTS_W OdometryFrame
{
public:
OdometryFrame();
OdometryFrame(OdometryFrameStoreType matType);
//TODO: add to docs: check image channels, if 3 or 4 then do cvtColor(BGR(A)2GRAY)
OdometryFrame(InputArray image = noArray(), InputArray depth = noArray(), InputArray mask = noArray(), InputArray normals = noArray());
~OdometryFrame() {};
void setImage(InputArray image);
void getImage(OutputArray image) const;
void getGrayImage(OutputArray image) const;
void setDepth(InputArray depth);
void getDepth(OutputArray depth) const;
void getScaledDepth(OutputArray depth) const;
void setMask(InputArray mask);
void getMask(OutputArray mask) const;
void setNormals(InputArray normals);
void getNormals(OutputArray normals) const;
void setPyramidLevel(size_t _nLevels, OdometryFramePyramidType oftype);
void setPyramidLevels(size_t _nLevels);
size_t getPyramidLevels(OdometryFramePyramidType oftype) const;
void setPyramidAt(InputArray img, OdometryFramePyramidType pyrType, size_t level);
//TODO: add docs
// returns amt of levels in pyramids (all of them should have the same amt of levels) or 0 if no pyramids were prepared yet
size_t getPyramidLevels() const;
//TODO: add docs
// returns empty img if no data in the pyramid or in the pyramid's level
void getPyramidAt(OutputArray img, OdometryFramePyramidType pyrType, size_t level) const;
class Impl;
private:
Ptr<Impl> impl;
};
}
@@ -33,8 +33,13 @@ public:
int getSobelSize() const;
void setSobelScale(double val);
double getSobelScale() const;
void setNormalWinSize(int val);
int getNormalWinSize() const;
void setNormalDiffThreshold(float val);
float getNormalDiffThreshold() const;
void setNormalMethod(RgbdNormals::RgbdNormalsMethod nm);
RgbdNormals::RgbdNormalsMethod getNormalMethod() const;
void setAngleThreshold(float val);
float getAngleThreshold() const;
-20
View File
@@ -61,15 +61,6 @@ public:
Rendered image size and camera intrinsics are taken from volume settings structure.
* @param cameraPose the pose of camera in global coordinates.
* @param outFrame the object where to store rendered points and normals.
*/
void raycast(InputArray cameraPose, OdometryFrame& outFrame) const;
/** @brief Renders the volume contents into an image. The resulting points and normals are in camera's coordinate system.
Rendered image size and camera intrinsics are taken from volume settings structure.
* @param cameraPose the pose of camera in global coordinates.
* @param points image to store rendered points.
* @param normals image to store rendered normals corresponding to points.
@@ -81,17 +72,6 @@ public:
Rendered image size and camera intrinsics are taken from volume settings structure.
* @param cameraPose the pose of camera in global coordinates.
* @param height the height of result image.
* @param width the width of result image.
* @param outFrame the object where to store rendered points and normals.
*/
void raycast(InputArray cameraPose, int height, int width, OdometryFrame& outFrame) const;
/** @brief Renders the volume contents into an image. The resulting points and normals are in camera's coordinate system.
Rendered image size and camera intrinsics are taken from volume settings structure.
* @param cameraPose the pose of camera in global coordinates.
* @param height the height of result image.
* @param width the width of result image.