rgbd.hpp 35.3 KB
Newer Older
Vincent Rabaud's avatar
Vincent Rabaud committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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 OWNER 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.
 *
 */

#ifndef __OPENCV_RGBD_HPP__
#define __OPENCV_RGBD_HPP__

#ifdef __cplusplus

#include <opencv2/core.hpp>
42
#include <limits>
Vincent Rabaud's avatar
Vincent Rabaud committed
43

44 45 46
/** @defgroup rgbd RGB-Depth Processing
*/

Vincent Rabaud's avatar
Vincent Rabaud committed
47 48
namespace cv
{
49
namespace rgbd
50
{
51 52 53 54

//! @addtogroup rgbd
//! @{

Vincent Rabaud's avatar
Vincent Rabaud committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
  /** Checks if the value is a valid depth. For CV_16U or CV_16S, the convention is to be invalid if it is
   * a limit. For a float/double, we just check if it is a NaN
   * @param depth the depth to check for validity
   */
  CV_EXPORTS
  inline bool
  isValidDepth(const float & depth)
  {
    return !cvIsNaN(depth);
  }
  CV_EXPORTS
  inline bool
  isValidDepth(const double & depth)
  {
    return !cvIsNaN(depth);
  }
  CV_EXPORTS
  inline bool
  isValidDepth(const short int & depth)
  {
    return (depth != std::numeric_limits<short int>::min()) && (depth != std::numeric_limits<short int>::max());
  }
  CV_EXPORTS
  inline bool
  isValidDepth(const unsigned short int & depth)
  {
    return (depth != std::numeric_limits<unsigned short int>::min())
        && (depth != std::numeric_limits<unsigned short int>::max());
  }
  CV_EXPORTS
  inline bool
  isValidDepth(const int & depth)
  {
    return (depth != std::numeric_limits<int>::min()) && (depth != std::numeric_limits<int>::max());
  }
  CV_EXPORTS
  inline bool
  isValidDepth(const unsigned int & depth)
  {
    return (depth != std::numeric_limits<unsigned int>::min()) && (depth != std::numeric_limits<unsigned int>::max());
  }

  /** Object that can compute the normals in an image.
   * It is an object as it can cache data for speed efficiency
   * The implemented methods are either:
   * - FALS (the fastest) and SRI from
   * ``Fast and Accurate Computation of Surface Normals from Range Images``
   * by H. Badino, D. Huber, Y. Park and T. Kanade
   * - the normals with bilateral filtering on a depth image from
   * ``Gradient Response Maps for Real-Time Detection of Texture-Less Objects``
   * by S. Hinterstoisser, C. Cagniart, S. Ilic, P. Sturm, N. Navab, P. Fua, and V. Lepetit
   */
107
  class CV_EXPORTS_W RgbdNormals: public Algorithm
Vincent Rabaud's avatar
Vincent Rabaud committed
108 109 110 111
  {
  public:
    enum RGBD_NORMALS_METHOD
    {
112 113 114
      RGBD_NORMALS_METHOD_FALS = 0,
      RGBD_NORMALS_METHOD_LINEMOD = 1,
      RGBD_NORMALS_METHOD_SRI = 2
Vincent Rabaud's avatar
Vincent Rabaud committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    };

    RgbdNormals()
        :
          rows_(0),
          cols_(0),
          depth_(0),
          K_(Mat()),
          window_size_(0),
          method_(RGBD_NORMALS_METHOD_FALS),
          rgbd_normals_impl_(0)
    {
    }

    /** Constructor
     * @param rows the number of rows of the depth image normals will be computed on
     * @param cols the number of cols of the depth image normals will be computed on
132
     * @param depth the depth of the normals (only CV_32F or CV_64F)
Vincent Rabaud's avatar
Vincent Rabaud committed
133 134 135 136 137
     * @param K the calibration matrix to use
     * @param window_size the window size to compute the normals: can only be 1,3,5 or 7
     * @param method one of the methods to use: RGBD_NORMALS_METHOD_SRI, RGBD_NORMALS_METHOD_FALS
     */
    RgbdNormals(int rows, int cols, int depth, InputArray K, int window_size = 5, int method =
138
        RgbdNormals::RGBD_NORMALS_METHOD_FALS);
Vincent Rabaud's avatar
Vincent Rabaud committed
139 140 141

    ~RgbdNormals();

142 143 144
    CV_WRAP static Ptr<RgbdNormals> create(int rows, int cols, int depth, InputArray K, int window_size = 5, int method =
        RgbdNormals::RGBD_NORMALS_METHOD_FALS);

Vincent Rabaud's avatar
Vincent Rabaud committed
145 146 147 148 149 150 151 152 153 154
    /** Given a set of 3d points in a depth image, compute the normals at each point.
     * @param points a rows x cols x 3 matrix of CV_32F/CV64F or a rows x cols x 1 CV_U16S
     * @param normals a rows x cols x 3 matrix
     */
    void
    operator()(InputArray points, OutputArray normals) const;

    /** Initializes some data that is cached for later computation
     * If that function is not called, it will be called the first time normals are computed
     */
155
    CV_WRAP void
Vincent Rabaud's avatar
Vincent Rabaud committed
156 157
    initialize() const;

158
    CV_WRAP int getRows() const
159 160 161
    {
        return rows_;
    }
162
    CV_WRAP void setRows(int val)
163 164 165
    {
        rows_ = val;
    }
166
    CV_WRAP int getCols() const
167 168 169
    {
        return cols_;
    }
170
    CV_WRAP void setCols(int val)
171 172 173
    {
        cols_ = val;
    }
174
    CV_WRAP int getWindowSize() const
175 176 177
    {
        return window_size_;
    }
178
    CV_WRAP void setWindowSize(int val)
179 180 181
    {
        window_size_ = val;
    }
182
    CV_WRAP int getDepth() const
183 184 185
    {
        return depth_;
    }
186
    CV_WRAP void setDepth(int val)
187 188 189
    {
        depth_ = val;
    }
190
    CV_WRAP cv::Mat getK() const
191 192 193
    {
        return K_;
    }
194
    CV_WRAP void setK(const cv::Mat &val)
195 196 197
    {
        K_ = val;
    }
198
    CV_WRAP int getMethod() const
199 200 201
    {
        return method_;
    }
202
    CV_WRAP void setMethod(int val)
203 204 205
    {
        method_ = val;
    }
206

Vincent Rabaud's avatar
Vincent Rabaud committed
207 208 209 210 211 212 213 214 215 216 217 218 219
  protected:
    void
    initialize_normals_impl(int rows, int cols, int depth, const Mat & K, int window_size, int method) const;

    int rows_, cols_, depth_;
    Mat K_;
    int window_size_;
    int method_;
    mutable void* rgbd_normals_impl_;
  };

  /** Object that can clean a noisy depth image
   */
220
  class CV_EXPORTS_W DepthCleaner: public Algorithm
Vincent Rabaud's avatar
Vincent Rabaud committed
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
  {
  public:
    /** NIL method is from
     * ``Modeling Kinect Sensor Noise for Improved 3d Reconstruction and Tracking``
     * by C. Nguyen, S. Izadi, D. Lovel
     */
    enum DEPTH_CLEANER_METHOD
    {
      DEPTH_CLEANER_NIL
    };

    DepthCleaner()
        :
          depth_(0),
          window_size_(0),
          method_(DEPTH_CLEANER_NIL),
          depth_cleaner_impl_(0)
    {
    }

    /** Constructor
242
     * @param depth the depth of the normals (only CV_32F or CV_64F)
Vincent Rabaud's avatar
Vincent Rabaud committed
243 244 245
     * @param window_size the window size to compute the normals: can only be 1,3,5 or 7
     * @param method one of the methods to use: RGBD_NORMALS_METHOD_SRI, RGBD_NORMALS_METHOD_FALS
     */
246
    DepthCleaner(int depth, int window_size = 5, int method = DepthCleaner::DEPTH_CLEANER_NIL);
Vincent Rabaud's avatar
Vincent Rabaud committed
247 248 249

    ~DepthCleaner();

250 251
    CV_WRAP static Ptr<DepthCleaner> create(int depth, int window_size = 5, int method = DepthCleaner::DEPTH_CLEANER_NIL);

Vincent Rabaud's avatar
Vincent Rabaud committed
252 253 254 255 256 257 258 259 260 261
    /** Given a set of 3d points in a depth image, compute the normals at each point.
     * @param points a rows x cols x 3 matrix of CV_32F/CV64F or a rows x cols x 1 CV_U16S
     * @param depth a rows x cols matrix of the cleaned up depth
     */
    void
    operator()(InputArray points, OutputArray depth) const;

    /** Initializes some data that is cached for later computation
     * If that function is not called, it will be called the first time normals are computed
     */
262
    CV_WRAP void
Vincent Rabaud's avatar
Vincent Rabaud committed
263 264
    initialize() const;

265
    CV_WRAP int getWindowSize() const
266 267 268
    {
        return window_size_;
    }
269
    CV_WRAP void setWindowSize(int val)
270 271 272
    {
        window_size_ = val;
    }
273
    CV_WRAP int getDepth() const
274 275 276
    {
        return depth_;
    }
277
    CV_WRAP void setDepth(int val)
278 279 280
    {
        depth_ = val;
    }
281
    CV_WRAP int getMethod() const
282 283 284
    {
        return method_;
    }
285
    CV_WRAP void setMethod(int val)
286 287 288
    {
        method_ = val;
    }
289

Vincent Rabaud's avatar
Vincent Rabaud committed
290 291 292 293 294 295 296 297 298 299
  protected:
    void
    initialize_cleaner_impl() const;

    int depth_;
    int window_size_;
    int method_;
    mutable void* depth_cleaner_impl_;
  };

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318

  /** Registers depth data to an external camera
   * Registration is performed by creating a depth cloud, transforming the cloud by
   * the rigid body transformation between the cameras, and then projecting the
   * transformed points into the RGB camera.
   *
   * uv_rgb = K_rgb * [R | t] * z * inv(K_ir) * uv_ir
   *
   * Currently does not check for negative depth values.
   *
   * @param unregisteredCameraMatrix the camera matrix of the depth camera
   * @param registeredCameraMatrix the camera matrix of the external camera
   * @param registeredDistCoeffs the distortion coefficients of the external camera
   * @param Rt the rigid body transform between the cameras. Transforms points from depth camera frame to external camera frame.
   * @param unregisteredDepth the input depth data
   * @param outputImagePlaneSize the image plane dimensions of the external camera (width, height)
   * @param registeredDepth the result of transforming the depth into the external camera
   * @param depthDilation whether or not the depth is dilated to avoid holes and occlusion errors (optional)
   */
319
  CV_EXPORTS_W
320 321 322 323 324
  void
  registerDepth(InputArray unregisteredCameraMatrix, InputArray registeredCameraMatrix, InputArray registeredDistCoeffs,
                InputArray Rt, InputArray unregisteredDepth, const Size& outputImagePlaneSize,
                OutputArray registeredDepth, bool depthDilation=false);

Vincent Rabaud's avatar
Vincent Rabaud committed
325 326
  /**
   * @param depth the depth image
327
   * @param in_K
Vincent Rabaud's avatar
Vincent Rabaud committed
328 329 330
   * @param in_points the list of xy coordinates
   * @param points3d the resulting 3d points
   */
331
  CV_EXPORTS_W
Vincent Rabaud's avatar
Vincent Rabaud committed
332 333 334 335 336 337 338 339 340 341 342 343
  void
  depthTo3dSparse(InputArray depth, InputArray in_K, InputArray in_points, OutputArray points3d);

  /** Converts a depth image to an organized set of 3d points.
   * 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. 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 mask the mask of the points to consider (can be empty)
   */
344
  CV_EXPORTS_W
Vincent Rabaud's avatar
Vincent Rabaud committed
345 346 347 348 349 350 351 352
  void
  depthTo3d(InputArray depth, InputArray K, OutputArray points3d, InputArray mask = noArray());

  /** If the input image is of type CV_16UC1 (like the Kinect one), the image is converted to floats, divided
   * by 1000 to get a depth in meters, and the values 0 are converted to std::numeric_limits<float>::quiet_NaN()
   * Otherwise, the image is simply converted to floats
   * @param in 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), it is assumed in meters)
353
   * @param depth the desired output depth (floats or double)
Vincent Rabaud's avatar
Vincent Rabaud committed
354 355
   * @param out The rescaled float depth image
   */
356
  CV_EXPORTS_W
Vincent Rabaud's avatar
Vincent Rabaud committed
357 358 359 360 361
  void
  rescaleDepth(InputArray in, int depth, OutputArray out);

  /** Object that can compute planes in an image
   */
362
  class CV_EXPORTS_W RgbdPlane: public Algorithm
Vincent Rabaud's avatar
Vincent Rabaud committed
363 364 365 366 367 368 369
  {
  public:
    enum RGBD_PLANE_METHOD
    {
      RGBD_PLANE_METHOD_DEFAULT
    };

370
      RgbdPlane(int method = RgbdPlane::RGBD_PLANE_METHOD_DEFAULT)
Vincent Rabaud's avatar
Vincent Rabaud committed
371 372 373 374 375 376 377 378 379 380 381 382 383
        :
          method_(method),
          block_size_(40),
          min_size_(block_size_*block_size_),
          threshold_(0.01),
          sensor_error_a_(0),
          sensor_error_b_(0),
          sensor_error_c_(0)
    {
    }

    /** Find The planes in a depth image
     * @param points3d the 3d points organized like the depth image: rows x cols with 3 channels
384
     * @param normals the normals for every point in the depth image
Vincent Rabaud's avatar
Vincent Rabaud committed
385 386
     * @param mask An image where each pixel is labeled with the plane it belongs to
     *        and 255 if it does not belong to any plane
387
     * @param plane_coefficients the coefficients of the corresponding planes (a,b,c,d) such that ax+by+cz+d=0, norm(a,b,c)=1
Vincent Rabaud's avatar
Vincent Rabaud committed
388 389 390 391 392 393 394 395 396 397
     *        and c < 0 (so that the normal points towards the camera)
     */
    void
    operator()(InputArray points3d, InputArray normals, OutputArray mask,
               OutputArray plane_coefficients);

    /** Find The planes in a depth image but without doing a normal check, which is faster but less accurate
     * @param points3d the 3d points organized like the depth image: rows x cols with 3 channels
     * @param mask An image where each pixel is labeled with the plane it belongs to
     *        and 255 if it does not belong to any plane
398
     * @param plane_coefficients the coefficients of the corresponding planes (a,b,c,d) such that ax+by+cz+d=0
Vincent Rabaud's avatar
Vincent Rabaud committed
399 400 401 402
     */
    void
    operator()(InputArray points3d, OutputArray mask, OutputArray plane_coefficients);

403
    CV_WRAP int getBlockSize() const
404 405 406
    {
        return block_size_;
    }
407
    CV_WRAP void setBlockSize(int val)
408 409 410
    {
        block_size_ = val;
    }
411
    CV_WRAP int getMinSize() const
412 413 414
    {
        return min_size_;
    }
415
    CV_WRAP void setMinSize(int val)
416 417 418
    {
        min_size_ = val;
    }
419
    CV_WRAP int getMethod() const
420 421 422
    {
        return method_;
    }
423
    CV_WRAP void setMethod(int val)
424 425 426
    {
        method_ = val;
    }
427
    CV_WRAP double getThreshold() const
428 429 430
    {
        return threshold_;
    }
431
    CV_WRAP void setThreshold(double val)
432 433 434
    {
        threshold_ = val;
    }
435
    CV_WRAP double getSensorErrorA() const
436 437 438
    {
        return sensor_error_a_;
    }
439
    CV_WRAP void setSensorErrorA(double val)
440 441 442
    {
        sensor_error_a_ = val;
    }
443
    CV_WRAP double getSensorErrorB() const
444 445 446
    {
        return sensor_error_b_;
    }
447
    CV_WRAP void setSensorErrorB(double val)
448 449 450
    {
        sensor_error_b_ = val;
    }
451
    CV_WRAP double getSensorErrorC() const
452 453 454
    {
        return sensor_error_c_;
    }
455
    CV_WRAP void setSensorErrorC(double val)
456 457 458
    {
        sensor_error_c_ = val;
    }
459

Vincent Rabaud's avatar
Vincent Rabaud committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
  private:
    /** The method to use to compute the planes */
    int method_;
    /** The size of the blocks to look at for a stable MSE */
    int block_size_;
    /** The minimum size of a cluster to be considered a plane */
    int min_size_;
    /** How far a point can be from a plane to belong to it (in meters) */
    double threshold_;
    /** coefficient of the sensor error with respect to the. All 0 by default but you want a=0.0075 for a Kinect */
    double sensor_error_a_, sensor_error_b_, sensor_error_c_;
  };

  /** Object that contains a frame data.
   */
475
  struct CV_EXPORTS_W RgbdFrame
Vincent Rabaud's avatar
Vincent Rabaud committed
476 477 478 479 480
  {
      RgbdFrame();
      RgbdFrame(const Mat& image, const Mat& depth, const Mat& mask=Mat(), const Mat& normals=Mat(), int ID=-1);
      virtual ~RgbdFrame();

481 482 483
      CV_WRAP static Ptr<RgbdFrame> create(const Mat& image=Mat(), const Mat& depth=Mat(), const Mat& mask=Mat(), const Mat& normals=Mat(), int ID=-1);

      CV_WRAP virtual void
Vincent Rabaud's avatar
Vincent Rabaud committed
484 485
      release();

486 487 488 489 490
      CV_PROP int ID;
      CV_PROP Mat image;
      CV_PROP Mat depth;
      CV_PROP Mat mask;
      CV_PROP Mat normals;
Vincent Rabaud's avatar
Vincent Rabaud committed
491 492 493 494 495 496
  };

  /** Object that contains a frame data that is possibly needed for the Odometry.
   * It's used for the efficiency (to pass precomputed/cached data of the frame that participates
   * in the Odometry processing several times).
   */
497
  struct CV_EXPORTS_W OdometryFrame : public RgbdFrame
Vincent Rabaud's avatar
Vincent Rabaud committed
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
  {
    /** These constants are used to set a type of cache which has to be prepared depending on the frame role:
     * srcFrame or dstFrame (see compute method of the Odometry class). For the srcFrame and dstFrame different cache data may be required,
     * some part of a cache may be common for both frame roles.
     * @param CACHE_SRC The cache data for the srcFrame will be prepared.
     * @param CACHE_DST The cache data for the dstFrame will be prepared.
     * @param CACHE_ALL The cache data for both srcFrame and dstFrame roles will be computed.
     */
    enum
    {
      CACHE_SRC = 1, CACHE_DST = 2, CACHE_ALL = CACHE_SRC + CACHE_DST
    };

    OdometryFrame();
    OdometryFrame(const Mat& image, const Mat& depth, const Mat& mask=Mat(), const Mat& normals=Mat(), int ID=-1);

514 515 516
    CV_WRAP static Ptr<OdometryFrame> create(const Mat& image=Mat(), const Mat& depth=Mat(), const Mat& mask=Mat(), const Mat& normals=Mat(), int ID=-1);

    CV_WRAP virtual void
Vincent Rabaud's avatar
Vincent Rabaud committed
517 518
    release();

519
    CV_WRAP void
Vincent Rabaud's avatar
Vincent Rabaud committed
520 521
    releasePyramids();

522 523 524
    CV_PROP std::vector<Mat> pyramidImage;
    CV_PROP std::vector<Mat> pyramidDepth;
    CV_PROP std::vector<Mat> pyramidMask;
Vincent Rabaud's avatar
Vincent Rabaud committed
525

526
    CV_PROP std::vector<Mat> pyramidCloud;
Vincent Rabaud's avatar
Vincent Rabaud committed
527

528 529 530
    CV_PROP std::vector<Mat> pyramid_dI_dx;
    CV_PROP std::vector<Mat> pyramid_dI_dy;
    CV_PROP std::vector<Mat> pyramidTexturedMask;
Vincent Rabaud's avatar
Vincent Rabaud committed
531

532 533
    CV_PROP std::vector<Mat> pyramidNormals;
    CV_PROP std::vector<Mat> pyramidNormalsMask;
Vincent Rabaud's avatar
Vincent Rabaud committed
534 535 536 537
  };

  /** Base class for computation of odometry.
   */
538
  class CV_EXPORTS_W Odometry: public Algorithm
Vincent Rabaud's avatar
Vincent Rabaud committed
539 540 541 542 543 544 545 546 547
  {
  public:

    /** A class of transformation*/
    enum
    {
      ROTATION = 1, TRANSLATION = 2, RIGID_BODY_MOTION = 4
    };

548
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
549 550 551 552
    DEFAULT_MIN_DEPTH()
    {
      return 0.f; // in meters
    }
553
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
554 555 556 557
    DEFAULT_MAX_DEPTH()
    {
      return 4.f; // in meters
    }
558
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
559 560 561 562
    DEFAULT_MAX_DEPTH_DIFF()
    {
      return 0.07f; // in meters
    }
563
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
564 565 566 567
    DEFAULT_MAX_POINTS_PART()
    {
      return 0.07f; // in [0, 1]
    }
568
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
569 570 571 572
    DEFAULT_MAX_TRANSLATION()
    {
      return 0.15f; // in meters
    }
573
    CV_WRAP static inline float
Vincent Rabaud's avatar
Vincent Rabaud committed
574 575 576 577 578 579 580
    DEFAULT_MAX_ROTATION()
    {
      return 15; // in degrees
    }

    /** Method to compute a transformation from the source frame to the destination one.
     * Some odometry algorithms do not used some data of frames (eg. ICP does not use images).
581
     * In such case corresponding arguments can be set as empty Mat.
582
     * The method returns true if all internal computions were possible (e.g. there were enough correspondences,
Vincent Rabaud's avatar
Vincent Rabaud committed
583 584 585 586 587 588 589 590 591 592 593 594 595 596
     * system of equations has a solution, etc) and resulting transformation satisfies some test if it's provided
     * by the Odometry inheritor implementation (e.g. thresholds for maximum translation and rotation).
     * @param srcImage Image data of the source frame (CV_8UC1)
     * @param srcDepth Depth data of the source frame (CV_32FC1, in meters)
     * @param srcMask Mask that sets which pixels have to be used from the source frame (CV_8UC1)
     * @param dstImage Image data of the destination frame (CV_8UC1)
     * @param dstDepth Depth data of the destination frame (CV_32FC1, in meters)
     * @param dstMask Mask that sets which pixels have to be used from the destination frame (CV_8UC1)
     * @param Rt Resulting transformation from the source frame to the destination one (rigid body motion):
     dst_p = Rt * src_p, where dst_p is a homogeneous point in the destination frame and src_p is
     homogeneous point in the source frame,
     Rt is 4x4 matrix of CV_64FC1 type.
     * @param initRt Initial transformation from the source frame to the destination one (optional)
     */
597
    CV_WRAP bool
Vincent Rabaud's avatar
Vincent Rabaud committed
598
    compute(const Mat& srcImage, const Mat& srcDepth, const Mat& srcMask, const Mat& dstImage, const Mat& dstDepth,
599
            const Mat& dstMask, OutputArray Rt, const Mat& initRt = Mat()) const;
Vincent Rabaud's avatar
Vincent Rabaud committed
600 601 602 603

    /** One more method to compute a transformation from the source frame to the destination one.
     * It is designed to save on computing the frame data (image pyramids, normals, etc.).
     */
604 605
    CV_WRAP_AS(compute2) bool
    compute(Ptr<OdometryFrame>& srcFrame, Ptr<OdometryFrame>& dstFrame, OutputArray Rt, const Mat& initRt = Mat()) const;
Vincent Rabaud's avatar
Vincent Rabaud committed
606 607 608 609

    /** Prepare a cache for the frame. The function checks the precomputed/passed data (throws the error if this data
     * does not satisfy) and computes all remaining cache data needed for the frame. Returned size is a resolution
     * of the prepared frame.
610
     * @param frame The odometry which will process the frame.
Vincent Rabaud's avatar
Vincent Rabaud committed
611 612
     * @param cacheType The cache type: CACHE_SRC, CACHE_DST or CACHE_ALL.
     */
613
    CV_WRAP virtual Size prepareFrameCache(Ptr<OdometryFrame>& frame, int cacheType) const;
Vincent Rabaud's avatar
Vincent Rabaud committed
614

615
    CV_WRAP static Ptr<Odometry> create(const String & odometryType);
616

617
    /** @see setCameraMatrix */
618
    CV_WRAP virtual cv::Mat getCameraMatrix() const = 0;
619
    /** @copybrief getCameraMatrix @see getCameraMatrix */
620
    CV_WRAP virtual void setCameraMatrix(const cv::Mat &val) = 0;
621
    /** @see setTransformType */
622
    CV_WRAP virtual int getTransformType() const = 0;
623
    /** @copybrief getTransformType @see getTransformType */
624
    CV_WRAP virtual void setTransformType(int val) = 0;
625

Vincent Rabaud's avatar
Vincent Rabaud committed
626 627 628 629 630
  protected:
    virtual void
    checkParams() const = 0;

    virtual bool
631
    computeImpl(const Ptr<OdometryFrame>& srcFrame, const Ptr<OdometryFrame>& dstFrame, OutputArray Rt,
Vincent Rabaud's avatar
Vincent Rabaud committed
632 633 634
                const Mat& initRt) const = 0;
  };

635
  /** Odometry based on the paper "Real-Time Visual Odometry from Dense RGB-D Images",
Vincent Rabaud's avatar
Vincent Rabaud committed
636 637
   * F. Steinbucker, J. Strum, D. Cremers, ICCV, 2011.
   */
638
  class CV_EXPORTS_W RgbdOdometry: public Odometry
Vincent Rabaud's avatar
Vincent Rabaud committed
639 640 641 642 643 644 645 646 647 648 649 650
  {
  public:
    RgbdOdometry();
    /** Constructor.
     * @param cameraMatrix Camera matrix
     * @param minDepth Pixels with depth less than minDepth will not be used (in meters)
     * @param maxDepth Pixels with depth larger than maxDepth will not be used (in meters)
     * @param maxDepthDiff Correspondences between pixels of two given frames will be filtered out
     *                     if their depth difference is larger than maxDepthDiff (in meters)
     * @param iterCounts Count of iterations on each pyramid level.
     * @param minGradientMagnitudes For each pyramid level the pixels will be filtered out
     *                              if they have gradient magnitude less than minGradientMagnitudes[level].
651 652
     * @param maxPointsPart The method uses a random pixels subset of size frameWidth x frameHeight x pointsPart
     * @param transformType Class of transformation
Vincent Rabaud's avatar
Vincent Rabaud committed
653
     */
654 655 656 657 658 659 660 661 662
    RgbdOdometry(const Mat& cameraMatrix, float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                 float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), const std::vector<int>& iterCounts = std::vector<int>(),
                 const std::vector<float>& minGradientMagnitudes = std::vector<float>(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
                 int transformType = Odometry::RIGID_BODY_MOTION);

    CV_WRAP static Ptr<RgbdOdometry> create(const Mat& cameraMatrix = Mat(), float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                 float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), const std::vector<int>& iterCounts = std::vector<int>(),
                 const std::vector<float>& minGradientMagnitudes = std::vector<float>(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
                 int transformType = Odometry::RIGID_BODY_MOTION);
Vincent Rabaud's avatar
Vincent Rabaud committed
663

664
    CV_WRAP virtual Size prepareFrameCache(Ptr<OdometryFrame>& frame, int cacheType) const;
Vincent Rabaud's avatar
Vincent Rabaud committed
665

666
    CV_WRAP cv::Mat getCameraMatrix() const
667 668 669
    {
        return cameraMatrix;
    }
670
    CV_WRAP void setCameraMatrix(const cv::Mat &val)
671 672 673
    {
        cameraMatrix = val;
    }
674
    CV_WRAP double getMinDepth() const
675 676 677
    {
        return minDepth;
    }
678
    CV_WRAP void setMinDepth(double val)
679 680 681
    {
        minDepth = val;
    }
682
    CV_WRAP double getMaxDepth() const
683 684 685
    {
        return maxDepth;
    }
686
    CV_WRAP void setMaxDepth(double val)
687 688 689
    {
        maxDepth = val;
    }
690
    CV_WRAP double getMaxDepthDiff() const
691 692 693
    {
        return maxDepthDiff;
    }
694
    CV_WRAP void setMaxDepthDiff(double val)
695 696 697
    {
        maxDepthDiff = val;
    }
698
    CV_WRAP cv::Mat getIterationCounts() const
699 700 701
    {
        return iterCounts;
    }
702
    CV_WRAP void setIterationCounts(const cv::Mat &val)
703 704 705
    {
        iterCounts = val;
    }
706
    CV_WRAP cv::Mat getMinGradientMagnitudes() const
707 708 709
    {
        return minGradientMagnitudes;
    }
710
    CV_WRAP void setMinGradientMagnitudes(const cv::Mat &val)
711 712 713
    {
        minGradientMagnitudes = val;
    }
714
    CV_WRAP double getMaxPointsPart() const
715 716 717
    {
        return maxPointsPart;
    }
718
    CV_WRAP void setMaxPointsPart(double val)
719 720 721
    {
        maxPointsPart = val;
    }
722
    CV_WRAP int getTransformType() const
723 724 725
    {
        return transformType;
    }
726
    CV_WRAP void setTransformType(int val)
727 728 729
    {
        transformType = val;
    }
730
    CV_WRAP double getMaxTranslation() const
731 732 733
    {
        return maxTranslation;
    }
734
    CV_WRAP void setMaxTranslation(double val)
735 736 737
    {
        maxTranslation = val;
    }
738
    CV_WRAP double getMaxRotation() const
739 740 741
    {
        return maxRotation;
    }
742
    CV_WRAP void setMaxRotation(double val)
743 744 745
    {
        maxRotation = val;
    }
Vincent Rabaud's avatar
Vincent Rabaud committed
746 747 748 749 750 751

  protected:
    virtual void
    checkParams() const;

    virtual bool
752
    computeImpl(const Ptr<OdometryFrame>& srcFrame, const Ptr<OdometryFrame>& dstFrame, OutputArray Rt,
Vincent Rabaud's avatar
Vincent Rabaud committed
753 754
                const Mat& initRt) const;

755
    // Some params have commented desired type. It's due to AlgorithmInfo::addParams does not support it now.
Vincent Rabaud's avatar
Vincent Rabaud committed
756 757 758 759 760 761 762 763 764 765 766 767 768 769
    /*float*/
    double minDepth, maxDepth, maxDepthDiff;
    /*vector<int>*/
    Mat iterCounts;
    /*vector<float>*/
    Mat minGradientMagnitudes;
    double maxPointsPart;

    Mat cameraMatrix;
    int transformType;

    double maxTranslation, maxRotation;
  };

770
  /** Odometry based on the paper "KinectFusion: Real-Time Dense Surface Mapping and Tracking",
Vincent Rabaud's avatar
Vincent Rabaud committed
771 772
   * Richard A. Newcombe, Andrew Fitzgibbon, at al, SIGGRAPH, 2011.
   */
773
  class CV_EXPORTS_W ICPOdometry: public Odometry
Vincent Rabaud's avatar
Vincent Rabaud committed
774 775 776 777 778 779 780 781 782
  {
  public:
    ICPOdometry();
    /** Constructor.
     * @param cameraMatrix Camera matrix
     * @param minDepth Pixels with depth less than minDepth will not be used
     * @param maxDepth Pixels with depth larger than maxDepth will not be used
     * @param maxDepthDiff Correspondences between pixels of two given frames will be filtered out
     *                     if their depth difference is larger than maxDepthDiff
783
     * @param maxPointsPart The method uses a random pixels subset of size frameWidth x frameHeight x pointsPart
Vincent Rabaud's avatar
Vincent Rabaud committed
784
     * @param iterCounts Count of iterations on each pyramid level.
785
     * @param transformType Class of trasformation
Vincent Rabaud's avatar
Vincent Rabaud committed
786
     */
787 788 789
    ICPOdometry(const Mat& cameraMatrix, float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
                const std::vector<int>& iterCounts = std::vector<int>(), int transformType = Odometry::RIGID_BODY_MOTION);
Vincent Rabaud's avatar
Vincent Rabaud committed
790

791 792 793
    CV_WRAP static Ptr<ICPOdometry> create(const Mat& cameraMatrix = Mat(), float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
                const std::vector<int>& iterCounts = std::vector<int>(), int transformType = Odometry::RIGID_BODY_MOTION);
Vincent Rabaud's avatar
Vincent Rabaud committed
794

795 796 797
    CV_WRAP virtual Size prepareFrameCache(Ptr<OdometryFrame>& frame, int cacheType) const;

    CV_WRAP cv::Mat getCameraMatrix() const
798 799 800
    {
        return cameraMatrix;
    }
801
    CV_WRAP void setCameraMatrix(const cv::Mat &val)
802 803 804
    {
        cameraMatrix = val;
    }
805
    CV_WRAP double getMinDepth() const
806 807 808
    {
        return minDepth;
    }
809
    CV_WRAP void setMinDepth(double val)
810 811 812
    {
        minDepth = val;
    }
813
    CV_WRAP double getMaxDepth() const
814 815 816
    {
        return maxDepth;
    }
817
    CV_WRAP void setMaxDepth(double val)
818 819 820
    {
        maxDepth = val;
    }
821
    CV_WRAP double getMaxDepthDiff() const
822 823 824
    {
        return maxDepthDiff;
    }
825
    CV_WRAP void setMaxDepthDiff(double val)
826 827 828
    {
        maxDepthDiff = val;
    }
829
    CV_WRAP cv::Mat getIterationCounts() const
830 831 832
    {
        return iterCounts;
    }
833
    CV_WRAP void setIterationCounts(const cv::Mat &val)
834 835 836
    {
        iterCounts = val;
    }
837
    CV_WRAP double getMaxPointsPart() const
838 839 840
    {
        return maxPointsPart;
    }
841
    CV_WRAP void setMaxPointsPart(double val)
842 843 844
    {
        maxPointsPart = val;
    }
845
    CV_WRAP int getTransformType() const
846 847 848
    {
        return transformType;
    }
849
    CV_WRAP void setTransformType(int val)
850 851 852
    {
        transformType = val;
    }
853
    CV_WRAP double getMaxTranslation() const
854 855 856
    {
        return maxTranslation;
    }
857
    CV_WRAP void setMaxTranslation(double val)
858 859 860
    {
        maxTranslation = val;
    }
861
    CV_WRAP double getMaxRotation() const
862 863 864
    {
        return maxRotation;
    }
865
    CV_WRAP void setMaxRotation(double val)
866 867 868
    {
        maxRotation = val;
    }
869
    CV_WRAP Ptr<RgbdNormals> getNormalsComputer() const
870 871 872
    {
        return normalsComputer;
    }
Vincent Rabaud's avatar
Vincent Rabaud committed
873 874 875 876 877 878

  protected:
    virtual void
    checkParams() const;

    virtual bool
879
    computeImpl(const Ptr<OdometryFrame>& srcFrame, const Ptr<OdometryFrame>& dstFrame, OutputArray Rt,
Vincent Rabaud's avatar
Vincent Rabaud committed
880 881
                const Mat& initRt) const;

882
    // Some params have commented desired type. It's due to AlgorithmInfo::addParams does not support it now.
Vincent Rabaud's avatar
Vincent Rabaud committed
883 884 885 886 887 888 889 890 891 892 893 894
    /*float*/
    double minDepth, maxDepth, maxDepthDiff;
    /*float*/
    double maxPointsPart;
    /*vector<int>*/
    Mat iterCounts;

    Mat cameraMatrix;
    int transformType;

    double maxTranslation, maxRotation;

895
    mutable Ptr<RgbdNormals> normalsComputer;
Vincent Rabaud's avatar
Vincent Rabaud committed
896 897 898 899 900
  };

  /** Odometry that merges RgbdOdometry and ICPOdometry by minimize sum of their energy functions.
   */

901
  class CV_EXPORTS_W RgbdICPOdometry: public Odometry
Vincent Rabaud's avatar
Vincent Rabaud committed
902 903 904 905 906 907 908 909 910
  {
  public:
    RgbdICPOdometry();
    /** Constructor.
     * @param cameraMatrix Camera matrix
     * @param minDepth Pixels with depth less than minDepth will not be used
     * @param maxDepth Pixels with depth larger than maxDepth will not be used
     * @param maxDepthDiff Correspondences between pixels of two given frames will be filtered out
     *                     if their depth difference is larger than maxDepthDiff
911
     * @param maxPointsPart The method uses a random pixels subset of size frameWidth x frameHeight x pointsPart
Vincent Rabaud's avatar
Vincent Rabaud committed
912 913 914
     * @param iterCounts Count of iterations on each pyramid level.
     * @param minGradientMagnitudes For each pyramid level the pixels will be filtered out
     *                              if they have gradient magnitude less than minGradientMagnitudes[level].
915
     * @param transformType Class of trasformation
Vincent Rabaud's avatar
Vincent Rabaud committed
916
     */
917 918 919 920 921 922 923 924
    RgbdICPOdometry(const Mat& cameraMatrix, float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                    float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
                    const std::vector<int>& iterCounts = std::vector<int>(),
                    const std::vector<float>& minGradientMagnitudes = std::vector<float>(),
                    int transformType = Odometry::RIGID_BODY_MOTION);

    CV_WRAP static Ptr<RgbdICPOdometry> create(const Mat& cameraMatrix = Mat(), float minDepth = Odometry::DEFAULT_MIN_DEPTH(), float maxDepth = Odometry::DEFAULT_MAX_DEPTH(),
                    float maxDepthDiff = Odometry::DEFAULT_MAX_DEPTH_DIFF(), float maxPointsPart = Odometry::DEFAULT_MAX_POINTS_PART(),
Vincent Rabaud's avatar
Vincent Rabaud committed
925 926
                    const std::vector<int>& iterCounts = std::vector<int>(),
                    const std::vector<float>& minGradientMagnitudes = std::vector<float>(),
927
                    int transformType = Odometry::RIGID_BODY_MOTION);
Vincent Rabaud's avatar
Vincent Rabaud committed
928

929
    CV_WRAP virtual Size prepareFrameCache(Ptr<OdometryFrame>& frame, int cacheType) const;
Vincent Rabaud's avatar
Vincent Rabaud committed
930

931
    CV_WRAP cv::Mat getCameraMatrix() const
932 933 934
    {
        return cameraMatrix;
    }
935
    CV_WRAP void setCameraMatrix(const cv::Mat &val)
936 937 938
    {
        cameraMatrix = val;
    }
939
    CV_WRAP double getMinDepth() const
940 941 942
    {
        return minDepth;
    }
943
    CV_WRAP void setMinDepth(double val)
944 945 946
    {
        minDepth = val;
    }
947
    CV_WRAP double getMaxDepth() const
948 949 950
    {
        return maxDepth;
    }
951
    CV_WRAP void setMaxDepth(double val)
952 953 954
    {
        maxDepth = val;
    }
955
    CV_WRAP double getMaxDepthDiff() const
956 957 958
    {
        return maxDepthDiff;
    }
959
    CV_WRAP void setMaxDepthDiff(double val)
960 961 962
    {
        maxDepthDiff = val;
    }
963
    CV_WRAP double getMaxPointsPart() const
964 965 966
    {
        return maxPointsPart;
    }
967
    CV_WRAP void setMaxPointsPart(double val)
968 969 970
    {
        maxPointsPart = val;
    }
971
    CV_WRAP cv::Mat getIterationCounts() const
972 973 974
    {
        return iterCounts;
    }
975
    CV_WRAP void setIterationCounts(const cv::Mat &val)
976 977 978
    {
        iterCounts = val;
    }
979
    CV_WRAP cv::Mat getMinGradientMagnitudes() const
980 981 982
    {
        return minGradientMagnitudes;
    }
983
    CV_WRAP void setMinGradientMagnitudes(const cv::Mat &val)
984 985 986
    {
        minGradientMagnitudes = val;
    }
987
    CV_WRAP int getTransformType() const
988 989 990
    {
        return transformType;
    }
991
    CV_WRAP void setTransformType(int val)
992 993 994
    {
        transformType = val;
    }
995
    CV_WRAP double getMaxTranslation() const
996 997 998
    {
        return maxTranslation;
    }
999
    CV_WRAP void setMaxTranslation(double val)
1000 1001 1002
    {
        maxTranslation = val;
    }
1003
    CV_WRAP double getMaxRotation() const
1004 1005 1006
    {
        return maxRotation;
    }
1007
    CV_WRAP void setMaxRotation(double val)
1008 1009 1010
    {
        maxRotation = val;
    }
1011
    CV_WRAP Ptr<RgbdNormals> getNormalsComputer() const
1012 1013 1014
    {
        return normalsComputer;
    }
Vincent Rabaud's avatar
Vincent Rabaud committed
1015 1016 1017 1018 1019 1020

  protected:
    virtual void
    checkParams() const;

    virtual bool
1021
    computeImpl(const Ptr<OdometryFrame>& srcFrame, const Ptr<OdometryFrame>& dstFrame, OutputArray Rt,
Vincent Rabaud's avatar
Vincent Rabaud committed
1022 1023
                const Mat& initRt) const;

1024
    // Some params have commented desired type. It's due to AlgorithmInfo::addParams does not support it now.
Vincent Rabaud's avatar
Vincent Rabaud committed
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
    /*float*/
    double minDepth, maxDepth, maxDepthDiff;
    /*float*/
    double maxPointsPart;
    /*vector<int>*/
    Mat iterCounts;
    /*vector<float>*/
    Mat minGradientMagnitudes;

    Mat cameraMatrix;
    int transformType;

    double maxTranslation, maxRotation;

1039
    mutable Ptr<RgbdNormals> normalsComputer;
Vincent Rabaud's avatar
Vincent Rabaud committed
1040 1041
  };

1042 1043
  /** Warp the image: compute 3d points from the depth, transform them using given transformation,
   * then project color point cloud to an image plane.
Vincent Rabaud's avatar
Vincent Rabaud committed
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
   * This function can be used to visualize results of the Odometry algorithm.
   * @param image The image (of CV_8UC1 or CV_8UC3 type)
   * @param depth The depth (of type used in depthTo3d fuction)
   * @param mask The mask of used pixels (of CV_8UC1), it can be empty
   * @param Rt The transformation that will be applied to the 3d points computed from the depth
   * @param cameraMatrix Camera matrix
   * @param distCoeff Distortion coefficients
   * @param warpedImage The warped image.
   * @param warpedDepth The warped depth.
   * @param warpedMask The warped mask.
   */
1055
  CV_EXPORTS_W
Vincent Rabaud's avatar
Vincent Rabaud committed
1056 1057
  void
  warpFrame(const Mat& image, const Mat& depth, const Mat& mask, const Mat& Rt, const Mat& cameraMatrix,
1058
            const Mat& distCoeff, OutputArray warpedImage, OutputArray warpedDepth = noArray(), OutputArray warpedMask = noArray());
Vincent Rabaud's avatar
Vincent Rabaud committed
1059 1060 1061 1062

// TODO Depth interpolation
// Curvature
// Get rescaleDepth return dubles if asked for
1063 1064 1065

//! @}

1066
} /* namespace rgbd */
Vincent Rabaud's avatar
Vincent Rabaud committed
1067 1068
} /* namespace cv */

1069
#include "opencv2/rgbd/linemod.hpp"
Vincent Rabaud's avatar
Vincent Rabaud committed
1070

1071
#endif /* __cplusplus */
Vincent Rabaud's avatar
Vincent Rabaud committed
1072 1073 1074
#endif

/* End of file. */
1075