TAPI: stitching: improve warpers
This commit is contained in:

committed by
Andrey Pavlenko

parent
89e3e448f5
commit
c1ea6f3c42
@@ -71,6 +71,7 @@
|
|||||||
#define LOG_(_level, _msg) \
|
#define LOG_(_level, _msg) \
|
||||||
for(;;) \
|
for(;;) \
|
||||||
{ \
|
{ \
|
||||||
|
using namespace std; \
|
||||||
if ((_level) >= ::cv::detail::stitchingLogLevel()) \
|
if ((_level) >= ::cv::detail::stitchingLogLevel()) \
|
||||||
{ \
|
{ \
|
||||||
LOG_STITCHING_MSG(_msg); \
|
LOG_STITCHING_MSG(_msg); \
|
||||||
|
@@ -160,6 +160,8 @@ class CV_EXPORTS SphericalWarper : public RotationWarperBase<SphericalProjector>
|
|||||||
public:
|
public:
|
||||||
SphericalWarper(float scale) { projector_.scale = scale; }
|
SphericalWarper(float scale) { projector_.scale = scale; }
|
||||||
|
|
||||||
|
Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
|
||||||
|
Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
|
||||||
protected:
|
protected:
|
||||||
void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
|
void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);
|
||||||
};
|
};
|
||||||
@@ -178,6 +180,8 @@ class CV_EXPORTS CylindricalWarper : public RotationWarperBase<CylindricalProjec
|
|||||||
public:
|
public:
|
||||||
CylindricalWarper(float scale) { projector_.scale = scale; }
|
CylindricalWarper(float scale) { projector_.scale = scale; }
|
||||||
|
|
||||||
|
Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
|
||||||
|
Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
|
||||||
protected:
|
protected:
|
||||||
void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
|
void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
|
||||||
{
|
{
|
||||||
@@ -503,45 +507,6 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////// OpenCL Accelerated Warpers /////////////////////////////////////
|
|
||||||
|
|
||||||
class CV_EXPORTS PlaneWarperOcl : public PlaneWarper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PlaneWarperOcl(float scale = 1.f) : PlaneWarper(scale) { }
|
|
||||||
|
|
||||||
virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
|
|
||||||
{
|
|
||||||
return buildMaps(src_size, K, R, Mat::zeros(3, 1, CV_32FC1), xmap, ymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst)
|
|
||||||
{
|
|
||||||
return warp(src, K, R, Mat::zeros(3, 1, CV_32FC1), interp_mode, border_mode, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap);
|
|
||||||
virtual Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, OutputArray dst);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CV_EXPORTS SphericalWarperOcl : public SphericalWarper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SphericalWarperOcl(float scale) : SphericalWarper(scale) { }
|
|
||||||
|
|
||||||
virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
|
|
||||||
virtual Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CV_EXPORTS CylindricalWarperOcl : public CylindricalWarper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CylindricalWarperOcl(float scale) : CylindricalWarper(scale) { }
|
|
||||||
|
|
||||||
virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap);
|
|
||||||
virtual Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
|
@@ -92,7 +92,7 @@ template <class P>
|
|||||||
Point RotationWarperBase<P>::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
|
Point RotationWarperBase<P>::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode,
|
||||||
OutputArray dst)
|
OutputArray dst)
|
||||||
{
|
{
|
||||||
Mat xmap, ymap;
|
UMat xmap, ymap;
|
||||||
Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);
|
Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap);
|
||||||
|
|
||||||
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
||||||
|
@@ -167,24 +167,6 @@ public:
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class PlaneWarperOcl: public WarperCreator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ptr<detail::RotationWarper> create(float scale) const { return makePtr<detail::PlaneWarperOcl>(scale); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class SphericalWarperOcl: public WarperCreator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ptr<detail::RotationWarper> create(float scale) const { return makePtr<detail::SphericalWarperOcl>(scale); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class CylindricalWarperOcl: public WarperCreator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ptr<detail::RotationWarper> create(float scale) const { return makePtr<detail::CylindricalWarperOcl>(scale); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
#endif // __OPENCV_STITCHING_WARPER_CREATORS_HPP__
|
#endif // __OPENCV_STITCHING_WARPER_CREATORS_HPP__
|
||||||
|
@@ -63,24 +63,12 @@ public:
|
|||||||
explicit WarperBase(int type, Size srcSize)
|
explicit WarperBase(int type, Size srcSize)
|
||||||
{
|
{
|
||||||
Ptr<WarperCreator> creator;
|
Ptr<WarperCreator> creator;
|
||||||
if (cv::ocl::useOpenCL())
|
if (type == SphericalWarperType)
|
||||||
{
|
creator = makePtr<SphericalWarper>();
|
||||||
if (type == SphericalWarperType)
|
else if (type == CylindricalWarperType)
|
||||||
creator = makePtr<SphericalWarperOcl>();
|
creator = makePtr<CylindricalWarper>();
|
||||||
else if (type == CylindricalWarperType)
|
else if (type == PlaneWarperType)
|
||||||
creator = makePtr<CylindricalWarperOcl>();
|
creator = makePtr<PlaneWarper>();
|
||||||
else if (type == PlaneWarperType)
|
|
||||||
creator = makePtr<PlaneWarperOcl>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (type == SphericalWarperType)
|
|
||||||
creator = makePtr<SphericalWarper>();
|
|
||||||
else if (type == CylindricalWarperType)
|
|
||||||
creator = makePtr<CylindricalWarper>();
|
|
||||||
else if (type == PlaneWarperType)
|
|
||||||
creator = makePtr<PlaneWarper>();
|
|
||||||
}
|
|
||||||
CV_Assert(!creator.empty());
|
CV_Assert(!creator.empty());
|
||||||
|
|
||||||
K = Mat::eye(3, 3, CV_32FC1);
|
K = Mat::eye(3, 3, CV_32FC1);
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "opencv2/core.hpp"
|
#include "opencv2/core.hpp"
|
||||||
#include "opencv2/core/ocl.hpp"
|
#include "opencv2/core/ocl.hpp"
|
||||||
|
@@ -309,9 +309,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra
|
|||||||
|
|
||||||
// Preliminary result is in CV_16SC3 format, but all values are in [0,255] range,
|
// Preliminary result is in CV_16SC3 format, but all values are in [0,255] range,
|
||||||
// so convert it to avoid user confusing
|
// so convert it to avoid user confusing
|
||||||
result.convertTo(pano_, CV_8U);
|
result.convertTo(pano, CV_8U);
|
||||||
|
|
||||||
pano.assign(pano_);
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -456,7 +454,7 @@ Stitcher::Status Stitcher::estimateCameraParams()
|
|||||||
Mat R;
|
Mat R;
|
||||||
cameras_[i].R.convertTo(R, CV_32F);
|
cameras_[i].R.convertTo(R, CV_32F);
|
||||||
cameras_[i].R = R;
|
cameras_[i].R = R;
|
||||||
LOGLN("Initial intrinsic parameters #" << indices_[i] + 1 << ":\n " << cameras_[i].K());
|
//LOGLN("Initial intrinsic parameters #" << indices_[i] + 1 << ":\n " << cameras_[i].K());
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle_adjuster_->setConfThresh(conf_thresh_);
|
bundle_adjuster_->setConfThresh(conf_thresh_);
|
||||||
@@ -467,7 +465,7 @@ Stitcher::Status Stitcher::estimateCameraParams()
|
|||||||
std::vector<double> focals;
|
std::vector<double> focals;
|
||||||
for (size_t i = 0; i < cameras_.size(); ++i)
|
for (size_t i = 0; i < cameras_.size(); ++i)
|
||||||
{
|
{
|
||||||
LOGLN("Camera #" << indices_[i] + 1 << ":\n" << cameras_[i].K());
|
//LOGLN("Camera #" << indices_[i] + 1 << ":\n" << cameras_[i].K());
|
||||||
focals.push_back(cameras_[i].focal);
|
focals.push_back(cameras_[i].focal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
#include "opencl_kernels.hpp"
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -86,7 +87,6 @@ Point2f PlaneWarper::warpPoint(const Point2f &pt, InputArray K, InputArray R, In
|
|||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray _xmap, OutputArray _ymap)
|
Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray _xmap, OutputArray _ymap)
|
||||||
{
|
{
|
||||||
projector_.setCameraParams(K, R, T);
|
projector_.setCameraParams(K, R, T);
|
||||||
@@ -94,8 +94,29 @@ Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArra
|
|||||||
Point dst_tl, dst_br;
|
Point dst_tl, dst_br;
|
||||||
detectResultRoi(src_size, dst_tl, dst_br);
|
detectResultRoi(src_size, dst_tl, dst_br);
|
||||||
|
|
||||||
_xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
|
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
||||||
_ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
|
_xmap.create(dsize, CV_32FC1);
|
||||||
|
_ymap.create(dsize, CV_32FC1);
|
||||||
|
|
||||||
|
if (ocl::useOpenCL()) // TODO !!!!! check T
|
||||||
|
{
|
||||||
|
ocl::Kernel k("buildWarpPlaneMaps", ocl::stitching::warpers_oclsrc);
|
||||||
|
if (!k.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv), t(1, 3, CV_32FC1, projector_.t);
|
||||||
|
UMat uxmap = _xmap.getUMat(), uymap = _ymap.getUMat(),
|
||||||
|
uk_rinv = k_rinv.getUMat(ACCESS_READ), ut = t.getUMat(ACCESS_READ);
|
||||||
|
|
||||||
|
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
||||||
|
ocl::KernelArg::PtrReadOnly(uk_rinv), ocl::KernelArg::PtrReadOnly(ut),
|
||||||
|
dst_tl.x, dst_tl.y, projector_.scale);
|
||||||
|
|
||||||
|
size_t globalsize[2] = { dsize.width, dsize.height };
|
||||||
|
if (k.run(2, globalsize, NULL, true))
|
||||||
|
return Rect(dst_tl, dst_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mat xmap = _xmap.getMat(), ymap = _ymap.getMat();
|
Mat xmap = _xmap.getMat(), ymap = _ymap.getMat();
|
||||||
|
|
||||||
@@ -117,11 +138,11 @@ Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArra
|
|||||||
Point PlaneWarper::warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
|
Point PlaneWarper::warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode,
|
||||||
OutputArray dst)
|
OutputArray dst)
|
||||||
{
|
{
|
||||||
Mat xmap, ymap;
|
UMat uxmap, uymap;
|
||||||
Rect dst_roi = buildMaps(src.size(), K, R, T, xmap, ymap);
|
Rect dst_roi = buildMaps(src.size(), K, R, T, uxmap, uymap);
|
||||||
|
|
||||||
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
||||||
remap(src, dst, xmap, ymap, interp_mode, border_mode);
|
remap(src, dst, uxmap, uymap, interp_mode, border_mode);
|
||||||
|
|
||||||
return dst_roi.tl();
|
return dst_roi.tl();
|
||||||
}
|
}
|
||||||
@@ -341,5 +362,93 @@ void SphericalPortraitWarper::detectResultRoi(Size src_size, Point &dst_tl, Poin
|
|||||||
dst_br.y = static_cast<int>(br_vf);
|
dst_br.y = static_cast<int>(br_vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////// SphericalWarper ////////////////////////////////////////
|
||||||
|
|
||||||
|
Rect SphericalWarper::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
|
||||||
|
{
|
||||||
|
if (ocl::useOpenCL())
|
||||||
|
{
|
||||||
|
ocl::Kernel k("buildWarpSphericalMaps", ocl::stitching::warpers_oclsrc);
|
||||||
|
if (!k.empty())
|
||||||
|
{
|
||||||
|
projector_.setCameraParams(K, R);
|
||||||
|
|
||||||
|
Point dst_tl, dst_br;
|
||||||
|
detectResultRoi(src_size, dst_tl, dst_br);
|
||||||
|
|
||||||
|
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
||||||
|
xmap.create(dsize, CV_32FC1);
|
||||||
|
ymap.create(dsize, CV_32FC1);
|
||||||
|
|
||||||
|
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv);
|
||||||
|
UMat uxmap = xmap.getUMat(), uymap = ymap.getUMat(), uk_rinv = k_rinv.getUMat(ACCESS_READ);
|
||||||
|
|
||||||
|
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
||||||
|
ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, projector_.scale);
|
||||||
|
|
||||||
|
size_t globalsize[2] = { dsize.width, dsize.height };
|
||||||
|
if (k.run(2, globalsize, NULL, true))
|
||||||
|
return Rect(dst_tl, dst_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RotationWarperBase<SphericalProjector>::buildMaps(src_size, K, R, xmap, ymap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point SphericalWarper::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst)
|
||||||
|
{
|
||||||
|
UMat uxmap, uymap;
|
||||||
|
Rect dst_roi = buildMaps(src.size(), K, R, uxmap, uymap);
|
||||||
|
|
||||||
|
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
||||||
|
remap(src, dst, uxmap, uymap, interp_mode, border_mode);
|
||||||
|
|
||||||
|
return dst_roi.tl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////// CylindricalWarper ////////////////////////////////////////
|
||||||
|
|
||||||
|
Rect CylindricalWarper::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
|
||||||
|
{
|
||||||
|
if (ocl::useOpenCL())
|
||||||
|
{
|
||||||
|
ocl::Kernel k("buildWarpCylindricalMaps", ocl::stitching::warpers_oclsrc);
|
||||||
|
if (!k.empty())
|
||||||
|
{
|
||||||
|
projector_.setCameraParams(K, R);
|
||||||
|
|
||||||
|
Point dst_tl, dst_br;
|
||||||
|
detectResultRoi(src_size, dst_tl, dst_br);
|
||||||
|
|
||||||
|
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
||||||
|
xmap.create(dsize, CV_32FC1);
|
||||||
|
ymap.create(dsize, CV_32FC1);
|
||||||
|
|
||||||
|
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv);
|
||||||
|
UMat uxmap = xmap.getUMat(), uymap = ymap.getUMat(), uk_rinv = k_rinv.getUMat(ACCESS_READ);
|
||||||
|
|
||||||
|
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
||||||
|
ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, projector_.scale);
|
||||||
|
|
||||||
|
size_t globalsize[2] = { dsize.width, dsize.height };
|
||||||
|
if (k.run(2, globalsize, NULL, true))
|
||||||
|
return Rect(dst_tl, dst_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RotationWarperBase<CylindricalProjector>::buildMaps(src_size, K, R, xmap, ymap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point CylindricalWarper::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst)
|
||||||
|
{
|
||||||
|
UMat uxmap, uymap;
|
||||||
|
Rect dst_roi = buildMaps(src.size(), K, R, uxmap, uymap);
|
||||||
|
|
||||||
|
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
||||||
|
remap(src, dst, uxmap, uymap, interp_mode, border_mode);
|
||||||
|
|
||||||
|
return dst_roi.tl();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@@ -1,187 +0,0 @@
|
|||||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
||||||
//
|
|
||||||
// By downloading, copying, installing or using the software you agree to this license.
|
|
||||||
// If you do not agree to this license, do not download, install,
|
|
||||||
// copy or use the software.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
|
||||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective owners.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
// are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistribution's of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// * The name of the copyright holders may not be used to endorse or promote products
|
|
||||||
// derived from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// This software is provided by the copyright holders and contributors "as is" and
|
|
||||||
// any express or implied warranties, including, but not limited to, the implied
|
|
||||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
|
||||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
|
||||||
// indirect, incidental, special, exemplary, or consequential damages
|
|
||||||
// (including, but not limited to, procurement of substitute goods or services;
|
|
||||||
// loss of use, data, or profits; or business interruption) however caused
|
|
||||||
// and on any theory of liability, whether in contract, strict liability,
|
|
||||||
// or tort (including negligence or otherwise) arising in any way out of
|
|
||||||
// the use of this software, even if advised of the possibility of such damage.
|
|
||||||
//
|
|
||||||
//M*/
|
|
||||||
|
|
||||||
#include "precomp.hpp"
|
|
||||||
#include "opencl_kernels.hpp"
|
|
||||||
|
|
||||||
namespace cv {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/////////////////////////////////////////// PlaneWarperOcl ////////////////////////////////////////////
|
|
||||||
|
|
||||||
Rect PlaneWarperOcl::buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap)
|
|
||||||
{
|
|
||||||
projector_.setCameraParams(K, R, T);
|
|
||||||
|
|
||||||
Point dst_tl, dst_br;
|
|
||||||
detectResultRoi(src_size, dst_tl, dst_br);
|
|
||||||
|
|
||||||
if (ocl::useOpenCL())
|
|
||||||
{
|
|
||||||
ocl::Kernel k("buildWarpPlaneMaps", ocl::stitching::warpers_oclsrc);
|
|
||||||
if (!k.empty())
|
|
||||||
{
|
|
||||||
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
|
||||||
xmap.create(dsize, CV_32FC1);
|
|
||||||
ymap.create(dsize, CV_32FC1);
|
|
||||||
|
|
||||||
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv), t(1, 3, CV_32FC1, projector_.t);
|
|
||||||
UMat uxmap = xmap.getUMat(), uymap = ymap.getUMat(),
|
|
||||||
uk_rinv = k_rinv.getUMat(ACCESS_READ), ut = t.getUMat(ACCESS_READ);
|
|
||||||
|
|
||||||
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
|
||||||
ocl::KernelArg::PtrReadOnly(uk_rinv), ocl::KernelArg::PtrReadOnly(ut),
|
|
||||||
dst_tl.x, dst_tl.y, projector_.scale);
|
|
||||||
|
|
||||||
size_t globalsize[2] = { dsize.width, dsize.height };
|
|
||||||
if (k.run(2, globalsize, NULL, true))
|
|
||||||
return Rect(dst_tl, dst_br);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PlaneWarper::buildMaps(src_size, K, R, T, xmap, ymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point PlaneWarperOcl::warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, OutputArray dst)
|
|
||||||
{
|
|
||||||
UMat uxmap, uymap;
|
|
||||||
Rect dst_roi = buildMaps(src.size(), K, R, T, uxmap, uymap);
|
|
||||||
|
|
||||||
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
|
||||||
UMat udst = dst.getUMat();
|
|
||||||
remap(src, udst, uxmap, uymap, interp_mode, border_mode);
|
|
||||||
|
|
||||||
return dst_roi.tl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////// SphericalWarperOcl ////////////////////////////////////////
|
|
||||||
|
|
||||||
Rect SphericalWarperOcl::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
|
|
||||||
{
|
|
||||||
projector_.setCameraParams(K, R);
|
|
||||||
|
|
||||||
Point dst_tl, dst_br;
|
|
||||||
detectResultRoi(src_size, dst_tl, dst_br);
|
|
||||||
|
|
||||||
if (ocl::useOpenCL())
|
|
||||||
{
|
|
||||||
ocl::Kernel k("buildWarpSphericalMaps", ocl::stitching::warpers_oclsrc);
|
|
||||||
if (!k.empty())
|
|
||||||
{
|
|
||||||
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
|
||||||
xmap.create(dsize, CV_32FC1);
|
|
||||||
ymap.create(dsize, CV_32FC1);
|
|
||||||
|
|
||||||
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv);
|
|
||||||
UMat uxmap = xmap.getUMat(), uymap = ymap.getUMat(), uk_rinv = k_rinv.getUMat(ACCESS_READ);
|
|
||||||
|
|
||||||
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
|
||||||
ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, projector_.scale);
|
|
||||||
|
|
||||||
size_t globalsize[2] = { dsize.width, dsize.height };
|
|
||||||
if (k.run(2, globalsize, NULL, true))
|
|
||||||
return Rect(dst_tl, dst_br);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SphericalWarper::buildMaps(src_size, K, R, xmap, ymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point SphericalWarperOcl::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst)
|
|
||||||
{
|
|
||||||
UMat uxmap, uymap;
|
|
||||||
Rect dst_roi = buildMaps(src.size(), K, R, uxmap, uymap);
|
|
||||||
|
|
||||||
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
|
||||||
UMat udst = dst.getUMat();
|
|
||||||
remap(src, udst, uxmap, uymap, interp_mode, border_mode);
|
|
||||||
|
|
||||||
return dst_roi.tl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////// CylindricalWarperOcl ////////////////////////////////////////
|
|
||||||
|
|
||||||
Rect CylindricalWarperOcl::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap)
|
|
||||||
{
|
|
||||||
projector_.setCameraParams(K, R);
|
|
||||||
|
|
||||||
Point dst_tl, dst_br;
|
|
||||||
detectResultRoi(src_size, dst_tl, dst_br);
|
|
||||||
|
|
||||||
if (ocl::useOpenCL())
|
|
||||||
{
|
|
||||||
ocl::Kernel k("buildWarpCylindricalMaps", ocl::stitching::warpers_oclsrc);
|
|
||||||
if (!k.empty())
|
|
||||||
{
|
|
||||||
Size dsize(dst_br.x - dst_tl.x + 1, dst_br.y - dst_tl.y + 1);
|
|
||||||
xmap.create(dsize, CV_32FC1);
|
|
||||||
ymap.create(dsize, CV_32FC1);
|
|
||||||
|
|
||||||
Mat k_rinv(1, 9, CV_32FC1, projector_.k_rinv);
|
|
||||||
UMat uxmap = xmap.getUMat(), uymap = ymap.getUMat(), uk_rinv = k_rinv.getUMat(ACCESS_READ);
|
|
||||||
|
|
||||||
k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap),
|
|
||||||
ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, projector_.scale);
|
|
||||||
|
|
||||||
size_t globalsize[2] = { dsize.width, dsize.height };
|
|
||||||
if (k.run(2, globalsize, NULL, true))
|
|
||||||
return Rect(dst_tl, dst_br);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CylindricalWarper::buildMaps(src_size, K, R, xmap, ymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point CylindricalWarperOcl::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst)
|
|
||||||
{
|
|
||||||
UMat uxmap, uymap;
|
|
||||||
Rect dst_roi = buildMaps(src.size(), K, R, uxmap, uymap);
|
|
||||||
|
|
||||||
dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type());
|
|
||||||
UMat udst = dst.getUMat();
|
|
||||||
remap(src, udst, uxmap, uymap, interp_mode, border_mode);
|
|
||||||
|
|
||||||
return dst_roi.tl();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cv
|
|
@@ -48,13 +48,11 @@
|
|||||||
namespace cvtest {
|
namespace cvtest {
|
||||||
namespace ocl {
|
namespace ocl {
|
||||||
|
|
||||||
///////////////////////// WarperTestBase ///////////////////////////
|
|
||||||
|
|
||||||
struct WarperTestBase :
|
struct WarperTestBase :
|
||||||
public Test, public TestUtils
|
public Test, public TestUtils
|
||||||
{
|
{
|
||||||
Mat src, dst, xmap, ymap;
|
Mat src, dst, xmap, ymap;
|
||||||
Mat udst, uxmap, uymap;
|
UMat usrc, udst, uxmap, uymap;
|
||||||
Mat K, R;
|
Mat K, R;
|
||||||
|
|
||||||
virtual void generateTestData()
|
virtual void generateTestData()
|
||||||
@@ -62,6 +60,7 @@ struct WarperTestBase :
|
|||||||
Size size = randomSize(1, MAX_VALUE);
|
Size size = randomSize(1, MAX_VALUE);
|
||||||
|
|
||||||
src = randomMat(size, CV_32FC1, -500, 500);
|
src = randomMat(size, CV_32FC1, -500, 500);
|
||||||
|
src.copyTo(usrc);
|
||||||
|
|
||||||
K = Mat::eye(3, 3, CV_32FC1);
|
K = Mat::eye(3, 3, CV_32FC1);
|
||||||
float angle = (float)(30.0 * CV_PI / 180.0);
|
float angle = (float)(30.0 * CV_PI / 180.0);
|
||||||
@@ -81,70 +80,64 @@ struct WarperTestBase :
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////// SphericalWarperOcl /////////////////////////////////////////////////
|
typedef WarperTestBase SphericalWarperTest;
|
||||||
|
|
||||||
typedef WarperTestBase SphericalWarperOclTest;
|
OCL_TEST_F(SphericalWarperTest, Mat)
|
||||||
|
|
||||||
OCL_TEST_F(SphericalWarperOclTest, Mat)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < test_loop_times; j++)
|
for (int j = 0; j < test_loop_times; j++)
|
||||||
{
|
{
|
||||||
generateTestData();
|
generateTestData();
|
||||||
|
|
||||||
Ptr<WarperCreator> creator = makePtr<SphericalWarperOcl>();
|
Ptr<WarperCreator> creator = makePtr<SphericalWarper>();
|
||||||
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
||||||
|
|
||||||
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
||||||
OCL_ON(warper->buildMaps(src.size(), K, R, uxmap, uymap));
|
OCL_ON(warper->buildMaps(usrc.size(), K, R, uxmap, uymap));
|
||||||
|
|
||||||
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
||||||
OCL_ON(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
OCL_ON(warper->warp(usrc, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
||||||
|
|
||||||
Near(1e-4);
|
Near(1e-4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////// CylindricalWarperOcl /////////////////////////////////////////////////
|
typedef WarperTestBase CylindricalWarperTest;
|
||||||
|
|
||||||
typedef WarperTestBase CylindricalWarperOclTest;
|
OCL_TEST_F(CylindricalWarperTest, Mat)
|
||||||
|
|
||||||
OCL_TEST_F(CylindricalWarperOclTest, Mat)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < test_loop_times; j++)
|
for (int j = 0; j < test_loop_times; j++)
|
||||||
{
|
{
|
||||||
generateTestData();
|
generateTestData();
|
||||||
|
|
||||||
Ptr<WarperCreator> creator = makePtr<CylindricalWarperOcl>();
|
Ptr<WarperCreator> creator = makePtr<CylindricalWarper>();
|
||||||
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
||||||
|
|
||||||
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
||||||
OCL_ON(warper->buildMaps(src.size(), K, R, uxmap, uymap));
|
OCL_ON(warper->buildMaps(usrc.size(), K, R, uxmap, uymap));
|
||||||
|
|
||||||
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
||||||
OCL_ON(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
OCL_ON(warper->warp(usrc, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
||||||
|
|
||||||
Near(1e-4);
|
Near(1e-4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////// PlaneWarperOcl /////////////////////////////////////////////////
|
typedef WarperTestBase PlaneWarperTest;
|
||||||
|
|
||||||
typedef WarperTestBase PlaneWarperOclTest;
|
OCL_TEST_F(PlaneWarperTest, Mat)
|
||||||
|
|
||||||
OCL_TEST_F(PlaneWarperOclTest, Mat)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < test_loop_times; j++)
|
for (int j = 0; j < test_loop_times; j++)
|
||||||
{
|
{
|
||||||
generateTestData();
|
generateTestData();
|
||||||
|
|
||||||
Ptr<WarperCreator> creator = makePtr<PlaneWarperOcl>();
|
Ptr<WarperCreator> creator = makePtr<PlaneWarper>();
|
||||||
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
Ptr<detail::RotationWarper> warper = creator->create(2.0);
|
||||||
|
|
||||||
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
|
||||||
OCL_ON(warper->buildMaps(src.size(), K, R, uxmap, uymap));
|
OCL_ON(warper->buildMaps(usrc.size(), K, R, uxmap, uymap));
|
||||||
|
|
||||||
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
|
||||||
OCL_ON(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
OCL_ON(warper->warp(usrc, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));
|
||||||
|
|
||||||
Near(1e-4);
|
Near(1e-4);
|
||||||
}
|
}
|
||||||
|
@@ -74,9 +74,6 @@ static void printUsage()
|
|||||||
" --try_cuda (yes|no)\n"
|
" --try_cuda (yes|no)\n"
|
||||||
" Try to use CUDA. The default value is 'no'. All default values\n"
|
" Try to use CUDA. The default value is 'no'. All default values\n"
|
||||||
" are for CPU mode.\n"
|
" are for CPU mode.\n"
|
||||||
" --try_ocl (yes|no)\n"
|
|
||||||
" Try to use OpenCL. The default value is 'no'. All default values\n"
|
|
||||||
" are for CPU mode.\n"
|
|
||||||
"\nMotion Estimation Flags:\n"
|
"\nMotion Estimation Flags:\n"
|
||||||
" --work_megapix <float>\n"
|
" --work_megapix <float>\n"
|
||||||
" Resolution for image registration step. The default is 0.6 Mpx.\n"
|
" Resolution for image registration step. The default is 0.6 Mpx.\n"
|
||||||
@@ -127,7 +124,6 @@ static void printUsage()
|
|||||||
vector<String> img_names;
|
vector<String> img_names;
|
||||||
bool preview = false;
|
bool preview = false;
|
||||||
bool try_cuda = false;
|
bool try_cuda = false;
|
||||||
bool try_ocl = false;
|
|
||||||
double work_megapix = 0.6;
|
double work_megapix = 0.6;
|
||||||
double seam_megapix = 0.1;
|
double seam_megapix = 0.1;
|
||||||
double compose_megapix = -1;
|
double compose_megapix = -1;
|
||||||
@@ -178,19 +174,6 @@ static int parseCmdArgs(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if (string(argv[i]) == "--try_ocl")
|
|
||||||
{
|
|
||||||
if (string(argv[i + 1]) == "no")
|
|
||||||
try_ocl = false;
|
|
||||||
else if (string(argv[i + 1]) == "yes")
|
|
||||||
try_ocl = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cout << "Bad --try_ocl flag value\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (string(argv[i]) == "--work_megapix")
|
else if (string(argv[i]) == "--work_megapix")
|
||||||
{
|
{
|
||||||
work_megapix = atof(argv[i + 1]);
|
work_megapix = atof(argv[i + 1]);
|
||||||
@@ -571,17 +554,8 @@ int main(int argc, char* argv[])
|
|||||||
// Warp images and their masks
|
// Warp images and their masks
|
||||||
|
|
||||||
Ptr<WarperCreator> warper_creator;
|
Ptr<WarperCreator> warper_creator;
|
||||||
if (try_ocl)
|
|
||||||
{
|
|
||||||
if (warp_type == "plane")
|
|
||||||
warper_creator = makePtr<cv::PlaneWarperOcl>();
|
|
||||||
else if (warp_type == "cylindrical")
|
|
||||||
warper_creator = makePtr<cv::CylindricalWarperOcl>();
|
|
||||||
else if (warp_type == "spherical")
|
|
||||||
warper_creator = makePtr<cv::SphericalWarperOcl>();
|
|
||||||
}
|
|
||||||
#ifdef HAVE_OPENCV_CUDAWARPING
|
#ifdef HAVE_OPENCV_CUDAWARPING
|
||||||
else if (try_cuda && cuda::getCudaEnabledDeviceCount() > 0)
|
if (try_cuda && cuda::getCudaEnabledDeviceCount() > 0)
|
||||||
{
|
{
|
||||||
if (warp_type == "plane")
|
if (warp_type == "plane")
|
||||||
warper_creator = makePtr<cv::PlaneWarperGpu>();
|
warper_creator = makePtr<cv::PlaneWarperGpu>();
|
||||||
|
Reference in New Issue
Block a user