提交 c5adaa71 编写于 作者: V Vladislav Vinogradov

minor stitching optimization (improve buffer reuse)

上级 b319e7f4
...@@ -1462,6 +1462,8 @@ namespace cv ...@@ -1462,6 +1462,8 @@ namespace cv
void operator()(const GpuMat& img, const GpuMat& mask, std::vector<KeyPoint>& keypoints, std::vector<float>& descriptors, void operator()(const GpuMat& img, const GpuMat& mask, std::vector<KeyPoint>& keypoints, std::vector<float>& descriptors,
bool useProvidedKeypoints = false); bool useProvidedKeypoints = false);
void releaseMemory();
//! max keypoints = min(keypointsRatio * img.size().area(), 65535) //! max keypoints = min(keypointsRatio * img.size().area(), 65535)
float keypointsRatio; float keypointsRatio;
......
...@@ -203,8 +203,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::matchSingle(const GpuMat& queryDescs, ...@@ -203,8 +203,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::matchSingle(const GpuMat& queryDescs,
const int nQuery = queryDescs.rows; const int nQuery = queryDescs.rows;
trainIdx.create(1, nQuery, CV_32S); ensureSizeIsEnough(1, nQuery, CV_32S, trainIdx);
distance.create(1, nQuery, CV_32F); ensureSizeIsEnough(1, nQuery, CV_32F, distance);
match_caller_t func = match_callers[distType][queryDescs.depth()]; match_caller_t func = match_callers[distType][queryDescs.depth()];
CV_Assert(func != 0); CV_Assert(func != 0);
...@@ -335,9 +335,9 @@ void cv::gpu::BruteForceMatcher_GPU_base::matchCollection(const GpuMat& queryDes ...@@ -335,9 +335,9 @@ void cv::gpu::BruteForceMatcher_GPU_base::matchCollection(const GpuMat& queryDes
const int nQuery = queryDescs.rows; const int nQuery = queryDescs.rows;
trainIdx.create(1, nQuery, CV_32S); ensureSizeIsEnough(1, nQuery, CV_32S, trainIdx);
imgIdx.create(1, nQuery, CV_32S); ensureSizeIsEnough(1, nQuery, CV_32S, imgIdx);
distance.create(1, nQuery, CV_32F); ensureSizeIsEnough(1, nQuery, CV_32F, distance);
match_caller_t func = match_callers[distType][queryDescs.depth()]; match_caller_t func = match_callers[distType][queryDescs.depth()];
CV_Assert(func != 0); CV_Assert(func != 0);
...@@ -435,8 +435,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::knnMatch(const GpuMat& queryDescs, con ...@@ -435,8 +435,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::knnMatch(const GpuMat& queryDescs, con
const int nQuery = queryDescs.rows; const int nQuery = queryDescs.rows;
const int nTrain = trainDescs.rows; const int nTrain = trainDescs.rows;
trainIdx.create(nQuery, k, CV_32S); ensureSizeIsEnough(nQuery, k, CV_32S, trainIdx);
distance.create(nQuery, k, CV_32F); ensureSizeIsEnough(nQuery, k, CV_32F, distance);
ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, allDist); ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, allDist);
if (stream) if (stream)
...@@ -593,8 +593,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::radiusMatch(const GpuMat& queryDescs, ...@@ -593,8 +593,8 @@ void cv::gpu::BruteForceMatcher_GPU_base::radiusMatch(const GpuMat& queryDescs,
ensureSizeIsEnough(1, nQuery, CV_32SC1, nMatches); ensureSizeIsEnough(1, nQuery, CV_32SC1, nMatches);
if (trainIdx.empty()) if (trainIdx.empty())
{ {
trainIdx.create(nQuery, nTrain, CV_32SC1); ensureSizeIsEnough(nQuery, nTrain, CV_32SC1, trainIdx);
distance.create(nQuery, nTrain, CV_32FC1); ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, distance);
} }
if (stream) if (stream)
......
...@@ -192,8 +192,8 @@ namespace ...@@ -192,8 +192,8 @@ namespace
Size src_size = src.size(); Size src_size = src.size();
dst.create(src_size, dstType); dst.create(src_size, dstType);
ensureSizeIsEnough(src_size, bufType, dstBuf); ensureSizeIsEnough(src_size, bufType, dstBuf);
//dstBuf.create(src_size, bufType);
if (stream) if (stream)
{ {
......
...@@ -59,6 +59,7 @@ void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, GpuMat&, GpuMat ...@@ -59,6 +59,7 @@ void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, GpuMat&, GpuMat
void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&) { throw_nogpu(); } void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&) { throw_nogpu(); }
void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&, GpuMat&, bool) { throw_nogpu(); } void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&, GpuMat&, bool) { throw_nogpu(); }
void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&, vector<float>&, bool) { throw_nogpu(); } void cv::gpu::SURF_GPU::operator()(const GpuMat&, const GpuMat&, vector<KeyPoint>&, vector<float>&, bool) { throw_nogpu(); }
void cv::gpu::SURF_GPU::releaseMemory() { throw_nogpu(); }
#else /* !defined (HAVE_CUDA) */ #else /* !defined (HAVE_CUDA) */
...@@ -201,7 +202,7 @@ namespace ...@@ -201,7 +202,7 @@ namespace
const int nFeatures = keypoints.cols; const int nFeatures = keypoints.cols;
if (nFeatures > 0) if (nFeatures > 0)
{ {
descriptors.create(nFeatures, descriptorSize, CV_32F); ensureSizeIsEnough(nFeatures, descriptorSize, CV_32F, descriptors);
compute_descriptors_gpu(descriptors, keypoints.ptr<float>(SURF_GPU::SF_X), keypoints.ptr<float>(SURF_GPU::SF_Y), compute_descriptors_gpu(descriptors, keypoints.ptr<float>(SURF_GPU::SF_X), keypoints.ptr<float>(SURF_GPU::SF_Y),
keypoints.ptr<float>(SURF_GPU::SF_SIZE), keypoints.ptr<float>(SURF_GPU::SF_DIR), nFeatures); keypoints.ptr<float>(SURF_GPU::SF_SIZE), keypoints.ptr<float>(SURF_GPU::SF_DIR), nFeatures);
} }
...@@ -431,4 +432,15 @@ void cv::gpu::SURF_GPU::operator()(const GpuMat& img, const GpuMat& mask, vector ...@@ -431,4 +432,15 @@ void cv::gpu::SURF_GPU::operator()(const GpuMat& img, const GpuMat& mask, vector
downloadDescriptors(descriptorsGPU, descriptors); downloadDescriptors(descriptorsGPU, descriptors);
} }
void cv::gpu::SURF_GPU::releaseMemory()
{
sum.release();
mask1.release();
maskSum.release();
intBuffer.release();
det.release();
trace.release();
maxPosBuffer.release();
}
#endif /* !defined (HAVE_CUDA) */ #endif /* !defined (HAVE_CUDA) */
...@@ -363,6 +363,8 @@ int main(int argc, char* argv[]) ...@@ -363,6 +363,8 @@ int main(int argc, char* argv[])
images[i] = img.clone(); images[i] = img.clone();
} }
finder.releaseMemory();
full_img.release(); full_img.release();
img.release(); img.release();
...@@ -373,6 +375,7 @@ int main(int argc, char* argv[]) ...@@ -373,6 +375,7 @@ int main(int argc, char* argv[])
vector<MatchesInfo> pairwise_matches; vector<MatchesInfo> pairwise_matches;
BestOf2NearestMatcher matcher(try_gpu, match_conf); BestOf2NearestMatcher matcher(try_gpu, match_conf);
matcher(features, pairwise_matches); matcher(features, pairwise_matches);
matcher.releaseMemory();
LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
// Leave only images we are sure are from the same panorama // Leave only images we are sure are from the same panorama
...@@ -571,7 +574,7 @@ int main(int argc, char* argv[]) ...@@ -571,7 +574,7 @@ int main(int argc, char* argv[])
resize(dilated_mask, seam_mask, mask_warped.size()); resize(dilated_mask, seam_mask, mask_warped.size());
mask_warped = seam_mask & mask_warped; mask_warped = seam_mask & mask_warped;
if (static_cast<Blender*>(blender) == 0) if (blender.empty())
{ {
blender = Blender::createDefault(blend_type, try_gpu); blender = Blender::createDefault(blend_type, try_gpu);
Size dst_sz = resultRoi(corners, sizes).size(); Size dst_sz = resultRoi(corners, sizes).size();
...@@ -598,7 +601,7 @@ int main(int argc, char* argv[]) ...@@ -598,7 +601,7 @@ int main(int argc, char* argv[])
} }
Mat result, result_mask; Mat result, result_mask;
blender->blend(result, result_mask); blender->blend(result, result_mask);
LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
......
...@@ -96,11 +96,17 @@ namespace ...@@ -96,11 +96,17 @@ namespace
num_layers_descr_ = num_layers_descr; num_layers_descr_ = num_layers_descr;
} }
void releaseMemory();
protected: protected:
void find(const Mat &image, ImageFeatures &features); void find(const Mat &image, ImageFeatures &features);
private: private:
GpuMat image_;
GpuMat gray_image_;
SURF_GPU surf_; SURF_GPU surf_;
GpuMat keypoints_;
GpuMat descriptors_;
int num_octaves_, num_layers_; int num_octaves_, num_layers_;
int num_octaves_descr_, num_layers_descr_; int num_octaves_descr_, num_layers_descr_;
}; };
...@@ -118,22 +124,34 @@ namespace ...@@ -118,22 +124,34 @@ namespace
void GpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features) void GpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
{ {
GpuMat gray_image;
CV_Assert(image.depth() == CV_8U); CV_Assert(image.depth() == CV_8U);
cvtColor(GpuMat(image), gray_image, CV_BGR2GRAY);
GpuMat d_keypoints; ensureSizeIsEnough(image.size(), image.type(), image_);
GpuMat d_descriptors; image_.upload(image);
ensureSizeIsEnough(image.size(), CV_8UC1, gray_image_);
cvtColor(image_, gray_image_, CV_BGR2GRAY);
surf_.nOctaves = num_octaves_; surf_.nOctaves = num_octaves_;
surf_.nOctaveLayers = num_layers_; surf_.nOctaveLayers = num_layers_;
surf_(gray_image, GpuMat(), d_keypoints); surf_(gray_image_, GpuMat(), keypoints_);
surf_.nOctaves = num_octaves_descr_; surf_.nOctaves = num_octaves_descr_;
surf_.nOctaveLayers = num_layers_descr_; surf_.nOctaveLayers = num_layers_descr_;
surf_(gray_image, GpuMat(), d_keypoints, d_descriptors, true); surf_.upright = true;
surf_.downloadKeypoints(d_keypoints, features.keypoints); surf_(gray_image_, GpuMat(), keypoints_, descriptors_, true);
surf_.downloadKeypoints(keypoints_, features.keypoints);
d_descriptors.download(features.descriptors); descriptors_.download(features.descriptors);
}
void GpuSurfFeaturesFinder::releaseMemory()
{
surf_.releaseMemory();
image_.release();
gray_image_.release();
keypoints_.release();
descriptors_.release();
} }
} // anonymous namespace } // anonymous namespace
...@@ -153,6 +171,11 @@ void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features) ...@@ -153,6 +171,11 @@ void SurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
(*impl_)(image, features); (*impl_)(image, features);
} }
void SurfFeaturesFinder::releaseMemory()
{
impl_->releaseMemory();
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -279,10 +302,13 @@ namespace ...@@ -279,10 +302,13 @@ namespace
GpuMatcher(float match_conf) : match_conf_(match_conf) {} GpuMatcher(float match_conf) : match_conf_(match_conf) {}
void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info); void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info);
void releaseMemory();
private: private:
float match_conf_; float match_conf_;
GpuMat descriptors1_, descriptors2_; GpuMat descriptors1_, descriptors2_;
GpuMat train_idx_, distance_, all_dist_; GpuMat train_idx_, distance_, all_dist_;
vector< vector<DMatch> > pair_matches;
}; };
...@@ -326,14 +352,19 @@ namespace ...@@ -326,14 +352,19 @@ namespace
void GpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info) void GpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info)
{ {
matches_info.matches.clear(); matches_info.matches.clear();
ensureSizeIsEnough(features1.descriptors.size(), features1.descriptors.type(), descriptors1_);
ensureSizeIsEnough(features2.descriptors.size(), features2.descriptors.type(), descriptors2_);
descriptors1_.upload(features1.descriptors); descriptors1_.upload(features1.descriptors);
descriptors2_.upload(features2.descriptors); descriptors2_.upload(features2.descriptors);
BruteForceMatcher_GPU< L2<float> > matcher; BruteForceMatcher_GPU< L2<float> > matcher;
vector< vector<DMatch> > pair_matches;
MatchesSet matches; MatchesSet matches;
// Find 1->2 matches // Find 1->2 matches
pair_matches.clear();
matcher.knnMatch(descriptors1_, descriptors2_, train_idx_, distance_, all_dist_, 2); matcher.knnMatch(descriptors1_, descriptors2_, train_idx_, distance_, all_dist_, 2);
matcher.knnMatchDownload(train_idx_, distance_, pair_matches); matcher.knnMatchDownload(train_idx_, distance_, pair_matches);
for (size_t i = 0; i < pair_matches.size(); ++i) for (size_t i = 0; i < pair_matches.size(); ++i)
...@@ -365,6 +396,16 @@ namespace ...@@ -365,6 +396,16 @@ namespace
} }
} }
void GpuMatcher::releaseMemory()
{
descriptors1_.release();
descriptors2_.release();
train_idx_.release();
distance_.release();
all_dist_.release();
vector< vector<DMatch> >().swap(pair_matches);
}
} // anonymous namespace } // anonymous namespace
...@@ -456,3 +497,8 @@ void BestOf2NearestMatcher::match(const ImageFeatures &features1, const ImageFea ...@@ -456,3 +497,8 @@ void BestOf2NearestMatcher::match(const ImageFeatures &features1, const ImageFea
// Rerun motion estimation on inliers only // Rerun motion estimation on inliers only
matches_info.H = findHomography(src_points, dst_points, CV_RANSAC); matches_info.H = findHomography(src_points, dst_points, CV_RANSAC);
} }
void BestOf2NearestMatcher::releaseMemory()
{
impl_->releaseMemory();
}
...@@ -59,6 +59,8 @@ public: ...@@ -59,6 +59,8 @@ public:
virtual ~FeaturesFinder() {} virtual ~FeaturesFinder() {}
void operator ()(const cv::Mat &image, ImageFeatures &features); void operator ()(const cv::Mat &image, ImageFeatures &features);
virtual void releaseMemory() {}
protected: protected:
virtual void find(const cv::Mat &image, ImageFeatures &features) = 0; virtual void find(const cv::Mat &image, ImageFeatures &features) = 0;
}; };
...@@ -71,6 +73,8 @@ public: ...@@ -71,6 +73,8 @@ public:
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); int num_octaves_descr = 4, int num_layers_descr = 2);
void releaseMemory();
protected: protected:
void find(const cv::Mat &image, ImageFeatures &features); void find(const cv::Mat &image, ImageFeatures &features);
...@@ -104,6 +108,8 @@ public: ...@@ -104,6 +108,8 @@ public:
bool isThreadSafe() const { return is_thread_safe_; } bool isThreadSafe() const { return is_thread_safe_; }
virtual void releaseMemory() {}
protected: protected:
FeaturesMatcher(bool is_thread_safe = false) : is_thread_safe_(is_thread_safe) {} FeaturesMatcher(bool is_thread_safe = false) : is_thread_safe_(is_thread_safe) {}
...@@ -120,6 +126,8 @@ public: ...@@ -120,6 +126,8 @@ public:
BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 6, BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 6,
int num_matches_thresh2 = 6); int num_matches_thresh2 = 6);
void releaseMemory();
protected: protected:
void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info); void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <set> #include <set>
#include <functional>
#include "opencv2/core/core.hpp" #include "opencv2/core/core.hpp"
#include "opencv2/core/internal.hpp" #include "opencv2/core/internal.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc.hpp"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册