Merge pull request #19619 from amirtu:OCV-221_get_and_set_cameras_on_stitcher

* Get and set cameras for sticher.

* Code review fixes.

Co-authored-by: amir.tulegenov <amir.tulegenov@xperience.ai>
Co-authored-by: Alexander Smorkalov <alexander.smorkalov@xperience.ai>
pull/19707/head
Amir Tulegenov 4 years ago committed by GitHub
parent e2610df073
commit 04d907fb97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      modules/stitching/include/opencv2/stitching.hpp
  2. 98
      modules/stitching/src/stitcher.cpp
  3. 28
      modules/stitching/test/test_stitcher.cpp

@ -259,6 +259,20 @@ public:
*/ */
CV_WRAP Status estimateTransform(InputArrayOfArrays images, InputArrayOfArrays masks = noArray()); CV_WRAP Status estimateTransform(InputArrayOfArrays images, InputArrayOfArrays masks = noArray());
/** @brief These function restors camera rotation and camera intrinsics of each camera
* that can be got with @ref Stitcher::cameras call
@param images Input images.
@param cameras Estimated rotation of cameras for each of the input images.
@param component Indices (0-based) of images constituting the final panorama (optional).
@return Status code.
*/
Status setTransform(InputArrayOfArrays images,
const std::vector<detail::CameraParams> &cameras,
const std::vector<int> &component);
/** @overload */
Status setTransform(InputArrayOfArrays images, const std::vector<detail::CameraParams> &cameras);
/** @overload */ /** @overload */
CV_WRAP Status composePanorama(OutputArray pano); CV_WRAP Status composePanorama(OutputArray pano);
/** @brief These functions try to compose the given images (or images stored internally from the other function /** @brief These functions try to compose the given images (or images stored internally from the other function

@ -118,7 +118,6 @@ Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images, InputArr
} }
Stitcher::Status Stitcher::composePanorama(OutputArray pano) Stitcher::Status Stitcher::composePanorama(OutputArray pano)
{ {
CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION();
@ -541,6 +540,103 @@ Stitcher::Status Stitcher::estimateCameraParams()
return OK; return OK;
} }
Stitcher::Status Stitcher::setTransform(InputArrayOfArrays images, const std::vector<detail::CameraParams> &cameras)
{
std::vector<int> component;
for (int i = 0; i < (int)images.total(); i++)
component.push_back(i);
return setTransform(images, cameras, component);
}
Stitcher::Status Stitcher::setTransform(
InputArrayOfArrays images, const std::vector<detail::CameraParams> &cameras, const std::vector<int> &component)
{
// CV_Assert(images.size() == cameras.size());
images.getUMatVector(imgs_);
masks_.clear();
if ((int)imgs_.size() < 2)
{
LOGLN("Need more images");
return ERR_NEED_MORE_IMGS;
}
work_scale_ = 1;
seam_work_aspect_ = 1;
seam_scale_ = 1;
bool is_work_scale_set = false;
bool is_seam_scale_set = false;
seam_est_imgs_.resize(imgs_.size());
full_img_sizes_.resize(imgs_.size());
for (size_t i = 0; i < imgs_.size(); ++i)
{
full_img_sizes_[i] = imgs_[i].size();
if (registr_resol_ < 0)
{
work_scale_ = 1;
is_work_scale_set = true;
}
else
{
if (!is_work_scale_set)
{
work_scale_ = std::min(1.0, std::sqrt(registr_resol_ * 1e6 / full_img_sizes_[i].area()));
is_work_scale_set = true;
}
}
if (!is_seam_scale_set)
{
seam_scale_ = std::min(1.0, std::sqrt(seam_est_resol_ * 1e6 / full_img_sizes_[i].area()));
seam_work_aspect_ = seam_scale_ / work_scale_;
is_seam_scale_set = true;
}
resize(imgs_[i], seam_est_imgs_[i], Size(), seam_scale_, seam_scale_, INTER_LINEAR_EXACT);
}
features_.clear();
pairwise_matches_.clear();
indices_ = component;
std::vector<UMat> seam_est_imgs_subset;
std::vector<UMat> imgs_subset;
std::vector<Size> full_img_sizes_subset;
for (size_t i = 0; i < indices_.size(); ++i)
{
imgs_subset.push_back(imgs_[indices_[i]]);
seam_est_imgs_subset.push_back(seam_est_imgs_[indices_[i]]);
full_img_sizes_subset.push_back(full_img_sizes_[indices_[i]]);
}
seam_est_imgs_ = seam_est_imgs_subset;
imgs_ = imgs_subset;
full_img_sizes_ = full_img_sizes_subset;
if ((int)imgs_.size() < 2)
{
LOGLN("Need more images");
return ERR_NEED_MORE_IMGS;
}
cameras_ = cameras;
std::vector<double> focals;
for (size_t i = 0; i < cameras.size(); ++i)
focals.push_back(cameras_[i].focal);
std::sort(focals.begin(), focals.end());
if (focals.size() % 2 == 1)
warped_image_scale_ = static_cast<float>(focals[focals.size() / 2]);
else
warped_image_scale_ = static_cast<float>(focals[focals.size() / 2 - 1] + focals[focals.size() / 2]) * 0.5f;
return Status::OK;
}
CV_DEPRECATED Ptr<Stitcher> createStitcher(bool /*ignored*/) CV_DEPRECATED Ptr<Stitcher> createStitcher(bool /*ignored*/)
{ {

@ -0,0 +1,28 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
namespace opencv_test { namespace {
TEST(ImageStitcher, setTransform)
{
vector<Mat> images;
images.push_back(imread(string(cvtest::TS::ptr()->get_data_path()) + "stitching/s1.jpg"));
images.push_back(imread(string(cvtest::TS::ptr()->get_data_path()) + "stitching/s2.jpg"));
Mat expected;
Ptr<Stitcher> stitcher = Stitcher::create(Stitcher::PANORAMA);
EXPECT_TRUE(Stitcher::OK == stitcher->estimateTransform(images));
EXPECT_TRUE(Stitcher::OK == stitcher->composePanorama(expected));
Mat result;
Ptr<Stitcher> another_stitcher = Stitcher::create(Stitcher::PANORAMA);
EXPECT_TRUE(Stitcher::OK == another_stitcher->setTransform(images, stitcher->cameras()));
EXPECT_TRUE(Stitcher::OK == another_stitcher->composePanorama(result));
EXPECT_DOUBLE_EQ(cvtest::norm(expected, result, NORM_INF), .0);
}
}} // namespace opencv_test
Loading…
Cancel
Save