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
pull/13604/head
Quentin Chateau 6 years ago committed by Alexander Alekhin
parent a9c1af39d6
commit 581d0ef8a9
  1. 3
      modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp
  2. 81
      samples/cpp/stitching_detailed.cpp

@ -165,6 +165,9 @@ public:
CV_WRAP void setMatGains(std::vector<Mat>& 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_; }

@ -44,8 +44,9 @@ static void printUsage()
"\nMotion Estimation Flags:\n"
" --work_megapix <float>\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 <float>\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 <int>\n"
" Number of exposure compensation feed. The default is 1.\n"
" --expos_comp_nr_filtering <int>\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 <int>\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 <float>\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<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
if (dynamic_cast<GainCompensator*>(compensator.get()))
{
GainCompensator* gcompensator = dynamic_cast<GainCompensator*>(compensator.get());
gcompensator->setNrFeeds(expos_comp_nr_feeds);
}
if (dynamic_cast<ChannelsCompensator*>(compensator.get()))
{
ChannelsCompensator* ccompensator = dynamic_cast<ChannelsCompensator*>(compensator.get());
ccompensator->setNrFeeds(expos_comp_nr_feeds);
}
if (dynamic_cast<BlocksCompensator*>(compensator.get()))
{
BlocksCompensator* bcompensator = dynamic_cast<BlocksCompensator*>(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<SeamFinder> seam_finder;
if (seam_find_type == "no")
seam_finder = makePtr<detail::NoSeamFinder>();
@ -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();

Loading…
Cancel
Save