Merge pull request #2565 from apavlenko:tapi_stitching
This commit is contained in:
commit
dab8e920b0
@ -218,6 +218,9 @@ public:
|
|||||||
virtual void release() const;
|
virtual void release() const;
|
||||||
virtual void clear() const;
|
virtual void clear() const;
|
||||||
virtual void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const;
|
virtual void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const;
|
||||||
|
|
||||||
|
void assign(const UMat& u) const;
|
||||||
|
void assign(const Mat& m) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -598,6 +598,8 @@ CV_EXPORTS int predictOptimalVectorWidth(InputArray src1, InputArray src2 = noAr
|
|||||||
InputArray src4 = noArray(), InputArray src5 = noArray(), InputArray src6 = noArray(),
|
InputArray src4 = noArray(), InputArray src5 = noArray(), InputArray src6 = noArray(),
|
||||||
InputArray src7 = noArray(), InputArray src8 = noArray(), InputArray src9 = noArray());
|
InputArray src7 = noArray(), InputArray src8 = noArray(), InputArray src9 = noArray());
|
||||||
|
|
||||||
|
CV_EXPORTS void buildOptionsAddMatrixDescription(String& buildOptions, const String& name, InputArray _m);
|
||||||
|
|
||||||
class CV_EXPORTS Image2D
|
class CV_EXPORTS Image2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1369,6 +1369,21 @@ void _InputArray::getUMatVector(std::vector<UMat>& umv) const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( k == UMAT )
|
||||||
|
{
|
||||||
|
UMat& v = *(UMat*)obj;
|
||||||
|
umv.resize(1);
|
||||||
|
umv[0] = v;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( k == MAT )
|
||||||
|
{
|
||||||
|
Mat& v = *(Mat*)obj;
|
||||||
|
umv.resize(1);
|
||||||
|
umv[0] = v.getUMat(accessFlags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2592,6 +2607,43 @@ void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
|
|||||||
CV_Error(Error::StsNotImplemented, "");
|
CV_Error(Error::StsNotImplemented, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _OutputArray::assign(const UMat& u) const
|
||||||
|
{
|
||||||
|
int k = kind();
|
||||||
|
if (k == UMAT)
|
||||||
|
{
|
||||||
|
*(UMat*)obj = u;
|
||||||
|
}
|
||||||
|
else if (k == MAT)
|
||||||
|
{
|
||||||
|
u.copyTo(*(Mat*)obj); // TODO check u.getMat()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsNotImplemented, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _OutputArray::assign(const Mat& m) const
|
||||||
|
{
|
||||||
|
int k = kind();
|
||||||
|
if (k == UMAT)
|
||||||
|
{
|
||||||
|
m.copyTo(*(UMat*)obj); // TODO check m.getUMat()
|
||||||
|
}
|
||||||
|
else if (k == MAT)
|
||||||
|
{
|
||||||
|
*(Mat*)obj = m;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsNotImplemented, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static _InputOutputArray _none;
|
static _InputOutputArray _none;
|
||||||
InputOutputArray noArray() { return _none; }
|
InputOutputArray noArray() { return _none; }
|
||||||
|
|
||||||
|
@ -3798,11 +3798,16 @@ public:
|
|||||||
|
|
||||||
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
|
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
|
||||||
|
|
||||||
if( u->refcount == 0 )
|
// FIXIT Workaround for UMat synchronization issue
|
||||||
|
// if( u->refcount == 0 )
|
||||||
{
|
{
|
||||||
if( !u->copyOnMap() )
|
if( !u->copyOnMap() )
|
||||||
{
|
{
|
||||||
CV_Assert(u->data == 0);
|
if (u->data) // FIXIT Workaround for UMat synchronization issue
|
||||||
|
{
|
||||||
|
//CV_Assert(u->hostCopyObsolete() == false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// because there can be other map requests for the same UMat with different access flags,
|
// because there can be other map requests for the same UMat with different access flags,
|
||||||
// we use the universal (read-write) access mode.
|
// we use the universal (read-write) access mode.
|
||||||
cl_int retval = 0;
|
cl_int retval = 0;
|
||||||
@ -3844,6 +3849,10 @@ public:
|
|||||||
|
|
||||||
UMatDataAutoLock autolock(u);
|
UMatDataAutoLock autolock(u);
|
||||||
|
|
||||||
|
// FIXIT Workaround for UMat synchronization issue
|
||||||
|
if(u->refcount > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
|
cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
|
||||||
cl_int retval = 0;
|
cl_int retval = 0;
|
||||||
if( !u->copyOnMap() && u->data )
|
if( !u->copyOnMap() && u->data )
|
||||||
@ -4404,7 +4413,24 @@ int predictOptimalVectorWidth(InputArray src1, InputArray src2, InputArray src3,
|
|||||||
|
|
||||||
#undef PROCESS_SRC
|
#undef PROCESS_SRC
|
||||||
|
|
||||||
/////////////////////////////////////////// Image2D ////////////////////////////////////////////////////
|
|
||||||
|
// TODO Make this as a method of OpenCL "BuildOptions" class
|
||||||
|
void buildOptionsAddMatrixDescription(String& buildOptions, const String& name, InputArray _m)
|
||||||
|
{
|
||||||
|
if (!buildOptions.empty())
|
||||||
|
buildOptions += " ";
|
||||||
|
int type = _m.type(), depth = CV_MAT_DEPTH(type);
|
||||||
|
buildOptions += format(
|
||||||
|
"-D %s_T=%s -D %s_T1=%s -D %s_CN=%d -D %s_TSIZE=%d -D %s_T1SIZE=%d -D %s_DEPTH=%d",
|
||||||
|
name.c_str(), ocl::typeToStr(type),
|
||||||
|
name.c_str(), ocl::typeToStr(CV_MAKE_TYPE(depth, 1)),
|
||||||
|
name.c_str(), (int)CV_MAT_CN(type),
|
||||||
|
name.c_str(), (int)CV_ELEM_SIZE(type),
|
||||||
|
name.c_str(), (int)CV_ELEM_SIZE1(type),
|
||||||
|
name.c_str(), (int)depth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Image2D::Impl
|
struct Image2D::Impl
|
||||||
{
|
{
|
||||||
|
@ -330,7 +330,7 @@ static bool ocl_match2Dispatcher(InputArray query, InputArray train, const UMat
|
|||||||
static bool ocl_kmatchDispatcher(InputArray query, InputArray train, const UMat &trainIdx,
|
static bool ocl_kmatchDispatcher(InputArray query, InputArray train, const UMat &trainIdx,
|
||||||
const UMat &distance, int distType)
|
const UMat &distance, int distType)
|
||||||
{
|
{
|
||||||
return ocl_match2Dispatcher(query, train, trainIdx, distance, distType);
|
return ocl_match2Dispatcher(query, train, trainIdx, distance, distType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainIdx,
|
static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainIdx,
|
||||||
@ -1209,8 +1209,8 @@ FlannBasedMatcher::FlannBasedMatcher( const Ptr<flann::IndexParams>& _indexParam
|
|||||||
void FlannBasedMatcher::add( InputArrayOfArrays _descriptors )
|
void FlannBasedMatcher::add( InputArrayOfArrays _descriptors )
|
||||||
{
|
{
|
||||||
DescriptorMatcher::add( _descriptors );
|
DescriptorMatcher::add( _descriptors );
|
||||||
std::vector<Mat> descriptors;
|
std::vector<UMat> descriptors;
|
||||||
_descriptors.getMatVector(descriptors);
|
_descriptors.getUMatVector(descriptors);
|
||||||
|
|
||||||
for( size_t i = 0; i < descriptors.size(); i++ )
|
for( size_t i = 0; i < descriptors.size(); i++ )
|
||||||
{
|
{
|
||||||
@ -1232,6 +1232,13 @@ void FlannBasedMatcher::train()
|
|||||||
{
|
{
|
||||||
if( !flannIndex || mergedDescriptors.size() < addedDescCount )
|
if( !flannIndex || mergedDescriptors.size() < addedDescCount )
|
||||||
{
|
{
|
||||||
|
// FIXIT: Workaround for 'utrainDescCollection' issue (PR #2142)
|
||||||
|
if (!utrainDescCollection.empty())
|
||||||
|
{
|
||||||
|
CV_Assert(trainDescCollection.size() == 0);
|
||||||
|
for (size_t i = 0; i < utrainDescCollection.size(); ++i)
|
||||||
|
trainDescCollection.push_back(utrainDescCollection[i].getMat(ACCESS_READ));
|
||||||
|
}
|
||||||
mergedDescriptors.set( trainDescCollection );
|
mergedDescriptors.set( trainDescCollection );
|
||||||
flannIndex = makePtr<flann::Index>( mergedDescriptors.getDescriptors(), *indexParams );
|
flannIndex = makePtr<flann::Index>( mergedDescriptors.getDescriptors(), *indexParams );
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ detail::Blender::feed
|
|||||||
|
|
||||||
Processes the image.
|
Processes the image.
|
||||||
|
|
||||||
.. ocv:function:: void detail::Blender::feed(const Mat &img, const Mat &mask, Point tl)
|
.. ocv:function:: void detail::Blender::feed(InputArray img, InputArray mask, Point tl)
|
||||||
|
|
||||||
:param img: Source image
|
:param img: Source image
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ detail::Blender::blend
|
|||||||
|
|
||||||
Blends and returns the final pano.
|
Blends and returns the final pano.
|
||||||
|
|
||||||
.. ocv:function:: void detail::Blender::blend(Mat &dst, Mat &dst_mask)
|
.. ocv:function:: void detail::Blender::blend(InputOutputArray dst, InputOutputArray dst_mask)
|
||||||
|
|
||||||
:param dst: Final pano
|
:param dst: Final pano
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ Base class for all exposure compensators. ::
|
|||||||
detail::ExposureCompensator::feed
|
detail::ExposureCompensator::feed
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
.. ocv:function:: void detail::ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<Mat> &images, const std::vector<Mat> &masks)
|
.. ocv:function:: void detail::ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images, const std::vector<UMat> &masks)
|
||||||
|
|
||||||
.. ocv:function:: void detail::ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<Mat> &images, const std::vector<std::pair<Mat,uchar> > &masks)
|
.. ocv:function:: void detail::ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images, const std::vector<std::pair<UMat,uchar> > &masks)
|
||||||
|
|
||||||
:param corners: Source image top-left corners
|
:param corners: Source image top-left corners
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ detil::ExposureCompensator::apply
|
|||||||
|
|
||||||
Compensate exposure in the specified image.
|
Compensate exposure in the specified image.
|
||||||
|
|
||||||
.. ocv:function:: void detail::ExposureCompensator::apply(int index, Point corner, Mat &image, const Mat &mask)
|
.. ocv:function:: void detail::ExposureCompensator::apply(int index, Point corner, InputOutputArray image, InputArray mask)
|
||||||
|
|
||||||
:param index: Image index
|
:param index: Image index
|
||||||
|
|
||||||
|
@ -110,9 +110,9 @@ These functions try to match the given images and to estimate rotations of each
|
|||||||
|
|
||||||
.. note:: Use the functions only if you're aware of the stitching pipeline, otherwise use :ocv:func:`Stitcher::stitch`.
|
.. note:: Use the functions only if you're aware of the stitching pipeline, otherwise use :ocv:func:`Stitcher::stitch`.
|
||||||
|
|
||||||
.. ocv:function:: Status Stitcher::estimateTransform(InputArray images)
|
.. ocv:function:: Status Stitcher::estimateTransform(InputArrayOfArrays images)
|
||||||
|
|
||||||
.. ocv:function:: Status Stitcher::estimateTransform(InputArray images, const std::vector<std::vector<Rect> > &rois)
|
.. ocv:function:: Status Stitcher::estimateTransform(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois)
|
||||||
|
|
||||||
:param images: Input images.
|
:param images: Input images.
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ These functions try to compose the given images (or images stored internally fro
|
|||||||
|
|
||||||
.. ocv:function:: Status Stitcher::composePanorama(OutputArray pano)
|
.. ocv:function:: Status Stitcher::composePanorama(OutputArray pano)
|
||||||
|
|
||||||
.. ocv:function:: Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
.. ocv:function:: Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArray pano)
|
||||||
|
|
||||||
:param images: Input images.
|
:param images: Input images.
|
||||||
|
|
||||||
@ -142,9 +142,9 @@ Stitcher::stitch
|
|||||||
|
|
||||||
These functions try to stitch the given images.
|
These functions try to stitch the given images.
|
||||||
|
|
||||||
.. ocv:function:: Status Stitcher::stitch(InputArray images, OutputArray pano)
|
.. ocv:function:: Status Stitcher::stitch(InputArrayOfArrays images, OutputArray pano)
|
||||||
|
|
||||||
.. ocv:function:: Status Stitcher::stitch(InputArray images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
|
.. ocv:function:: Status Stitcher::stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
|
||||||
|
|
||||||
:param images: Input images.
|
:param images: Input images.
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ detail::FeaturesFinder::operator()
|
|||||||
|
|
||||||
Finds features in the given image.
|
Finds features in the given image.
|
||||||
|
|
||||||
.. ocv:function:: void detail::FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features)
|
.. ocv:function:: void detail::FeaturesFinder::operator ()(InputArray image, ImageFeatures &features)
|
||||||
|
|
||||||
.. ocv:function:: void detail::FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features, const std::vector<cv::Rect> &rois)
|
.. ocv:function:: void detail::FeaturesFinder::operator ()(InputArray image, ImageFeatures &features, const std::vector<cv::Rect> &rois)
|
||||||
|
|
||||||
:param image: Source image
|
:param image: Source image
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ detail::FeaturesFinder::find
|
|||||||
|
|
||||||
This method must implement features finding logic in order to make the wrappers `detail::FeaturesFinder::operator()`_ work.
|
This method must implement features finding logic in order to make the wrappers `detail::FeaturesFinder::operator()`_ work.
|
||||||
|
|
||||||
.. ocv:function:: void detail::FeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
.. ocv:function:: void detail::FeaturesFinder::find(InputArray image, ImageFeatures &features)
|
||||||
|
|
||||||
:param image: Source image
|
:param image: Source image
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ Performs images matching.
|
|||||||
|
|
||||||
:param matches_info: Found matches
|
:param matches_info: Found matches
|
||||||
|
|
||||||
.. ocv:function:: void detail::FeaturesMatcher::operator ()( const std::vector<ImageFeatures> & features, std::vector<MatchesInfo> & pairwise_matches, const Mat & mask=Mat() )
|
.. ocv:function:: void detail::FeaturesMatcher::operator ()( const std::vector<ImageFeatures> & features, std::vector<MatchesInfo> & pairwise_matches, const UMat & mask=UMat() )
|
||||||
|
|
||||||
:param features: Features of the source images
|
:param features: Features of the source images
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ detail::SeamFinder::find
|
|||||||
|
|
||||||
Estimates seams.
|
Estimates seams.
|
||||||
|
|
||||||
.. ocv:function:: void detail::SeamFinder::find(const std::vector<Mat> &src, const std::vector<Point> &corners, std::vector<Mat> &masks)
|
.. ocv:function:: void detail::SeamFinder::find(const std::vector<UMat> &src, const std::vector<Point> &corners, std::vector<UMat> &masks)
|
||||||
|
|
||||||
:param src: Source images
|
:param src: Source images
|
||||||
|
|
||||||
|
@ -98,8 +98,8 @@ public:
|
|||||||
void setFeaturesMatcher(Ptr<detail::FeaturesMatcher> features_matcher)
|
void setFeaturesMatcher(Ptr<detail::FeaturesMatcher> features_matcher)
|
||||||
{ features_matcher_ = features_matcher; }
|
{ features_matcher_ = features_matcher; }
|
||||||
|
|
||||||
const cv::Mat& matchingMask() const { return matching_mask_; }
|
const cv::UMat& matchingMask() const { return matching_mask_; }
|
||||||
void setMatchingMask(const cv::Mat &mask)
|
void setMatchingMask(const cv::UMat &mask)
|
||||||
{
|
{
|
||||||
CV_Assert(mask.type() == CV_8U && mask.cols == mask.rows);
|
CV_Assert(mask.type() == CV_8U && mask.cols == mask.rows);
|
||||||
matching_mask_ = mask.clone();
|
matching_mask_ = mask.clone();
|
||||||
@ -127,14 +127,14 @@ public:
|
|||||||
const Ptr<detail::Blender> blender() const { return blender_; }
|
const Ptr<detail::Blender> blender() const { return blender_; }
|
||||||
void setBlender(Ptr<detail::Blender> b) { blender_ = b; }
|
void setBlender(Ptr<detail::Blender> b) { blender_ = b; }
|
||||||
|
|
||||||
Status estimateTransform(InputArray images);
|
Status estimateTransform(InputArrayOfArrays images);
|
||||||
Status estimateTransform(InputArray images, const std::vector<std::vector<Rect> > &rois);
|
Status estimateTransform(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois);
|
||||||
|
|
||||||
Status composePanorama(OutputArray pano);
|
Status composePanorama(OutputArray pano);
|
||||||
Status composePanorama(InputArray images, OutputArray pano);
|
Status composePanorama(InputArrayOfArrays images, OutputArray pano);
|
||||||
|
|
||||||
Status stitch(InputArray images, OutputArray pano);
|
Status stitch(InputArrayOfArrays images, OutputArray pano);
|
||||||
Status stitch(InputArray images, const std::vector<std::vector<Rect> > &rois, OutputArray pano);
|
Status stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano);
|
||||||
|
|
||||||
std::vector<int> component() const { return indices_; }
|
std::vector<int> component() const { return indices_; }
|
||||||
std::vector<detail::CameraParams> cameras() const { return cameras_; }
|
std::vector<detail::CameraParams> cameras() const { return cameras_; }
|
||||||
@ -152,7 +152,7 @@ private:
|
|||||||
double conf_thresh_;
|
double conf_thresh_;
|
||||||
Ptr<detail::FeaturesFinder> features_finder_;
|
Ptr<detail::FeaturesFinder> features_finder_;
|
||||||
Ptr<detail::FeaturesMatcher> features_matcher_;
|
Ptr<detail::FeaturesMatcher> features_matcher_;
|
||||||
cv::Mat matching_mask_;
|
cv::UMat matching_mask_;
|
||||||
Ptr<detail::BundleAdjusterBase> bundle_adjuster_;
|
Ptr<detail::BundleAdjusterBase> bundle_adjuster_;
|
||||||
bool do_wave_correct_;
|
bool do_wave_correct_;
|
||||||
detail::WaveCorrectKind wave_correct_kind_;
|
detail::WaveCorrectKind wave_correct_kind_;
|
||||||
@ -161,12 +161,12 @@ private:
|
|||||||
Ptr<detail::SeamFinder> seam_finder_;
|
Ptr<detail::SeamFinder> seam_finder_;
|
||||||
Ptr<detail::Blender> blender_;
|
Ptr<detail::Blender> blender_;
|
||||||
|
|
||||||
std::vector<cv::Mat> imgs_;
|
std::vector<cv::UMat> imgs_;
|
||||||
std::vector<std::vector<cv::Rect> > rois_;
|
std::vector<std::vector<cv::Rect> > rois_;
|
||||||
std::vector<cv::Size> full_img_sizes_;
|
std::vector<cv::Size> full_img_sizes_;
|
||||||
std::vector<detail::ImageFeatures> features_;
|
std::vector<detail::ImageFeatures> features_;
|
||||||
std::vector<detail::MatchesInfo> pairwise_matches_;
|
std::vector<detail::MatchesInfo> pairwise_matches_;
|
||||||
std::vector<cv::Mat> seam_est_imgs_;
|
std::vector<cv::UMat> seam_est_imgs_;
|
||||||
std::vector<int> indices_;
|
std::vector<int> indices_;
|
||||||
std::vector<detail::CameraParams> cameras_;
|
std::vector<detail::CameraParams> cameras_;
|
||||||
double work_scale_;
|
double work_scale_;
|
||||||
|
@ -60,11 +60,11 @@ public:
|
|||||||
|
|
||||||
void prepare(const std::vector<Point> &corners, const std::vector<Size> &sizes);
|
void prepare(const std::vector<Point> &corners, const std::vector<Size> &sizes);
|
||||||
virtual void prepare(Rect dst_roi);
|
virtual void prepare(Rect dst_roi);
|
||||||
virtual void feed(const Mat &img, const Mat &mask, Point tl);
|
virtual void feed(InputArray img, InputArray mask, Point tl);
|
||||||
virtual void blend(Mat &dst, Mat &dst_mask);
|
virtual void blend(InputOutputArray dst, InputOutputArray dst_mask);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Mat dst_, dst_mask_;
|
UMat dst_, dst_mask_;
|
||||||
Rect dst_roi_;
|
Rect dst_roi_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,18 +78,18 @@ public:
|
|||||||
void setSharpness(float val) { sharpness_ = val; }
|
void setSharpness(float val) { sharpness_ = val; }
|
||||||
|
|
||||||
void prepare(Rect dst_roi);
|
void prepare(Rect dst_roi);
|
||||||
void feed(const Mat &img, const Mat &mask, Point tl);
|
void feed(InputArray img, InputArray mask, Point tl);
|
||||||
void blend(Mat &dst, Mat &dst_mask);
|
void blend(InputOutputArray dst, InputOutputArray dst_mask);
|
||||||
|
|
||||||
// Creates weight maps for fixed set of source images by their masks and top-left corners.
|
// Creates weight maps for fixed set of source images by their masks and top-left corners.
|
||||||
// Final image can be obtained by simple weighting of the source images.
|
// Final image can be obtained by simple weighting of the source images.
|
||||||
Rect createWeightMaps(const std::vector<Mat> &masks, const std::vector<Point> &corners,
|
Rect createWeightMaps(const std::vector<UMat> &masks, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &weight_maps);
|
std::vector<UMat> &weight_maps);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float sharpness_;
|
float sharpness_;
|
||||||
Mat weight_map_;
|
UMat weight_map_;
|
||||||
Mat dst_weight_map_;
|
UMat dst_weight_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline FeatherBlender::FeatherBlender(float _sharpness) { setSharpness(_sharpness); }
|
inline FeatherBlender::FeatherBlender(float _sharpness) { setSharpness(_sharpness); }
|
||||||
@ -104,13 +104,13 @@ public:
|
|||||||
void setNumBands(int val) { actual_num_bands_ = val; }
|
void setNumBands(int val) { actual_num_bands_ = val; }
|
||||||
|
|
||||||
void prepare(Rect dst_roi);
|
void prepare(Rect dst_roi);
|
||||||
void feed(const Mat &img, const Mat &mask, Point tl);
|
void feed(InputArray img, InputArray mask, Point tl);
|
||||||
void blend(Mat &dst, Mat &dst_mask);
|
void blend(InputOutputArray dst, InputOutputArray dst_mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int actual_num_bands_, num_bands_;
|
int actual_num_bands_, num_bands_;
|
||||||
std::vector<Mat> dst_pyr_laplace_;
|
std::vector<UMat> dst_pyr_laplace_;
|
||||||
std::vector<Mat> dst_band_weights_;
|
std::vector<UMat> dst_band_weights_;
|
||||||
Rect dst_roi_final_;
|
Rect dst_roi_final_;
|
||||||
bool can_use_gpu_;
|
bool can_use_gpu_;
|
||||||
int weight_type_; //CV_32F or CV_16S
|
int weight_type_; //CV_32F or CV_16S
|
||||||
@ -120,16 +120,16 @@ private:
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Auxiliary functions
|
// Auxiliary functions
|
||||||
|
|
||||||
void CV_EXPORTS normalizeUsingWeightMap(const Mat& weight, Mat& src);
|
void CV_EXPORTS normalizeUsingWeightMap(InputArray weight, InputOutputArray src);
|
||||||
|
|
||||||
void CV_EXPORTS createWeightMap(const Mat& mask, float sharpness, Mat& weight);
|
void CV_EXPORTS createWeightMap(InputArray mask, float sharpness, InputOutputArray weight);
|
||||||
|
|
||||||
void CV_EXPORTS createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat>& pyr);
|
void CV_EXPORTS createLaplacePyr(InputArray img, int num_levels, std::vector<UMat>& pyr);
|
||||||
void CV_EXPORTS createLaplacePyrGpu(const Mat &img, int num_levels, std::vector<Mat>& pyr);
|
void CV_EXPORTS createLaplacePyrGpu(InputArray img, int num_levels, std::vector<UMat>& pyr);
|
||||||
|
|
||||||
// Restores source image
|
// Restores source image
|
||||||
void CV_EXPORTS restoreImageFromLaplacePyr(std::vector<Mat>& pyr);
|
void CV_EXPORTS restoreImageFromLaplacePyr(std::vector<UMat>& pyr);
|
||||||
void CV_EXPORTS restoreImageFromLaplacePyrGpu(std::vector<Mat>& pyr);
|
void CV_EXPORTS restoreImageFromLaplacePyrGpu(std::vector<UMat>& pyr);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -56,29 +56,29 @@ public:
|
|||||||
enum { NO, GAIN, GAIN_BLOCKS };
|
enum { NO, GAIN, GAIN_BLOCKS };
|
||||||
static Ptr<ExposureCompensator> createDefault(int type);
|
static Ptr<ExposureCompensator> createDefault(int type);
|
||||||
|
|
||||||
void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<Mat> &masks);
|
const std::vector<UMat> &masks);
|
||||||
virtual void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
virtual void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<std::pair<Mat,uchar> > &masks) = 0;
|
const std::vector<std::pair<UMat,uchar> > &masks) = 0;
|
||||||
virtual void apply(int index, Point corner, Mat &image, const Mat &mask) = 0;
|
virtual void apply(int index, Point corner, InputOutputArray image, InputArray mask) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CV_EXPORTS NoExposureCompensator : public ExposureCompensator
|
class CV_EXPORTS NoExposureCompensator : public ExposureCompensator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void feed(const std::vector<Point> &/*corners*/, const std::vector<Mat> &/*images*/,
|
void feed(const std::vector<Point> &/*corners*/, const std::vector<UMat> &/*images*/,
|
||||||
const std::vector<std::pair<Mat,uchar> > &/*masks*/) { }
|
const std::vector<std::pair<UMat,uchar> > &/*masks*/) { }
|
||||||
void apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/) { }
|
void apply(int /*index*/, Point /*corner*/, InputOutputArray /*image*/, InputArray /*mask*/) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CV_EXPORTS GainCompensator : public ExposureCompensator
|
class CV_EXPORTS GainCompensator : public ExposureCompensator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<std::pair<Mat,uchar> > &masks);
|
const std::vector<std::pair<UMat,uchar> > &masks);
|
||||||
void apply(int index, Point corner, Mat &image, const Mat &mask);
|
void apply(int index, Point corner, InputOutputArray image, InputArray mask);
|
||||||
std::vector<double> gains() const;
|
std::vector<double> gains() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -91,13 +91,13 @@ class CV_EXPORTS BlocksGainCompensator : public ExposureCompensator
|
|||||||
public:
|
public:
|
||||||
BlocksGainCompensator(int bl_width = 32, int bl_height = 32)
|
BlocksGainCompensator(int bl_width = 32, int bl_height = 32)
|
||||||
: bl_width_(bl_width), bl_height_(bl_height) {}
|
: bl_width_(bl_width), bl_height_(bl_height) {}
|
||||||
void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<std::pair<Mat,uchar> > &masks);
|
const std::vector<std::pair<UMat,uchar> > &masks);
|
||||||
void apply(int index, Point corner, Mat &image, const Mat &mask);
|
void apply(int index, Point corner, InputOutputArray image, InputArray mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int bl_width_, bl_height_;
|
int bl_width_, bl_height_;
|
||||||
std::vector<Mat_<float> > gain_maps_;
|
std::vector<UMat> gain_maps_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
@ -60,7 +60,7 @@ struct CV_EXPORTS ImageFeatures
|
|||||||
int img_idx;
|
int img_idx;
|
||||||
Size img_size;
|
Size img_size;
|
||||||
std::vector<KeyPoint> keypoints;
|
std::vector<KeyPoint> keypoints;
|
||||||
Mat descriptors;
|
UMat descriptors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -68,12 +68,12 @@ class CV_EXPORTS FeaturesFinder
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~FeaturesFinder() {}
|
virtual ~FeaturesFinder() {}
|
||||||
void operator ()(const Mat &image, ImageFeatures &features);
|
void operator ()(InputArray image, ImageFeatures &features);
|
||||||
void operator ()(const Mat &image, ImageFeatures &features, const std::vector<cv::Rect> &rois);
|
void operator ()(InputArray image, ImageFeatures &features, const std::vector<cv::Rect> &rois);
|
||||||
virtual void collectGarbage() {}
|
virtual void collectGarbage() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void find(const Mat &image, ImageFeatures &features) = 0;
|
virtual void find(InputArray image, ImageFeatures &features) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ public:
|
|||||||
int num_octaves_descr = /*4*/3, int num_layers_descr = /*2*/4);
|
int num_octaves_descr = /*4*/3, int num_layers_descr = /*2*/4);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
void find(InputArray image, ImageFeatures &features);
|
||||||
|
|
||||||
Ptr<FeatureDetector> detector_;
|
Ptr<FeatureDetector> detector_;
|
||||||
Ptr<DescriptorExtractor> extractor_;
|
Ptr<DescriptorExtractor> extractor_;
|
||||||
@ -97,7 +97,7 @@ public:
|
|||||||
OrbFeaturesFinder(Size _grid_size = Size(3,1), int nfeatures=1500, float scaleFactor=1.3f, int nlevels=5);
|
OrbFeaturesFinder(Size _grid_size = Size(3,1), int nfeatures=1500, float scaleFactor=1.3f, int nlevels=5);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
void find(InputArray image, ImageFeatures &features);
|
||||||
|
|
||||||
Ptr<ORB> orb;
|
Ptr<ORB> orb;
|
||||||
Size grid_size;
|
Size grid_size;
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
void collectGarbage();
|
void collectGarbage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
void find(InputArray image, ImageFeatures &features);
|
||||||
|
|
||||||
cuda::GpuMat image_;
|
cuda::GpuMat image_;
|
||||||
cuda::GpuMat gray_image_;
|
cuda::GpuMat gray_image_;
|
||||||
@ -151,7 +151,7 @@ public:
|
|||||||
MatchesInfo& matches_info) { match(features1, features2, matches_info); }
|
MatchesInfo& matches_info) { match(features1, features2, matches_info); }
|
||||||
|
|
||||||
void operator ()(const std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
|
void operator ()(const std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
|
||||||
const cv::Mat &mask = cv::Mat());
|
const cv::UMat &mask = cv::UMat());
|
||||||
|
|
||||||
bool isThreadSafe() const { return is_thread_safe_; }
|
bool isThreadSafe() const { return is_thread_safe_; }
|
||||||
|
|
||||||
|
@ -54,32 +54,32 @@ class CV_EXPORTS SeamFinder
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~SeamFinder() {}
|
virtual ~SeamFinder() {}
|
||||||
virtual void find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks) = 0;
|
std::vector<UMat> &masks) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CV_EXPORTS NoSeamFinder : public SeamFinder
|
class CV_EXPORTS NoSeamFinder : public SeamFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void find(const std::vector<Mat>&, const std::vector<Point>&, std::vector<Mat>&) {}
|
void find(const std::vector<UMat>&, const std::vector<Point>&, std::vector<UMat>&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CV_EXPORTS PairwiseSeamFinder : public SeamFinder
|
class CV_EXPORTS PairwiseSeamFinder : public SeamFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks);
|
std::vector<UMat> &masks);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
virtual void findInPair(size_t first, size_t second, Rect roi) = 0;
|
virtual void findInPair(size_t first, size_t second, Rect roi) = 0;
|
||||||
|
|
||||||
std::vector<Mat> images_;
|
std::vector<UMat> images_;
|
||||||
std::vector<Size> sizes_;
|
std::vector<Size> sizes_;
|
||||||
std::vector<Point> corners_;
|
std::vector<Point> corners_;
|
||||||
std::vector<Mat> masks_;
|
std::vector<UMat> masks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class CV_EXPORTS VoronoiSeamFinder : public PairwiseSeamFinder
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void find(const std::vector<Size> &size, const std::vector<Point> &corners,
|
virtual void find(const std::vector<Size> &size, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks);
|
std::vector<UMat> &masks);
|
||||||
private:
|
private:
|
||||||
void findInPair(size_t first, size_t second, Rect roi);
|
void findInPair(size_t first, size_t second, Rect roi);
|
||||||
};
|
};
|
||||||
@ -103,8 +103,8 @@ public:
|
|||||||
CostFunction costFunction() const { return costFunc_; }
|
CostFunction costFunction() const { return costFunc_; }
|
||||||
void setCostFunction(CostFunction val) { costFunc_ = val; }
|
void setCostFunction(CostFunction val) { costFunc_ = val; }
|
||||||
|
|
||||||
virtual void find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks);
|
std::vector<UMat> &masks);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ComponentState
|
enum ComponentState
|
||||||
@ -154,7 +154,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void process(
|
void process(
|
||||||
const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2);
|
const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2);
|
||||||
|
|
||||||
void findComponents();
|
void findComponents();
|
||||||
|
|
||||||
@ -217,8 +217,8 @@ public:
|
|||||||
|
|
||||||
~GraphCutSeamFinder();
|
~GraphCutSeamFinder();
|
||||||
|
|
||||||
void find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks);
|
std::vector<UMat> &masks);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// To avoid GCGraph dependency
|
// To avoid GCGraph dependency
|
||||||
@ -236,8 +236,8 @@ public:
|
|||||||
: cost_type_(cost_type), terminal_cost_(terminal_cost),
|
: cost_type_(cost_type), terminal_cost_(terminal_cost),
|
||||||
bad_region_penalty_(bad_region_penalty) {}
|
bad_region_penalty_(bad_region_penalty) {}
|
||||||
|
|
||||||
void find(const std::vector<cv::Mat> &src, const std::vector<cv::Point> &corners,
|
void find(const std::vector<cv::UMat> &src, const std::vector<cv::Point> &corners,
|
||||||
std::vector<cv::Mat> &masks);
|
std::vector<cv::UMat> &masks);
|
||||||
void findInPair(size_t first, size_t second, Rect roi);
|
void findInPair(size_t first, size_t second, Rect roi);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -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); \
|
||||||
@ -145,7 +146,7 @@ private:
|
|||||||
// Auxiliary functions
|
// Auxiliary functions
|
||||||
|
|
||||||
CV_EXPORTS bool overlapRoi(Point tl1, Point tl2, Size sz1, Size sz2, Rect &roi);
|
CV_EXPORTS bool overlapRoi(Point tl1, Point tl2, Size sz1, Size sz2, Rect &roi);
|
||||||
CV_EXPORTS Rect resultRoi(const std::vector<Point> &corners, const std::vector<Mat> &images);
|
CV_EXPORTS Rect resultRoi(const std::vector<Point> &corners, const std::vector<UMat> &images);
|
||||||
CV_EXPORTS Rect resultRoi(const std::vector<Point> &corners, const std::vector<Size> &sizes);
|
CV_EXPORTS Rect resultRoi(const std::vector<Point> &corners, const std::vector<Size> &sizes);
|
||||||
CV_EXPORTS Point resultTl(const std::vector<Point> &corners);
|
CV_EXPORTS Point resultTl(const std::vector<Point> &corners);
|
||||||
|
|
||||||
|
@ -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__
|
||||||
|
144
modules/stitching/perf/opencl/perf_stitch.cpp
Normal file
144
modules/stitching/perf/opencl/perf_stitch.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, Itseez, Inc, all rights reserved.
|
||||||
|
|
||||||
|
#include "perf_precomp.hpp"
|
||||||
|
#include "opencv2/ts/ocl_perf.hpp"
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace perf;
|
||||||
|
using namespace cvtest::ocl;
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::tr1;
|
||||||
|
|
||||||
|
#define SURF_MATCH_CONFIDENCE 0.65f
|
||||||
|
#define ORB_MATCH_CONFIDENCE 0.3f
|
||||||
|
#define WORK_MEGAPIX 0.6
|
||||||
|
|
||||||
|
typedef TestBaseWithParam<string> stitch;
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENCV_NONFREE_TODO_FIND_WHY_SURF_IS_NOT_ABLE_TO_STITCH_PANOS
|
||||||
|
#define TEST_DETECTORS testing::Values("surf", "orb")
|
||||||
|
#else
|
||||||
|
#define TEST_DETECTORS testing::Values<string>("orb")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(stitch, a123, TEST_DETECTORS)
|
||||||
|
{
|
||||||
|
UMat 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") ) );
|
||||||
|
vector<UMat> imgs = ToUMat(_imgs);
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
|
||||||
|
? Ptr<detail::FeaturesFinder>(new detail::OrbFeaturesFinder())
|
||||||
|
: Ptr<detail::FeaturesFinder>(new detail::SurfFeaturesFinder());
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
|
||||||
|
? makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE)
|
||||||
|
: makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
|
||||||
|
|
||||||
|
declare.iterations(20);
|
||||||
|
|
||||||
|
while(next())
|
||||||
|
{
|
||||||
|
Stitcher stitcher = Stitcher::createDefault();
|
||||||
|
stitcher.setFeaturesFinder(featuresFinder);
|
||||||
|
stitcher.setFeaturesMatcher(featuresMatcher);
|
||||||
|
stitcher.setWarper(makePtr<SphericalWarper>());
|
||||||
|
stitcher.setRegistrationResol(WORK_MEGAPIX);
|
||||||
|
|
||||||
|
startTimer();
|
||||||
|
stitcher.stitch(imgs, pano);
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NEAR(pano.size().width, 1182, 50);
|
||||||
|
EXPECT_NEAR(pano.size().height, 682, 30);
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING();
|
||||||
|
}
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(stitch, b12, TEST_DETECTORS)
|
||||||
|
{
|
||||||
|
UMat pano;
|
||||||
|
|
||||||
|
vector<Mat> imgs;
|
||||||
|
imgs.push_back( imread( getDataPath("stitching/b1.png") ) );
|
||||||
|
imgs.push_back( imread( getDataPath("stitching/b2.png") ) );
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
|
||||||
|
? Ptr<detail::FeaturesFinder>(new detail::OrbFeaturesFinder())
|
||||||
|
: Ptr<detail::FeaturesFinder>(new detail::SurfFeaturesFinder());
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
|
||||||
|
? makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE)
|
||||||
|
: makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
|
||||||
|
|
||||||
|
declare.iterations(20);
|
||||||
|
|
||||||
|
while(next())
|
||||||
|
{
|
||||||
|
Stitcher stitcher = Stitcher::createDefault();
|
||||||
|
stitcher.setFeaturesFinder(featuresFinder);
|
||||||
|
stitcher.setFeaturesMatcher(featuresMatcher);
|
||||||
|
stitcher.setWarper(makePtr<SphericalWarper>());
|
||||||
|
stitcher.setRegistrationResol(WORK_MEGAPIX);
|
||||||
|
|
||||||
|
startTimer();
|
||||||
|
stitcher.stitch(imgs, pano);
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NEAR(pano.size().width, 1124, 50);
|
||||||
|
EXPECT_NEAR(pano.size().height, 644, 30);
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING();
|
||||||
|
}
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(stitch, boat, TEST_DETECTORS)
|
||||||
|
{
|
||||||
|
UMat pano;
|
||||||
|
|
||||||
|
vector<Mat> _imgs;
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat1.jpg") ) );
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat2.jpg") ) );
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat3.jpg") ) );
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat4.jpg") ) );
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat5.jpg") ) );
|
||||||
|
_imgs.push_back( imread( getDataPath("stitching/boat6.jpg") ) );
|
||||||
|
vector<UMat> imgs = ToUMat(_imgs);
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
|
||||||
|
? Ptr<detail::FeaturesFinder>(new detail::OrbFeaturesFinder())
|
||||||
|
: Ptr<detail::FeaturesFinder>(new detail::SurfFeaturesFinder());
|
||||||
|
|
||||||
|
Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
|
||||||
|
? makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE)
|
||||||
|
: makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
|
||||||
|
|
||||||
|
declare.iterations(20);
|
||||||
|
|
||||||
|
while(next())
|
||||||
|
{
|
||||||
|
Stitcher stitcher = Stitcher::createDefault();
|
||||||
|
stitcher.setFeaturesFinder(featuresFinder);
|
||||||
|
stitcher.setFeaturesMatcher(featuresMatcher);
|
||||||
|
stitcher.setWarper(makePtr<SphericalWarper>());
|
||||||
|
stitcher.setRegistrationResol(WORK_MEGAPIX);
|
||||||
|
|
||||||
|
startTimer();
|
||||||
|
stitcher.stitch(imgs, pano);
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NEAR(pano.size().width, 10789, 200);
|
||||||
|
EXPECT_NEAR(pano.size().height, 2663, 100);
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING();
|
||||||
|
}
|
@ -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);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
#include "opencl_kernels.hpp"
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -76,8 +77,13 @@ void Blender::prepare(Rect dst_roi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Blender::feed(const Mat &img, const Mat &mask, Point tl)
|
void Blender::feed(InputArray _img, InputArray _mask, Point tl)
|
||||||
{
|
{
|
||||||
|
Mat img = _img.getMat();
|
||||||
|
Mat mask = _mask.getMat();
|
||||||
|
Mat dst = dst_.getMat(ACCESS_RW);
|
||||||
|
Mat dst_mask = dst_mask_.getMat(ACCESS_RW);
|
||||||
|
|
||||||
CV_Assert(img.type() == CV_16SC3);
|
CV_Assert(img.type() == CV_16SC3);
|
||||||
CV_Assert(mask.type() == CV_8U);
|
CV_Assert(mask.type() == CV_8U);
|
||||||
int dx = tl.x - dst_roi_.x;
|
int dx = tl.x - dst_roi_.x;
|
||||||
@ -86,9 +92,9 @@ void Blender::feed(const Mat &img, const Mat &mask, Point tl)
|
|||||||
for (int y = 0; y < img.rows; ++y)
|
for (int y = 0; y < img.rows; ++y)
|
||||||
{
|
{
|
||||||
const Point3_<short> *src_row = img.ptr<Point3_<short> >(y);
|
const Point3_<short> *src_row = img.ptr<Point3_<short> >(y);
|
||||||
Point3_<short> *dst_row = dst_.ptr<Point3_<short> >(dy + y);
|
Point3_<short> *dst_row = dst.ptr<Point3_<short> >(dy + y);
|
||||||
const uchar *mask_row = mask.ptr<uchar>(y);
|
const uchar *mask_row = mask.ptr<uchar>(y);
|
||||||
uchar *dst_mask_row = dst_mask_.ptr<uchar>(dy + y);
|
uchar *dst_mask_row = dst_mask.ptr<uchar>(dy + y);
|
||||||
|
|
||||||
for (int x = 0; x < img.cols; ++x)
|
for (int x = 0; x < img.cols; ++x)
|
||||||
{
|
{
|
||||||
@ -100,11 +106,13 @@ void Blender::feed(const Mat &img, const Mat &mask, Point tl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Blender::blend(Mat &dst, Mat &dst_mask)
|
void Blender::blend(InputOutputArray dst, InputOutputArray dst_mask)
|
||||||
{
|
{
|
||||||
dst_.setTo(Scalar::all(0), dst_mask_ == 0);
|
UMat mask;
|
||||||
dst = dst_;
|
compare(dst_mask_, 0, mask, CMP_EQ);
|
||||||
dst_mask = dst_mask_;
|
dst_.setTo(Scalar::all(0), mask);
|
||||||
|
dst.assign(dst_);
|
||||||
|
dst_mask.assign(dst_mask_);
|
||||||
dst_.release();
|
dst_.release();
|
||||||
dst_mask_.release();
|
dst_mask_.release();
|
||||||
}
|
}
|
||||||
@ -118,21 +126,27 @@ void FeatherBlender::prepare(Rect dst_roi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FeatherBlender::feed(const Mat &img, const Mat &mask, Point tl)
|
void FeatherBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||||
{
|
{
|
||||||
|
Mat img = _img.getMat();
|
||||||
|
Mat dst = dst_.getMat(ACCESS_RW);
|
||||||
|
|
||||||
CV_Assert(img.type() == CV_16SC3);
|
CV_Assert(img.type() == CV_16SC3);
|
||||||
CV_Assert(mask.type() == CV_8U);
|
CV_Assert(mask.type() == CV_8U);
|
||||||
|
|
||||||
createWeightMap(mask, sharpness_, weight_map_);
|
createWeightMap(mask, sharpness_, weight_map_);
|
||||||
|
Mat weight_map = weight_map_.getMat(ACCESS_READ);
|
||||||
|
Mat dst_weight_map = dst_weight_map_.getMat(ACCESS_RW);
|
||||||
|
|
||||||
int dx = tl.x - dst_roi_.x;
|
int dx = tl.x - dst_roi_.x;
|
||||||
int dy = tl.y - dst_roi_.y;
|
int dy = tl.y - dst_roi_.y;
|
||||||
|
|
||||||
for (int y = 0; y < img.rows; ++y)
|
for (int y = 0; y < img.rows; ++y)
|
||||||
{
|
{
|
||||||
const Point3_<short>* src_row = img.ptr<Point3_<short> >(y);
|
const Point3_<short>* src_row = img.ptr<Point3_<short> >(y);
|
||||||
Point3_<short>* dst_row = dst_.ptr<Point3_<short> >(dy + y);
|
Point3_<short>* dst_row = dst.ptr<Point3_<short> >(dy + y);
|
||||||
const float* weight_row = weight_map_.ptr<float>(y);
|
const float* weight_row = weight_map.ptr<float>(y);
|
||||||
float* dst_weight_row = dst_weight_map_.ptr<float>(dy + y);
|
float* dst_weight_row = dst_weight_map.ptr<float>(dy + y);
|
||||||
|
|
||||||
for (int x = 0; x < img.cols; ++x)
|
for (int x = 0; x < img.cols; ++x)
|
||||||
{
|
{
|
||||||
@ -145,16 +159,16 @@ void FeatherBlender::feed(const Mat &img, const Mat &mask, Point tl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FeatherBlender::blend(Mat &dst, Mat &dst_mask)
|
void FeatherBlender::blend(InputOutputArray dst, InputOutputArray dst_mask)
|
||||||
{
|
{
|
||||||
normalizeUsingWeightMap(dst_weight_map_, dst_);
|
normalizeUsingWeightMap(dst_weight_map_, dst_);
|
||||||
dst_mask_ = dst_weight_map_ > WEIGHT_EPS;
|
compare(dst_weight_map_, WEIGHT_EPS, dst_mask_, CMP_GT);
|
||||||
Blender::blend(dst, dst_mask);
|
Blender::blend(dst, dst_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rect FeatherBlender::createWeightMaps(const std::vector<Mat> &masks, const std::vector<Point> &corners,
|
Rect FeatherBlender::createWeightMaps(const std::vector<UMat> &masks, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &weight_maps)
|
std::vector<UMat> &weight_maps)
|
||||||
{
|
{
|
||||||
weight_maps.resize(masks.size());
|
weight_maps.resize(masks.size());
|
||||||
for (size_t i = 0; i < masks.size(); ++i)
|
for (size_t i = 0; i < masks.size(); ++i)
|
||||||
@ -168,7 +182,7 @@ Rect FeatherBlender::createWeightMaps(const std::vector<Mat> &masks, const std::
|
|||||||
{
|
{
|
||||||
Rect roi(corners[i].x - dst_roi.x, corners[i].y - dst_roi.y,
|
Rect roi(corners[i].x - dst_roi.x, corners[i].y - dst_roi.y,
|
||||||
weight_maps[i].cols, weight_maps[i].rows);
|
weight_maps[i].cols, weight_maps[i].rows);
|
||||||
weights_sum(roi) += weight_maps[i];
|
add(weights_sum(roi), weight_maps[i], weights_sum(roi));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < weight_maps.size(); ++i)
|
for (size_t i = 0; i < weight_maps.size(); ++i)
|
||||||
@ -232,9 +246,39 @@ void MultiBandBlender::prepare(Rect dst_roi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENCL
|
||||||
void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
|
static bool ocl_MultiBandBlender_feed(InputArray _src, InputArray _weight,
|
||||||
|
InputOutputArray _dst, InputOutputArray _dst_weight)
|
||||||
{
|
{
|
||||||
|
String buildOptions = "-D DEFINE_feed";
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "src", _src);
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "weight", _weight);
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "dst", _dst);
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "dstWeight", _dst_weight);
|
||||||
|
ocl::Kernel k("feed", ocl::stitching::multibandblend_oclsrc, buildOptions);
|
||||||
|
if (k.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UMat src = _src.getUMat();
|
||||||
|
|
||||||
|
k.args(ocl::KernelArg::ReadOnly(src),
|
||||||
|
ocl::KernelArg::ReadOnly(_weight.getUMat()),
|
||||||
|
ocl::KernelArg::ReadWrite(_dst.getUMat()),
|
||||||
|
ocl::KernelArg::ReadWrite(_dst_weight.getUMat())
|
||||||
|
);
|
||||||
|
|
||||||
|
size_t globalsize[2] = {src.cols, src.rows };
|
||||||
|
return k.run(2, globalsize, NULL, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||||
|
{
|
||||||
|
#if ENABLE_LOG
|
||||||
|
int64 t = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UMat img = _img.getUMat();
|
||||||
CV_Assert(img.type() == CV_16SC3 || img.type() == CV_8UC3);
|
CV_Assert(img.type() == CV_16SC3 || img.type() == CV_8UC3);
|
||||||
CV_Assert(mask.type() == CV_8U);
|
CV_Assert(mask.type() == CV_8U);
|
||||||
|
|
||||||
@ -269,27 +313,39 @@ void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
|
|||||||
int right = br_new.x - tl.x - img.cols;
|
int right = br_new.x - tl.x - img.cols;
|
||||||
|
|
||||||
// Create the source image Laplacian pyramid
|
// Create the source image Laplacian pyramid
|
||||||
Mat img_with_border;
|
UMat img_with_border;
|
||||||
copyMakeBorder(img, img_with_border, top, bottom, left, right,
|
copyMakeBorder(_img, img_with_border, top, bottom, left, right,
|
||||||
BORDER_REFLECT);
|
BORDER_REFLECT);
|
||||||
std::vector<Mat> src_pyr_laplace;
|
LOGLN(" Add border to the source image, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
t = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<UMat> src_pyr_laplace;
|
||||||
if (can_use_gpu_ && img_with_border.depth() == CV_16S)
|
if (can_use_gpu_ && img_with_border.depth() == CV_16S)
|
||||||
createLaplacePyrGpu(img_with_border, num_bands_, src_pyr_laplace);
|
createLaplacePyrGpu(img_with_border, num_bands_, src_pyr_laplace);
|
||||||
else
|
else
|
||||||
createLaplacePyr(img_with_border, num_bands_, src_pyr_laplace);
|
createLaplacePyr(img_with_border, num_bands_, src_pyr_laplace);
|
||||||
|
|
||||||
|
LOGLN(" Create the source image Laplacian pyramid, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
t = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create the weight map Gaussian pyramid
|
// Create the weight map Gaussian pyramid
|
||||||
Mat weight_map;
|
UMat weight_map;
|
||||||
std::vector<Mat> weight_pyr_gauss(num_bands_ + 1);
|
std::vector<UMat> weight_pyr_gauss(num_bands_ + 1);
|
||||||
|
|
||||||
if(weight_type_ == CV_32F)
|
if(weight_type_ == CV_32F)
|
||||||
{
|
{
|
||||||
mask.convertTo(weight_map, CV_32F, 1./255.);
|
mask.getUMat().convertTo(weight_map, CV_32F, 1./255.);
|
||||||
}
|
}
|
||||||
else// weight_type_ == CV_16S
|
else // weight_type_ == CV_16S
|
||||||
{
|
{
|
||||||
mask.convertTo(weight_map, CV_16S);
|
mask.getUMat().convertTo(weight_map, CV_16S);
|
||||||
add(weight_map, 1, weight_map, mask != 0);
|
UMat add_mask;
|
||||||
|
compare(mask, 0, add_mask, CMP_NE);
|
||||||
|
add(weight_map, Scalar::all(1), weight_map, add_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyMakeBorder(weight_map, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);
|
copyMakeBorder(weight_map, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);
|
||||||
@ -297,66 +353,77 @@ void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
|
|||||||
for (int i = 0; i < num_bands_; ++i)
|
for (int i = 0; i < num_bands_; ++i)
|
||||||
pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);
|
pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);
|
||||||
|
|
||||||
|
LOGLN(" Create the weight map Gaussian pyramid, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
t = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
int y_tl = tl_new.y - dst_roi_.y;
|
int y_tl = tl_new.y - dst_roi_.y;
|
||||||
int y_br = br_new.y - dst_roi_.y;
|
int y_br = br_new.y - dst_roi_.y;
|
||||||
int x_tl = tl_new.x - dst_roi_.x;
|
int x_tl = tl_new.x - dst_roi_.x;
|
||||||
int x_br = br_new.x - dst_roi_.x;
|
int x_br = br_new.x - dst_roi_.x;
|
||||||
|
|
||||||
// Add weighted layer of the source image to the final Laplacian pyramid layer
|
// Add weighted layer of the source image to the final Laplacian pyramid layer
|
||||||
if(weight_type_ == CV_32F)
|
for (int i = 0; i <= num_bands_; ++i)
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= num_bands_; ++i)
|
Rect rc(x_tl, y_tl, x_br - x_tl, y_br - y_tl);
|
||||||
|
#ifdef HAVE_OPENCL
|
||||||
|
if ( !cv::ocl::useOpenCL() ||
|
||||||
|
!ocl_MultiBandBlender_feed(src_pyr_laplace[i], weight_pyr_gauss[i],
|
||||||
|
dst_pyr_laplace_[i](rc), dst_band_weights_[i](rc)) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
for (int y = y_tl; y < y_br; ++y)
|
Mat _src_pyr_laplace = src_pyr_laplace[i].getMat(ACCESS_READ);
|
||||||
|
Mat _dst_pyr_laplace = dst_pyr_laplace_[i](rc).getMat(ACCESS_RW);
|
||||||
|
Mat _weight_pyr_gauss = weight_pyr_gauss[i].getMat(ACCESS_READ);
|
||||||
|
Mat _dst_band_weights = dst_band_weights_[i](rc).getMat(ACCESS_RW);
|
||||||
|
if(weight_type_ == CV_32F)
|
||||||
{
|
{
|
||||||
int y_ = y - y_tl;
|
for (int y = 0; y < rc.height; ++y)
|
||||||
const Point3_<short>* src_row = src_pyr_laplace[i].ptr<Point3_<short> >(y_);
|
|
||||||
Point3_<short>* dst_row = dst_pyr_laplace_[i].ptr<Point3_<short> >(y);
|
|
||||||
const float* weight_row = weight_pyr_gauss[i].ptr<float>(y_);
|
|
||||||
float* dst_weight_row = dst_band_weights_[i].ptr<float>(y);
|
|
||||||
|
|
||||||
for (int x = x_tl; x < x_br; ++x)
|
|
||||||
{
|
{
|
||||||
int x_ = x - x_tl;
|
const Point3_<short>* src_row = _src_pyr_laplace.ptr<Point3_<short> >(y);
|
||||||
dst_row[x].x += static_cast<short>(src_row[x_].x * weight_row[x_]);
|
Point3_<short>* dst_row = _dst_pyr_laplace.ptr<Point3_<short> >(y);
|
||||||
dst_row[x].y += static_cast<short>(src_row[x_].y * weight_row[x_]);
|
const float* weight_row = _weight_pyr_gauss.ptr<float>(y);
|
||||||
dst_row[x].z += static_cast<short>(src_row[x_].z * weight_row[x_]);
|
float* dst_weight_row = _dst_band_weights.ptr<float>(y);
|
||||||
dst_weight_row[x] += weight_row[x_];
|
|
||||||
|
for (int x = 0; x < rc.width; ++x)
|
||||||
|
{
|
||||||
|
dst_row[x].x += static_cast<short>(src_row[x].x * weight_row[x]);
|
||||||
|
dst_row[x].y += static_cast<short>(src_row[x].y * weight_row[x]);
|
||||||
|
dst_row[x].z += static_cast<short>(src_row[x].z * weight_row[x]);
|
||||||
|
dst_weight_row[x] += weight_row[x];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x_tl /= 2; y_tl /= 2;
|
else // weight_type_ == CV_16S
|
||||||
x_br /= 2; y_br /= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else// weight_type_ == CV_16S
|
|
||||||
{
|
|
||||||
for (int i = 0; i <= num_bands_; ++i)
|
|
||||||
{
|
|
||||||
for (int y = y_tl; y < y_br; ++y)
|
|
||||||
{
|
{
|
||||||
int y_ = y - y_tl;
|
for (int y = 0; y < y_br - y_tl; ++y)
|
||||||
const Point3_<short>* src_row = src_pyr_laplace[i].ptr<Point3_<short> >(y_);
|
|
||||||
Point3_<short>* dst_row = dst_pyr_laplace_[i].ptr<Point3_<short> >(y);
|
|
||||||
const short* weight_row = weight_pyr_gauss[i].ptr<short>(y_);
|
|
||||||
short* dst_weight_row = dst_band_weights_[i].ptr<short>(y);
|
|
||||||
|
|
||||||
for (int x = x_tl; x < x_br; ++x)
|
|
||||||
{
|
{
|
||||||
int x_ = x - x_tl;
|
const Point3_<short>* src_row = _src_pyr_laplace.ptr<Point3_<short> >(y);
|
||||||
dst_row[x].x += short((src_row[x_].x * weight_row[x_]) >> 8);
|
Point3_<short>* dst_row = _dst_pyr_laplace.ptr<Point3_<short> >(y);
|
||||||
dst_row[x].y += short((src_row[x_].y * weight_row[x_]) >> 8);
|
const short* weight_row = _weight_pyr_gauss.ptr<short>(y);
|
||||||
dst_row[x].z += short((src_row[x_].z * weight_row[x_]) >> 8);
|
short* dst_weight_row = _dst_band_weights.ptr<short>(y);
|
||||||
dst_weight_row[x] += weight_row[x_];
|
|
||||||
|
for (int x = 0; x < x_br - x_tl; ++x)
|
||||||
|
{
|
||||||
|
dst_row[x].x += short((src_row[x].x * weight_row[x]) >> 8);
|
||||||
|
dst_row[x].y += short((src_row[x].y * weight_row[x]) >> 8);
|
||||||
|
dst_row[x].z += short((src_row[x].z * weight_row[x]) >> 8);
|
||||||
|
dst_weight_row[x] += weight_row[x];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x_tl /= 2; y_tl /= 2;
|
|
||||||
x_br /= 2; y_br /= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x_tl /= 2; y_tl /= 2;
|
||||||
|
x_br /= 2; y_br /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGLN(" Add weighted layer of the source image to the final Laplacian pyramid layer, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MultiBandBlender::blend(Mat &dst, Mat &dst_mask)
|
void MultiBandBlender::blend(InputOutputArray dst, InputOutputArray dst_mask)
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= num_bands_; ++i)
|
for (int i = 0; i <= num_bands_; ++i)
|
||||||
normalizeUsingWeightMap(dst_band_weights_[i], dst_pyr_laplace_[i]);
|
normalizeUsingWeightMap(dst_band_weights_[i], dst_pyr_laplace_[i]);
|
||||||
@ -366,10 +433,10 @@ void MultiBandBlender::blend(Mat &dst, Mat &dst_mask)
|
|||||||
else
|
else
|
||||||
restoreImageFromLaplacePyr(dst_pyr_laplace_);
|
restoreImageFromLaplacePyr(dst_pyr_laplace_);
|
||||||
|
|
||||||
dst_ = dst_pyr_laplace_[0];
|
Rect dst_rc(0, 0, dst_roi_final_.width, dst_roi_final_.height);
|
||||||
dst_ = dst_(Range(0, dst_roi_final_.height), Range(0, dst_roi_final_.width));
|
dst_ = dst_pyr_laplace_[0](dst_rc);
|
||||||
dst_mask_ = dst_band_weights_[0] > WEIGHT_EPS;
|
UMat _dst_mask;
|
||||||
dst_mask_ = dst_mask_(Range(0, dst_roi_final_.height), Range(0, dst_roi_final_.width));
|
compare(dst_band_weights_[0](dst_rc), WEIGHT_EPS, dst_mask_, CMP_GT);
|
||||||
dst_pyr_laplace_.clear();
|
dst_pyr_laplace_.clear();
|
||||||
dst_band_weights_.clear();
|
dst_band_weights_.clear();
|
||||||
|
|
||||||
@ -380,59 +447,92 @@ void MultiBandBlender::blend(Mat &dst, Mat &dst_mask)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Auxiliary functions
|
// Auxiliary functions
|
||||||
|
|
||||||
void normalizeUsingWeightMap(const Mat& weight, Mat& src)
|
#ifdef HAVE_OPENCL
|
||||||
|
static bool ocl_normalizeUsingWeightMap(InputArray _weight, InputOutputArray _mat)
|
||||||
|
{
|
||||||
|
String buildOptions = "-D DEFINE_normalizeUsingWeightMap";
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "mat", _mat);
|
||||||
|
ocl::buildOptionsAddMatrixDescription(buildOptions, "weight", _weight);
|
||||||
|
ocl::Kernel k("normalizeUsingWeightMap", ocl::stitching::multibandblend_oclsrc, buildOptions);
|
||||||
|
if (k.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UMat mat = _mat.getUMat();
|
||||||
|
|
||||||
|
k.args(ocl::KernelArg::ReadWrite(mat),
|
||||||
|
ocl::KernelArg::ReadOnly(_weight.getUMat())
|
||||||
|
);
|
||||||
|
|
||||||
|
size_t globalsize[2] = {mat.cols, mat.rows };
|
||||||
|
return k.run(2, globalsize, NULL, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void normalizeUsingWeightMap(InputArray _weight, InputOutputArray _src)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||||
if(tegra::normalizeUsingWeightMap(weight, src))
|
if(tegra::normalizeUsingWeightMap(weight, src))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
CV_Assert(src.type() == CV_16SC3);
|
|
||||||
|
|
||||||
if(weight.type() == CV_32FC1)
|
#ifdef HAVE_OPENCL
|
||||||
|
if ( !cv::ocl::useOpenCL() ||
|
||||||
|
!ocl_normalizeUsingWeightMap(_weight, _src) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
for (int y = 0; y < src.rows; ++y)
|
Mat weight = _weight.getMat();
|
||||||
{
|
Mat src = _src.getMat();
|
||||||
Point3_<short> *row = src.ptr<Point3_<short> >(y);
|
|
||||||
const float *weight_row = weight.ptr<float>(y);
|
|
||||||
|
|
||||||
for (int x = 0; x < src.cols; ++x)
|
CV_Assert(src.type() == CV_16SC3);
|
||||||
|
|
||||||
|
if(weight.type() == CV_32FC1)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < src.rows; ++y)
|
||||||
{
|
{
|
||||||
row[x].x = static_cast<short>(row[x].x / (weight_row[x] + WEIGHT_EPS));
|
Point3_<short> *row = src.ptr<Point3_<short> >(y);
|
||||||
row[x].y = static_cast<short>(row[x].y / (weight_row[x] + WEIGHT_EPS));
|
const float *weight_row = weight.ptr<float>(y);
|
||||||
row[x].z = static_cast<short>(row[x].z / (weight_row[x] + WEIGHT_EPS));
|
|
||||||
|
for (int x = 0; x < src.cols; ++x)
|
||||||
|
{
|
||||||
|
row[x].x = static_cast<short>(row[x].x / (weight_row[x] + WEIGHT_EPS));
|
||||||
|
row[x].y = static_cast<short>(row[x].y / (weight_row[x] + WEIGHT_EPS));
|
||||||
|
row[x].z = static_cast<short>(row[x].z / (weight_row[x] + WEIGHT_EPS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
CV_Assert(weight.type() == CV_16SC1);
|
|
||||||
|
|
||||||
for (int y = 0; y < src.rows; ++y)
|
|
||||||
{
|
{
|
||||||
const short *weight_row = weight.ptr<short>(y);
|
CV_Assert(weight.type() == CV_16SC1);
|
||||||
Point3_<short> *row = src.ptr<Point3_<short> >(y);
|
|
||||||
|
|
||||||
for (int x = 0; x < src.cols; ++x)
|
for (int y = 0; y < src.rows; ++y)
|
||||||
{
|
{
|
||||||
int w = weight_row[x] + 1;
|
const short *weight_row = weight.ptr<short>(y);
|
||||||
row[x].x = static_cast<short>((row[x].x << 8) / w);
|
Point3_<short> *row = src.ptr<Point3_<short> >(y);
|
||||||
row[x].y = static_cast<short>((row[x].y << 8) / w);
|
|
||||||
row[x].z = static_cast<short>((row[x].z << 8) / w);
|
for (int x = 0; x < src.cols; ++x)
|
||||||
|
{
|
||||||
|
int w = weight_row[x] + 1;
|
||||||
|
row[x].x = static_cast<short>((row[x].x << 8) / w);
|
||||||
|
row[x].y = static_cast<short>((row[x].y << 8) / w);
|
||||||
|
row[x].z = static_cast<short>((row[x].z << 8) / w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createWeightMap(const Mat &mask, float sharpness, Mat &weight)
|
void createWeightMap(InputArray mask, float sharpness, InputOutputArray weight)
|
||||||
{
|
{
|
||||||
CV_Assert(mask.type() == CV_8U);
|
CV_Assert(mask.type() == CV_8U);
|
||||||
distanceTransform(mask, weight, DIST_L1, 3);
|
distanceTransform(mask, weight, DIST_L1, 3);
|
||||||
threshold(weight * sharpness, weight, 1.f, 1.f, THRESH_TRUNC);
|
UMat tmp;
|
||||||
|
multiply(weight, sharpness, tmp);
|
||||||
|
threshold(tmp, weight, 1.f, 1.f, THRESH_TRUNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
void createLaplacePyr(InputArray img, int num_levels, std::vector<UMat> &pyr)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||||
if(tegra::createLaplacePyr(img, num_levels, pyr))
|
if(tegra::createLaplacePyr(img, num_levels, pyr))
|
||||||
@ -445,18 +545,18 @@ void createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
|||||||
{
|
{
|
||||||
if(num_levels == 0)
|
if(num_levels == 0)
|
||||||
{
|
{
|
||||||
img.convertTo(pyr[0], CV_16S);
|
img.getUMat().convertTo(pyr[0], CV_16S);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat downNext;
|
UMat downNext;
|
||||||
Mat current = img;
|
UMat current = img.getUMat();
|
||||||
pyrDown(img, downNext);
|
pyrDown(img, downNext);
|
||||||
|
|
||||||
for(int i = 1; i < num_levels; ++i)
|
for(int i = 1; i < num_levels; ++i)
|
||||||
{
|
{
|
||||||
Mat lvl_up;
|
UMat lvl_up;
|
||||||
Mat lvl_down;
|
UMat lvl_down;
|
||||||
|
|
||||||
pyrDown(downNext, lvl_down);
|
pyrDown(downNext, lvl_down);
|
||||||
pyrUp(downNext, lvl_up, current.size());
|
pyrUp(downNext, lvl_up, current.size());
|
||||||
@ -467,7 +567,7 @@ void createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Mat lvl_up;
|
UMat lvl_up;
|
||||||
pyrUp(downNext, lvl_up, current.size());
|
pyrUp(downNext, lvl_up, current.size());
|
||||||
subtract(current, lvl_up, pyr[num_levels-1], noArray(), CV_16S);
|
subtract(current, lvl_up, pyr[num_levels-1], noArray(), CV_16S);
|
||||||
|
|
||||||
@ -476,10 +576,10 @@ void createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pyr[0] = img;
|
pyr[0] = img.getUMat();
|
||||||
for (int i = 0; i < num_levels; ++i)
|
for (int i = 0; i < num_levels; ++i)
|
||||||
pyrDown(pyr[i], pyr[i + 1]);
|
pyrDown(pyr[i], pyr[i + 1]);
|
||||||
Mat tmp;
|
UMat tmp;
|
||||||
for (int i = 0; i < num_levels; ++i)
|
for (int i = 0; i < num_levels; ++i)
|
||||||
{
|
{
|
||||||
pyrUp(pyr[i + 1], tmp, pyr[i].size());
|
pyrUp(pyr[i + 1], tmp, pyr[i].size());
|
||||||
@ -489,7 +589,7 @@ void createLaplacePyr(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createLaplacePyrGpu(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
void createLaplacePyrGpu(InputArray img, int num_levels, std::vector<UMat> &pyr)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||||
pyr.resize(num_levels + 1);
|
pyr.resize(num_levels + 1);
|
||||||
@ -517,11 +617,11 @@ void createLaplacePyrGpu(const Mat &img, int num_levels, std::vector<Mat> &pyr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void restoreImageFromLaplacePyr(std::vector<Mat> &pyr)
|
void restoreImageFromLaplacePyr(std::vector<UMat> &pyr)
|
||||||
{
|
{
|
||||||
if (pyr.empty())
|
if (pyr.empty())
|
||||||
return;
|
return;
|
||||||
Mat tmp;
|
UMat tmp;
|
||||||
for (size_t i = pyr.size() - 1; i > 0; --i)
|
for (size_t i = pyr.size() - 1; i > 0; --i)
|
||||||
{
|
{
|
||||||
pyrUp(pyr[i], tmp, pyr[i - 1].size());
|
pyrUp(pyr[i], tmp, pyr[i - 1].size());
|
||||||
@ -530,7 +630,7 @@ void restoreImageFromLaplacePyr(std::vector<Mat> &pyr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void restoreImageFromLaplacePyrGpu(std::vector<Mat> &pyr)
|
void restoreImageFromLaplacePyrGpu(std::vector<UMat> &pyr)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||||
if (pyr.empty())
|
if (pyr.empty())
|
||||||
|
@ -58,18 +58,18 @@ Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void ExposureCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<Mat> &masks)
|
const std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<Mat,uchar> > level_masks;
|
std::vector<std::pair<UMat,uchar> > level_masks;
|
||||||
for (size_t i = 0; i < masks.size(); ++i)
|
for (size_t i = 0; i < masks.size(); ++i)
|
||||||
level_masks.push_back(std::make_pair(masks[i], 255));
|
level_masks.push_back(std::make_pair(masks[i], 255));
|
||||||
feed(corners, images, level_masks);
|
feed(corners, images, level_masks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<std::pair<Mat,uchar> > &masks)
|
const std::vector<std::pair<UMat,uchar> > &masks)
|
||||||
{
|
{
|
||||||
LOGLN("Exposure compensation...");
|
LOGLN("Exposure compensation...");
|
||||||
#if ENABLE_LOG
|
#if ENABLE_LOG
|
||||||
@ -93,11 +93,11 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
|
|||||||
Rect roi;
|
Rect roi;
|
||||||
if (overlapRoi(corners[i], corners[j], images[i].size(), images[j].size(), roi))
|
if (overlapRoi(corners[i], corners[j], images[i].size(), images[j].size(), roi))
|
||||||
{
|
{
|
||||||
subimg1 = images[i](Rect(roi.tl() - corners[i], roi.br() - corners[i]));
|
subimg1 = images[i](Rect(roi.tl() - corners[i], roi.br() - corners[i])).getMat(ACCESS_READ);
|
||||||
subimg2 = images[j](Rect(roi.tl() - corners[j], roi.br() - corners[j]));
|
subimg2 = images[j](Rect(roi.tl() - corners[j], roi.br() - corners[j])).getMat(ACCESS_READ);
|
||||||
|
|
||||||
submask1 = masks[i].first(Rect(roi.tl() - corners[i], roi.br() - corners[i]));
|
submask1 = masks[i].first(Rect(roi.tl() - corners[i], roi.br() - corners[i])).getMat(ACCESS_READ);
|
||||||
submask2 = masks[j].first(Rect(roi.tl() - corners[j], roi.br() - corners[j]));
|
submask2 = masks[j].first(Rect(roi.tl() - corners[j], roi.br() - corners[j])).getMat(ACCESS_READ);
|
||||||
intersect = (submask1 == masks[i].second) & (submask2 == masks[j].second);
|
intersect = (submask1 == masks[i].second) & (submask2 == masks[j].second);
|
||||||
|
|
||||||
N(i, j) = N(j, i) = std::max(1, countNonZero(intersect));
|
N(i, j) = N(j, i) = std::max(1, countNonZero(intersect));
|
||||||
@ -145,9 +145,9 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GainCompensator::apply(int index, Point /*corner*/, Mat &image, const Mat &/*mask*/)
|
void GainCompensator::apply(int index, Point /*corner*/, InputOutputArray image, InputArray /*mask*/)
|
||||||
{
|
{
|
||||||
image *= gains_(index, 0);
|
multiply(image, gains_(index, 0), image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ std::vector<double> GainCompensator::gains() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
|
void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
|
||||||
const std::vector<std::pair<Mat,uchar> > &masks)
|
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());
|
||||||
|
|
||||||
@ -169,8 +169,8 @@ void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::v
|
|||||||
|
|
||||||
std::vector<Size> bl_per_imgs(num_images);
|
std::vector<Size> bl_per_imgs(num_images);
|
||||||
std::vector<Point> block_corners;
|
std::vector<Point> block_corners;
|
||||||
std::vector<Mat> block_images;
|
std::vector<UMat> block_images;
|
||||||
std::vector<std::pair<Mat,uchar> > block_masks;
|
std::vector<std::pair<UMat,uchar> > block_masks;
|
||||||
|
|
||||||
// Construct blocks for gain compensator
|
// Construct blocks for gain compensator
|
||||||
for (int img_idx = 0; img_idx < num_images; ++img_idx)
|
for (int img_idx = 0; img_idx < num_images; ++img_idx)
|
||||||
@ -208,11 +208,14 @@ void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::v
|
|||||||
for (int img_idx = 0; img_idx < num_images; ++img_idx)
|
for (int img_idx = 0; img_idx < num_images; ++img_idx)
|
||||||
{
|
{
|
||||||
Size bl_per_img = bl_per_imgs[img_idx];
|
Size bl_per_img = bl_per_imgs[img_idx];
|
||||||
gain_maps_[img_idx].create(bl_per_img);
|
gain_maps_[img_idx].create(bl_per_img, CV_32F);
|
||||||
|
|
||||||
for (int by = 0; by < bl_per_img.height; ++by)
|
{
|
||||||
for (int bx = 0; bx < bl_per_img.width; ++bx, ++bl_idx)
|
Mat_<float> gain_map = gain_maps_[img_idx].getMat(ACCESS_WRITE);
|
||||||
gain_maps_[img_idx](by, bx) = static_cast<float>(gains[bl_idx]);
|
for (int by = 0; by < bl_per_img.height; ++by)
|
||||||
|
for (int bx = 0; bx < bl_per_img.width; ++bx, ++bl_idx)
|
||||||
|
gain_map(by, bx) = static_cast<float>(gains[bl_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
sepFilter2D(gain_maps_[img_idx], gain_maps_[img_idx], CV_32F, ker, ker);
|
sepFilter2D(gain_maps_[img_idx], gain_maps_[img_idx], CV_32F, ker, ker);
|
||||||
sepFilter2D(gain_maps_[img_idx], gain_maps_[img_idx], CV_32F, ker, ker);
|
sepFilter2D(gain_maps_[img_idx], gain_maps_[img_idx], CV_32F, ker, ker);
|
||||||
@ -220,16 +223,18 @@ void BlocksGainCompensator::feed(const std::vector<Point> &corners, const std::v
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlocksGainCompensator::apply(int index, Point /*corner*/, Mat &image, const Mat &/*mask*/)
|
void BlocksGainCompensator::apply(int index, Point /*corner*/, InputOutputArray _image, InputArray /*mask*/)
|
||||||
{
|
{
|
||||||
CV_Assert(image.type() == CV_8UC3);
|
CV_Assert(_image.type() == CV_8UC3);
|
||||||
|
|
||||||
Mat_<float> gain_map;
|
UMat u_gain_map;
|
||||||
if (gain_maps_[index].size() == image.size())
|
if (gain_maps_[index].size() == _image.size())
|
||||||
gain_map = gain_maps_[index];
|
u_gain_map = gain_maps_[index];
|
||||||
else
|
else
|
||||||
resize(gain_maps_[index], gain_map, image.size(), 0, 0, INTER_LINEAR);
|
resize(gain_maps_[index], u_gain_map, _image.size(), 0, 0, INTER_LINEAR);
|
||||||
|
|
||||||
|
Mat_<float> gain_map = u_gain_map.getMat(ACCESS_READ);
|
||||||
|
Mat image = _image.getMat();
|
||||||
for (int y = 0; y < image.rows; ++y)
|
for (int y = 0; y < image.rows; ++y)
|
||||||
{
|
{
|
||||||
const float* gain_row = gain_map.ptr<float>(y);
|
const float* gain_row = gain_map.ptr<float>(y);
|
||||||
|
@ -155,21 +155,31 @@ void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat
|
|||||||
|
|
||||||
matches_info.matches.clear();
|
matches_info.matches.clear();
|
||||||
|
|
||||||
Ptr<flann::IndexParams> indexParams = makePtr<flann::KDTreeIndexParams>();
|
Ptr<DescriptorMatcher> matcher;
|
||||||
Ptr<flann::SearchParams> searchParams = makePtr<flann::SearchParams>();
|
#if 0 // TODO check this
|
||||||
|
if (ocl::useOpenCL())
|
||||||
if (features2.descriptors.depth() == CV_8U)
|
|
||||||
{
|
{
|
||||||
indexParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
|
matcher = makePtr<BFMatcher>((int)NORM_L2);
|
||||||
searchParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Ptr<flann::IndexParams> indexParams = makePtr<flann::KDTreeIndexParams>();
|
||||||
|
Ptr<flann::SearchParams> searchParams = makePtr<flann::SearchParams>();
|
||||||
|
|
||||||
FlannBasedMatcher matcher(indexParams, searchParams);
|
if (features2.descriptors.depth() == CV_8U)
|
||||||
|
{
|
||||||
|
indexParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
|
||||||
|
searchParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher = makePtr<FlannBasedMatcher>(indexParams, searchParams);
|
||||||
|
}
|
||||||
std::vector< std::vector<DMatch> > pair_matches;
|
std::vector< std::vector<DMatch> > pair_matches;
|
||||||
MatchesSet matches;
|
MatchesSet matches;
|
||||||
|
|
||||||
// Find 1->2 matches
|
// Find 1->2 matches
|
||||||
matcher.knnMatch(features1.descriptors, features2.descriptors, pair_matches, 2);
|
matcher->knnMatch(features1.descriptors, features2.descriptors, pair_matches, 2);
|
||||||
for (size_t i = 0; i < pair_matches.size(); ++i)
|
for (size_t i = 0; i < pair_matches.size(); ++i)
|
||||||
{
|
{
|
||||||
if (pair_matches[i].size() < 2)
|
if (pair_matches[i].size() < 2)
|
||||||
@ -186,7 +196,7 @@ void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat
|
|||||||
|
|
||||||
// Find 2->1 matches
|
// Find 2->1 matches
|
||||||
pair_matches.clear();
|
pair_matches.clear();
|
||||||
matcher.knnMatch(features2.descriptors, features1.descriptors, pair_matches, 2);
|
matcher->knnMatch(features2.descriptors, features1.descriptors, pair_matches, 2);
|
||||||
for (size_t i = 0; i < pair_matches.size(); ++i)
|
for (size_t i = 0; i < pair_matches.size(); ++i)
|
||||||
{
|
{
|
||||||
if (pair_matches[i].size() < 2)
|
if (pair_matches[i].size() < 2)
|
||||||
@ -264,14 +274,14 @@ void GpuMatcher::collectGarbage()
|
|||||||
namespace cv {
|
namespace cv {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
void FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features)
|
void FeaturesFinder::operator ()(InputArray image, ImageFeatures &features)
|
||||||
{
|
{
|
||||||
find(image, features);
|
find(image, features);
|
||||||
features.img_size = image.size();
|
features.img_size = image.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features, const std::vector<Rect> &rois)
|
void FeaturesFinder::operator ()(InputArray image, ImageFeatures &features, const std::vector<Rect> &rois)
|
||||||
{
|
{
|
||||||
std::vector<ImageFeatures> roi_features(rois.size());
|
std::vector<ImageFeatures> roi_features(rois.size());
|
||||||
size_t total_kps_count = 0;
|
size_t total_kps_count = 0;
|
||||||
@ -279,7 +289,7 @@ void FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features, cons
|
|||||||
|
|
||||||
for (size_t i = 0; i < rois.size(); ++i)
|
for (size_t i = 0; i < rois.size(); ++i)
|
||||||
{
|
{
|
||||||
find(image(rois[i]), roi_features[i]);
|
find(image.getUMat()(rois[i]), roi_features[i]);
|
||||||
total_kps_count += roi_features[i].keypoints.size();
|
total_kps_count += roi_features[i].keypoints.size();
|
||||||
total_descriptors_height += roi_features[i].descriptors.rows;
|
total_descriptors_height += roi_features[i].descriptors.rows;
|
||||||
}
|
}
|
||||||
@ -300,7 +310,7 @@ void FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features, cons
|
|||||||
features.keypoints[kp_idx].pt.x += (float)rois[i].x;
|
features.keypoints[kp_idx].pt.x += (float)rois[i].x;
|
||||||
features.keypoints[kp_idx].pt.y += (float)rois[i].y;
|
features.keypoints[kp_idx].pt.y += (float)rois[i].y;
|
||||||
}
|
}
|
||||||
Mat subdescr = features.descriptors.rowRange(
|
UMat subdescr = features.descriptors.rowRange(
|
||||||
descr_offset, descr_offset + roi_features[i].descriptors.rows);
|
descr_offset, descr_offset + roi_features[i].descriptors.rows);
|
||||||
roi_features[i].descriptors.copyTo(subdescr);
|
roi_features[i].descriptors.copyTo(subdescr);
|
||||||
descr_offset += roi_features[i].descriptors.rows;
|
descr_offset += roi_features[i].descriptors.rows;
|
||||||
@ -337,9 +347,9 @@ SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
||||||
{
|
{
|
||||||
Mat gray_image;
|
UMat gray_image;
|
||||||
CV_Assert((image.type() == CV_8UC3) || (image.type() == CV_8UC1));
|
CV_Assert((image.type() == CV_8UC3) || (image.type() == CV_8UC1));
|
||||||
if(image.type() == CV_8UC3)
|
if(image.type() == CV_8UC3)
|
||||||
{
|
{
|
||||||
@ -347,7 +357,7 @@ void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gray_image = image;
|
gray_image = image.getUMat();
|
||||||
}
|
}
|
||||||
if (!surf)
|
if (!surf)
|
||||||
{
|
{
|
||||||
@ -356,7 +366,7 @@ void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Mat descriptors;
|
UMat descriptors;
|
||||||
(*surf)(gray_image, Mat(), features.keypoints, descriptors);
|
(*surf)(gray_image, Mat(), features.keypoints, descriptors);
|
||||||
features.descriptors = descriptors.reshape(1, (int)features.keypoints.size());
|
features.descriptors = descriptors.reshape(1, (int)features.keypoints.size());
|
||||||
}
|
}
|
||||||
@ -368,9 +378,9 @@ OrbFeaturesFinder::OrbFeaturesFinder(Size _grid_size, int n_features, float scal
|
|||||||
orb = makePtr<ORB>(n_features * (99 + grid_size.area())/100/grid_size.area(), scaleFactor, nlevels);
|
orb = makePtr<ORB>(n_features * (99 + grid_size.area())/100/grid_size.area(), scaleFactor, nlevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OrbFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
void OrbFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
||||||
{
|
{
|
||||||
Mat gray_image;
|
UMat gray_image;
|
||||||
|
|
||||||
CV_Assert((image.type() == CV_8UC3) || (image.type() == CV_8UC4) || (image.type() == CV_8UC1));
|
CV_Assert((image.type() == CV_8UC3) || (image.type() == CV_8UC4) || (image.type() == CV_8UC1));
|
||||||
|
|
||||||
@ -379,7 +389,7 @@ void OrbFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
} else if (image.type() == CV_8UC4) {
|
} else if (image.type() == CV_8UC4) {
|
||||||
cvtColor(image, gray_image, COLOR_BGRA2GRAY);
|
cvtColor(image, gray_image, COLOR_BGRA2GRAY);
|
||||||
} else if (image.type() == CV_8UC1) {
|
} else if (image.type() == CV_8UC1) {
|
||||||
gray_image=image;
|
gray_image = image.getUMat();
|
||||||
} else {
|
} else {
|
||||||
CV_Error(Error::StsUnsupportedFormat, "");
|
CV_Error(Error::StsUnsupportedFormat, "");
|
||||||
}
|
}
|
||||||
@ -392,7 +402,8 @@ void OrbFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
features.descriptors.release();
|
features.descriptors.release();
|
||||||
|
|
||||||
std::vector<KeyPoint> points;
|
std::vector<KeyPoint> points;
|
||||||
Mat descriptors;
|
Mat _descriptors;
|
||||||
|
UMat descriptors;
|
||||||
|
|
||||||
for (int r = 0; r < grid_size.height; ++r)
|
for (int r = 0; r < grid_size.height; ++r)
|
||||||
for (int c = 0; c < grid_size.width; ++c)
|
for (int c = 0; c < grid_size.width; ++c)
|
||||||
@ -408,13 +419,13 @@ void OrbFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
// << " xl=" << xl << ", xr=" << xr << ", gray_image.data=" << ((size_t)gray_image.data) << ", "
|
// << " xl=" << xl << ", xr=" << xr << ", gray_image.data=" << ((size_t)gray_image.data) << ", "
|
||||||
// << "gray_image.dims=" << gray_image.dims << "\n");
|
// << "gray_image.dims=" << gray_image.dims << "\n");
|
||||||
|
|
||||||
Mat gray_image_part=gray_image(Range(yl, yr), Range(xl, xr));
|
UMat gray_image_part=gray_image(Range(yl, yr), Range(xl, xr));
|
||||||
// LOGLN("OrbFeaturesFinder::find: gray_image_part.empty=" << (gray_image_part.empty()?"true":"false") << ", "
|
// LOGLN("OrbFeaturesFinder::find: gray_image_part.empty=" << (gray_image_part.empty()?"true":"false") << ", "
|
||||||
// << " gray_image_part.size()=(" << gray_image_part.size().width << "x" << gray_image_part.size().height << "), "
|
// << " gray_image_part.size()=(" << gray_image_part.size().width << "x" << gray_image_part.size().height << "), "
|
||||||
// << " gray_image_part.dims=" << gray_image_part.dims << ", "
|
// << " gray_image_part.dims=" << gray_image_part.dims << ", "
|
||||||
// << " gray_image_part.data=" << ((size_t)gray_image_part.data) << "\n");
|
// << " gray_image_part.data=" << ((size_t)gray_image_part.data) << "\n");
|
||||||
|
|
||||||
(*orb)(gray_image_part, Mat(), points, descriptors);
|
(*orb)(gray_image_part, UMat(), points, descriptors);
|
||||||
|
|
||||||
features.keypoints.reserve(features.keypoints.size() + points.size());
|
features.keypoints.reserve(features.keypoints.size() + points.size());
|
||||||
for (std::vector<KeyPoint>::iterator kp = points.begin(); kp != points.end(); ++kp)
|
for (std::vector<KeyPoint>::iterator kp = points.begin(); kp != points.end(); ++kp)
|
||||||
@ -423,8 +434,12 @@ void OrbFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|||||||
kp->pt.y += yl;
|
kp->pt.y += yl;
|
||||||
features.keypoints.push_back(*kp);
|
features.keypoints.push_back(*kp);
|
||||||
}
|
}
|
||||||
features.descriptors.push_back(descriptors);
|
_descriptors.push_back(descriptors.getMat(ACCESS_READ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO optimize copyTo()
|
||||||
|
//features.descriptors = _descriptors.getUMat(ACCESS_READ);
|
||||||
|
_descriptors.copyTo(features.descriptors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +457,7 @@ SurfFeaturesFinderGpu::SurfFeaturesFinderGpu(double hess_thresh, int num_octaves
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SurfFeaturesFinderGpu::find(const Mat &image, ImageFeatures &features)
|
void SurfFeaturesFinderGpu::find(InputArray image, ImageFeatures &features)
|
||||||
{
|
{
|
||||||
CV_Assert(image.depth() == CV_8U);
|
CV_Assert(image.depth() == CV_8U);
|
||||||
|
|
||||||
@ -499,12 +514,12 @@ const MatchesInfo& MatchesInfo::operator =(const MatchesInfo &other)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FeaturesMatcher::operator ()(const std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
|
void FeaturesMatcher::operator ()(const std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
|
||||||
const Mat &mask)
|
const UMat &mask)
|
||||||
{
|
{
|
||||||
const int num_images = static_cast<int>(features.size());
|
const int num_images = static_cast<int>(features.size());
|
||||||
|
|
||||||
CV_Assert(mask.empty() || (mask.type() == CV_8U && mask.cols == num_images && mask.rows));
|
CV_Assert(mask.empty() || (mask.type() == CV_8U && mask.cols == num_images && mask.rows));
|
||||||
Mat_<uchar> mask_(mask);
|
Mat_<uchar> mask_(mask.getMat(ACCESS_READ));
|
||||||
if (mask_.empty())
|
if (mask_.empty())
|
||||||
mask_ = Mat::ones(num_images, num_images, CV_8U);
|
mask_ = Mat::ones(num_images, num_images, CV_8U);
|
||||||
|
|
||||||
|
282
modules/stitching/src/opencl/multibandblend.cl
Normal file
282
modules/stitching/src/opencl/multibandblend.cl
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, Itseez, Inc, all rights reserved.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Common preprocessors macro
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Move this common code into "header" file
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NL // New Line: for preprocessor debugging
|
||||||
|
#define NL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REF(x) x
|
||||||
|
#define __CAT(x, y) x##y
|
||||||
|
#define CAT(x, y) __CAT(x, y)
|
||||||
|
|
||||||
|
//
|
||||||
|
// All matrixes are come with this description ("name" is a name of matrix):
|
||||||
|
// * name_CN - number of channels (1,2,3,4)
|
||||||
|
// * name_DEPTH - numeric value of CV_MAT_DEPTH(type). See CV_8U, CV_32S, etc macro below.
|
||||||
|
//
|
||||||
|
// Currently we also pass these attributes (to reduce this macro block):
|
||||||
|
// * name_T - datatype (int, float, uchar4, float4)
|
||||||
|
// * name_T1 - datatype for one channel (int, float, uchar).
|
||||||
|
// It is equal to result of "T1(name_T)" macro
|
||||||
|
// * name_TSIZE - CV_ELEM_SIZE(type).
|
||||||
|
// We can't use sizeof(name_T) here, because sizeof(float3) is usually equal to 8, not 6.
|
||||||
|
// * name_T1SIZE - CV_ELEM_SIZE1(type)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Usage sample:
|
||||||
|
//
|
||||||
|
// #define workType TYPE(float, src_CN)
|
||||||
|
// #define convertToWorkType CONVERT_TO(workType)
|
||||||
|
// #define convertWorkTypeToDstType CONVERT(workType, dst_T)
|
||||||
|
//
|
||||||
|
// __kernel void kernelFn(DECLARE_MAT_ARG(src), DECLARE_MAT_ARG(dst))
|
||||||
|
// {
|
||||||
|
// const int x = get_global_id(0);
|
||||||
|
// const int y = get_global_id(1);
|
||||||
|
//
|
||||||
|
// if (x < srcWidth && y < srcHeight)
|
||||||
|
// {
|
||||||
|
// int src_byteOffset = MAT_BYTE_OFFSET(src, x, y);
|
||||||
|
// int dst_byteOffset = MAT_BYTE_OFFSET(dst, x, y);
|
||||||
|
// workType value = convertToWorkType(LOAD_MAT_AT(src, src_byteOffset));
|
||||||
|
//
|
||||||
|
// ... value processing ...
|
||||||
|
//
|
||||||
|
// STORE_MAT_AT(dst, dst_byteOffset, convertWorkTypeToDstType(value));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
#define DECLARE_MAT_ARG(name) \
|
||||||
|
__global uchar* restrict name ## Ptr, \
|
||||||
|
int name ## StepBytes, \
|
||||||
|
int name ## Offset, \
|
||||||
|
int name ## Height, \
|
||||||
|
int name ## Width NL
|
||||||
|
|
||||||
|
#define MAT_BYTE_OFFSET(name, x, y) mad24((y)/* + name ## OffsetY*/, name ## StepBytes, ((x)/* + name ## OffsetX*/) * (int)(name ## _TSIZE) + name ## Offset)
|
||||||
|
#define MAT_RELATIVE_BYTE_OFFSET(name, x, y) mad24(y, name ## StepBytes, (x) * (int)(name ## _TSIZE))
|
||||||
|
|
||||||
|
#define __LOAD_MAT_AT(name, byteOffset) *((const __global name ## _T*)(name ## Ptr + (byteOffset)))
|
||||||
|
#define __vload_CN__(name_cn) vload ## name_cn
|
||||||
|
#define __vload_CN_(name_cn) __vload_CN__(name_cn)
|
||||||
|
#define __vload_CN(name) __vload_CN_(name ## _CN)
|
||||||
|
#define __LOAD_MAT_AT_vload(name, byteOffset) __vload_CN(name)(0, ((const __global name ## _T1*)(name ## Ptr + (byteOffset))))
|
||||||
|
#define __LOAD_MAT_AT_1 __LOAD_MAT_AT
|
||||||
|
#define __LOAD_MAT_AT_2 __LOAD_MAT_AT
|
||||||
|
#define __LOAD_MAT_AT_3 __LOAD_MAT_AT_vload
|
||||||
|
#define __LOAD_MAT_AT_4 __LOAD_MAT_AT
|
||||||
|
#define __LOAD_MAT_AT_CN__(name_cn) __LOAD_MAT_AT_ ## name_cn
|
||||||
|
#define __LOAD_MAT_AT_CN_(name_cn) __LOAD_MAT_AT_CN__(name_cn)
|
||||||
|
#define __LOAD_MAT_AT_CN(name) __LOAD_MAT_AT_CN_(name ## _CN)
|
||||||
|
#define LOAD_MAT_AT(name, byteOffset) __LOAD_MAT_AT_CN(name)(name, byteOffset)
|
||||||
|
|
||||||
|
#define __STORE_MAT_AT(name, byteOffset, v) *((__global name ## _T*)(name ## Ptr + (byteOffset))) = v
|
||||||
|
#define __vstore_CN__(name_cn) vstore ## name_cn
|
||||||
|
#define __vstore_CN_(name_cn) __vstore_CN__(name_cn)
|
||||||
|
#define __vstore_CN(name) __vstore_CN_(name ## _CN)
|
||||||
|
#define __STORE_MAT_AT_vstore(name, byteOffset, v) __vstore_CN(name)(v, 0, ((__global name ## _T1*)(name ## Ptr + (byteOffset))))
|
||||||
|
#define __STORE_MAT_AT_1 __STORE_MAT_AT
|
||||||
|
#define __STORE_MAT_AT_2 __STORE_MAT_AT
|
||||||
|
#define __STORE_MAT_AT_3 __STORE_MAT_AT_vstore
|
||||||
|
#define __STORE_MAT_AT_4 __STORE_MAT_AT
|
||||||
|
#define __STORE_MAT_AT_CN__(name_cn) __STORE_MAT_AT_ ## name_cn
|
||||||
|
#define __STORE_MAT_AT_CN_(name_cn) __STORE_MAT_AT_CN__(name_cn)
|
||||||
|
#define __STORE_MAT_AT_CN(name) __STORE_MAT_AT_CN_(name ## _CN)
|
||||||
|
#define STORE_MAT_AT(name, byteOffset, v) __STORE_MAT_AT_CN(name)(name, byteOffset, v)
|
||||||
|
|
||||||
|
#define T1_uchar uchar
|
||||||
|
#define T1_uchar2 uchar
|
||||||
|
#define T1_uchar3 uchar
|
||||||
|
#define T1_uchar4 uchar
|
||||||
|
#define T1_char char
|
||||||
|
#define T1_char2 char
|
||||||
|
#define T1_char3 char
|
||||||
|
#define T1_char4 char
|
||||||
|
#define T1_ushort ushort
|
||||||
|
#define T1_ushort2 ushort
|
||||||
|
#define T1_ushort3 ushort
|
||||||
|
#define T1_ushort4 ushort
|
||||||
|
#define T1_short short
|
||||||
|
#define T1_short2 short
|
||||||
|
#define T1_short3 short
|
||||||
|
#define T1_short4 short
|
||||||
|
#define T1_int int
|
||||||
|
#define T1_int2 int
|
||||||
|
#define T1_int3 int
|
||||||
|
#define T1_int4 int
|
||||||
|
#define T1_float float
|
||||||
|
#define T1_float2 float
|
||||||
|
#define T1_float3 float
|
||||||
|
#define T1_float4 float
|
||||||
|
#define T1_double double
|
||||||
|
#define T1_double2 double
|
||||||
|
#define T1_double3 double
|
||||||
|
#define T1_double4 double
|
||||||
|
#define T1(type) REF(CAT(T1_, REF(type)))
|
||||||
|
|
||||||
|
#define uchar1 uchar
|
||||||
|
#define char1 char
|
||||||
|
#define short1 short
|
||||||
|
#define ushort1 ushort
|
||||||
|
#define int1 int
|
||||||
|
#define float1 float
|
||||||
|
#define double1 double
|
||||||
|
#define TYPE(type, cn) REF(CAT(REF(type), REF(cn)))
|
||||||
|
|
||||||
|
#define __CONVERT_MODE_uchar_uchar __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_uchar_char __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_uchar_ushort __CONVERT
|
||||||
|
#define __CONVERT_MODE_uchar_short __CONVERT
|
||||||
|
#define __CONVERT_MODE_uchar_int __CONVERT
|
||||||
|
#define __CONVERT_MODE_uchar_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_uchar_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_char_uchar __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_char_char __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_char_ushort __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_char_short __CONVERT
|
||||||
|
#define __CONVERT_MODE_char_int __CONVERT
|
||||||
|
#define __CONVERT_MODE_char_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_char_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_ushort_uchar __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_ushort_char __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_ushort_ushort __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_ushort_short __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_ushort_int __CONVERT
|
||||||
|
#define __CONVERT_MODE_ushort_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_ushort_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_short_uchar __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_short_char __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_short_ushort __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_short_short __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_short_int __CONVERT
|
||||||
|
#define __CONVERT_MODE_short_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_short_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_int_uchar __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_int_char __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_int_ushort __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_int_short __CONVERT_sat
|
||||||
|
#define __CONVERT_MODE_int_int __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_int_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_int_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_float_uchar __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_float_char __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_float_ushort __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_float_short __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_float_int __CONVERT_rte
|
||||||
|
#define __CONVERT_MODE_float_float __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE_float_double __CONVERT
|
||||||
|
#define __CONVERT_MODE_double_uchar __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_double_char __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_double_ushort __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_double_short __CONVERT_sat_rte
|
||||||
|
#define __CONVERT_MODE_double_int __CONVERT_rte
|
||||||
|
#define __CONVERT_MODE_double_float __CONVERT
|
||||||
|
#define __CONVERT_MODE_double_double __NO_CONVERT
|
||||||
|
#define __CONVERT_MODE(srcType, dstType) CAT(__CONVERT_MODE_, CAT(REF(T1(srcType)), CAT(_, REF(T1(dstType)))))
|
||||||
|
|
||||||
|
#define __ROUND_MODE__NO_CONVERT
|
||||||
|
#define __ROUND_MODE__CONVERT // nothing
|
||||||
|
#define __ROUND_MODE__CONVERT_rte _rte
|
||||||
|
#define __ROUND_MODE__CONVERT_sat _sat
|
||||||
|
#define __ROUND_MODE__CONVERT_sat_rte _sat_rte
|
||||||
|
#define ROUND_MODE(srcType, dstType) CAT(__ROUND_MODE_, __CONVERT_MODE(srcType, dstType))
|
||||||
|
|
||||||
|
#define __CONVERT_ROUND(dstType, roundMode) CAT(CAT(convert_, REF(dstType)), roundMode)
|
||||||
|
#define __NO_CONVERT(dstType) // nothing
|
||||||
|
#define __CONVERT(dstType) __CONVERT_ROUND(dstType,)
|
||||||
|
#define __CONVERT_rte(dstType) __CONVERT_ROUND(dstType,_rte)
|
||||||
|
#define __CONVERT_sat(dstType) __CONVERT_ROUND(dstType,_sat)
|
||||||
|
#define __CONVERT_sat_rte(dstType) __CONVERT_ROUND(dstType,_sat_rte)
|
||||||
|
#define CONVERT(srcType, dstType) REF(__CONVERT_MODE(srcType,dstType))(dstType)
|
||||||
|
#define CONVERT_TO(dstType) __CONVERT_ROUND(dstType,)
|
||||||
|
|
||||||
|
// OpenCV depths
|
||||||
|
#define CV_8U 0
|
||||||
|
#define CV_8S 1
|
||||||
|
#define CV_16U 2
|
||||||
|
#define CV_16S 3
|
||||||
|
#define CV_32S 4
|
||||||
|
#define CV_32F 5
|
||||||
|
#define CV_64F 6
|
||||||
|
|
||||||
|
//
|
||||||
|
// End of common preprocessors macro
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DEFINE_feed)
|
||||||
|
|
||||||
|
#define workType TYPE(weight_T1, src_CN)
|
||||||
|
#define convertSrcToWorkType CONVERT_TO(workType)
|
||||||
|
#define convertToDstType CONVERT_TO(dst_T) // sat_rte provides incompatible results with CPU path
|
||||||
|
|
||||||
|
__kernel void feed(
|
||||||
|
DECLARE_MAT_ARG(src), DECLARE_MAT_ARG(weight),
|
||||||
|
DECLARE_MAT_ARG(dst), DECLARE_MAT_ARG(dstWeight)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const int x = get_global_id(0);
|
||||||
|
const int y = get_global_id(1);
|
||||||
|
|
||||||
|
if (x < srcWidth && y < srcHeight)
|
||||||
|
{
|
||||||
|
int src_byteOffset = MAT_BYTE_OFFSET(src, x, y);
|
||||||
|
int weight_byteOffset = MAT_BYTE_OFFSET(weight, x, y);
|
||||||
|
int dst_byteOffset = MAT_BYTE_OFFSET(dst, x, y);
|
||||||
|
int dstWeight_byteOffset = MAT_BYTE_OFFSET(dstWeight, x, y);
|
||||||
|
|
||||||
|
weight_T w = LOAD_MAT_AT(weight, weight_byteOffset);
|
||||||
|
workType src_value = convertSrcToWorkType(LOAD_MAT_AT(src, src_byteOffset));
|
||||||
|
STORE_MAT_AT(dst, dst_byteOffset, LOAD_MAT_AT(dst, dst_byteOffset) + convertToDstType(src_value * w));
|
||||||
|
STORE_MAT_AT(dstWeight, dstWeight_byteOffset, LOAD_MAT_AT(dstWeight, dstWeight_byteOffset) + w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEFINE_normalizeUsingWeightMap)
|
||||||
|
|
||||||
|
#define workType TYPE(weight_T1, mat_CN)
|
||||||
|
#define convertSrcToWorkType CONVERT_TO(workType)
|
||||||
|
#define convertToDstType CONVERT_TO(mat_T) // sat_rte provides incompatible results with CPU path
|
||||||
|
|
||||||
|
#if weight_DEPTH >= CV_32F
|
||||||
|
#define WEIGHT_EPS 1e-5f
|
||||||
|
#else
|
||||||
|
#define WEIGHT_EPS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__kernel void normalizeUsingWeightMap(
|
||||||
|
DECLARE_MAT_ARG(mat), DECLARE_MAT_ARG(weight)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const int x = get_global_id(0);
|
||||||
|
const int y = get_global_id(1);
|
||||||
|
|
||||||
|
if (x < matWidth && y < matHeight)
|
||||||
|
{
|
||||||
|
int mat_byteOffset = MAT_BYTE_OFFSET(mat, x, y);
|
||||||
|
int weight_byteOffset = MAT_BYTE_OFFSET(weight, x, y);
|
||||||
|
|
||||||
|
weight_T w = LOAD_MAT_AT(weight, weight_byteOffset);
|
||||||
|
workType value = convertSrcToWorkType(LOAD_MAT_AT(mat, mat_byteOffset));
|
||||||
|
value = value / (w + WEIGHT_EPS);
|
||||||
|
STORE_MAT_AT(mat, mat_byteOffset, convertToDstType(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -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"
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
namespace cv {
|
namespace cv {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
void PairwiseSeamFinder::find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
void PairwiseSeamFinder::find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks)
|
std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
LOGLN("Finding seams...");
|
LOGLN("Finding seams...");
|
||||||
if (src.size() == 0)
|
if (src.size() == 0)
|
||||||
@ -84,7 +84,7 @@ void PairwiseSeamFinder::run()
|
|||||||
|
|
||||||
|
|
||||||
void VoronoiSeamFinder::find(const std::vector<Size> &sizes, const std::vector<Point> &corners,
|
void VoronoiSeamFinder::find(const std::vector<Size> &sizes, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks)
|
std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
LOGLN("Finding seams...");
|
LOGLN("Finding seams...");
|
||||||
if (sizes.size() == 0)
|
if (sizes.size() == 0)
|
||||||
@ -110,7 +110,7 @@ void VoronoiSeamFinder::findInPair(size_t first, size_t second, Rect roi)
|
|||||||
Mat submask2(roi.height + 2 * gap, roi.width + 2 * gap, CV_8U);
|
Mat submask2(roi.height + 2 * gap, roi.width + 2 * gap, CV_8U);
|
||||||
|
|
||||||
Size img1 = sizes_[first], img2 = sizes_[second];
|
Size img1 = sizes_[first], img2 = sizes_[second];
|
||||||
Mat mask1 = masks_[first], mask2 = masks_[second];
|
Mat mask1 = masks_[first].getMat(ACCESS_READ), mask2 = masks_[second].getMat(ACCESS_READ);
|
||||||
Point tl1 = corners_[first], tl2 = corners_[second];
|
Point tl1 = corners_[first], tl2 = corners_[second];
|
||||||
|
|
||||||
// Cut submasks with some gap
|
// Cut submasks with some gap
|
||||||
@ -160,7 +160,7 @@ void VoronoiSeamFinder::findInPair(size_t first, size_t second, Rect roi)
|
|||||||
DpSeamFinder::DpSeamFinder(CostFunction costFunc) : costFunc_(costFunc) {}
|
DpSeamFinder::DpSeamFinder(CostFunction costFunc) : costFunc_(costFunc) {}
|
||||||
|
|
||||||
|
|
||||||
void DpSeamFinder::find(const std::vector<Mat> &src, const std::vector<Point> &corners, std::vector<Mat> &masks)
|
void DpSeamFinder::find(const std::vector<UMat> &src, const std::vector<Point> &corners, std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
LOGLN("Finding seams...");
|
LOGLN("Finding seams...");
|
||||||
#if ENABLE_LOG
|
#if ENABLE_LOG
|
||||||
@ -176,13 +176,18 @@ void DpSeamFinder::find(const std::vector<Mat> &src, const std::vector<Point> &c
|
|||||||
for (size_t j = i+1; j < src.size(); ++j)
|
for (size_t j = i+1; j < src.size(); ++j)
|
||||||
pairs.push_back(std::make_pair(i, j));
|
pairs.push_back(std::make_pair(i, j));
|
||||||
|
|
||||||
sort(pairs.begin(), pairs.end(), ImagePairLess(src, corners));
|
{
|
||||||
|
std::vector<Mat> _src(src.size());
|
||||||
|
for (size_t i = 0; i < src.size(); ++i) _src[i] = src[i].getMat(ACCESS_READ);
|
||||||
|
sort(pairs.begin(), pairs.end(), ImagePairLess(_src, corners));
|
||||||
|
}
|
||||||
std::reverse(pairs.begin(), pairs.end());
|
std::reverse(pairs.begin(), pairs.end());
|
||||||
|
|
||||||
for (size_t i = 0; i < pairs.size(); ++i)
|
for (size_t i = 0; i < pairs.size(); ++i)
|
||||||
{
|
{
|
||||||
size_t i0 = pairs[i].first, i1 = pairs[i].second;
|
size_t i0 = pairs[i].first, i1 = pairs[i].second;
|
||||||
process(src[i0], src[i1], corners[i0], corners[i1], masks[i0], masks[i1]);
|
Mat mask0 = masks[i0].getMat(ACCESS_RW), mask1 = masks[i1].getMat(ACCESS_RW);
|
||||||
|
process(src[i0].getMat(ACCESS_READ), src[i1].getMat(ACCESS_READ), corners[i0], corners[i1], mask0, mask1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
@ -1055,7 +1060,7 @@ public:
|
|||||||
|
|
||||||
~Impl() {}
|
~Impl() {}
|
||||||
|
|
||||||
void find(const std::vector<Mat> &src, const std::vector<Point> &corners, std::vector<Mat> &masks);
|
void find(const std::vector<UMat> &src, const std::vector<Point> &corners, std::vector<UMat> &masks);
|
||||||
void findInPair(size_t first, size_t second, Rect roi);
|
void findInPair(size_t first, size_t second, Rect roi);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1072,8 +1077,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void GraphCutSeamFinder::Impl::find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
void GraphCutSeamFinder::Impl::find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks)
|
std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
// Compute gradients
|
// Compute gradients
|
||||||
dx_.resize(src.size());
|
dx_.resize(src.size());
|
||||||
@ -1207,10 +1212,10 @@ void GraphCutSeamFinder::Impl::setGraphWeightsColorGrad(
|
|||||||
|
|
||||||
void GraphCutSeamFinder::Impl::findInPair(size_t first, size_t second, Rect roi)
|
void GraphCutSeamFinder::Impl::findInPair(size_t first, size_t second, Rect roi)
|
||||||
{
|
{
|
||||||
Mat img1 = images_[first], img2 = images_[second];
|
Mat img1 = images_[first].getMat(ACCESS_READ), img2 = images_[second].getMat(ACCESS_READ);
|
||||||
Mat dx1 = dx_[first], dx2 = dx_[second];
|
Mat dx1 = dx_[first], dx2 = dx_[second];
|
||||||
Mat dy1 = dy_[first], dy2 = dy_[second];
|
Mat dy1 = dy_[first], dy2 = dy_[second];
|
||||||
Mat mask1 = masks_[first], mask2 = masks_[second];
|
Mat mask1 = masks_[first].getMat(ACCESS_RW), mask2 = masks_[second].getMat(ACCESS_RW);
|
||||||
Point tl1 = corners_[first], tl2 = corners_[second];
|
Point tl1 = corners_[first], tl2 = corners_[second];
|
||||||
|
|
||||||
const int gap = 10;
|
const int gap = 10;
|
||||||
@ -1309,16 +1314,16 @@ GraphCutSeamFinder::GraphCutSeamFinder(int cost_type, float terminal_cost, float
|
|||||||
GraphCutSeamFinder::~GraphCutSeamFinder() {}
|
GraphCutSeamFinder::~GraphCutSeamFinder() {}
|
||||||
|
|
||||||
|
|
||||||
void GraphCutSeamFinder::find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
void GraphCutSeamFinder::find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks)
|
std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
impl_->find(src, corners, masks);
|
impl_->find(src, corners, masks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENCV_CUDA
|
#ifdef HAVE_OPENCV_CUDA
|
||||||
void GraphCutSeamFinderGpu::find(const std::vector<Mat> &src, const std::vector<Point> &corners,
|
void GraphCutSeamFinderGpu::find(const std::vector<UMat> &src, const std::vector<Point> &corners,
|
||||||
std::vector<Mat> &masks)
|
std::vector<UMat> &masks)
|
||||||
{
|
{
|
||||||
// Compute gradients
|
// Compute gradients
|
||||||
dx_.resize(src.size());
|
dx_.resize(src.size());
|
||||||
@ -1350,10 +1355,10 @@ void GraphCutSeamFinderGpu::find(const std::vector<Mat> &src, const std::vector<
|
|||||||
|
|
||||||
void GraphCutSeamFinderGpu::findInPair(size_t first, size_t second, Rect roi)
|
void GraphCutSeamFinderGpu::findInPair(size_t first, size_t second, Rect roi)
|
||||||
{
|
{
|
||||||
Mat img1 = images_[first], img2 = images_[second];
|
Mat img1 = images_[first].getMat(ACCESS_READ), img2 = images_[second].getMat(ACCESS_READ);
|
||||||
Mat dx1 = dx_[first], dx2 = dx_[second];
|
Mat dx1 = dx_[first], dx2 = dx_[second];
|
||||||
Mat dy1 = dy_[first], dy2 = dy_[second];
|
Mat dy1 = dy_[first], dy2 = dy_[second];
|
||||||
Mat mask1 = masks_[first], mask2 = masks_[second];
|
Mat mask1 = masks_[first].getMat(ACCESS_READ), mask2 = masks_[second].getMat(ACCESS_READ);
|
||||||
Point tl1 = corners_[first], tl2 = corners_[second];
|
Point tl1 = corners_[first], tl2 = corners_[second];
|
||||||
|
|
||||||
const int gap = 10;
|
const int gap = 10;
|
||||||
|
@ -86,15 +86,15 @@ Stitcher Stitcher::createDefault(bool try_use_gpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stitcher::Status Stitcher::estimateTransform(InputArray images)
|
Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images)
|
||||||
{
|
{
|
||||||
return estimateTransform(images, std::vector<std::vector<Rect> >());
|
return estimateTransform(images, std::vector<std::vector<Rect> >());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stitcher::Status Stitcher::estimateTransform(InputArray images, const std::vector<std::vector<Rect> > &rois)
|
Stitcher::Status Stitcher::estimateTransform(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois)
|
||||||
{
|
{
|
||||||
images.getMatVector(imgs_);
|
images.getUMatVector(imgs_);
|
||||||
rois_ = rois;
|
rois_ = rois;
|
||||||
|
|
||||||
Status status;
|
Status status;
|
||||||
@ -112,21 +112,21 @@ Stitcher::Status Stitcher::estimateTransform(InputArray images, const std::vecto
|
|||||||
|
|
||||||
Stitcher::Status Stitcher::composePanorama(OutputArray pano)
|
Stitcher::Status Stitcher::composePanorama(OutputArray pano)
|
||||||
{
|
{
|
||||||
return composePanorama(std::vector<Mat>(), pano);
|
return composePanorama(std::vector<UMat>(), pano);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArray pano)
|
||||||
{
|
{
|
||||||
LOGLN("Warping images (auxiliary)... ");
|
LOGLN("Warping images (auxiliary)... ");
|
||||||
|
|
||||||
std::vector<Mat> imgs;
|
std::vector<UMat> imgs;
|
||||||
images.getMatVector(imgs);
|
images.getUMatVector(imgs);
|
||||||
if (!imgs.empty())
|
if (!imgs.empty())
|
||||||
{
|
{
|
||||||
CV_Assert(imgs.size() == imgs_.size());
|
CV_Assert(imgs.size() == imgs_.size());
|
||||||
|
|
||||||
Mat img;
|
UMat img;
|
||||||
seam_est_imgs_.resize(imgs.size());
|
seam_est_imgs_.resize(imgs.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < imgs.size(); ++i)
|
for (size_t i = 0; i < imgs.size(); ++i)
|
||||||
@ -136,8 +136,8 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
seam_est_imgs_[i] = img.clone();
|
seam_est_imgs_[i] = img.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Mat> seam_est_imgs_subset;
|
std::vector<UMat> seam_est_imgs_subset;
|
||||||
std::vector<Mat> imgs_subset;
|
std::vector<UMat> imgs_subset;
|
||||||
|
|
||||||
for (size_t i = 0; i < indices_.size(); ++i)
|
for (size_t i = 0; i < indices_.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -149,17 +149,17 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
imgs_ = imgs_subset;
|
imgs_ = imgs_subset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat &pano_ = pano.getMatRef();
|
UMat pano_;
|
||||||
|
|
||||||
#if ENABLE_LOG
|
#if ENABLE_LOG
|
||||||
int64 t = getTickCount();
|
int64 t = getTickCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<Point> corners(imgs_.size());
|
std::vector<Point> corners(imgs_.size());
|
||||||
std::vector<Mat> masks_warped(imgs_.size());
|
std::vector<UMat> masks_warped(imgs_.size());
|
||||||
std::vector<Mat> images_warped(imgs_.size());
|
std::vector<UMat> images_warped(imgs_.size());
|
||||||
std::vector<Size> sizes(imgs_.size());
|
std::vector<Size> sizes(imgs_.size());
|
||||||
std::vector<Mat> masks(imgs_.size());
|
std::vector<UMat> masks(imgs_.size());
|
||||||
|
|
||||||
// Prepare image masks
|
// Prepare image masks
|
||||||
for (size_t i = 0; i < imgs_.size(); ++i)
|
for (size_t i = 0; i < imgs_.size(); ++i)
|
||||||
@ -179,13 +179,13 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
K(1,1) *= (float)seam_work_aspect_;
|
K(1,1) *= (float)seam_work_aspect_;
|
||||||
K(1,2) *= (float)seam_work_aspect_;
|
K(1,2) *= (float)seam_work_aspect_;
|
||||||
|
|
||||||
corners[i] = w->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
|
corners[i] = w->warp(seam_est_imgs_[i], K, cameras_[i].R, INTER_LINEAR, BORDER_CONSTANT, images_warped[i]);
|
||||||
sizes[i] = images_warped[i].size();
|
sizes[i] = images_warped[i].size();
|
||||||
|
|
||||||
w->warp(masks[i], K, cameras_[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
|
w->warp(masks[i], K, cameras_[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Mat> images_warped_f(imgs_.size());
|
std::vector<UMat> images_warped_f(imgs_.size());
|
||||||
for (size_t i = 0; i < imgs_.size(); ++i)
|
for (size_t i = 0; i < imgs_.size(); ++i)
|
||||||
images_warped[i].convertTo(images_warped_f[i], CV_32F);
|
images_warped[i].convertTo(images_warped_f[i], CV_32F);
|
||||||
|
|
||||||
@ -206,8 +206,8 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
t = getTickCount();
|
t = getTickCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Mat img_warped, img_warped_s;
|
UMat img_warped, img_warped_s;
|
||||||
Mat dilated_mask, seam_mask, mask, mask_warped;
|
UMat dilated_mask, seam_mask, mask, mask_warped;
|
||||||
|
|
||||||
//double compose_seam_aspect = 1;
|
//double compose_seam_aspect = 1;
|
||||||
double compose_work_aspect = 1;
|
double compose_work_aspect = 1;
|
||||||
@ -216,10 +216,13 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
double compose_scale = 1;
|
double compose_scale = 1;
|
||||||
bool is_compose_scale_set = false;
|
bool is_compose_scale_set = false;
|
||||||
|
|
||||||
Mat full_img, img;
|
UMat full_img, img;
|
||||||
for (size_t img_idx = 0; img_idx < imgs_.size(); ++img_idx)
|
for (size_t img_idx = 0; img_idx < imgs_.size(); ++img_idx)
|
||||||
{
|
{
|
||||||
LOGLN("Compositing image #" << indices_[img_idx] + 1);
|
LOGLN("Compositing image #" << indices_[img_idx] + 1);
|
||||||
|
#if ENABLE_LOG
|
||||||
|
int64 compositing_t = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Read image and resize it if necessary
|
// Read image and resize it if necessary
|
||||||
full_img = imgs_[img_idx];
|
full_img = imgs_[img_idx];
|
||||||
@ -261,25 +264,48 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (std::abs(compose_scale - 1) > 1e-1)
|
if (std::abs(compose_scale - 1) > 1e-1)
|
||||||
|
{
|
||||||
|
#if ENABLE_LOG
|
||||||
|
int64 resize_t = getTickCount();
|
||||||
|
#endif
|
||||||
resize(full_img, img, Size(), compose_scale, compose_scale);
|
resize(full_img, img, Size(), compose_scale, compose_scale);
|
||||||
|
LOGLN(" resize time: " << ((getTickCount() - resize_t) / getTickFrequency()) << " sec");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
img = full_img;
|
img = full_img;
|
||||||
full_img.release();
|
full_img.release();
|
||||||
Size img_size = img.size();
|
Size img_size = img.size();
|
||||||
|
|
||||||
|
LOGLN(" after resize time: " << ((getTickCount() - compositing_t) / getTickFrequency()) << " sec");
|
||||||
|
|
||||||
Mat K;
|
Mat K;
|
||||||
cameras_[img_idx].K().convertTo(K, CV_32F);
|
cameras_[img_idx].K().convertTo(K, CV_32F);
|
||||||
|
|
||||||
|
#if ENABLE_LOG
|
||||||
|
int64 pt = getTickCount();
|
||||||
|
#endif
|
||||||
// Warp the current image
|
// Warp the current image
|
||||||
w->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);
|
w->warp(img, K, cameras_[img_idx].R, INTER_LINEAR, BORDER_CONSTANT, img_warped);
|
||||||
|
LOGLN(" warp the current image: " << ((getTickCount() - pt) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
pt = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Warp the current image mask
|
// Warp the current image mask
|
||||||
mask.create(img_size, CV_8U);
|
mask.create(img_size, CV_8U);
|
||||||
mask.setTo(Scalar::all(255));
|
mask.setTo(Scalar::all(255));
|
||||||
w->warp(mask, K, cameras_[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
|
w->warp(mask, K, cameras_[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
|
||||||
|
LOGLN(" warp the current image mask: " << ((getTickCount() - pt) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
pt = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Compensate exposure
|
// Compensate exposure
|
||||||
exposure_comp_->apply((int)img_idx, corners[img_idx], img_warped, mask_warped);
|
exposure_comp_->apply((int)img_idx, corners[img_idx], img_warped, mask_warped);
|
||||||
|
LOGLN(" compensate exposure: " << ((getTickCount() - pt) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
pt = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
img_warped.convertTo(img_warped_s, CV_16S);
|
img_warped.convertTo(img_warped_s, CV_16S);
|
||||||
img_warped.release();
|
img_warped.release();
|
||||||
@ -290,7 +316,12 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
dilate(masks_warped[img_idx], dilated_mask, Mat());
|
dilate(masks_warped[img_idx], dilated_mask, Mat());
|
||||||
resize(dilated_mask, seam_mask, mask_warped.size());
|
resize(dilated_mask, seam_mask, mask_warped.size());
|
||||||
|
|
||||||
mask_warped = seam_mask & mask_warped;
|
bitwise_and(seam_mask, mask_warped, mask_warped);
|
||||||
|
|
||||||
|
LOGLN(" other: " << ((getTickCount() - pt) / getTickFrequency()) << " sec");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
pt = getTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!is_blender_prepared)
|
if (!is_blender_prepared)
|
||||||
{
|
{
|
||||||
@ -298,24 +329,36 @@ Stitcher::Status Stitcher::composePanorama(InputArray images, OutputArray pano)
|
|||||||
is_blender_prepared = true;
|
is_blender_prepared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGLN(" other2: " << ((getTickCount() - pt) / getTickFrequency()) << " sec");
|
||||||
|
|
||||||
|
LOGLN(" feed...");
|
||||||
|
#if ENABLE_LOG
|
||||||
|
int64 feed_t = getTickCount();
|
||||||
|
#endif
|
||||||
// Blend the current image
|
// Blend the current image
|
||||||
blender_->feed(img_warped_s, mask_warped, corners[img_idx]);
|
blender_->feed(img_warped_s, mask_warped, corners[img_idx]);
|
||||||
|
LOGLN(" feed time: " << ((getTickCount() - feed_t) / getTickFrequency()) << " sec");
|
||||||
|
LOGLN("Compositing ## time: " << ((getTickCount() - compositing_t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat result, result_mask;
|
#if ENABLE_LOG
|
||||||
|
int64 blend_t = getTickCount();
|
||||||
|
#endif
|
||||||
|
UMat result, result_mask;
|
||||||
blender_->blend(result, result_mask);
|
blender_->blend(result, result_mask);
|
||||||
|
LOGLN("blend time: " << ((getTickCount() - blend_t) / getTickFrequency()) << " sec");
|
||||||
|
|
||||||
LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stitcher::Status Stitcher::stitch(InputArray images, OutputArray pano)
|
Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, OutputArray pano)
|
||||||
{
|
{
|
||||||
Status status = estimateTransform(images);
|
Status status = estimateTransform(images);
|
||||||
if (status != OK)
|
if (status != OK)
|
||||||
@ -324,7 +367,7 @@ Stitcher::Status Stitcher::stitch(InputArray images, OutputArray pano)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stitcher::Status Stitcher::stitch(InputArray images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
|
Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
|
||||||
{
|
{
|
||||||
Status status = estimateTransform(images, rois);
|
Status status = estimateTransform(images, rois);
|
||||||
if (status != OK)
|
if (status != OK)
|
||||||
@ -346,7 +389,7 @@ Stitcher::Status Stitcher::matchImages()
|
|||||||
seam_scale_ = 1;
|
seam_scale_ = 1;
|
||||||
bool is_work_scale_set = false;
|
bool is_work_scale_set = false;
|
||||||
bool is_seam_scale_set = false;
|
bool is_seam_scale_set = false;
|
||||||
Mat full_img, img;
|
UMat full_img, img;
|
||||||
features_.resize(imgs_.size());
|
features_.resize(imgs_.size());
|
||||||
seam_est_imgs_.resize(imgs_.size());
|
seam_est_imgs_.resize(imgs_.size());
|
||||||
full_img_sizes_.resize(imgs_.size());
|
full_img_sizes_.resize(imgs_.size());
|
||||||
@ -420,8 +463,8 @@ Stitcher::Status Stitcher::matchImages()
|
|||||||
|
|
||||||
// Leave only images we are sure are from the same panorama
|
// Leave only images we are sure are from the same panorama
|
||||||
indices_ = detail::leaveBiggestComponent(features_, pairwise_matches_, (float)conf_thresh_);
|
indices_ = detail::leaveBiggestComponent(features_, pairwise_matches_, (float)conf_thresh_);
|
||||||
std::vector<Mat> seam_est_imgs_subset;
|
std::vector<UMat> seam_est_imgs_subset;
|
||||||
std::vector<Mat> imgs_subset;
|
std::vector<UMat> imgs_subset;
|
||||||
std::vector<Size> full_img_sizes_subset;
|
std::vector<Size> full_img_sizes_subset;
|
||||||
for (size_t i = 0; i < indices_.size(); ++i)
|
for (size_t i = 0; i < indices_.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -454,7 +497,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_);
|
||||||
@ -465,7 +508,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ bool overlapRoi(Point tl1, Point tl2, Size sz1, Size sz2, Rect &roi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rect resultRoi(const std::vector<Point> &corners, const std::vector<Mat> &images)
|
Rect resultRoi(const std::vector<Point> &corners, const std::vector<UMat> &images)
|
||||||
{
|
{
|
||||||
std::vector<Size> sizes(images.size());
|
std::vector<Size> sizes(images.size());
|
||||||
for (size_t i = 0; i < images.size(); ++i)
|
for (size_t i = 0; i < images.size(); ++i)
|
||||||
|
@ -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())
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,6 @@ TEST(MultiBandBlender, CanBlendTwoImages)
|
|||||||
Mat result; result_s.convertTo(result, CV_8U);
|
Mat result; result_s.convertTo(result, CV_8U);
|
||||||
|
|
||||||
Mat expected = imread(string(cvtest::TS::ptr()->get_data_path()) + "stitching/baboon_lena.png");
|
Mat expected = imread(string(cvtest::TS::ptr()->get_data_path()) + "stitching/baboon_lena.png");
|
||||||
double rmsErr = cvtest::norm(expected, result, NORM_L2) / sqrt(double(expected.size().area()));
|
double psnr = cvtest::PSNR(expected, result);
|
||||||
ASSERT_LT(rmsErr, 1e-3);
|
EXPECT_GE(psnr, 50);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,31 @@ namespace ocl {
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
inline std::vector<UMat> ToUMat(const std::vector<Mat>& src)
|
||||||
|
{
|
||||||
|
std::vector<UMat> dst;
|
||||||
|
dst.resize(src.size());
|
||||||
|
for (size_t i = 0; i < src.size(); ++i)
|
||||||
|
{
|
||||||
|
src[i].copyTo(dst[i]);
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UMat ToUMat(const Mat& src)
|
||||||
|
{
|
||||||
|
UMat dst;
|
||||||
|
src.copyTo(dst);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UMat ToUMat(InputArray src)
|
||||||
|
{
|
||||||
|
UMat dst;
|
||||||
|
src.getMat().copyTo(dst);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
extern int test_loop_times;
|
extern int test_loop_times;
|
||||||
|
|
||||||
#define MAX_VALUE 357
|
#define MAX_VALUE 357
|
||||||
|
@ -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]);
|
||||||
@ -348,7 +331,9 @@ int main(int argc, char* argv[])
|
|||||||
int64 app_start_time = getTickCount();
|
int64 app_start_time = getTickCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
cv::setBreakOnError(true);
|
cv::setBreakOnError(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
int retval = parseCmdArgs(argc, argv);
|
int retval = parseCmdArgs(argc, argv);
|
||||||
if (retval)
|
if (retval)
|
||||||
@ -554,10 +539,10 @@ int main(int argc, char* argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
vector<Point> corners(num_images);
|
vector<Point> corners(num_images);
|
||||||
vector<Mat> masks_warped(num_images);
|
vector<UMat> masks_warped(num_images);
|
||||||
vector<Mat> images_warped(num_images);
|
vector<UMat> images_warped(num_images);
|
||||||
vector<Size> sizes(num_images);
|
vector<Size> sizes(num_images);
|
||||||
vector<Mat> masks(num_images);
|
vector<UMat> masks(num_images);
|
||||||
|
|
||||||
// Preapre images masks
|
// Preapre images masks
|
||||||
for (int i = 0; i < num_images; ++i)
|
for (int i = 0; i < num_images; ++i)
|
||||||
@ -569,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>();
|
||||||
@ -645,7 +621,7 @@ int main(int argc, char* argv[])
|
|||||||
warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
|
warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Mat> images_warped_f(num_images);
|
vector<UMat> images_warped_f(num_images);
|
||||||
for (int i = 0; i < num_images; ++i)
|
for (int i = 0; i < num_images; ++i)
|
||||||
images_warped[i].convertTo(images_warped_f[i], CV_32F);
|
images_warped[i].convertTo(images_warped_f[i], CV_32F);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user