提交 957e80ab 编写于 作者: V Vadim Pisarevsky

lot's of changes; nonfree & photo modules added; SIFT & SURF -> nonfree...

lot's of changes; nonfree & photo modules added; SIFT & SURF -> nonfree module; Inpainting -> photo; refactored features2d (ORB is still failing tests), optimized brute-force matcher and made it non-template.
上级 6300215b
......@@ -48,6 +48,7 @@
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
......
***************************************
contrib. Contributed/Experimental Stuff
***************************************
The module contains some recently added functionality that has not been stabilized, or functionality that is considered optional.
......@@ -145,9 +145,8 @@ public:
class CV_EXPORTS CvFeatureTracker
{
private:
FeatureDetector* detector;
DescriptorExtractor* descriptor;
DescriptorMatcher* matcher;
Ptr<Feature2D> dd;
Ptr<DescriptorMatcher> matcher;
vector<DMatch> matches;
Mat prev_image;
......
......@@ -53,22 +53,24 @@ CvFeatureTracker::CvFeatureTracker(CvFeatureTrackerParams _params) :
switch (params.feature_type)
{
case CvFeatureTrackerParams::SIFT:
detector = new SiftFeatureDetector(
SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(),
SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD() + 0.7,
SIFT::CommonParams::DEFAULT_NOCTAVES + 4,
SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS + 2,
SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
SIFT::CommonParams::FIRST_ANGLE);
dd = Algorithm::create<Feature2D>("Feature2D.SIFT");
if( dd.empty() )
CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SIFT support");
dd->set("nOctaveLayers", 5);
dd->set("contrastThreshold", 0.04);
dd->set("edgeThreshold", 10.7);
case CvFeatureTrackerParams::SURF:
detector = new SurfFeatureDetector(400, 3, 4);
default:
detector = new GoodFeaturesToTrackDetector();
dd = Algorithm::create<Feature2D>("Feature2D.SURF");
if( dd.empty() )
CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SURF support");
dd->set("hessianThreshold", 400);
dd->set("nOctaves", 3);
dd->set("nOctaveLayers", 4);
default:
CV_Error(CV_StsBadArg, "Unknown feature type");
}
descriptor = new SurfDescriptorExtractor(3, 4, false);
matcher = new BruteForceMatcher<L2<float> > ();
matcher = new BFMatcher(NORM_L2);
}
CvFeatureTracker::~CvFeatureTracker()
......@@ -105,7 +107,7 @@ Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image)
rectangle(mask, Point(window.x, window.y), Point(window.x + window.width,
window.y + window.height), Scalar(255), CV_FILLED);
detector->detect(prev_image, prev_keypoints, mask);
dd->operator()(prev_image, mask, prev_keypoints, prev_desc);
window.x -= params.window_size;
window.y -= params.window_size;
......@@ -114,12 +116,12 @@ Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image)
rectangle(mask, Point(window.x, window.y), Point(window.x + window.width,
window.y + window.height), Scalar(255), CV_FILLED);
detector->detect(image, curr_keypoints, mask);
dd->operator()(image, mask, curr_keypoints, curr_desc);
if (prev_keypoints.size() > 4 && curr_keypoints.size() > 4)
{
descriptor->compute(prev_image, prev_keypoints, prev_desc);
descriptor->compute(image, curr_keypoints, curr_desc);
//descriptor->compute(prev_image, prev_keypoints, prev_desc);
//descriptor->compute(image, curr_keypoints, curr_desc);
matcher->match(prev_desc, curr_desc, matches);
......
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts/ts.hpp"
#include "opencv2/contrib/contrib.hpp"
#include <iostream>
#endif
......@@ -118,7 +118,7 @@ CV_EXPORTS string tempfile( const char* suffix CV_DEFAULT(0));
// matrix decomposition types
enum { DECOMP_LU=0, DECOMP_SVD=1, DECOMP_EIG=2, DECOMP_CHOLESKY=3, DECOMP_QR=4, DECOMP_NORMAL=16 };
enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_TYPE_MASK=7, NORM_RELATIVE=8, NORM_MINMAX=32};
enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_L2SQR=5, NORM_HAMMING=6, NORM_HAMMING2=7, NORM_TYPE_MASK=7, NORM_RELATIVE=8, NORM_MINMAX=32 };
enum { CMP_EQ=0, CMP_GT=1, CMP_GE=2, CMP_LT=3, CMP_LE=4, CMP_NE=5 };
enum { GEMM_1_T=1, GEMM_2_T=2, GEMM_3_T=4 };
enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_OUTPUT=32,
......@@ -2057,6 +2057,14 @@ CV_EXPORTS_W double norm(InputArray src1, int normType=NORM_L2, InputArray mask=
//! computes norm of selected part of the difference between two arrays
CV_EXPORTS_W double norm(InputArray src1, InputArray src2,
int normType=NORM_L2, InputArray mask=noArray());
//! naive nearest neighbor finder
CV_EXPORTS_W void batchDistance(InputArray src1, InputArray src2,
OutputArray dist, int dtype, OutputArray nidx,
int normType=NORM_L2, int K=0,
InputArray mask=noArray(), int update=0,
bool crosscheck=false);
//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values
CV_EXPORTS_W void normalize( InputArray src, OutputArray dst, double alpha=1, double beta=0,
int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray());
......@@ -4244,10 +4252,20 @@ public:
template<typename _Tp> typename ParamType<_Tp>::member_type get(const string& name) const;
template<typename _Tp> typename ParamType<_Tp>::member_type get(const char* name) const;
template<typename _Tp> void set(const string& name,
typename ParamType<_Tp>::const_param_type value);
template<typename _Tp> void set(const char* name,
typename ParamType<_Tp>::const_param_type value);
void set(const string& name, int value);
void set(const string& name, double value);
void set(const string& name, bool value);
void set(const string& name, const string& value);
void set(const string& name, const Mat& value);
void set(const string& name, const Ptr<Algorithm>& value);
void set(const char* name, int value);
void set(const char* name, double value);
void set(const char* name, bool value);
void set(const char* name, const string& value);
void set(const char* name, const Mat& value);
void set(const char* name, const Ptr<Algorithm>& value);
string paramHelp(const string& name) const;
int paramType(const char* name) const;
int paramType(const string& name) const;
......@@ -4293,6 +4311,11 @@ public:
int (Algorithm::*getter)()=0,
void (Algorithm::*setter)(int)=0,
const string& help=string());
void addParam(const Algorithm* algo, const char* name,
const bool& value, bool readOnly=false,
int (Algorithm::*getter)()=0,
void (Algorithm::*setter)(int)=0,
const string& help=string());
void addParam(const Algorithm* algo, const char* name,
const double& value, bool readOnly=false,
double (Algorithm::*getter)()=0,
......
......@@ -3823,18 +3823,6 @@ template<typename _Tp> inline typename ParamType<_Tp>::member_type Algorithm::ge
return value;
}
template<typename _Tp> inline void Algorithm::set(const string& name,
typename ParamType<_Tp>::const_param_type value)
{
info()->set(this, name.c_str(), ParamType<_Tp>::type, &value);
}
template<typename _Tp> inline void Algorithm::set(const char* name,
typename ParamType<_Tp>::const_param_type value)
{
info()->set(this, name, ParamType<_Tp>::type, &value);
}
}
#endif // __cplusplus
......
......@@ -77,7 +77,7 @@ template<typename _KeyTp, typename _ValueTp> struct sorted_vector
b = c;
}
if( vec[a].first == key )
if( a < vec.size() && vec[a].first == key )
{
value = vec[a].second;
return true;
......@@ -176,6 +176,66 @@ string Algorithm::name() const
{
return info()->name();
}
void Algorithm::set(const string& name, int value)
{
info()->set(this, name.c_str(), ParamType<int>::type, &value);
}
void Algorithm::set(const string& name, double value)
{
info()->set(this, name.c_str(), ParamType<double>::type, &value);
}
void Algorithm::set(const string& name, bool value)
{
info()->set(this, name.c_str(), ParamType<bool>::type, &value);
}
void Algorithm::set(const string& name, const string& value)
{
info()->set(this, name.c_str(), ParamType<string>::type, &value);
}
void Algorithm::set(const string& name, const Mat& value)
{
info()->set(this, name.c_str(), ParamType<Mat>::type, &value);
}
void Algorithm::set(const string& name, const Ptr<Algorithm>& value)
{
info()->set(this, name.c_str(), ParamType<Algorithm>::type, &value);
}
void Algorithm::set(const char* name, int value)
{
info()->set(this, name, ParamType<int>::type, &value);
}
void Algorithm::set(const char* name, double value)
{
info()->set(this, name, ParamType<double>::type, &value);
}
void Algorithm::set(const char* name, bool value)
{
info()->set(this, name, ParamType<bool>::type, &value);
}
void Algorithm::set(const char* name, const string& value)
{
info()->set(this, name, ParamType<string>::type, &value);
}
void Algorithm::set(const char* name, const Mat& value)
{
info()->set(this, name, ParamType<Mat>::type, &value);
}
void Algorithm::set(const char* name, const Ptr<Algorithm>& value)
{
info()->set(this, name, ParamType<Algorithm>::type, &value);
}
string Algorithm::paramHelp(const string& name) const
{
......@@ -261,25 +321,25 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const
if( n.empty() )
continue;
if( p.type == Param::INT )
algo->set<int>(pname, (int)n);
algo->set(pname, (int)n);
else if( p.type == Param::BOOLEAN )
algo->set<bool>(pname, (int)n != 0);
algo->set(pname, (int)n != 0);
else if( p.type == Param::REAL )
algo->set<double>(pname, (double)n);
algo->set(pname, (double)n);
else if( p.type == Param::STRING )
algo->set<string>(pname, (string)n);
algo->set(pname, (string)n);
else if( p.type == Param::MAT )
{
Mat m;
cv::read(fn, m);
algo->set<Mat>(pname, m);
algo->set(pname, m);
}
else if( p.type == Param::ALGORITHM )
{
Ptr<Algorithm> nestedAlgo = Algorithm::_create((string)n["name"]);
CV_Assert( !nestedAlgo.empty() );
nestedAlgo->read(n);
algo->set<Algorithm>(pname, nestedAlgo);
algo->set(pname, nestedAlgo);
}
else
CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported parameter type");
......@@ -505,6 +565,16 @@ void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
(Algorithm::Getter)getter, (Algorithm::Setter)setter, help);
}
void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
const bool& value, bool readOnly,
int (Algorithm::*getter)(),
void (Algorithm::*setter)(int),
const string& help)
{
addParam_(algo, name, ParamType<bool>::type, &value, readOnly,
(Algorithm::Getter)getter, (Algorithm::Setter)setter, help);
}
void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
const double& value, bool readOnly,
double (Algorithm::*getter)(),
......
......@@ -113,11 +113,13 @@ namespace
const CvOpenGlFuncTab* g_glFuncTab = 0;
#ifdef HAVE_CUDA
const CvOpenGlFuncTab* glFuncTab()
{
static EmptyGlFuncTab empty;
return g_glFuncTab ? g_glFuncTab : &empty;
}
#endif
}
CvOpenGlFuncTab::~CvOpenGlFuncTab()
......
......@@ -41,6 +41,7 @@
//M*/
#include "precomp.hpp"
#include <climits>
namespace cv
{
......@@ -1425,6 +1426,339 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m
}
///////////////////////////////////// batch distance ///////////////////////////////////////
namespace cv
{
template<typename _Tp, typename _Rt>
void batchDistL1_(const _Tp* src1, const _Tp* src2, size_t step2,
int nvecs, int len, _Rt* dist, const uchar* mask)
{
step2 /= sizeof(src2[0]);
if( !mask )
{
for( int i = 0; i < nvecs; i++ )
dist[i] = normL1<_Tp, _Rt>(src1, src2 + step2*i, len);
}
else
{
_Rt val0 = std::numeric_limits<_Rt>::max();
for( int i = 0; i < nvecs; i++ )
dist[i] = mask[i] ? normL1<_Tp, _Rt>(src1, src2 + step2*i, len) : val0;
}
}
template<typename _Tp, typename _Rt>
void batchDistL2Sqr_(const _Tp* src1, const _Tp* src2, size_t step2,
int nvecs, int len, _Rt* dist, const uchar* mask)
{
step2 /= sizeof(src2[0]);
if( !mask )
{
for( int i = 0; i < nvecs; i++ )
dist[i] = normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len);
}
else
{
_Rt val0 = std::numeric_limits<_Rt>::max();
for( int i = 0; i < nvecs; i++ )
dist[i] = mask[i] ? normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len) : val0;
}
}
template<typename _Tp, typename _Rt>
void batchDistL2_(const _Tp* src1, const _Tp* src2, size_t step2,
int nvecs, int len, _Rt* dist, const uchar* mask)
{
step2 /= sizeof(src2[0]);
if( !mask )
{
for( int i = 0; i < nvecs; i++ )
dist[i] = std::sqrt(normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len));
}
else
{
_Rt val0 = std::numeric_limits<_Rt>::max();
for( int i = 0; i < nvecs; i++ )
dist[i] = mask[i] ? std::sqrt(normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len)) : val0;
}
}
static void batchDistHamming(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, int* dist, const uchar* mask)
{
step2 /= sizeof(src2[0]);
if( !mask )
{
for( int i = 0; i < nvecs; i++ )
dist[i] = normHamming(src1, src2 + step2*i, len);
}
else
{
int val0 = INT_MAX;
for( int i = 0; i < nvecs; i++ )
dist[i] = mask[i] ? normHamming(src1, src2 + step2*i, len) : val0;
}
}
static void batchDistHamming2(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, int* dist, const uchar* mask)
{
step2 /= sizeof(src2[0]);
if( !mask )
{
for( int i = 0; i < nvecs; i++ )
dist[i] = normHamming(src1, src2 + step2*i, len, 2);
}
else
{
int val0 = INT_MAX;
for( int i = 0; i < nvecs; i++ )
dist[i] = mask[i] ? normHamming(src1, src2 + step2*i, len, 2) : val0;
}
}
static void batchDistL1_8u32s(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, int* dist, const uchar* mask)
{
batchDistL1_<uchar, int>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL1_8u32f(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL1_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL2Sqr_8u32s(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, int* dist, const uchar* mask)
{
batchDistL2Sqr_<uchar, int>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL2Sqr_8u32f(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL2Sqr_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL2_8u32f(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL2_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL1_32f(const float* src1, const float* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL1_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL2Sqr_32f(const float* src1, const float* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL2Sqr_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
}
static void batchDistL2_32f(const float* src1, const float* src2, size_t step2,
int nvecs, int len, float* dist, const uchar* mask)
{
batchDistL2_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
}
typedef void (*BatchDistFunc)(const uchar* src1, const uchar* src2, size_t step2,
int nvecs, int len, uchar* dist, const uchar* mask);
struct BatchDistInvoker
{
BatchDistInvoker( const Mat& _src1, const Mat& _src2,
Mat& _dist, Mat& _nidx, int _K,
const Mat& _mask, int _update,
BatchDistFunc _func)
{
src1 = &_src1;
src2 = &_src2;
dist = &_dist;
nidx = &_nidx;
K = _K;
mask = &_mask;
update = _update;
func = _func;
}
void operator()(const BlockedRange& range) const
{
AutoBuffer<int> buf(src2->rows);
int* bufptr = buf;
Cv32suf val0;
if( dist->type() == CV_32S )
val0.i = INT_MAX;
else
val0.f = FLT_MAX;
for( int i = range.begin(); i < range.end(); i++ )
{
func(src1->ptr(i), src2->ptr(), src2->step, src2->rows, src2->cols,
K > 0 ? (uchar*)bufptr : dist->ptr(i), mask->data ? mask->ptr(i) : 0);
if( K > 0 )
{
int* nidxptr = nidx->ptr<int>(i);
// since positive float's can be compared just like int's,
// we handle both CV_32S and CV_32F cases with a single branch
int* distptr = (int*)dist->ptr(i);
int k, k0, k0_, j;
for( k0 = 0; k0 < K; k0++ )
if( nidxptr[k0] < 0 )
break;
k0_ = std::max(k0, 1);
for( j = 0; j < src2->rows; j++ )
{
int d = bufptr[j];
if( d < distptr[k0_-1] )
{
for( k = std::min(k0-1, K-2); k >= 0 && distptr[k] > d; k-- )
{
nidxptr[k+1] = nidxptr[k];
distptr[k+1] = distptr[k];
}
nidxptr[k+1] = j + update;
distptr[k+1] = d;
k0_ = k0 = std::min(k0 + 1, K);
}
}
}
}
}
const Mat *src1;
const Mat *src2;
Mat *dist;
Mat *nidx;
const Mat *mask;
int K;
int update;
BatchDistFunc func;
};
}
void cv::batchDistance( InputArray _src1, InputArray _src2,
OutputArray _dist, int dtype, OutputArray _nidx,
int normType, int K, InputArray _mask,
int update, bool crosscheck )
{
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
int type = src1.type();
CV_Assert( type == src2.type() && src1.cols == src2.cols &&
(type == CV_32F || type == CV_8U));
CV_Assert( _nidx.needed() == (K > 0) );
if( dtype == -1 )
{
dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ? CV_32S : CV_32F;
}
CV_Assert( (type == CV_8U && dtype == CV_32S) || dtype == CV_32F);
K = std::min(K, src2.rows);
_dist.create(src1.rows, (K > 0 ? K : src2.rows), dtype);
Mat dist = _dist.getMat(), nidx;
if( _nidx.needed() )
{
_nidx.create(dist.size(), CV_32S);
nidx = _nidx.getMat();
}
if( update == 0 && K > 0 )
{
dist = Scalar::all(dtype == CV_32S ? (double)INT_MAX : (double)FLT_MAX);
nidx = Scalar::all(-1);
}
if( crosscheck )
{
CV_Assert( K == 1 && update == 0 && mask.empty() );
Mat tdist, tidx;
batchDistance(src2, src1, tdist, dtype, tidx, normType, K, mask, 0, false);
// if an idx-th element from src1 appeared to be the nearest to i-th element of src2,
// we update the minimum mutual distance between idx-th element of src1 and the whole src2 set.
// As a result, if nidx[idx] = i*, it means that idx-th element of src1 is the nearest
// to i*-th element of src2 and i*-th element of src2 is the closest to idx-th element of src1.
// If nidx[idx] = -1, it means that there is no such ideal couple for it in src2.
// This O(N) procedure is called cross-check and it helps to eliminate some false matches.
if( dtype == CV_32S )
{
for( int i = 0; i < tdist.rows; i++ )
{
int idx = tidx.at<int>(i);
int d = tdist.at<int>(i), d0 = dist.at<int>(idx);
if( d < d0 )
{
dist.at<int>(idx) = d0;
nidx.at<int>(idx) = i + update;
}
}
}
else
{
for( int i = 0; i < tdist.rows; i++ )
{
int idx = tidx.at<int>(i);
float d = tdist.at<float>(i), d0 = dist.at<float>(idx);
if( d < d0 )
{
dist.at<float>(idx) = d0;
nidx.at<int>(idx) = i + update;
}
}
}
return;
}
BatchDistFunc func = 0;
if( type == CV_8U )
{
if( normType == NORM_L1 && dtype == CV_32S )
func = (BatchDistFunc)batchDistL1_8u32s;
else if( normType == NORM_L1 && dtype == CV_32F )
func = (BatchDistFunc)batchDistL1_8u32f;
else if( normType == NORM_L2SQR && dtype == CV_32S )
func = (BatchDistFunc)batchDistL2Sqr_8u32s;
else if( normType == NORM_L2SQR && dtype == CV_32F )
func = (BatchDistFunc)batchDistL2Sqr_8u32f;
else if( normType == NORM_L2 && dtype == CV_32F )
func = (BatchDistFunc)batchDistL2_8u32f;
else if( normType == NORM_HAMMING && dtype == CV_32S )
func = (BatchDistFunc)batchDistHamming;
else if( normType == NORM_HAMMING2 && dtype == CV_32S )
func = (BatchDistFunc)batchDistHamming2;
}
else if( type == CV_32F && dtype == CV_32F )
{
if( normType == NORM_L1 )
func = (BatchDistFunc)batchDistL1_32f;
else if( normType == NORM_L2SQR )
func = (BatchDistFunc)batchDistL2Sqr_32f;
else if( normType == NORM_L2 )
func = (BatchDistFunc)batchDistL2_32f;
}
if( func == 0 )
CV_Error_(CV_StsUnsupportedFormat,
("The combination of type=%d, dtype=%d and normType=%d is not supported",
type, dtype, normType));
parallel_for(BlockedRange(0, src1.rows),
BatchDistInvoker(src1, src2, dist, nidx, K, mask, update, func));
}
CV_IMPL CvScalar cvSum( const CvArr* srcarr )
{
cv::Scalar sum = cv::sum(cv::cvarrToMat(srcarr, false, true, 1));
......
......@@ -92,177 +92,6 @@ Finds keypoints in an image
:param params: The algorithm parameters stored in ``CvStarDetectorParams`` (OpenCV 1.x API only)
SIFT
----
.. ocv:class:: SIFT
Class for extracting keypoints and computing descriptors using the Scale Invariant Feature Transform (SIFT) approach. ::
class CV_EXPORTS SIFT
{
public:
struct CommonParams
{
static const int DEFAULT_NOCTAVES = 4;
static const int DEFAULT_NOCTAVE_LAYERS = 3;
static const int DEFAULT_FIRST_OCTAVE = -1;
enum{ FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 };
CommonParams();
CommonParams( int _nOctaves, int _nOctaveLayers, int _firstOctave,
int _angleMode );
int nOctaves, nOctaveLayers, firstOctave;
int angleMode;
};
struct DetectorParams
{
static double GET_DEFAULT_THRESHOLD()
{ return 0.04 / SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS / 2.0; }
static double GET_DEFAULT_EDGE_THRESHOLD() { return 10.0; }
DetectorParams();
DetectorParams( double _threshold, double _edgeThreshold );
double threshold, edgeThreshold;
};
struct DescriptorParams
{
static double GET_DEFAULT_MAGNIFICATION() { return 3.0; }
static const bool DEFAULT_IS_NORMALIZE = true;
static const int DESCRIPTOR_SIZE = 128;
DescriptorParams();
DescriptorParams( double _magnification, bool _isNormalize,
bool _recalculateAngles );
double magnification;
bool isNormalize;
bool recalculateAngles;
};
SIFT();
//! sift-detector constructor
SIFT( double _threshold, double _edgeThreshold,
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
int _angleMode=CommonParams::FIRST_ANGLE );
//! sift-descriptor constructor
SIFT( double _magnification, bool _isNormalize=true,
bool _recalculateAngles = true,
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
int _angleMode=CommonParams::FIRST_ANGLE );
SIFT( const CommonParams& _commParams,
const DetectorParams& _detectorParams = DetectorParams(),
const DescriptorParams& _descriptorParams = DescriptorParams() );
//! returns the descriptor size in floats (128)
int descriptorSize() const { return DescriptorParams::DESCRIPTOR_SIZE; }
//! finds the keypoints using the SIFT algorithm
void operator()(const Mat& img, const Mat& mask,
vector<KeyPoint>& keypoints) const;
//! finds the keypoints and computes descriptors for them using SIFT algorithm.
//! Optionally it can compute descriptors for the user-provided keypoints
void operator()(const Mat& img, const Mat& mask,
vector<KeyPoint>& keypoints,
Mat& descriptors,
bool useProvidedKeypoints=false) const;
CommonParams getCommonParams () const { return commParams; }
DetectorParams getDetectorParams () const { return detectorParams; }
DescriptorParams getDescriptorParams () const { return descriptorParams; }
protected:
...
};
SURF
----
.. ocv:class:: SURF
Class for extracting Speeded Up Robust Features from an image [Bay06]_. The class is derived from ``CvSURFParams`` structure, which specifies the algorithm parameters:
.. ocv:member:: int extended
* 0 means that the basic descriptors (64 elements each) shall be computed
* 1 means that the extended descriptors (128 elements each) shall be computed
.. ocv:member:: int upright
* 0 means that detector computes orientation of each feature.
* 1 means that the orientation is not computed (which is much, much faster). For example, if you match images from a stereo pair, or do image stitching, the matched features likely have very similar angles, and you can speed up feature extraction by setting ``upright=1``.
.. ocv:member:: double hessianThreshold
Threshold for the keypoint detector. Only features, whose hessian is larger than ``hessianThreshold`` are retained by the detector. Therefore, the larger the value, the less keypoints you will get. A good default value could be from 300 to 500, depending from the image contrast.
.. ocv:member:: int nOctaves
The number of a gaussian pyramid octaves that the detector uses. It is set to 4 by default. If you want to get very large features, use the larger value. If you want just small features, decrease it.
.. ocv:member:: int nOctaveLayers
The number of images within each octave of a gaussian pyramid. It is set to 2 by default.
.. [Bay06] Bay, H. and Tuytelaars, T. and Van Gool, L. "SURF: Speeded Up Robust Features", 9th European Conference on Computer Vision, 2006
SURF::SURF
----------
The SURF extractor constructors.
.. ocv:function:: SURF::SURF()
.. ocv:function:: SURF::SURF(double hessianThreshold, int nOctaves=4, int nOctaveLayers=2, bool extended=false, bool upright=false)
.. ocv:pyfunction:: cv2.SURF(_hessianThreshold[, _nOctaves[, _nOctaveLayers[, _extended[, _upright]]]]) -> <SURF object>
:param hessianThreshold: Threshold for hessian keypoint detector used in SURF.
:param nOctaves: Number of pyramid octaves the keypoint detector will use.
:param nOctaveLayers: Number of octave layers within each octave.
:param extended: Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).
:param upright: Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).
SURF::operator()
----------------
Detects keypoints and computes SURF descriptors for them.
.. ocv:function:: void SURF::operator()(const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints)
.. ocv:function:: void SURF::operator()(const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints, vector<float>& descriptors, bool useProvidedKeypoints=false)
.. ocv:pyfunction:: cv2.SURF.detect(img, mask) -> keypoints
.. ocv:pyfunction:: cv2.SURF.detect(img, mask[, useProvidedKeypoints]) -> keypoints, descriptors
.. ocv:cfunction:: void cvExtractSURF( const CvArr* image, const CvArr* mask, CvSeq** keypoints, CvSeq** descriptors, CvMemStorage* storage, CvSURFParams params )
.. ocv:pyoldfunction:: cv.ExtractSURF(image, mask, storage, params)-> (keypoints, descriptors)
:param image: Input 8-bit grayscale image
:param mask: Optional input mask that marks the regions where we should detect features.
:param keypoints: The input/output vector of keypoints
:param descriptors: The output concatenated vectors of descriptors. Each descriptor is 64- or 128-element vector, as returned by ``SURF::descriptorSize()``. So the total size of ``descriptors`` will be ``keypoints.size()*descriptorSize()``.
:param useProvidedKeypoints: Boolean flag. If it is true, the keypoint detector is not run. Instead, the provided vector of keypoints is used and the algorithm just computes their descriptors.
:param storage: Memory storage for the output keypoints and descriptors in OpenCV 1.x API.
:param params: SURF algorithm parameters in OpenCV 1.x API.
ORB
----
.. ocv:class:: ORB
......
......@@ -22,7 +22,7 @@ PERF_TEST_P(orb, detect, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
TEST_CYCLE() detector(frame, mask, points);
......@@ -39,7 +39,7 @@ PERF_TEST_P(orb, extract, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
detector(frame, mask, points);
......@@ -58,7 +58,7 @@ PERF_TEST_P(orb, full, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
Mat descriptors;
......
......@@ -77,11 +77,11 @@ void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<ve
compute( imageCollection[i], pointCollection[i], descCollection[i] );
}
void DescriptorExtractor::read( const FileNode& )
/*void DescriptorExtractor::read( const FileNode& )
{}
void DescriptorExtractor::write( FileStorage& ) const
{}
{}*/
bool DescriptorExtractor::empty() const
{
......@@ -96,184 +96,16 @@ void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{
DescriptorExtractor* de = 0;
size_t pos = 0;
if (!descriptorExtractorType.compare("SIFT"))
if( descriptorExtractorType.find("Opponent") == 0)
{
de = new SiftDescriptorExtractor();
size_t pos = string("Opponent").size();
return DescriptorExtractor::create(descriptorExtractorType.substr(pos));
}
else if (!descriptorExtractorType.compare("SURF"))
{
de = new SurfDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("ORB"))
{
de = new OrbDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("BRIEF"))
{
de = new BriefDescriptorExtractor();
}
else if ( (pos=descriptorExtractorType.find("Opponent")) == 0)
{
pos += string("Opponent").size();
de = new OpponentColorDescriptorExtractor( DescriptorExtractor::create(descriptorExtractorType.substr(pos)) );
}
return de;
}
/****************************************************************************************\
* SiftDescriptorExtractor *
\****************************************************************************************/
SiftDescriptorExtractor::SiftDescriptorExtractor(const SIFT::DescriptorParams& descriptorParams,
const SIFT::CommonParams& commonParams)
: sift( descriptorParams.magnification, descriptorParams.isNormalize, descriptorParams.recalculateAngles,
commonParams.nOctaves, commonParams.nOctaveLayers, commonParams.firstOctave, commonParams.angleMode )
{}
SiftDescriptorExtractor::SiftDescriptorExtractor( double magnification, bool isNormalize, bool recalculateAngles,
int nOctaves, int nOctaveLayers, int firstOctave, int angleMode )
: sift( magnification, isNormalize, recalculateAngles, nOctaves, nOctaveLayers, firstOctave, angleMode )
{}
void SiftDescriptorExtractor::computeImpl( const Mat& image,
vector<KeyPoint>& keypoints,
Mat& descriptors) const
{
bool useProvidedKeypoints = true;
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
sift(grayImage, Mat(), keypoints, descriptors, useProvidedKeypoints);
}
void SiftDescriptorExtractor::read (const FileNode &fn)
{
double magnification = fn["magnification"];
bool isNormalize = (int)fn["isNormalize"] != 0;
bool recalculateAngles = (int)fn["recalculateAngles"] != 0;
int nOctaves = fn["nOctaves"];
int nOctaveLayers = fn["nOctaveLayers"];
int firstOctave = fn["firstOctave"];
int angleMode = fn["angleMode"];
sift = SIFT( magnification, isNormalize, recalculateAngles, nOctaves, nOctaveLayers, firstOctave, angleMode );
}
void SiftDescriptorExtractor::write (FileStorage &fs) const
{
// fs << "algorithm" << getAlgorithmName ();
SIFT::CommonParams commParams = sift.getCommonParams ();
SIFT::DescriptorParams descriptorParams = sift.getDescriptorParams ();
fs << "magnification" << descriptorParams.magnification;
fs << "isNormalize" << descriptorParams.isNormalize;
fs << "recalculateAngles" << descriptorParams.recalculateAngles;
fs << "nOctaves" << commParams.nOctaves;
fs << "nOctaveLayers" << commParams.nOctaveLayers;
fs << "firstOctave" << commParams.firstOctave;
fs << "angleMode" << commParams.angleMode;
}
int SiftDescriptorExtractor::descriptorSize() const
{
return sift.descriptorSize();
}
int SiftDescriptorExtractor::descriptorType() const
{
return CV_32FC1;
}
/****************************************************************************************\
* SurfDescriptorExtractor *
\****************************************************************************************/
SurfDescriptorExtractor::SurfDescriptorExtractor( int nOctaves,
int nOctaveLayers, bool extended, bool upright )
: surf( 0.0, nOctaves, nOctaveLayers, extended, upright )
{}
void SurfDescriptorExtractor::computeImpl( const Mat& image,
vector<KeyPoint>& keypoints,
Mat& descriptors) const
{
// Compute descriptors for given keypoints
vector<float> _descriptors;
Mat mask;
bool useProvidedKeypoints = true;
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
surf(grayImage, mask, keypoints, _descriptors, useProvidedKeypoints);
descriptors.create((int)keypoints.size(), (int)surf.descriptorSize(), CV_32FC1);
assert( (int)_descriptors.size() == descriptors.rows * descriptors.cols );
std::copy(_descriptors.begin(), _descriptors.end(), descriptors.begin<float>());
}
void SurfDescriptorExtractor::read( const FileNode &fn )
{
int nOctaves = fn["nOctaves"];
int nOctaveLayers = fn["nOctaveLayers"];
bool extended = (int)fn["extended"] != 0;
bool upright = (int)fn["upright"] != 0;
surf = SURF( 0.0, nOctaves, nOctaveLayers, extended, upright );
}
void SurfDescriptorExtractor::write( FileStorage &fs ) const
{
// fs << "algorithm" << getAlgorithmName ();
fs << "nOctaves" << surf.nOctaves;
fs << "nOctaveLayers" << surf.nOctaveLayers;
fs << "extended" << surf.extended;
fs << "upright" << surf.upright;
}
int SurfDescriptorExtractor::descriptorSize() const
{
return surf.descriptorSize();
}
int SurfDescriptorExtractor::descriptorType() const
{
return CV_32FC1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** Default constructor */
OrbDescriptorExtractor::OrbDescriptorExtractor(ORB::CommonParams params)
{
orb_ = ORB(0, params);
}
void OrbDescriptorExtractor::computeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints,
cv::Mat& descriptors) const
{
cv::Mat empty_mask;
orb_(image, empty_mask, keypoints, descriptors, true);
}
void OrbDescriptorExtractor::read(const cv::FileNode& fn)
{
orb_.read(fn);
}
void OrbDescriptorExtractor::write(cv::FileStorage& fs) const
{
orb_.write(fs);
}
int OrbDescriptorExtractor::descriptorSize() const
{
return orb_.descriptorSize();
}
int OrbDescriptorExtractor::descriptorType() const
{
return CV_8UC1;
return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************************\
* OpponentColorDescriptorExtractor *
......
......@@ -169,8 +169,9 @@ SurfAdjuster::SurfAdjuster( double initial_thresh, double min_thresh, double max
void SurfAdjuster::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const cv::Mat& mask) const
{
SurfFeatureDetector detector_tmp(thresh_);
detector_tmp.detect(image, keypoints, mask);
Ptr<FeatureDetector> surf = FeatureDetector::create("SURF");
surf->set("hessianThreshold", thresh_);
surf->detect(image, keypoints, mask);
}
void SurfAdjuster::tooFew(int, int)
......
......@@ -185,11 +185,10 @@ static int cornerScore(const uchar* ptr, const int pixel[], int threshold)
return threshold;
}
}
void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
{
Mat img = _img.getMat();
const int K = 8, N = 16 + K + 1;
int i, j, k, pixel[N];
makeOffsets(pixel, img.step);
......@@ -280,7 +279,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j+k;
if(nonmax_suppression)
curr[j+k] = (uchar)cornerScore(ptr+k, pixel, threshold);
curr[j+k] = cornerScore(ptr+k, pixel, threshold);
}
}
#endif
......@@ -318,7 +317,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j;
if(nonmax_suppression)
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
curr[j] = cornerScore(ptr, pixel, threshold);
break;
}
}
......@@ -340,7 +339,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j;
if(nonmax_suppression)
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
curr[j] = cornerScore(ptr, pixel, threshold);
break;
}
}
......@@ -375,3 +374,38 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
}
}
}
/*
* FastFeatureDetector
*/
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression)
{}
void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
KeyPointsFilter::runByPixelsMask( keypoints, mask );
}
static Algorithm* createFAST() { return new FastFeatureDetector; }
static AlgorithmInfo fast_info("Feature2D.FAST", createFAST);
AlgorithmInfo* FastFeatureDetector::info() const
{
static volatile bool initialized = false;
if( !initialized )
{
fast_info.addParam(this, "threshold", threshold);
fast_info.addParam(this, "nonmaxSuppression", nonmaxSuppression);
initialized = true;
}
return &fast_info;
}
}
......@@ -165,6 +165,52 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 )
return ovrl;
}
struct KeypointResponseGreaterThanThreshold
{
KeypointResponseGreaterThanThreshold(float _value) :
value(_value)
{
}
inline bool operator()(const KeyPoint& kpt) const
{
return kpt.response >= value;
}
float value;
};
struct KeypointResponseGreater
{
inline bool operator()(const KeyPoint& kp1, const KeyPoint& kp2) const
{
return kp1.response > kp2.response;
}
};
// takes keypoints and culls them by the response
void KeyPointsFilter::retainBest(vector<KeyPoint>& keypoints, int n_points)
{
//this is only necessary if the keypoints size is greater than the number of desired points.
if( n_points > 0 && keypoints.size() > (size_t)n_points )
{
if (n_points==0)
{
keypoints.clear();
return;
}
//first use nth element to partition the keypoints into the best and worst.
std::nth_element(keypoints.begin(), keypoints.begin() + n_points, keypoints.end(), KeypointResponseGreater());
//this is the boundary response, and in the case of FAST may be ambigous
float ambiguous_response = keypoints[n_points - 1].response;
//use std::partition to grab all of the keypoints with the boundary response.
vector<KeyPoint>::const_iterator new_end =
std::partition(keypoints.begin() + n_points, keypoints.end(),
KeypointResponseGreaterThanThreshold(ambiguous_response));
//resize the keypoints, given this new end point. nth_element and partition reordered the points inplace
keypoints.resize(new_end - keypoints.begin());
}
}
struct RoiPredicate
{
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -440,7 +440,7 @@ protected:
fs.open( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::WRITE );
if( fs.isOpened() )
{
SurfFeatureDetector fd;
ORB fd;
fd.detect(img, keypoints);
write( fs, "keypoints", keypoints );
}
......@@ -491,7 +491,7 @@ private:
CV_DescriptorExtractorTest& operator=(const CV_DescriptorExtractorTest&) { return *this; }
};
template<typename T, typename Distance>
/*template<typename T, typename Distance>
class CV_CalonderDescriptorExtractorTest : public CV_DescriptorExtractorTest<Distance>
{
public:
......@@ -506,7 +506,7 @@ protected:
new CalonderDescriptorExtractor<T>( string(CV_DescriptorExtractorTest<Distance>::ts->get_data_path()) +
FEATURES2D_DIR + "/calonder_classifier.rtc");
}
};
};*/
/****************************************************************************************\
* Algorithmic tests for descriptor matchers *
......@@ -991,24 +991,12 @@ TEST( Features2d_Detector_MSER, regression )
test.safe_run();
}
TEST( Features2d_Detector_SIFT, regression )
{
CV_FeatureDetectorTest test( "detector-sift", FeatureDetector::create("SIFT") );
test.safe_run();
}
TEST( Features2d_Detector_STAR, regression )
{
CV_FeatureDetectorTest test( "detector-star", FeatureDetector::create("STAR") );
test.safe_run();
}
TEST( Features2d_Detector_SURF, regression )
{
CV_FeatureDetectorTest test( "detector-surf", FeatureDetector::create("SURF") );
test.safe_run();
}
TEST( Features2d_Detector_ORB, regression )
{
CV_FeatureDetectorTest test( "detector-orb", FeatureDetector::create("ORB") );
......@@ -1027,23 +1015,6 @@ TEST( Features2d_Detector_PyramidFAST, regression )
test.safe_run();
}
/*
* Descriptors
*/
TEST( Features2d_DescriptorExtractor_SIFT, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-sift", 0.03f,
DescriptorExtractor::create("SIFT"), 8.06652f );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_SURF, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf", 0.035f,
DescriptorExtractor::create("SURF"), 0.147372f );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_ORB, regression )
{
// TODO adjust the parameters below
......@@ -1066,13 +1037,6 @@ TEST( Features2d_DescriptorExtractor_BRIEF, regression )
test.safe_run();
}*/
TEST( Features2d_DescriptorExtractor_OpponentSURF, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-opponent-surf", 0.18f,
DescriptorExtractor::create("OpponentSURF"), 0.147372f );
test.safe_run();
}
#if CV_SSE2
TEST( Features2d_DescriptorExtractor_Calonder_uchar, regression )
{
......@@ -1096,7 +1060,7 @@ TEST( Features2d_DescriptorExtractor_Calonder_float, regression )
*/
TEST( Features2d_DescriptorMatcher_BruteForce, regression )
{
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", new BruteForceMatcher<L2<float> >, 0.01f );
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", new BFMatcher(NORM_L2), 0.01f );
test.safe_run();
}
......
......@@ -155,27 +155,24 @@ void CV_MserTest::run(int)
{
string image_path = string(ts->get_data_path()) + "mser/puzzle.png";
IplImage* img = cvLoadImage( image_path.c_str());
if (!img)
Mat img = imread( image_path );
if (img.empty())
{
ts->printf( cvtest::TS::LOG, "Unable to open image mser/puzzle.png\n");
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
return;
}
CvSeq* contours;
CvMemStorage* storage= cvCreateMemStorage();
IplImage* hsv = cvCreateImage( cvGetSize( img ), IPL_DEPTH_8U, 3 );
cvCvtColor( img, hsv, CV_BGR2YCrCb );
CvMSERParams params = cvMSERParams();//cvMSERParams( 5, 60, cvRound(.2*img->width*img->height), .25, .2 );
cvExtractMSER( hsv, NULL, &contours, storage, params );
Mat yuv;
cvtColor(img, yuv, COLOR_BGR2YCrCb);
vector<vector<Point> > msers;
MSER()(yuv, msers);
vector<CvBox2D> boxes;
vector<CvBox2D> boxes_orig;
for ( int i = 0; i < contours->total; i++ )
for ( size_t i = 0; i < msers.size(); i++ )
{
CvContour* r = *(CvContour**)cvGetSeqElem( contours, i );
CvBox2D box = cvFitEllipse2( r );
RotatedRect box = fitEllipse(msers[i]);
box.angle=(float)CV_PI/2-box.angle;
boxes.push_back(box);
}
......@@ -203,10 +200,6 @@ void CV_MserTest::run(int)
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->printf( cvtest::TS::LOG, "Incorrect correspondence in box %d\n",n_box);
}
cvReleaseMemStorage(&storage);
cvReleaseImage(&hsv);
cvReleaseImage(&img);
}
TEST(Features2d_MSER, regression) { CV_MserTest test; test.safe_run(); }
......
......@@ -1511,7 +1511,7 @@ private:
////////////////////////////////// SURF //////////////////////////////////////////
class CV_EXPORTS SURF_GPU : public CvSURFParams
class CV_EXPORTS SURF_GPU
{
public:
enum KeypointLayout
......@@ -1566,6 +1566,14 @@ public:
void releaseMemory();
// SURF parameters;
int extended;
int upright;
double hessianThreshold;
int nOctaves;
int nOctaveLayers;
//! max keypoints = min(keypointsRatio * img.size().area(), 65535)
float keypointsRatio;
......@@ -1656,7 +1664,7 @@ public:
//! Constructor
//! n_features - the number of desired features
//! detector_params - parameters to use
explicit ORB_GPU(size_t n_features = 500, const ORB::CommonParams& detector_params = ORB::CommonParams());
explicit ORB_GPU(size_t n_features = 500, float scaleFactor = 1.2f, int nlevels = 3);
//! Compute the ORB features on an image
//! image - the image to compute the features (supports only CV_8UC1 images)
......@@ -1682,7 +1690,7 @@ public:
//! returns the descriptor size in bytes
inline int descriptorSize() const { return kBytes; }
void setParams(size_t n_features, const ORB::CommonParams& detector_params);
void setParams(size_t n_features, float scaleFactor, int nlevels);
inline void setFastParams(int threshold, bool nonmaxSupression = true)
{
fastDetector_.threshold = threshold;
......@@ -1706,7 +1714,7 @@ private:
void mergeKeyPoints(GpuMat& keypoints);
ORB::CommonParams params_;
ORB params_;
// The number of desired features per scale
std::vector<size_t> n_features_per_level_;
......
此差异已折叠。
......@@ -345,7 +345,7 @@ void prefix##remove_at_##type(_CVLIST* l, CVPOS pos)\
void prefix##set_##type(CVPOS pos, type* data)\
{\
ELEMENT_##type* element = ((ELEMENT_##type*)(pos.m_pos));\
memcpy(&(element->m_data), data, sizeof(data));\
memcpy(&(element->m_data), data, sizeof(*data));\
}\
type* prefix##get_##type(CVPOS pos)\
{\
......
此差异已折叠。
此差异已折叠。
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
此差异已折叠。
set(the_description "Functionality with possible limitations on the use")
ocv_define_module(nonfree opencv_imgproc opencv_features2d)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册