From 60769f544face6e30a7aa46289ca28be29304b75 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 25 Sep 2012 15:50:03 +0400 Subject: [PATCH] possibly repaired FAST test (however, FAST<7/12> and <5/8> could still do something different than described in the paper) --- modules/features2d/src/fast.cpp | 2 +- modules/features2d/src/fast_score.cpp | 87 ++++++++++++++--------------------- modules/features2d/test/test_fast.cpp | 31 +++++++------ 3 files changed, 53 insertions(+), 67 deletions(-) diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 9beba21..d940463 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -89,7 +89,7 @@ void FAST_t(InputArray _img, std::vector& keypoints, int threshold, bo if( i < img.rows - 3 ) { j = 3; - #if CV_SSE2 + #if 0 //CV_SSE2 for(; j < img.cols - 16 - 3; j += 16, ptr += 16) { __m128i m0, m1; diff --git a/modules/features2d/src/fast_score.cpp b/modules/features2d/src/fast_score.cpp index aa5881e..b897860 100644 --- a/modules/features2d/src/fast_score.cpp +++ b/modules/features2d/src/fast_score.cpp @@ -46,58 +46,39 @@ The references are: namespace cv { -void makeOffsets(int pixel[25], int row_stride, int patternSize) +void makeOffsets(int pixel[25], int rowStride, int patternSize) { - CV_Assert(pixel != 0); - switch(patternSize) { - case 16: - pixel[0] = 0 + row_stride * 3; - pixel[1] = 1 + row_stride * 3; - pixel[2] = 2 + row_stride * 2; - pixel[3] = 3 + row_stride * 1; - pixel[4] = 3 + row_stride * 0; - pixel[5] = 3 + row_stride * -1; - pixel[6] = 2 + row_stride * -2; - pixel[7] = 1 + row_stride * -3; - pixel[8] = 0 + row_stride * -3; - pixel[9] = -1 + row_stride * -3; - pixel[10] = -2 + row_stride * -2; - pixel[11] = -3 + row_stride * -1; - pixel[12] = -3 + row_stride * 0; - pixel[13] = -3 + row_stride * 1; - pixel[14] = -2 + row_stride * 2; - 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; - } - for(int k = patternSize; k < 25; k++) - pixel[k] = pixel[k - patternSize]; + static const int offsets16[][2] = + { + {0, 3}, { 1, 3}, { 2, 2}, { 3, 1}, { 3, 0}, { 3, -1}, { 2, -2}, { 1, -3}, + {0, -3}, {-1, -3}, {-2, -2}, {-3, -1}, {-3, 0}, {-3, 1}, {-2, 2}, {-1, 3} + }; + + static const int offsets12[][2] = + { + {0, 2}, { 1, 2}, { 2, 1}, { 2, 0}, { 2, -1}, { 1, -2}, + {0, -2}, {-1, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-1, 2} + }; + + static const int offsets8[][2] = + { + {0, 1}, { 1, 1}, { 1, 0}, { 1, -1}, + {0, -1}, {-1, -1}, {-1, 0}, {-1, 1} + }; + + const int (*offsets)[2] = patternSize == 16 ? offsets16 : + patternSize == 12 ? offsets12 : patternSize == 8 ? offsets8 : 0; + + CV_Assert(pixel != 0 && offsets); + + int k = 0; + for( ; k < patternSize; k++ ) + pixel[k] = offsets[k][0] + offsets[k][1]*rowStride; + for( ; k < 25; k++ ) + pixel[k] = pixel[k - patternSize]; } -/*static void testCorner(const uchar* ptr, const int pixel[], int K, int N, 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++ ) @@ -129,12 +110,12 @@ void makeOffsets(int pixel[25], int row_stride, int patternSize) CV_Assert( (delta == 0 && std::max(c0, c1) > K) || (delta == 1 && std::max(c0, c1) <= K) ); } -}*/ +} 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 = K*3 + 1; int k, v = ptr[0]; short d[N]; for( k = 0; k < N; k++ ) @@ -224,7 +205,7 @@ int cornerScore<16>(const uchar* ptr, const int pixel[], int threshold) template<> int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold) { - const int K = 6, N = 12 + K + 1; + const int K = 6, N = K*3 + 1; int k, v = ptr[0]; short d[N]; for( k = 0; k < N; k++ ) @@ -304,7 +285,7 @@ int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold) template<> int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold) { - const int K = 4, N = 8 + K + 1; + const int K = 4, N = K*3 + 1; int k, v = ptr[0]; short d[N]; for( k = 0; k < N; k++ ) diff --git a/modules/features2d/test/test_fast.cpp b/modules/features2d/test/test_fast.cpp index eef395b..477989d 100644 --- a/modules/features2d/test/test_fast.cpp +++ b/modules/features2d/test/test_fast.cpp @@ -61,7 +61,7 @@ void CV_FastTest::run( int ) for(int type=0; type <= 2; ++type) { Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.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()) + format("fast/result%d.xml", type); if (image1.empty() || image2.empty()) { @@ -76,7 +76,7 @@ void CV_FastTest::run( int ) vector keypoints1; vector keypoints2; FAST(gray1, keypoints1, 30, true, type); - FAST(gray2, keypoints2, 30, true, type); + FAST(gray2, keypoints2, (type > 0 ? 30 : 20), true, type); for(size_t i = 0; i < keypoints1.size(); ++i) { @@ -97,27 +97,32 @@ void CV_FastTest::run( int ) if (!fs.isOpened()) { fs.open(xml, FileStorage::WRITE); + if (!fs.isOpened()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } fs << "exp_kps1" << kps1; fs << "exp_kps2" << kps2; fs.release(); - } - - if (!fs.isOpened()) fs.open(xml, FileStorage::READ); + if (!fs.isOpened()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + } Mat exp_kps1, exp_kps2; read( fs["exp_kps1"], exp_kps1, Mat() ); read( fs["exp_kps2"], exp_kps2, Mat() ); 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 ( exp_kps1.size != kps1.size || 0 != norm(exp_kps1, kps1, NORM_L2) || - exp_kps2.size != kps2.size || 0 != norm(exp_kps2, kps2, NORM_L2)) - { - ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); - return; - } + if ( exp_kps1.size != kps1.size || 0 != norm(exp_kps1, kps1, NORM_L2) || + exp_kps2.size != kps2.size || 0 != norm(exp_kps2, kps2, NORM_L2)) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + return; } /*cv::namedWindow("Img1"); cv::imshow("Img1", image1); -- 2.7.4