Merge pull request #13503 from Tytan:gain_comp_multi_feed

Stitching: multi-feed on gain and block compensator (#13503)

* multi-feed on gain and block compensator

* ABI compatibility
pull/13534/head
Quentin Chateau 6 years ago committed by Alexander Alekhin
parent 6142b21dd5
commit 757411bffc
  1. 17
      modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp
  2. 42
      modules/stitching/perf/perf_stich.cpp
  3. 31
      modules/stitching/src/exposure_compensate.cpp

@ -110,15 +110,24 @@ intensities, see @cite BL07 and @cite WJ10 for details.
class CV_EXPORTS_W GainCompensator : public ExposureCompensator class CV_EXPORTS_W GainCompensator : public ExposureCompensator
{ {
public: public:
CV_WRAP GainCompensator()
: GainCompensator(1) {}
CV_WRAP GainCompensator(int nr_feeds)
: nr_feeds_(nr_feeds) {}
void feed(const std::vector<Point> &corners, const std::vector<UMat> &images, void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
const std::vector<std::pair<UMat,uchar> > &masks) CV_OVERRIDE; const std::vector<std::pair<UMat,uchar> > &masks) CV_OVERRIDE;
void singleFeed(const std::vector<Point> &corners, const std::vector<UMat> &images,
const std::vector<std::pair<UMat,uchar> > &masks);
CV_WRAP void apply(int index, Point corner, InputOutputArray image, InputArray mask) CV_OVERRIDE; CV_WRAP void apply(int index, Point corner, InputOutputArray image, InputArray mask) CV_OVERRIDE;
CV_WRAP void getMatGains(CV_OUT std::vector<Mat>& umv) CV_OVERRIDE ; CV_WRAP void getMatGains(CV_OUT std::vector<Mat>& umv) CV_OVERRIDE ;
CV_WRAP void setMatGains(std::vector<Mat>& umv) CV_OVERRIDE ; 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_; }
std::vector<double> gains() const; std::vector<double> gains() const;
private: private:
Mat_<double> gains_; Mat_<double> gains_;
int nr_feeds_;
}; };
/** @brief Exposure compensator which tries to remove exposure related artifacts by adjusting image block /** @brief Exposure compensator which tries to remove exposure related artifacts by adjusting image block
@ -128,18 +137,22 @@ class CV_EXPORTS_W BlocksGainCompensator : public ExposureCompensator
{ {
public: public:
CV_WRAP BlocksGainCompensator(int bl_width = 32, int bl_height = 32) CV_WRAP BlocksGainCompensator(int bl_width = 32, int bl_height = 32)
: bl_width_(bl_width), bl_height_(bl_height) {setUpdateGain(true);} : BlocksGainCompensator(bl_width, bl_height, 1) {}
CV_WRAP BlocksGainCompensator(int bl_width, int bl_height, int nr_feeds)
: bl_width_(bl_width), bl_height_(bl_height), nr_feeds_(nr_feeds) {setUpdateGain(true);}
void feed(const std::vector<Point> &corners, const std::vector<UMat> &images, void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
const std::vector<std::pair<UMat,uchar> > &masks) CV_OVERRIDE; const std::vector<std::pair<UMat,uchar> > &masks) CV_OVERRIDE;
CV_WRAP void apply(int index, Point corner, InputOutputArray image, InputArray mask) CV_OVERRIDE; CV_WRAP void apply(int index, Point corner, InputOutputArray image, InputArray mask) CV_OVERRIDE;
CV_WRAP void getMatGains(CV_OUT std::vector<Mat>& umv) CV_OVERRIDE; CV_WRAP void getMatGains(CV_OUT std::vector<Mat>& umv) CV_OVERRIDE;
CV_WRAP void setMatGains(std::vector<Mat>& umv) CV_OVERRIDE; 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_; }
private: private:
int bl_width_, bl_height_; int bl_width_, bl_height_;
std::vector<UMat> gain_maps_; std::vector<UMat> gain_maps_;
int nr_feeds_;
}; };
//! @} //! @}
} // namespace detail } // namespace detail

@ -15,6 +15,7 @@ using namespace perf;
typedef TestBaseWithParam<string> stitch; typedef TestBaseWithParam<string> stitch;
typedef TestBaseWithParam<int> stitchExposureCompensation; typedef TestBaseWithParam<int> stitchExposureCompensation;
typedef TestBaseWithParam<tuple<string, string> > stitchDatasets; typedef TestBaseWithParam<tuple<string, string> > stitchDatasets;
typedef TestBaseWithParam<tuple<string, int>> stitchExposureCompMultiFeed;
#ifdef HAVE_OPENCV_XFEATURES2D #ifdef HAVE_OPENCV_XFEATURES2D
#define TEST_DETECTORS testing::Values("surf", "orb", "akaze") #define TEST_DETECTORS testing::Values("surf", "orb", "akaze")
@ -22,6 +23,8 @@ typedef TestBaseWithParam<tuple<string, string> > stitchDatasets;
#define TEST_DETECTORS testing::Values("orb", "akaze") #define TEST_DETECTORS testing::Values("orb", "akaze")
#endif #endif
#define TEST_EXP_COMP_BS testing::Values(32, 16, 12, 10, 8) #define TEST_EXP_COMP_BS testing::Values(32, 16, 12, 10, 8)
#define TEST_EXP_COMP_NR_FEED testing::Values(1, 2, 3, 4, 5)
#define TEST_EXP_COMP_MODE testing::Values("gain", "blocks")
#define AFFINE_DATASETS testing::Values("s", "budapest", "newspaper", "prague") #define AFFINE_DATASETS testing::Values("s", "budapest", "newspaper", "prague")
PERF_TEST_P(stitch, a123, TEST_DETECTORS) PERF_TEST_P(stitch, a123, TEST_DETECTORS)
@ -92,6 +95,45 @@ PERF_TEST_P(stitchExposureCompensation, a123, TEST_EXP_COMP_BS)
SANITY_CHECK_NOTHING(); SANITY_CHECK_NOTHING();
} }
PERF_TEST_P(stitchExposureCompMultiFeed, a123, testing::Combine(TEST_EXP_COMP_MODE, TEST_EXP_COMP_NR_FEED))
{
const int block_size = 32;
Mat pano;
vector<Mat> imgs;
imgs.push_back( imread( getDataPath("stitching/a1.png") ) );
imgs.push_back( imread( getDataPath("stitching/a2.png") ) );
imgs.push_back( imread( getDataPath("stitching/a3.png") ) );
string mode = get<0>(GetParam());
int nr_feeds = get<1>(GetParam());
declare.time(30 * 10).iterations(10);
Ptr<detail::ExposureCompensator> exp_comp;
if (mode == "blocks")
exp_comp = makePtr<detail::BlocksGainCompensator>(block_size, block_size, nr_feeds);
else if (mode == "gain")
exp_comp = makePtr<detail::GainCompensator>(nr_feeds);
while(next())
{
Ptr<Stitcher> stitcher = Stitcher::create();
stitcher->setWarper(makePtr<SphericalWarper>());
stitcher->setRegistrationResol(WORK_MEGAPIX);
stitcher->setExposureCompensator(exp_comp);
startTimer();
stitcher->stitch(imgs, pano);
stopTimer();
}
EXPECT_NEAR(pano.size().width, 1182, 50);
EXPECT_NEAR(pano.size().height, 682, 30);
SANITY_CHECK_NOTHING();
}
PERF_TEST_P(stitch, b12, TEST_DETECTORS) PERF_TEST_P(stitch, b12, TEST_DETECTORS)
{ {
Mat pano; Mat pano;

@ -85,6 +85,33 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
int64 t = getTickCount(); int64 t = getTickCount();
#endif #endif
const int num_images = static_cast<int>(images.size());
Mat accumulated_gains;
for (int n = 0; n < nr_feeds_; ++n)
{
if (n > 0)
{
// Apply previous iteration gains
for (int i = 0; i < num_images; ++i)
apply(i, corners[i], images[i], masks[i].first);
}
singleFeed(corners, images, masks);
if (n == 0)
accumulated_gains = gains_.clone();
else
multiply(accumulated_gains, gains_, accumulated_gains);
}
gains_ = accumulated_gains;
LOGLN("Exposure compensation, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
}
void GainCompensator::singleFeed(const std::vector<Point> &corners, const std::vector<UMat> &images,
const std::vector<std::pair<UMat,uchar> > &masks)
{
CV_Assert(corners.size() == images.size() && images.size() == masks.size()); CV_Assert(corners.size() == images.size() && images.size() == masks.size());
const int num_images = static_cast<int>(images.size()); const int num_images = static_cast<int>(images.size());
@ -204,8 +231,6 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
gains_.at<double>(i, 0) = l_gains(j++, 0); gains_.at<double>(i, 0) = l_gains(j++, 0);
} }
} }
LOGLN("Exposure compensation, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
} }
@ -282,7 +307,7 @@ void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::v
if (getUpdateGain()) if (getUpdateGain())
{ {
GainCompensator compensator; GainCompensator compensator(nr_feeds_);
compensator.feed(block_corners, block_images, block_masks); compensator.feed(block_corners, block_images, block_masks);
std::vector<double> gains = compensator.gains(); std::vector<double> gains = compensator.gains();
gain_maps_.resize(num_images); gain_maps_.resize(num_images);

Loading…
Cancel
Save