From 581d0ef8a910a9a5f2d5e87960db4dc5539ccb9e Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Wed, 9 Jan 2019 15:01:07 +0100 Subject: [PATCH] Merge pull request #13584 from qchateau:improve_stitching_detailed Improve stitching detailed (#13584) * Added block size getter/setters * Added a bunch of new features to the stitching_detailed sample * Do not required XFEATURES2D for default use * Add support for akaze features in stitching_detailed * Improved sample logs --- .../stitching/detail/exposure_compensate.hpp | 3 + samples/cpp/stitching_detailed.cpp | 81 ++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp index 54ab8087bf..f1b6012218 100644 --- a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp @@ -165,6 +165,9 @@ public: CV_WRAP void setMatGains(std::vector& umv) CV_OVERRIDE; CV_WRAP void setNrFeeds(int nr_feeds) { nr_feeds_ = nr_feeds; } CV_WRAP int getNrFeeds() { return nr_feeds_; } + CV_WRAP void setBlockSize(int width, int height) { bl_width_ = width; bl_height_ = height; } + CV_WRAP void setBlockSize(Size size) { setBlockSize(size.width, size.height); } + CV_WRAP Size getBlockSize() const { return Size(bl_width_, bl_height_); } CV_WRAP void setNrGainsFilteringIterations(int nr_iterations) { nr_gain_filtering_iterations_ = nr_iterations; } CV_WRAP int getNrGainsFilteringIterations() const { return nr_gain_filtering_iterations_; } diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index 9e3103f954..69221691d2 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -44,8 +44,9 @@ static void printUsage() "\nMotion Estimation Flags:\n" " --work_megapix \n" " Resolution for image registration step. The default is 0.6 Mpx.\n" - " --features (surf|orb|sift)\n" - " Type of features used for images matching. The default is surf.\n" + " --features (surf|orb|sift|akaze)\n" + " Type of features used for images matching.\n" + " The default is surf if available, orb otherwise.\n" " --matcher (homography|affine)\n" " Matcher used for pairwise image matching.\n" " --estimator (homography|affine)\n" @@ -80,8 +81,18 @@ static void printUsage() " --compose_megapix \n" " Resolution for compositing step. Use -1 for original resolution.\n" " The default is -1.\n" - " --expos_comp (no|gain|gain_blocks)\n" + " --expos_comp (no|gain|gain_blocks|channels|channels_blocks)\n" " Exposure compensation method. The default is 'gain_blocks'.\n" + " --expos_comp_nr_feeds \n" + " Number of exposure compensation feed. The default is 1.\n" + " --expos_comp_nr_filtering \n" + " Number of filtering iterations of the exposure compensation gains.\n" + " Only used when using a block exposure compensation method.\n" + " The default is 2.\n" + " --expos_comp_block_size \n" + " BLock size in pixels used by the exposure compensator.\n" + " Only used when using a block exposure compensation method.\n" + " The default is 32.\n" " --blend (no|feather|multiband)\n" " Blending method. The default is 'multiband'.\n" " --blend_strength \n" @@ -103,7 +114,11 @@ double work_megapix = 0.6; double seam_megapix = 0.1; double compose_megapix = -1; float conf_thresh = 1.f; +#ifdef HAVE_OPENCV_XFEATURES2D string features_type = "surf"; +#else +string features_type = "orb"; +#endif string matcher_type = "homography"; string estimator_type = "homography"; string ba_cost_func = "ray"; @@ -114,6 +129,9 @@ bool save_graph = false; std::string save_graph_to; string warp_type = "spherical"; int expos_comp_type = ExposureCompensator::GAIN_BLOCKS; +int expos_comp_nr_feeds = 1; +int expos_comp_nr_filtering = 2; +int expos_comp_block_size = 32; float match_conf = 0.3f; string seam_find_type = "gc_color"; int blend_type = Blender::MULTI_BAND; @@ -269,6 +287,10 @@ static int parseCmdArgs(int argc, char** argv) expos_comp_type = ExposureCompensator::GAIN; else if (string(argv[i + 1]) == "gain_blocks") expos_comp_type = ExposureCompensator::GAIN_BLOCKS; + else if (string(argv[i + 1]) == "channels") + expos_comp_type = ExposureCompensator::CHANNELS; + else if (string(argv[i + 1]) == "channels_blocks") + expos_comp_type = ExposureCompensator::CHANNELS_BLOCKS; else { cout << "Bad exposure compensation method\n"; @@ -276,6 +298,21 @@ static int parseCmdArgs(int argc, char** argv) } i++; } + else if (string(argv[i]) == "--expos_comp_nr_feeds") + { + expos_comp_nr_feeds = atoi(argv[i + 1]); + i++; + } + else if (string(argv[i]) == "--expos_comp_nr_filtering") + { + expos_comp_nr_filtering = atoi(argv[i + 1]); + i++; + } + else if (string(argv[i]) == "--expos_comp_block_size") + { + expos_comp_block_size = atoi(argv[i + 1]); + i++; + } else if (string(argv[i]) == "--seam") { if (string(argv[i + 1]) == "no" || @@ -383,6 +420,10 @@ int main(int argc, char* argv[]) { finder = ORB::create(); } + else if (features_type == "akaze") + { + finder = AKAZE::create(); + } #ifdef HAVE_OPENCV_XFEATURES2D else if (features_type == "surf") { @@ -666,9 +707,41 @@ int main(int argc, char* argv[]) LOGLN("Warping images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); + LOGLN("Compensating exposure..."); +#if ENABLE_LOG + t = getTickCount(); +#endif + Ptr compensator = ExposureCompensator::createDefault(expos_comp_type); + if (dynamic_cast(compensator.get())) + { + GainCompensator* gcompensator = dynamic_cast(compensator.get()); + gcompensator->setNrFeeds(expos_comp_nr_feeds); + } + + if (dynamic_cast(compensator.get())) + { + ChannelsCompensator* ccompensator = dynamic_cast(compensator.get()); + ccompensator->setNrFeeds(expos_comp_nr_feeds); + } + + if (dynamic_cast(compensator.get())) + { + BlocksCompensator* bcompensator = dynamic_cast(compensator.get()); + bcompensator->setNrFeeds(expos_comp_nr_feeds); + bcompensator->setNrGainsFilteringIterations(expos_comp_nr_filtering); + bcompensator->setBlockSize(expos_comp_block_size, expos_comp_block_size); + } + compensator->feed(corners, images_warped, masks_warped); + LOGLN("Compensating exposure, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); + + LOGLN("Finding seams..."); +#if ENABLE_LOG + t = getTickCount(); +#endif + Ptr seam_finder; if (seam_find_type == "no") seam_finder = makePtr(); @@ -704,6 +777,8 @@ int main(int argc, char* argv[]) seam_finder->find(images_warped_f, corners, masks_warped); + LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); + // Release unused memory images.clear(); images_warped.clear();