estimate_transform.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2015-2016, Jiri Horner.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the author nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *********************************************************************/
00036 
00037 #include <combine_grids/estimate_transform.h>
00038 
00039 #include <cmath>
00040 
00041 #include <opencv2/core/utility.hpp>
00042 
00043 #include <ros/console.h>
00044 #include <ros/assert.h>
00045 
00046 #include <combine_grids/features_matcher.h>
00047 #include <combine_grids/transform_estimator.h>
00048 
00049 namespace combine_grids
00050 {
00051 namespace internal
00052 {
00053 size_t opencvEstimateTransform(const std::vector<cv::Mat>& images,
00054                                std::vector<cv::Mat>& final_transforms,
00055                                double confidence)
00056 {
00057   std::vector<cv::detail::ImageFeatures> image_features;
00058   std::vector<cv::detail::MatchesInfo> pairwise_matches;
00059   std::vector<cv::detail::CameraParams> transforms;
00060   std::vector<int> matched_indices;
00061   cv::Ptr<cv::detail::FeaturesFinder> finder =
00062       cv::makePtr<cv::detail::OrbFeaturesFinder>();
00063   cv::Ptr<cv::detail::FeaturesMatcher> matcher =
00064       cv::makePtr<internal::AffineBestOf2NearestMatcher>();
00065   cv::Ptr<cv::detail::Estimator> estimator =
00066       cv::makePtr<internal::AffineBasedEstimator>();
00067 
00068   if (images.size() < 2) {
00069     return 0;
00070   }
00071 
00072   /* find features in images */
00073   ROS_DEBUG("computing features");
00074   image_features.reserve(images.size());
00075   for (const cv::Mat& image : images) {
00076     image_features.emplace_back();
00077     (*finder)(image, image_features.back());
00078   }
00079   finder->collectGarbage();
00080 
00081   /* find corespondent features */
00082   // matches only some (5) images, scales better than full pairwise matcher
00083   ROS_DEBUG("pairwise matching features");
00084   (*matcher)(image_features, pairwise_matches);
00085   matcher->collectGarbage();
00086 
00087   /* use only matches that has enough confidence. leave out matches that are not
00088    * connected (small components) */
00089   matched_indices = cv::detail::leaveBiggestComponent(
00090       image_features, pairwise_matches, static_cast<float>(confidence));
00091 
00092   /* estimate transform */
00093   ROS_DEBUG("estimating final transform");
00094   // note: currently used estimator never fails
00095   if (!(*estimator)(image_features, pairwise_matches, transforms)) {
00096     return 0;
00097   }
00098 
00099   ROS_ASSERT(matched_indices.size() == transforms.size());
00100 
00101   final_transforms.clear();
00102   final_transforms.resize(images.size());
00103   size_t i = 0;
00104   for (auto& transform : transforms) {
00105     if (!transform.R.empty()) {
00106       ROS_DEBUG("TRANSFORM: trans x: %f, trans y %f, rot: %f\n",
00107                 transform.R.at<double>(0, 2), transform.R.at<double>(1, 2),
00108                 std::atan2(transform.R.at<double>(0, 1),
00109                            transform.R.at<double>(1, 1)));
00110     }
00111 
00112     final_transforms[i] = transform.R;
00113     ++i;
00114   }
00115 
00116   ROS_ASSERT(final_transforms.size() == images.size());
00117 
00118   return transforms.size();
00119 }
00120 }  // namespace internal
00121 }  // namespace combine_grids


map_merge
Author(s): Jiri Horner
autogenerated on Sun Mar 26 2017 03:48:10