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:
committed by
GitHub
parent
8358efaca1
commit
8b7e586faa
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user