refactored features finders in stitching module
This commit is contained in:
parent
6d09dd5cf7
commit
cbb6ac0c34
@ -46,6 +46,10 @@
|
|||||||
#include "opencv2/core/core.hpp"
|
#include "opencv2/core/core.hpp"
|
||||||
#include "opencv2/features2d/features2d.hpp"
|
#include "opencv2/features2d/features2d.hpp"
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
#include "opencv2/gpu/gpu.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@ -63,8 +67,6 @@ class CV_EXPORTS FeaturesFinder
|
|||||||
public:
|
public:
|
||||||
virtual ~FeaturesFinder() {}
|
virtual ~FeaturesFinder() {}
|
||||||
void operator ()(const Mat &image, ImageFeatures &features);
|
void operator ()(const Mat &image, ImageFeatures &features);
|
||||||
|
|
||||||
// TODO put it into operator ()
|
|
||||||
virtual void collectGarbage() {}
|
virtual void collectGarbage() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -75,17 +77,38 @@ protected:
|
|||||||
class CV_EXPORTS SurfFeaturesFinder : public FeaturesFinder
|
class CV_EXPORTS SurfFeaturesFinder : public FeaturesFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SurfFeaturesFinder(bool try_use_gpu = true, double hess_thresh = 300.0,
|
SurfFeaturesFinder(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4,
|
||||||
int num_octaves = 3, int num_layers = 4,
|
int num_octaves_descr = 4, int num_layers_descr = 2);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void find(const Mat &image, ImageFeatures &features);
|
||||||
|
|
||||||
|
Ptr<FeatureDetector> detector_;
|
||||||
|
Ptr<DescriptorExtractor> extractor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
class SurfFeaturesFinderGpu : public FeaturesFinder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SurfFeaturesFinderGpu(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4,
|
||||||
int num_octaves_descr = 4, int num_layers_descr = 2);
|
int num_octaves_descr = 4, int num_layers_descr = 2);
|
||||||
|
|
||||||
void collectGarbage();
|
void collectGarbage();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
void find(const Mat &image, ImageFeatures &features);
|
||||||
|
|
||||||
Ptr<FeaturesFinder> impl_;
|
gpu::GpuMat image_;
|
||||||
|
gpu::GpuMat gray_image_;
|
||||||
|
gpu::SURF_GPU surf_;
|
||||||
|
gpu::GpuMat keypoints_;
|
||||||
|
gpu::GpuMat descriptors_;
|
||||||
|
int num_octaves_, num_layers_;
|
||||||
|
int num_octaves_descr_, num_layers_descr_;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct CV_EXPORTS MatchesInfo
|
struct CV_EXPORTS MatchesInfo
|
||||||
|
@ -77,7 +77,6 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
||||||
class PlaneWarperGpu: public WarperCreator
|
class PlaneWarperGpu: public WarperCreator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -97,7 +96,6 @@ class SphericalWarperGpu: public WarperCreator
|
|||||||
public:
|
public:
|
||||||
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::SphericalWarperGpu(f); }
|
Ptr<detail::Warper> createByFocalLength(double f) const { return new detail::SphericalWarperGpu(f); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -51,104 +51,6 @@ using namespace cv::gpu;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class CpuSurfFeaturesFinder : public FeaturesFinder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
|
||||||
int num_octaves_descr, int num_layers_descr)
|
|
||||||
{
|
|
||||||
detector_ = new SurfFeatureDetector(hess_thresh, num_octaves, num_layers);
|
|
||||||
extractor_ = new SurfDescriptorExtractor(num_octaves_descr, num_layers_descr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ptr<FeatureDetector> detector_;
|
|
||||||
Ptr<DescriptorExtractor> extractor_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
|
||||||
class GpuSurfFeaturesFinder : public FeaturesFinder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
|
||||||
int num_octaves_descr, int num_layers_descr)
|
|
||||||
{
|
|
||||||
surf_.keypointsRatio = 0.1f;
|
|
||||||
surf_.hessianThreshold = hess_thresh;
|
|
||||||
surf_.extended = false;
|
|
||||||
num_octaves_ = num_octaves;
|
|
||||||
num_layers_ = num_layers;
|
|
||||||
num_octaves_descr_ = num_octaves_descr;
|
|
||||||
num_layers_descr_ = num_layers_descr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void collectGarbage();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void find(const Mat &image, ImageFeatures &features);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GpuMat image_;
|
|
||||||
GpuMat gray_image_;
|
|
||||||
SURF_GPU surf_;
|
|
||||||
GpuMat keypoints_;
|
|
||||||
GpuMat descriptors_;
|
|
||||||
int num_octaves_, num_layers_;
|
|
||||||
int num_octaves_descr_, num_layers_descr_;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void CpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|
||||||
{
|
|
||||||
Mat gray_image;
|
|
||||||
CV_Assert(image.depth() == CV_8U);
|
|
||||||
cvtColor(image, gray_image, CV_BGR2GRAY);
|
|
||||||
detector_->detect(gray_image, features.keypoints);
|
|
||||||
extractor_->compute(gray_image, features.keypoints, features.descriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
|
||||||
void GpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
|
||||||
{
|
|
||||||
CV_Assert(image.depth() == CV_8U);
|
|
||||||
|
|
||||||
ensureSizeIsEnough(image.size(), image.type(), image_);
|
|
||||||
image_.upload(image);
|
|
||||||
|
|
||||||
ensureSizeIsEnough(image.size(), CV_8UC1, gray_image_);
|
|
||||||
cvtColor(image_, gray_image_, CV_BGR2GRAY);
|
|
||||||
|
|
||||||
surf_.nOctaves = num_octaves_;
|
|
||||||
surf_.nOctaveLayers = num_layers_;
|
|
||||||
surf_.upright = false;
|
|
||||||
surf_(gray_image_, GpuMat(), keypoints_);
|
|
||||||
|
|
||||||
surf_.nOctaves = num_octaves_descr_;
|
|
||||||
surf_.nOctaveLayers = num_layers_descr_;
|
|
||||||
surf_.upright = true;
|
|
||||||
surf_(gray_image_, GpuMat(), keypoints_, descriptors_, true);
|
|
||||||
surf_.downloadKeypoints(keypoints_, features.keypoints);
|
|
||||||
|
|
||||||
descriptors_.download(features.descriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuSurfFeaturesFinder::collectGarbage()
|
|
||||||
{
|
|
||||||
surf_.releaseMemory();
|
|
||||||
image_.release();
|
|
||||||
gray_image_.release();
|
|
||||||
keypoints_.release();
|
|
||||||
descriptors_.release();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DistIdxPair
|
struct DistIdxPair
|
||||||
{
|
{
|
||||||
bool operator<(const DistIdxPair &other) const { return dist < other.dist; }
|
bool operator<(const DistIdxPair &other) const { return dist < other.dist; }
|
||||||
@ -347,34 +249,76 @@ void FeaturesFinder::operator ()(const Mat &image, ImageFeatures &features)
|
|||||||
{
|
{
|
||||||
find(image, features);
|
find(image, features);
|
||||||
features.img_size = image.size();
|
features.img_size = image.size();
|
||||||
//features.img = image.clone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SurfFeaturesFinder::SurfFeaturesFinder(bool try_use_gpu, double hess_thresh, int num_octaves, int num_layers,
|
SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
||||||
int num_octaves_descr, int num_layers_descr)
|
int num_octaves_descr, int num_layers_descr)
|
||||||
{
|
{
|
||||||
#ifndef ANDROID
|
detector_ = new SurfFeatureDetector(hess_thresh, num_octaves, num_layers);
|
||||||
if (try_use_gpu && getCudaEnabledDeviceCount() > 0)
|
extractor_ = new SurfDescriptorExtractor(num_octaves_descr, num_layers_descr);
|
||||||
impl_ = new GpuSurfFeaturesFinder(hess_thresh, num_octaves, num_layers, num_octaves_descr, num_layers_descr);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
impl_ = new CpuSurfFeaturesFinder(hess_thresh, num_octaves, num_layers, num_octaves_descr, num_layers_descr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
|
||||||
{
|
{
|
||||||
(*impl_)(image, features);
|
Mat gray_image;
|
||||||
|
CV_Assert(image.depth() == CV_8U);
|
||||||
|
cvtColor(image, gray_image, CV_BGR2GRAY);
|
||||||
|
detector_->detect(gray_image, features.keypoints);
|
||||||
|
extractor_->compute(gray_image, features.keypoints, features.descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SurfFeaturesFinder::collectGarbage()
|
#ifndef ANDROID
|
||||||
|
SurfFeaturesFinderGpu::SurfFeaturesFinderGpu(double hess_thresh, int num_octaves, int num_layers,
|
||||||
|
int num_octaves_descr, int num_layers_descr)
|
||||||
{
|
{
|
||||||
impl_->collectGarbage();
|
surf_.keypointsRatio = 0.1f;
|
||||||
|
surf_.hessianThreshold = hess_thresh;
|
||||||
|
surf_.extended = false;
|
||||||
|
num_octaves_ = num_octaves;
|
||||||
|
num_layers_ = num_layers;
|
||||||
|
num_octaves_descr_ = num_octaves_descr;
|
||||||
|
num_layers_descr_ = num_layers_descr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SurfFeaturesFinderGpu::find(const Mat &image, ImageFeatures &features)
|
||||||
|
{
|
||||||
|
CV_Assert(image.depth() == CV_8U);
|
||||||
|
|
||||||
|
ensureSizeIsEnough(image.size(), image.type(), image_);
|
||||||
|
image_.upload(image);
|
||||||
|
|
||||||
|
ensureSizeIsEnough(image.size(), CV_8UC1, gray_image_);
|
||||||
|
cvtColor(image_, gray_image_, CV_BGR2GRAY);
|
||||||
|
|
||||||
|
surf_.nOctaves = num_octaves_;
|
||||||
|
surf_.nOctaveLayers = num_layers_;
|
||||||
|
surf_.upright = false;
|
||||||
|
surf_(gray_image_, GpuMat(), keypoints_);
|
||||||
|
|
||||||
|
surf_.nOctaves = num_octaves_descr_;
|
||||||
|
surf_.nOctaveLayers = num_layers_descr_;
|
||||||
|
surf_.upright = true;
|
||||||
|
surf_(gray_image_, GpuMat(), keypoints_, descriptors_, true);
|
||||||
|
surf_.downloadKeypoints(keypoints_, features.keypoints);
|
||||||
|
|
||||||
|
descriptors_.download(features.descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfFeaturesFinderGpu::collectGarbage()
|
||||||
|
{
|
||||||
|
surf_.releaseMemory();
|
||||||
|
image_.release();
|
||||||
|
gray_image_.release();
|
||||||
|
keypoints_.release();
|
||||||
|
descriptors_.release();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MatchesInfo::MatchesInfo() : src_img_idx(-1), dst_img_idx(-1), num_inliers(0), confidence(0) {}
|
MatchesInfo::MatchesInfo() : src_img_idx(-1), dst_img_idx(-1), num_inliers(0), confidence(0) {}
|
||||||
|
@ -46,7 +46,6 @@ using namespace std;
|
|||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
|
|
||||||
// TODO put all #ifndef ANDROID here, avoid passing try_use_gpu
|
|
||||||
Stitcher Stitcher::createDefault(bool try_use_gpu)
|
Stitcher Stitcher::createDefault(bool try_use_gpu)
|
||||||
{
|
{
|
||||||
Stitcher stitcher;
|
Stitcher stitcher;
|
||||||
@ -55,18 +54,25 @@ Stitcher Stitcher::createDefault(bool try_use_gpu)
|
|||||||
stitcher.setCompositingResol(ORIG_RESOL);
|
stitcher.setCompositingResol(ORIG_RESOL);
|
||||||
stitcher.setPanoConfidenceThresh(1);
|
stitcher.setPanoConfidenceThresh(1);
|
||||||
stitcher.setHorizontalStrightening(true);
|
stitcher.setHorizontalStrightening(true);
|
||||||
stitcher.setFeaturesFinder(new detail::SurfFeaturesFinder(try_use_gpu));
|
|
||||||
stitcher.setFeaturesMatcher(new detail::BestOf2NearestMatcher(try_use_gpu));
|
stitcher.setFeaturesMatcher(new detail::BestOf2NearestMatcher(try_use_gpu));
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
bool must_use_gpu = try_use_gpu && (gpu::getCudaEnabledDeviceCount() > 0);
|
if (try_use_gpu && gpu::getCudaEnabledDeviceCount() > 0)
|
||||||
stitcher.setWarper(must_use_gpu ? static_cast<WarperCreator*>(new SphericalWarperGpu()) :
|
{
|
||||||
static_cast<WarperCreator*>(new SphericalWarper()));
|
stitcher.setFeaturesFinder(new detail::SurfFeaturesFinderGpu());
|
||||||
#else
|
stitcher.setWarper(new SphericalWarperGpu());
|
||||||
stitcher.setWarper(new SphericalWarper());
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
stitcher.setFeaturesFinder(new detail::SurfFeaturesFinder());
|
||||||
|
stitcher.setWarper(new SphericalWarper());
|
||||||
|
}
|
||||||
|
|
||||||
stitcher.setExposureCompenstor(new detail::BlocksGainCompensator());
|
stitcher.setExposureCompenstor(new detail::BlocksGainCompensator());
|
||||||
stitcher.setSeamFinder(new detail::GraphCutSeamFinder());
|
stitcher.setSeamFinder(new detail::GraphCutSeamFinder());
|
||||||
stitcher.setBlender(new detail::MultiBandBlender(try_use_gpu));
|
stitcher.setBlender(new detail::MultiBandBlender(try_use_gpu));
|
||||||
|
|
||||||
return stitcher;
|
return stitcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,10 +326,16 @@ int main(int argc, char* argv[])
|
|||||||
LOGLN("Finding features...");
|
LOGLN("Finding features...");
|
||||||
int64 t = getTickCount();
|
int64 t = getTickCount();
|
||||||
|
|
||||||
vector<ImageFeatures> features(num_images);
|
Ptr<FeaturesFinder> finder;
|
||||||
SurfFeaturesFinder finder(try_gpu);
|
#ifndef ANDROID
|
||||||
Mat full_img, img;
|
if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0)
|
||||||
|
finder = new SurfFeaturesFinderGpu();
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
finder = new SurfFeaturesFinder();
|
||||||
|
|
||||||
|
Mat full_img, img;
|
||||||
|
vector<ImageFeatures> features(num_images);
|
||||||
vector<Mat> images(num_images);
|
vector<Mat> images(num_images);
|
||||||
vector<Size> full_img_sizes(num_images);
|
vector<Size> full_img_sizes(num_images);
|
||||||
double seam_work_aspect = 1;
|
double seam_work_aspect = 1;
|
||||||
@ -366,7 +372,7 @@ int main(int argc, char* argv[])
|
|||||||
is_seam_scale_set = true;
|
is_seam_scale_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
finder(img, features[i]);
|
(*finder)(img, features[i]);
|
||||||
features[i].img_idx = i;
|
features[i].img_idx = i;
|
||||||
LOGLN("Features in image #" << i+1 << ": " << features[i].keypoints.size());
|
LOGLN("Features in image #" << i+1 << ": " << features[i].keypoints.size());
|
||||||
|
|
||||||
@ -374,8 +380,7 @@ int main(int argc, char* argv[])
|
|||||||
images[i] = img.clone();
|
images[i] = img.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
finder.collectGarbage();
|
finder->collectGarbage();
|
||||||
|
|
||||||
full_img.release();
|
full_img.release();
|
||||||
img.release();
|
img.release();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user