refactored GoodFeaturesToTrackDetector

This commit is contained in:
Vladislav Vinogradov 2013-04-30 16:07:56 +04:00
parent d7ff3ad0cf
commit 70e6dc615a
9 changed files with 148 additions and 146 deletions

View File

@ -148,17 +148,17 @@ PERF_TEST_P(Image_Depth, GoodFeaturesToTrack,
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k); cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k);
cv::gpu::GpuMat d_src(src); cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat d_mask(mask); cv::gpu::GpuMat d_mask(mask);
cv::gpu::GpuMat d_pts; cv::gpu::GpuMat d_pts;
d_detector(d_src, d_pts, d_mask); detector->detect(d_src, d_pts, d_mask);
TEST_CYCLE() TEST_CYCLE()
{ {
d_detector(d_src, d_pts, d_mask); detector->detect(d_src, d_pts, d_mask);
} }
} }
else else

View File

@ -394,54 +394,17 @@ inline void cornerMinEigenVal(InputArray src, OutputArray dst, int blockSize, in
gpu::createMinEigenValCorner(src.type(), blockSize, ksize, borderType)->compute(src, dst, stream); gpu::createMinEigenValCorner(src.type(), blockSize, ksize, borderType)->compute(src, dst, stream);
} }
////////////////////////// Feature Detection /////////////////////////// ////////////////////////// Corners Detection ///////////////////////////
class CV_EXPORTS GoodFeaturesToTrackDetector_GPU class CV_EXPORTS CornersDetector : public Algorithm
{ {
public: public:
explicit GoodFeaturesToTrackDetector_GPU(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
//! return 1 rows matrix with CV_32FC2 type //! return 1 rows matrix with CV_32FC2 type
void operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask = GpuMat()); virtual void detect(InputArray image, OutputArray corners, InputArray mask = noArray()) = 0;
int maxCorners;
double qualityLevel;
double minDistance;
int blockSize;
bool useHarrisDetector;
double harrisK;
void releaseMemory()
{
Dx_.release();
Dy_.release();
buf_.release();
eig_.release();
minMaxbuf_.release();
tmpCorners_.release();
}
private:
GpuMat Dx_;
GpuMat Dy_;
GpuMat buf_;
GpuMat eig_;
GpuMat minMaxbuf_;
GpuMat tmpCorners_;
}; };
inline GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU(int maxCorners_, double qualityLevel_, double minDistance_, CV_EXPORTS Ptr<CornersDetector> createGoodFeaturesToTrackDetector(int srcType, int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
int blockSize_, bool useHarrisDetector_, double harrisK_) int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
{
maxCorners = maxCorners_;
qualityLevel = qualityLevel_;
minDistance = minDistance_;
blockSize = blockSize_;
useHarrisDetector = useHarrisDetector_;
harrisK = harrisK_;
}
///////////////////////////// Mean Shift ////////////////////////////// ///////////////////////////// Mean Shift //////////////////////////////

View File

@ -66,12 +66,12 @@ PERF_TEST_P(Image_MinDistance, GoodFeaturesToTrack,
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance); cv::Ptr<cv::gpu::CornersDetector> d_detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance);
const cv::gpu::GpuMat d_image(image); const cv::gpu::GpuMat d_image(image);
cv::gpu::GpuMat pts; cv::gpu::GpuMat pts;
TEST_CYCLE() d_detector(d_image, pts); TEST_CYCLE() d_detector->detect(d_image, pts);
GPU_SANITY_CHECK(pts); GPU_SANITY_CHECK(pts);
} }

View File

@ -45,9 +45,9 @@
using namespace cv; using namespace cv;
using namespace cv::gpu; using namespace cv::gpu;
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUARITHM)
void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat&, GpuMat&, const GpuMat&) { throw_no_cuda(); } Ptr<gpu::CornersDetector> cv::gpu::createGoodFeaturesToTrackDetector(int, int, double, double, int, bool, double) { throw_no_cuda(); return Ptr<gpu::CornersDetector>(); }
#else /* !defined (HAVE_CUDA) */ #else /* !defined (HAVE_CUDA) */
@ -60,45 +60,73 @@ namespace cv { namespace gpu { namespace cudev
} }
}}} }}}
void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask) namespace
{ {
#ifndef HAVE_OPENCV_GPUARITHM class GoodFeaturesToTrackDetector : public CornersDetector
(void) image; {
(void) corners; public:
(void) mask; GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
throw_no_cuda(); int blockSize, bool useHarrisDetector, double harrisK);
#else
void detect(InputArray image, OutputArray corners, InputArray mask = noArray());
private:
int maxCorners_;
double qualityLevel_;
double minDistance_;
Ptr<gpu::CornernessCriteria> cornerCriteria_;
GpuMat Dx_;
GpuMat Dy_;
GpuMat buf_;
GpuMat eig_;
GpuMat minMaxbuf_;
GpuMat tmpCorners_;
};
GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
int blockSize, bool useHarrisDetector, double harrisK) :
maxCorners_(maxCorners), qualityLevel_(qualityLevel), minDistance_(minDistance)
{
CV_Assert( qualityLevel_ > 0 && minDistance_ >= 0 && maxCorners_ >= 0 );
cornerCriteria_ = useHarrisDetector ?
gpu::createHarrisCorner(srcType, blockSize, 3, harrisK) :
gpu::createMinEigenValCorner(srcType, blockSize, 3);
}
void GoodFeaturesToTrackDetector::detect(InputArray _image, OutputArray _corners, InputArray _mask)
{
using namespace cv::gpu::cudev::gfft; using namespace cv::gpu::cudev::gfft;
CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0); GpuMat image = _image.getGpuMat();
CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size())); GpuMat mask = _mask.getGpuMat();
ensureSizeIsEnough(image.size(), CV_32F, eig_); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
Ptr<gpu::CornernessCriteria> cornerCriteria = ensureSizeIsEnough(image.size(), CV_32FC1, eig_);
useHarrisDetector ? cornerCriteria_->compute(image, eig_);
gpu::createHarrisCorner(image.type(), blockSize, 3, harrisK) :
gpu::createMinEigenValCorner(image.type(), blockSize, 3);
cornerCriteria->compute(image, eig_);
double maxVal = 0; double maxVal = 0;
gpu::minMax(eig_, 0, &maxVal, GpuMat(), minMaxbuf_); gpu::minMax(eig_, 0, &maxVal, noArray(), minMaxbuf_);
ensureSizeIsEnough(1, std::max(1000, static_cast<int>(image.size().area() * 0.05)), CV_32FC2, tmpCorners_); ensureSizeIsEnough(1, std::max(1000, static_cast<int>(image.size().area() * 0.05)), CV_32FC2, tmpCorners_);
int total = findCorners_gpu(eig_, static_cast<float>(maxVal * qualityLevel), mask, tmpCorners_.ptr<float2>(), tmpCorners_.cols); int total = findCorners_gpu(eig_, static_cast<float>(maxVal * qualityLevel_), mask, tmpCorners_.ptr<float2>(), tmpCorners_.cols);
if (total == 0) if (total == 0)
{ {
corners.release(); _corners.release();
return; return;
} }
sortCorners_gpu(eig_, tmpCorners_.ptr<float2>(), total); sortCorners_gpu(eig_, tmpCorners_.ptr<float2>(), total);
if (minDistance < 1) if (minDistance_ < 1)
tmpCorners_.colRange(0, maxCorners > 0 ? std::min(maxCorners, total) : total).copyTo(corners); {
tmpCorners_.colRange(0, maxCorners_ > 0 ? std::min(maxCorners_, total) : total).copyTo(_corners);
}
else else
{ {
std::vector<Point2f> tmp(total); std::vector<Point2f> tmp(total);
@ -108,7 +136,7 @@ void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image,
std::vector<Point2f> tmp2; std::vector<Point2f> tmp2;
tmp2.reserve(total); tmp2.reserve(total);
const int cell_size = cvRound(minDistance); const int cell_size = cvRound(minDistance_);
const int grid_width = (image.cols + cell_size - 1) / cell_size; const int grid_width = (image.cols + cell_size - 1) / cell_size;
const int grid_height = (image.rows + cell_size - 1) / cell_size; const int grid_height = (image.rows + cell_size - 1) / cell_size;
@ -147,7 +175,7 @@ void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image,
float dx = p.x - m[j].x; float dx = p.x - m[j].x;
float dy = p.y - m[j].y; float dy = p.y - m[j].y;
if (dx * dx + dy * dy < minDistance * minDistance) if (dx * dx + dy * dy < minDistance_ * minDistance_)
{ {
good = false; good = false;
goto break_out; goto break_out;
@ -165,14 +193,23 @@ void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image,
tmp2.push_back(p); tmp2.push_back(p);
if (maxCorners > 0 && tmp2.size() == static_cast<size_t>(maxCorners)) if (maxCorners_ > 0 && tmp2.size() == static_cast<size_t>(maxCorners_))
break; break;
} }
} }
_corners.create(1, static_cast<int>(tmp2.size()), CV_32FC2);
GpuMat corners = _corners.getGpuMat();
corners.upload(Mat(1, static_cast<int>(tmp2.size()), CV_32FC2, &tmp2[0])); corners.upload(Mat(1, static_cast<int>(tmp2.size()), CV_32FC2, &tmp2[0]));
} }
#endif }
}
Ptr<gpu::CornersDetector> cv::gpu::createGoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
int blockSize, bool useHarrisDetector, double harrisK)
{
return new GoodFeaturesToTrackDetector(srcType, maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, harrisK);
} }
#endif /* !defined (HAVE_CUDA) */ #endif /* !defined (HAVE_CUDA) */

View File

@ -76,10 +76,10 @@ GPU_TEST_P(GoodFeaturesToTrack, Accuracy)
int maxCorners = 1000; int maxCorners = 1000;
double qualityLevel = 0.01; double qualityLevel = 0.01;
cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance); cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance);
cv::gpu::GpuMat d_pts; cv::gpu::GpuMat d_pts;
detector(loadMat(image), d_pts); detector->detect(loadMat(image), d_pts);
ASSERT_FALSE(d_pts.empty()); ASSERT_FALSE(d_pts.empty());
@ -114,12 +114,12 @@ GPU_TEST_P(GoodFeaturesToTrack, EmptyCorners)
int maxCorners = 1000; int maxCorners = 1000;
double qualityLevel = 0.01; double qualityLevel = 0.01;
cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance);
cv::gpu::GpuMat src(100, 100, CV_8UC1, cv::Scalar::all(0)); cv::gpu::GpuMat src(100, 100, CV_8UC1, cv::Scalar::all(0));
cv::gpu::GpuMat corners(1, maxCorners, CV_32FC2); cv::gpu::GpuMat corners(1, maxCorners, CV_32FC2);
detector(src, corners); cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance);
detector->detect(src, corners);
ASSERT_TRUE(corners.empty()); ASSERT_TRUE(corners.empty());
} }

View File

@ -217,7 +217,7 @@ public:
private: private:
Ptr<MotionEstimatorBase> motionEstimator_; Ptr<MotionEstimatorBase> motionEstimator_;
gpu::GoodFeaturesToTrackDetector_GPU detector_; Ptr<gpu::CornersDetector> detector_;
SparsePyrLkOptFlowEstimatorGpu optFlowEstimator_; SparsePyrLkOptFlowEstimatorGpu optFlowEstimator_;
Ptr<IOutlierRejector> outlierRejector_; Ptr<IOutlierRejector> outlierRejector_;

View File

@ -742,6 +742,8 @@ Mat KeypointBasedMotionEstimator::estimate(const Mat &frame0, const Mat &frame1,
KeypointBasedMotionEstimatorGpu::KeypointBasedMotionEstimatorGpu(Ptr<MotionEstimatorBase> estimator) KeypointBasedMotionEstimatorGpu::KeypointBasedMotionEstimatorGpu(Ptr<MotionEstimatorBase> estimator)
: ImageMotionEstimatorBase(estimator->motionModel()), motionEstimator_(estimator) : ImageMotionEstimatorBase(estimator->motionModel()), motionEstimator_(estimator)
{ {
detector_ = gpu::createGoodFeaturesToTrackDetector(CV_8UC1);
CV_Assert(gpu::getCudaEnabledDeviceCount() > 0); CV_Assert(gpu::getCudaEnabledDeviceCount() > 0);
setOutlierRejector(new NullOutlierRejector()); setOutlierRejector(new NullOutlierRejector());
} }
@ -769,7 +771,7 @@ Mat KeypointBasedMotionEstimatorGpu::estimate(const gpu::GpuMat &frame0, const g
} }
// find keypoints // find keypoints
detector_(grayFrame0, pointsPrev_); detector_->detect(grayFrame0, pointsPrev_);
// find correspondences // find correspondences
optFlowEstimator_.run(frame0, frame1, pointsPrev_, points_, status_); optFlowEstimator_.run(frame0, frame1, pointsPrev_, points_, status_);

View File

@ -1174,15 +1174,15 @@ TEST(GoodFeaturesToTrack)
goodFeaturesToTrack(src, pts, 8000, 0.01, 0.0); goodFeaturesToTrack(src, pts, 8000, 0.01, 0.0);
CPU_OFF; CPU_OFF;
gpu::GoodFeaturesToTrackDetector_GPU detector(8000, 0.01, 0.0); Ptr<gpu::CornersDetector> detector = gpu::createGoodFeaturesToTrackDetector(src.type(), 8000, 0.01, 0.0);
gpu::GpuMat d_src(src); gpu::GpuMat d_src(src);
gpu::GpuMat d_pts; gpu::GpuMat d_pts;
detector(d_src, d_pts); detector->detect(d_src, d_pts);
GPU_ON; GPU_ON;
detector(d_src, d_pts); detector->detect(d_src, d_pts);
GPU_OFF; GPU_OFF;
} }

View File

@ -176,12 +176,12 @@ int main(int argc, const char* argv[])
// goodFeaturesToTrack // goodFeaturesToTrack
GoodFeaturesToTrackDetector_GPU detector(points, 0.01, minDist);
GpuMat d_frame0Gray(frame0Gray); GpuMat d_frame0Gray(frame0Gray);
GpuMat d_prevPts; GpuMat d_prevPts;
detector(d_frame0Gray, d_prevPts); Ptr<gpu::CornersDetector> detector = gpu::createGoodFeaturesToTrackDetector(d_frame0Gray.type(), points, 0.01, minDist);
detector->detect(d_frame0Gray, d_prevPts);
// Sparse // Sparse