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
This commit is contained in:
Quentin Chateau 2018-12-26 08:24:38 +01:00 committed by Alexander Alekhin
parent 6142b21dd5
commit 757411bffc
3 changed files with 85 additions and 5 deletions

View File

@ -110,15 +110,24 @@ intensities, see @cite BL07 and @cite WJ10 for details.
class CV_EXPORTS_W GainCompensator : public ExposureCompensator
{
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,
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 getMatGains(CV_OUT 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;
private:
Mat_<double> gains_;
int nr_feeds_;
};
/** @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:
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,
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 getMatGains(CV_OUT 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:
int bl_width_, bl_height_;
std::vector<UMat> gain_maps_;
int nr_feeds_;
};
//! @}
} // namespace detail

View File

@ -15,6 +15,7 @@ using namespace perf;
typedef TestBaseWithParam<string> stitch;
typedef TestBaseWithParam<int> stitchExposureCompensation;
typedef TestBaseWithParam<tuple<string, string> > stitchDatasets;
typedef TestBaseWithParam<tuple<string, int>> stitchExposureCompMultiFeed;
#ifdef HAVE_OPENCV_XFEATURES2D
#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")
#endif
#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")
PERF_TEST_P(stitch, a123, TEST_DETECTORS)
@ -92,6 +95,45 @@ PERF_TEST_P(stitchExposureCompensation, a123, TEST_EXP_COMP_BS)
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)
{
Mat pano;

View File

@ -85,6 +85,33 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
int64 t = getTickCount();
#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());
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);
}
}
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())
{
GainCompensator compensator;
GainCompensator compensator(nr_feeds_);
compensator.feed(block_corners, block_images, block_masks);
std::vector<double> gains = compensator.gains();
gain_maps_.resize(num_images);