mirror of
https://github.com/opencv/opencv.git
synced 2025-06-13 13:13:26 +08:00
added FAST<5/8> & FAST<7/12> (by Vincent Rabaud)
This commit is contained in:
parent
b43cec3301
commit
640408ebe7
@ -473,12 +473,18 @@ protected:
|
|||||||
|
|
||||||
//! detects corners using FAST algorithm by E. Rosten
|
//! detects corners using FAST algorithm by E. Rosten
|
||||||
CV_EXPORTS void FAST( InputArray image, CV_OUT vector<KeyPoint>& keypoints,
|
CV_EXPORTS void FAST( InputArray image, CV_OUT vector<KeyPoint>& keypoints,
|
||||||
int threshold, bool nonmaxSupression=true );
|
int threshold, bool nonmaxSupression=true, int type = 2 );
|
||||||
|
|
||||||
class CV_EXPORTS_W FastFeatureDetector : public FeatureDetector
|
class CV_EXPORTS_W FastFeatureDetector : public FeatureDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2
|
||||||
|
};
|
||||||
|
|
||||||
CV_WRAP FastFeatureDetector( int threshold=10, bool nonmaxSuppression=true);
|
CV_WRAP FastFeatureDetector( int threshold=10, bool nonmaxSuppression=true);
|
||||||
|
CV_WRAP FastFeatureDetector( int threshold, bool nonmaxSuppression, int type);
|
||||||
AlgorithmInfo* info() const;
|
AlgorithmInfo* info() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -486,6 +492,7 @@ protected:
|
|||||||
|
|
||||||
int threshold;
|
int threshold;
|
||||||
bool nonmaxSuppression;
|
bool nonmaxSuppression;
|
||||||
|
int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,9 +22,13 @@ PERF_TEST_P(fast, detectForORB, testing::Values(FAST_IMAGES))
|
|||||||
|
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
|
|
||||||
FastFeatureDetector fd(20, true);
|
FastFeatureDetector fd(20, true, FastFeatureDetector::TYPE_5_8);
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
|
|
||||||
TEST_CYCLE() fd.detect(frame, points);
|
TEST_CYCLE() fd.detect(frame, points);
|
||||||
|
fd = FastFeatureDetector(20, true, FastFeatureDetector::TYPE_7_12);
|
||||||
|
TEST_CYCLE() fd.detect(frame, points);
|
||||||
|
fd = FastFeatureDetector(20, true, FastFeatureDetector::TYPE_9_16);
|
||||||
|
TEST_CYCLE() fd.detect(frame, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,10 @@ The references are:
|
|||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
|
||||||
static void makeOffsets(int pixel[], int row_stride)
|
static void makeOffsets(int pixel[], int row_stride, int patternSize)
|
||||||
{
|
{
|
||||||
|
switch(patternSize) {
|
||||||
|
case 16:
|
||||||
pixel[0] = 0 + row_stride * 3;
|
pixel[0] = 0 + row_stride * 3;
|
||||||
pixel[1] = 1 + row_stride * 3;
|
pixel[1] = 1 + row_stride * 3;
|
||||||
pixel[2] = 2 + row_stride * 2;
|
pixel[2] = 2 + row_stride * 2;
|
||||||
@ -64,9 +66,73 @@ static void makeOffsets(int pixel[], int row_stride)
|
|||||||
pixel[13] = -3 + row_stride * 1;
|
pixel[13] = -3 + row_stride * 1;
|
||||||
pixel[14] = -2 + row_stride * 2;
|
pixel[14] = -2 + row_stride * 2;
|
||||||
pixel[15] = -1 + row_stride * 3;
|
pixel[15] = -1 + row_stride * 3;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
pixel[0] = 0 + row_stride * 2;
|
||||||
|
pixel[1] = 1 + row_stride * 2;
|
||||||
|
pixel[2] = 2 + row_stride * 1;
|
||||||
|
pixel[3] = 2 + row_stride * 0;
|
||||||
|
pixel[4] = 2 + row_stride * -1;
|
||||||
|
pixel[5] = 1 + row_stride * -2;
|
||||||
|
pixel[6] = 0 + row_stride * -2;
|
||||||
|
pixel[7] = -1 + row_stride * -2;
|
||||||
|
pixel[8] = -2 + row_stride * -1;
|
||||||
|
pixel[9] = -2 + row_stride * 0;
|
||||||
|
pixel[10] = -2 + row_stride * 1;
|
||||||
|
pixel[11] = -1 + row_stride * 2;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
pixel[0] = 0 + row_stride * 1;
|
||||||
|
pixel[1] = 1 + row_stride * 1;
|
||||||
|
pixel[2] = 1 + row_stride * 0;
|
||||||
|
pixel[3] = 1 + row_stride * -1;
|
||||||
|
pixel[4] = 0 + row_stride * -1;
|
||||||
|
pixel[5] = -1 + row_stride * -1;
|
||||||
|
pixel[6] = 0 + row_stride * 0;
|
||||||
|
pixel[7] = 1 + row_stride * 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cornerScore(const uchar* ptr, const int pixel[], int threshold)
|
/*static void testCorner(const uchar* ptr, const int pixel[], int K, int N, int threshold) {
|
||||||
|
// check that with the computed "threshold" the pixel is still a corner
|
||||||
|
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
|
||||||
|
for( int delta = 0; delta <= 1; delta++ )
|
||||||
|
{
|
||||||
|
int v0 = std::min(ptr[0] + threshold + delta, 255);
|
||||||
|
int v1 = std::max(ptr[0] - threshold - delta, 0);
|
||||||
|
int c0 = 0, c1 = 0;
|
||||||
|
|
||||||
|
for( int k = 0; k < N; k++ )
|
||||||
|
{
|
||||||
|
int x = ptr[pixel[k]];
|
||||||
|
if(x > v0)
|
||||||
|
{
|
||||||
|
if( ++c0 > K )
|
||||||
|
break;
|
||||||
|
c1 = 0;
|
||||||
|
}
|
||||||
|
else if( x < v1 )
|
||||||
|
{
|
||||||
|
if( ++c1 > K )
|
||||||
|
break;
|
||||||
|
c0 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c0 = c1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CV_Assert( (delta == 0 && std::max(c0, c1) > K) ||
|
||||||
|
(delta == 1 && std::max(c0, c1) <= K) );
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
template<int patternSize>
|
||||||
|
int cornerScore(const uchar* ptr, const int pixel[], int threshold);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
int cornerScore<16>(const uchar* ptr, const int pixel[], int threshold)
|
||||||
{
|
{
|
||||||
const int K = 8, N = 16 + K + 1;
|
const int K = 8, N = 16 + K + 1;
|
||||||
int k, v = ptr[0];
|
int k, v = ptr[0];
|
||||||
@ -150,50 +216,170 @@ static int cornerScore(const uchar* ptr, const int pixel[], int threshold)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// check that with the computed "threshold" the pixel is still a corner
|
testCorner(ptr, pixel, K, N, threshold);
|
||||||
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
|
|
||||||
for( int delta = 0; delta <= 1; delta++ )
|
|
||||||
{
|
|
||||||
int v0 = std::min(ptr[0] + threshold + delta, 255);
|
|
||||||
int v1 = std::max(ptr[0] - threshold - delta, 0);
|
|
||||||
int c0 = 0, c1 = 0;
|
|
||||||
|
|
||||||
for( int k = 0; k < N; k++ )
|
|
||||||
{
|
|
||||||
int x = ptr[pixel[k]];
|
|
||||||
if(x > v0)
|
|
||||||
{
|
|
||||||
if( ++c0 > K )
|
|
||||||
break;
|
|
||||||
c1 = 0;
|
|
||||||
}
|
|
||||||
else if( x < v1 )
|
|
||||||
{
|
|
||||||
if( ++c1 > K )
|
|
||||||
break;
|
|
||||||
c0 = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c0 = c1 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CV_Assert( (delta == 0 && std::max(c0, c1) > K) ||
|
|
||||||
(delta == 1 && std::max(c0, c1) <= K) );
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return threshold;
|
return threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold)
|
||||||
|
{
|
||||||
|
const int K = 6, N = 12 + K + 1;
|
||||||
|
int k, v = ptr[0];
|
||||||
|
short d[N];
|
||||||
|
for( k = 0; k < N; k++ )
|
||||||
|
d[k] = (short)(v - ptr[pixel[k]]);
|
||||||
|
|
||||||
void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
|
#if CV_SSE2
|
||||||
|
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||||
|
for( k = 0; k < 16; k += 8 )
|
||||||
|
{
|
||||||
|
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||||
|
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||||
|
__m128i a = _mm_min_epi16(v0, v1);
|
||||||
|
__m128i b = _mm_max_epi16(v0, v1);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+6));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||||
|
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+7));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||||
|
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||||
|
}
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||||
|
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||||
|
#else
|
||||||
|
int a0 = threshold;
|
||||||
|
for( k = 0; k < 12; k += 2 )
|
||||||
|
{
|
||||||
|
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||||
|
if( a <= a0 )
|
||||||
|
continue;
|
||||||
|
a = std::min(a, (int)d[k+3]);
|
||||||
|
a = std::min(a, (int)d[k+4]);
|
||||||
|
a = std::min(a, (int)d[k+5]);
|
||||||
|
a = std::min(a, (int)d[k+6]);
|
||||||
|
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||||
|
a0 = std::max(a0, std::min(a, (int)d[k+7]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int b0 = -a0;
|
||||||
|
for( k = 0; k < 12; k += 2 )
|
||||||
|
{
|
||||||
|
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||||
|
b = std::max(b, (int)d[k+3]);
|
||||||
|
b = std::max(b, (int)d[k+4]);
|
||||||
|
if( b >= b0 )
|
||||||
|
continue;
|
||||||
|
b = std::max(b, (int)d[k+5]);
|
||||||
|
b = std::max(b, (int)d[k+6]);
|
||||||
|
|
||||||
|
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||||
|
b0 = std::min(b0, std::max(b, (int)d[k+7]));
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold = -b0-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
testCorner(ptr, pixel, K, N, threshold);
|
||||||
|
#endif
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold)
|
||||||
|
{
|
||||||
|
const int K = 4, N = 8 + K + 1;
|
||||||
|
int k, v = ptr[0];
|
||||||
|
short d[N];
|
||||||
|
for( k = 0; k < N; k++ )
|
||||||
|
d[k] = (short)(v - ptr[pixel[k]]);
|
||||||
|
|
||||||
|
#if CV_SSE2
|
||||||
|
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||||
|
for( k = 0; k < 16; k += 8 )
|
||||||
|
{
|
||||||
|
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||||
|
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||||
|
__m128i a = _mm_min_epi16(v0, v1);
|
||||||
|
__m128i b = _mm_max_epi16(v0, v1);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||||
|
a = _mm_min_epi16(a, v0);
|
||||||
|
b = _mm_max_epi16(b, v0);
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||||
|
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||||
|
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||||
|
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||||
|
}
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||||
|
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||||
|
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||||
|
#else
|
||||||
|
int a0 = threshold;
|
||||||
|
for( k = 0; k < 8; k += 2 )
|
||||||
|
{
|
||||||
|
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||||
|
if( a <= a0 )
|
||||||
|
continue;
|
||||||
|
a = std::min(a, (int)d[k+3]);
|
||||||
|
a = std::min(a, (int)d[k+4]);
|
||||||
|
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||||
|
a0 = std::max(a0, std::min(a, (int)d[k+5]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int b0 = -a0;
|
||||||
|
for( k = 0; k < 12; k += 2 )
|
||||||
|
{
|
||||||
|
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||||
|
b = std::max(b, (int)d[k+3]);
|
||||||
|
if( b >= b0 )
|
||||||
|
continue;
|
||||||
|
b = std::max(b, (int)d[k+4]);
|
||||||
|
|
||||||
|
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||||
|
b0 = std::min(b0, std::max(b, (int)d[k+5]));
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold = -b0-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
testCorner(ptr, pixel, K, N, threshold);
|
||||||
|
#endif
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int patternSize>
|
||||||
|
void FAST_t(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
|
||||||
{
|
{
|
||||||
Mat img = _img.getMat();
|
Mat img = _img.getMat();
|
||||||
const int K = 8, N = 16 + K + 1;
|
const int K = patternSize/2, N = patternSize + K + 1, quarterPatternSize = patternSize/4;
|
||||||
int i, j, k, pixel[N];
|
int i, j, k, pixel[25];
|
||||||
makeOffsets(pixel, (int)img.step);
|
makeOffsets(pixel, (int)img.step, patternSize);
|
||||||
for(k = 16; k < N; k++)
|
for(k = patternSize; k < 25; k++)
|
||||||
pixel[k] = pixel[k - 16];
|
pixel[k] = pixel[k - patternSize];
|
||||||
|
|
||||||
keypoints.clear();
|
keypoints.clear();
|
||||||
|
|
||||||
@ -235,9 +421,9 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
v0 = _mm_xor_si128(_mm_adds_epu8(v0, t), delta);
|
v0 = _mm_xor_si128(_mm_adds_epu8(v0, t), delta);
|
||||||
|
|
||||||
__m128i x0 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[0])), delta);
|
__m128i x0 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[0])), delta);
|
||||||
__m128i x1 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[4])), delta);
|
__m128i x1 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[quarterPatternSize])), delta);
|
||||||
__m128i x2 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[8])), delta);
|
__m128i x2 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[2*quarterPatternSize])), delta);
|
||||||
__m128i x3 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[12])), delta);
|
__m128i x3 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[3*quarterPatternSize])), delta);
|
||||||
m0 = _mm_and_si128(_mm_cmpgt_epi8(x0, v0), _mm_cmpgt_epi8(x1, v0));
|
m0 = _mm_and_si128(_mm_cmpgt_epi8(x0, v0), _mm_cmpgt_epi8(x1, v0));
|
||||||
m1 = _mm_and_si128(_mm_cmpgt_epi8(v1, x0), _mm_cmpgt_epi8(v1, x1));
|
m1 = _mm_and_si128(_mm_cmpgt_epi8(v1, x0), _mm_cmpgt_epi8(v1, x1));
|
||||||
m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x1, v0), _mm_cmpgt_epi8(x2, v0)));
|
m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x1, v0), _mm_cmpgt_epi8(x2, v0)));
|
||||||
@ -279,7 +465,7 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
{
|
{
|
||||||
cornerpos[ncorners++] = j+k;
|
cornerpos[ncorners++] = j+k;
|
||||||
if(nonmax_suppression)
|
if(nonmax_suppression)
|
||||||
curr[j+k] = (uchar)cornerScore(ptr+k, pixel, threshold);
|
curr[j+k] = (uchar)cornerScore<patternSize>(ptr+k, pixel, threshold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -317,7 +503,7 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
{
|
{
|
||||||
cornerpos[ncorners++] = j;
|
cornerpos[ncorners++] = j;
|
||||||
if(nonmax_suppression)
|
if(nonmax_suppression)
|
||||||
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
|
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,7 +525,7 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
{
|
{
|
||||||
cornerpos[ncorners++] = j;
|
cornerpos[ncorners++] = j;
|
||||||
if(nonmax_suppression)
|
if(nonmax_suppression)
|
||||||
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
|
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,19 +561,36 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression, int type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case FastFeatureDetector::TYPE_5_8:
|
||||||
|
FAST_t<8>(_img, keypoints, threshold, nonmax_suppression);
|
||||||
|
break;
|
||||||
|
case FastFeatureDetector::TYPE_7_12:
|
||||||
|
FAST_t<12>(_img, keypoints, threshold, nonmax_suppression);
|
||||||
|
break;
|
||||||
|
case FastFeatureDetector::TYPE_9_16:
|
||||||
|
FAST_t<16>(_img, keypoints, threshold, nonmax_suppression);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* FastFeatureDetector
|
* FastFeatureDetector
|
||||||
*/
|
*/
|
||||||
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
|
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
|
||||||
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression)
|
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type(FastFeatureDetector::TYPE_9_16)
|
||||||
|
{}
|
||||||
|
|
||||||
|
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression, int _type )
|
||||||
|
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type(_type)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
|
void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
|
||||||
{
|
{
|
||||||
Mat grayImage = image;
|
Mat grayImage = image;
|
||||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||||
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
|
FAST( grayImage, keypoints, threshold, nonmaxSuppression, type );
|
||||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ CV_INIT_ALGORITHM(BriefDescriptorExtractor, "Feature2D.BRIEF",
|
|||||||
|
|
||||||
CV_INIT_ALGORITHM(FastFeatureDetector, "Feature2D.FAST",
|
CV_INIT_ALGORITHM(FastFeatureDetector, "Feature2D.FAST",
|
||||||
obj.info()->addParam(obj, "threshold", obj.threshold);
|
obj.info()->addParam(obj, "threshold", obj.threshold);
|
||||||
obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression));
|
obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression);
|
||||||
|
obj.info()->addParam(obj, "type", obj.type, FastFeatureDetector::TYPE_9_16));
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ CV_FastTest::~CV_FastTest() {}
|
|||||||
|
|
||||||
void CV_FastTest::run( int )
|
void CV_FastTest::run( int )
|
||||||
{
|
{
|
||||||
|
for(int type=0; type <= 2; ++type) {
|
||||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.jpg");
|
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.jpg");
|
||||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.jpg");
|
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.jpg");
|
||||||
string xml = string(ts->get_data_path()) + "fast/result.xml";
|
string xml = string(ts->get_data_path()) + "fast/result.xml";
|
||||||
@ -74,8 +75,8 @@ void CV_FastTest::run( int )
|
|||||||
|
|
||||||
vector<KeyPoint> keypoints1;
|
vector<KeyPoint> keypoints1;
|
||||||
vector<KeyPoint> keypoints2;
|
vector<KeyPoint> keypoints2;
|
||||||
FAST(gray1, keypoints1, 30);
|
FAST(gray1, keypoints1, 30, type);
|
||||||
FAST(gray2, keypoints2, 30);
|
FAST(gray2, keypoints2, 30, type);
|
||||||
|
|
||||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -109,15 +110,19 @@ void CV_FastTest::run( int )
|
|||||||
read( fs["exp_kps2"], exp_kps2, Mat() );
|
read( fs["exp_kps2"], exp_kps2, Mat() );
|
||||||
fs.release();
|
fs.release();
|
||||||
|
|
||||||
|
// We only have testing data for 9_16 but it actually works equally well for 7_12
|
||||||
|
if ((type==1) || (type==2)){
|
||||||
if ( 0 != norm(exp_kps1, kps1, NORM_L2) || 0 != norm(exp_kps2, kps2, NORM_L2))
|
if ( 0 != norm(exp_kps1, kps1, NORM_L2) || 0 != norm(exp_kps2, kps2, NORM_L2))
|
||||||
{
|
{
|
||||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*cv::namedWindow("Img1"); cv::imshow("Img1", image1);
|
/*cv::namedWindow("Img1"); cv::imshow("Img1", image1);
|
||||||
cv::namedWindow("Img2"); cv::imshow("Img2", image2);
|
cv::namedWindow("Img2"); cv::imshow("Img2", image2);
|
||||||
cv::waitKey(0);*/
|
cv::waitKey(0);*/
|
||||||
|
}
|
||||||
|
|
||||||
ts->set_failed_test_info(cvtest::TS::OK);
|
ts->set_failed_test_info(cvtest::TS::OK);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user