From 2bdd395357eb5b3491b0d0b2b9879390915cef68 Mon Sep 17 00:00:00 2001 From: Alexey Spizhevoy Date: Wed, 18 Jan 2012 13:43:34 +0000 Subject: [PATCH] Added the first version of the stitching module docs --- modules/refman.rst | 2 + modules/stitching/doc/high_level.rst | 145 ++++++++++++++++ modules/stitching/doc/matching.rst | 151 +++++++++++++++++ modules/stitching/doc/motion_estimation.rst | 174 ++++++++++++++++++++ modules/stitching/doc/stitching.rst | 12 ++ 5 files changed, 484 insertions(+) create mode 100644 modules/stitching/doc/high_level.rst create mode 100644 modules/stitching/doc/matching.rst create mode 100644 modules/stitching/doc/motion_estimation.rst create mode 100644 modules/stitching/doc/stitching.rst diff --git a/modules/refman.rst b/modules/refman.rst index 5dc0c13c42..394f616f78 100644 --- a/modules/refman.rst +++ b/modules/refman.rst @@ -16,3 +16,5 @@ OpenCV API Reference ml/doc/ml.rst flann/doc/flann.rst gpu/doc/gpu.rst + stitching/doc/stitching.rst + diff --git a/modules/stitching/doc/high_level.rst b/modules/stitching/doc/high_level.rst new file mode 100644 index 0000000000..6800eea629 --- /dev/null +++ b/modules/stitching/doc/high_level.rst @@ -0,0 +1,145 @@ +High Level Functionality +======================== + +.. highlight:: cpp + +Stitcher +-------- +.. ocv:class:: Stitcher + +High level image stitcher. It's possible to use this class without being aware of the entire stitching pipeline. However, to be able to achieve higher stitching stability and quality of the final images at least being familiar with the theory is recommended. :: + + class CV_EXPORTS Stitcher + { + public: + enum { ORIG_RESOL = -1 }; + enum Status { OK, ERR_NEED_MORE_IMGS }; + + // Creates stitcher with default parameters + static Stitcher createDefault(bool try_use_gpu = false); + + Status estimateTransform(InputArray images); + Status estimateTransform(InputArray images, const std::vector > &rois); + + Status composePanorama(OutputArray pano); + Status composePanorama(InputArray images, OutputArray pano); + + Status stitch(InputArray images, OutputArray pano); + Status stitch(InputArray images, const std::vector > &rois, OutputArray pano); + + double registrationResol() const { return registr_resol_; } + void setRegistrationResol(double resol_mpx) { registr_resol_ = resol_mpx; } + + double seamEstimationResol() const { return seam_est_resol_; } + void setSeamEstimationResol(double resol_mpx) { seam_est_resol_ = resol_mpx; } + + double compositingResol() const { return compose_resol_; } + void setCompositingResol(double resol_mpx) { compose_resol_ = resol_mpx; } + + double panoConfidenceThresh() const { return conf_thresh_; } + void setPanoConfidenceThresh(double conf_thresh) { conf_thresh_ = conf_thresh; } + + bool waveCorrection() const { return do_wave_correct_; } + void setWaveCorrection(bool flag) { do_wave_correct_ = flag; } + + detail::WaveCorrectKind waveCorrectKind() const { return wave_correct_kind_; } + void setWaveCorrectKind(detail::WaveCorrectKind kind) { wave_correct_kind_ = kind; } + + Ptr featuresFinder() { return features_finder_; } + const Ptr featuresFinder() const { return features_finder_; } + void setFeaturesFinder(Ptr features_finder) + { features_finder_ = features_finder; } + + Ptr featuresMatcher() { return features_matcher_; } + const Ptr featuresMatcher() const { return features_matcher_; } + void setFeaturesMatcher(Ptr features_matcher) + { features_matcher_ = features_matcher; } + + const cv::Mat& matchingMask() const { return matching_mask_; } + void setMatchingMask(const cv::Mat &mask) + { + CV_Assert(mask.type() == CV_8U && mask.cols == mask.rows); + matching_mask_ = mask.clone(); + } + + Ptr bundleAdjuster() { return bundle_adjuster_; } + const Ptr bundleAdjuster() const { return bundle_adjuster_; } + void setBundleAdjuster(Ptr bundle_adjuster) + { bundle_adjuster_ = bundle_adjuster; } + + Ptr warper() { return warper_; } + const Ptr warper() const { return warper_; } + void setWarper(Ptr warper) { warper_ = warper; } + + Ptr exposureCompensator() { return exposure_comp_; } + const Ptr exposureCompensator() const { return exposure_comp_; } + void setExposureCompensator(Ptr exposure_comp) + { exposure_comp_ = exposure_comp; } + + Ptr seamFinder() { return seam_finder_; } + const Ptr seamFinder() const { return seam_finder_; } + void setSeamFinder(Ptr seam_finder) { seam_finder_ = seam_finder; } + + Ptr blender() { return blender_; } + const Ptr blender() const { return blender_; } + void setBlender(Ptr blender) { blender_ = blender; } + + private: + /* hidden */ + }; + +WarperCreator +------------- +.. ocv:class:: WarperCreator + +Image warper factories base class. :: + + class WarperCreator + { + public: + virtual ~WarperCreator() {} + virtual Ptr create(float scale) const = 0; + }; + +PlaneWarper +----------- +.. ocv:class:: PlaneWarper + +Plane warper factory class. :: + + class PlaneWarper : public WarperCreator + { + public: + Ptr create(float scale) const { return new detail::PlaneWarper(scale); } + }; + +.. seealso:: :ocv:class:`detail::PlaneWarper` + +CylindricalWarper +----------------- +.. ocv:class:: CylindricalWarper + +Cylindrical warper factory class. :: + + class CylindricalWarper: public WarperCreator + { + public: + Ptr create(float scale) const { return new detail::CylindricalWarper(scale); } + }; + +.. seealso:: :ocv:class:`detail::CylindricalWarper` + +SphericalWarper +--------------- +.. ocv:class:: SphericalWarper + +Spherical warper factory class. :: + + class SphericalWarper: public WarperCreator + { + public: + Ptr create(float scale) const { return new detail::SphericalWarper(scale); } + }; + +.. seealso:: :ocv:class:`detail::SphericalWarper` + diff --git a/modules/stitching/doc/matching.rst b/modules/stitching/doc/matching.rst new file mode 100644 index 0000000000..28bf7b8632 --- /dev/null +++ b/modules/stitching/doc/matching.rst @@ -0,0 +1,151 @@ +Features Finding and Images Matching +==================================== + +.. highlight:: cpp + +detail::ImageFeatures +----------------------- +.. ocv:struct:: detail::ImageFeatures + +Structure containing image keypoints and descriptors. :: + + struct CV_EXPORTS ImageFeatures + { + int img_idx; + Size img_size; + std::vector keypoints; + Mat descriptors; + }; + +detail::FeaturesFinder +---------------------- +.. ocv:class:: detail::FeaturesFinder + +Feature finders base class. :: + + class CV_EXPORTS FeaturesFinder + { + public: + virtual ~FeaturesFinder() {} + void operator ()(const Mat &image, ImageFeatures &features); + void operator ()(const Mat &image, ImageFeatures &features, const std::vector &rois); + virtual void collectGarbage() {} + + protected: + virtual void find(const Mat &image, ImageFeatures &features) = 0; + }; + +detail::SurfFeaturesFinder +-------------------------- +.. ocv:class:: detail::SurfFeaturesFinder + +SURF features finder. :: + + class CV_EXPORTS SurfFeaturesFinder : public FeaturesFinder + { + public: + SurfFeaturesFinder(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4, + int num_octaves_descr = /*4*/3, int num_layers_descr = /*2*/4); + + private: + /* hidden */ + }; + +.. seealso:: + :ocv:class:`detail::FeaturesFinder` + :ocv:class:`SURF` + +detail::OrbFeaturesFinder +------------------------- +.. ocv:class:: detail::OrbFeaturesFinder + +ORB features finder. :: + + class CV_EXPORTS OrbFeaturesFinder : public FeaturesFinder + { + public: + OrbFeaturesFinder(Size _grid_size = Size(3,1), size_t n_features = 1500, + const ORB::CommonParams &detector_params = ORB::CommonParams(1.3f, 5)); + + private: + /* hidden */ + }; + +.. seealso:: + :ocv:class:`detail::FeaturesFinder`, + :ocv:class:`ORB` + +detail::MatchesInfo +------------------- +.. ocv:struct: detail::MatchesInfo + +Structure containing information about matches between two images. It's assumed that there is a homography between those images. :: + + struct CV_EXPORTS MatchesInfo + { + MatchesInfo(); + MatchesInfo(const MatchesInfo &other); + const MatchesInfo& operator =(const MatchesInfo &other); + + int src_img_idx, dst_img_idx; // Images indices (optional) + std::vector matches; + std::vector inliers_mask; // Geometrically consistent matches mask + int num_inliers; // Number of geometrically consistent matches + Mat H; // Estimated homography + double confidence; // Confidence two images are from the same panorama + }; + +detail::FeaturesMatcher +----------------------- +.. ocv:class:: detail::FeaturesMatcher + +Feature matchers base class. :: + + class CV_EXPORTS FeaturesMatcher + { + public: + virtual ~FeaturesMatcher() {} + + void operator ()(const ImageFeatures &features1, const ImageFeatures &features2, + MatchesInfo& matches_info) { match(features1, features2, matches_info); } + + void operator ()(const std::vector &features, std::vector &pairwise_matches, + const cv::Mat &mask = cv::Mat()); + + bool isThreadSafe() const { return is_thread_safe_; } + + virtual void collectGarbage() {} + + protected: + FeaturesMatcher(bool is_thread_safe = false) : is_thread_safe_(is_thread_safe) {} + + virtual void match(const ImageFeatures &features1, const ImageFeatures &features2, + MatchesInfo& matches_info) = 0; + + bool is_thread_safe_; + }; + +detail::BestOf2NearestMatcher +----------------------------- +.. ocv:class:: detail::BestOf2NearestMatcher + +Features matcher which finds two best matches for each feature and leaves the best one only if the ratio between descriptor distances is greater than the threshold ``match_conf``. :: + + class CV_EXPORTS BestOf2NearestMatcher : public FeaturesMatcher + { + public: + BestOf2NearestMatcher(bool try_use_gpu = false, float match_conf = 0.65f, + int num_matches_thresh1 = 6, int num_matches_thresh2 = 6); + + void collectGarbage(); + + protected: + void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info); + + int num_matches_thresh1_; + int num_matches_thresh2_; + Ptr impl_; + }; + +.. seealso:: :ocv:class:`detail::FeaturesMatcher` + diff --git a/modules/stitching/doc/motion_estimation.rst b/modules/stitching/doc/motion_estimation.rst new file mode 100644 index 0000000000..b3c7f887cd --- /dev/null +++ b/modules/stitching/doc/motion_estimation.rst @@ -0,0 +1,174 @@ +Rotation Estimation +=================== + +.. highlight:: cpp + +detail::Estimator +----------------- +.. ocv:class:: detail::Estimator + +Rotation estimator base class. It takes features of all images, pairwise matches between all images and estimates rotations of all cameras. + +.. note:: The coordinate system origin is implementation-dependent, but you can always normalize the rotations in respect to the first camera, for instance. + +:: + + class CV_EXPORTS Estimator + { + public: + virtual ~Estimator() {} + + void operator ()(const std::vector &features, const std::vector &pairwise_matches, + std::vector &cameras) + { estimate(features, pairwise_matches, cameras); } + + protected: + virtual void estimate(const std::vector &features, const std::vector &pairwise_matches, + std::vector &cameras) = 0; + }; + +detail::HomographyBasedEstimator +-------------------------------- +.. ocv:class:: detail::HomographyBasedEstimator + +Homography based rotation estimator. :: + + class CV_EXPORTS HomographyBasedEstimator : public Estimator + { + public: + HomographyBasedEstimator(bool is_focals_estimated = false) + : is_focals_estimated_(is_focals_estimated) {} + + bool isFocalsEstimated() const { return is_focals_estimated_; } + + private: + void estimate(const std::vector &features, const std::vector &pairwise_matches, + std::vector &cameras); + + bool is_focals_estimated_; + }; + +detail::BundleAdjusterBase +-------------------------- +.. ocv:class:: detail::BundleAdjusterBase + +Base class for all camera parameters refinement methods. :: + + class CV_EXPORTS BundleAdjusterBase : public Estimator + { + public: + const Mat refinementMask() const { return refinement_mask_.clone(); } + void setRefinementMask(const Mat &mask) + { + CV_Assert(mask.type() == CV_8U && mask.size() == Size(3, 3)); + refinement_mask_ = mask.clone(); + } + + double confThresh() const { return conf_thresh_; } + void setConfThresh(double conf_thresh) { conf_thresh_ = conf_thresh; } + + CvTermCriteria termCriteria() { return term_criteria_; } + void setTermCriteria(const CvTermCriteria& term_criteria) { term_criteria_ = term_criteria; } + + protected: + BundleAdjusterBase(int num_params_per_cam, int num_errs_per_measurement) + : num_params_per_cam_(num_params_per_cam), + num_errs_per_measurement_(num_errs_per_measurement) + { + setRefinementMask(Mat::ones(3, 3, CV_8U)); + setConfThresh(1.); + setTermCriteria(cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 1000, DBL_EPSILON)); + } + + // Runs bundle adjustment + virtual void estimate(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &cameras); + + virtual void setUpInitialCameraParams(const std::vector &cameras) = 0; + virtual void obtainRefinedCameraParams(std::vector &cameras) const = 0; + virtual void calcError(Mat &err) = 0; + virtual void calcJacobian(Mat &jac) = 0; + + // 3x3 8U mask, where 0 means don't refine respective parameter, != 0 means refine + Mat refinement_mask_; + + int num_images_; + int total_num_matches_; + + int num_params_per_cam_; + int num_errs_per_measurement_; + + const ImageFeatures *features_; + const MatchesInfo *pairwise_matches_; + + // Threshold to filter out poorly matched image pairs + double conf_thresh_; + + //Levenberg–Marquardt algorithm termination criteria + CvTermCriteria term_criteria_; + + // Camera parameters matrix (CV_64F) + Mat cam_params_; + + // Connected images pairs + std::vector > edges_; + }; + + +detail::BundleAdjusterReproj +---------------------------- +.. ocv:class:: detail::BundleAdjusterReproj + +Implementation of the camera parameters refinement algorithm which minimizes sum of the reprojection error squares. :: + + class CV_EXPORTS BundleAdjusterReproj : public BundleAdjusterBase + { + public: + BundleAdjusterReproj() : BundleAdjusterBase(7, 2) {} + + private: + /* hidden */ + }; + +.. seealso:: :ocv:class:`detail::BundleAdjusterBase` + +detail::BundleAdjusterRay +------------------------- + +Implementation of the camera parameters refinement algorithm which minimizes sum of the distances between the rays passing through the camera center and a feature. :: + + class CV_EXPORTS BundleAdjusterRay : public BundleAdjusterBase + { + public: + BundleAdjusterRay() : BundleAdjusterBase(4, 3) {} + + private: + /* hidden */ + }; + +.. seealso:: :ocv:class:`detail::BundleAdjusterBase` + +detail::WaveCorrectKind +----------------------- +.. ocv:class:: detail::WaveCorrectKind + +Wave correction kind. :: + + enum CV_EXPORTS WaveCorrectKind + { + WAVE_CORRECT_HORIZ, + WAVE_CORRECT_VERT + }; + +detail::waveCorrect +------------------- +Tries to make panorama more horizontal (or verical). + +.. ocv:function:: void waveCorrect(std::vector &rmats, WaveCorrectKind kind) + + :param rmats: Camera rotation matrices. + + :param kind: Correction kind, see :ocv:class:`detail::WaveCorrectKind`. + + diff --git a/modules/stitching/doc/stitching.rst b/modules/stitching/doc/stitching.rst new file mode 100644 index 0000000000..0c91a8e9cd --- /dev/null +++ b/modules/stitching/doc/stitching.rst @@ -0,0 +1,12 @@ +*************************** +stitching. Images stitching +*************************** + +.. toctree:: + :maxdepth: 2 + + high_level + matching + motion_estimation + +