diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index f77275cac3..aeddafb2cf 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1024,13 +1024,14 @@ public: const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1, int pca_dim_high = 100, int pca_dim_low = 100); - OneWayDescriptorBase(CvSize patch_size, int pose_count, const string &pca_filename, const string &train_path = string(), const string &images_list = string(), - int pyr_levels = 1, + float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1, int pca_dim_high = 100, int pca_dim_low = 100); virtual ~OneWayDescriptorBase(); + void clear (); + // Allocate: allocates memory for a given number of descriptors void Allocate(int train_feature_count); @@ -1124,7 +1125,7 @@ public: // GeneratePCA: calculate and save PCA components and descriptors // - img_path: path to training PCA images directory // - images_list: filename with filenames of training PCA images - void GeneratePCA(const char* img_path, const char* images_list); + void GeneratePCA(const char* img_path, const char* images_list, int pose_count=500); // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures) void SetPCAHigh(CvMat* avg, CvMat* eigenvectors); @@ -1168,6 +1169,9 @@ protected: int m_pca_dim_low; int m_pyr_levels; + const float scale_min; + const float scale_max; + const float scale_step; }; class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase @@ -1184,9 +1188,9 @@ public: OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config, const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1); - OneWayDescriptorObject(CvSize patch_size, int pose_count, const string &pca_filename, - const string &train_path = string (), const string &images_list = string (), int pyr_levels = 1); + const string &train_path = string (), const string &images_list = string (), + float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1); virtual ~OneWayDescriptorObject(); @@ -1705,9 +1709,9 @@ public: static const int POSE_COUNT = 500; static const int PATCH_WIDTH = 24; static const int PATCH_HEIGHT = 24; - static float GET_MIN_SCALE() { return 1.f; } - static float GET_MAX_SCALE() { return 3.f; } - static float GET_STEP_SCALE() { return 1.15f; } + static float GET_MIN_SCALE() { return 0.7f; } + static float GET_MAX_SCALE() { return 1.5f; } + static float GET_STEP_SCALE() { return 1.2f; } Params( int _poseCount = POSE_COUNT, Size _patchSize = Size(PATCH_WIDTH, PATCH_HEIGHT), @@ -1755,6 +1759,8 @@ public: // Classify a set of keypoints. The same as match, but returns point classes rather than indices virtual void classify( const Mat& image, vector& points ); + virtual void clear (); + protected: Ptr base; Params params; diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index c723a450eb..e8fd15ffeb 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -204,7 +204,7 @@ void OneWayDescriptorMatch::add( const Mat& image, vector& keypoints ) { if( base.empty() ) base = new OneWayDescriptorObject( params.patchSize, params.poseCount, params.pcaFilename, - params.trainPath, params.trainImagesList); + params.trainPath, params.trainImagesList, params.minScale, params.maxScale, params.stepScale); size_t trainFeatureCount = keypoints.size(); @@ -225,7 +225,7 @@ void OneWayDescriptorMatch::add( KeyPointCollection& keypoints ) { if( base.empty() ) base = new OneWayDescriptorObject( params.patchSize, params.poseCount, params.pcaFilename, - params.trainPath, params.trainImagesList); + params.trainPath, params.trainImagesList, params.minScale, params.maxScale, params.stepScale); size_t trainFeatureCount = keypoints.calcKeypointCount(); @@ -275,6 +275,12 @@ void OneWayDescriptorMatch::classify( const Mat& image, vector& points } } +void OneWayDescriptorMatch::clear () +{ + GenericDescriptorMatch::clear(); + base->clear (); +} + /****************************************************************************************\ * CalonderDescriptorMatch * \****************************************************************************************/ diff --git a/modules/features2d/src/oneway.cpp b/modules/features2d/src/oneway.cpp index 4987243974..63a95326ef 100644 --- a/modules/features2d/src/oneway.cpp +++ b/modules/features2d/src/oneway.cpp @@ -1213,7 +1213,8 @@ namespace cv{ OneWayDescriptorBase::OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config, const char* pca_hr_config, const char* pca_desc_config, int pyr_levels, - int pca_dim_high, int pca_dim_low) : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low) + int pca_dim_high, int pca_dim_low) + : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low), scale_min (0.7f), scale_max(1.5f), scale_step (1.2f) { // m_pca_descriptors_matrix = 0; m_patch_size = patch_size; @@ -1270,8 +1271,10 @@ namespace cv{ } OneWayDescriptorBase::OneWayDescriptorBase(CvSize patch_size, int pose_count, const string &pca_filename, - const string &train_path, const string &images_list, int pyr_levels, - int pca_dim_high, int pca_dim_low) : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low) + const string &train_path, const string &images_list, float _scale_min, float _scale_max, + float _scale_step, int pyr_levels, + int pca_dim_high, int pca_dim_low) + : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low), scale_min(_scale_min), scale_max(_scale_max), scale_step(_scale_step) { // m_pca_descriptors_matrix = 0; m_patch_size = patch_size; @@ -1341,6 +1344,20 @@ namespace cv{ #endif } + void OneWayDescriptorBase::clear(){ + delete []m_descriptors; + m_descriptors = 0; + +#if defined(_KDTREE) + // if (m_pca_descriptors_matrix) + // delete m_pca_descriptors_matrix; + cvReleaseMat(&m_pca_descriptors_matrix); + m_pca_descriptors_matrix = 0; + delete m_pca_descriptors_tree; + m_pca_descriptors_tree = 0; +#endif + } + void OneWayDescriptorBase::InitializePoses() { m_poses = new CvAffinePose[m_pose_count]; @@ -1423,25 +1440,25 @@ namespace cv{ #if 0 ::FindOneWayDescriptor(m_train_feature_count, m_descriptors, patch, desc_idx, pose_idx, distance, m_pca_avg, m_pca_eigenvectors); #else - float scale_min = 0.7f; - float scale_max = 2.0f; - float scale_step = 1.2f; + float min = scale_min; + float max = scale_max; + float step = scale_step; if (scale_ranges) { - scale_min = scale_ranges[0]; - scale_max = scale_ranges[1]; + min = scale_ranges[0]; + max = scale_ranges[1]; } float scale = 1.0f; #if !defined(_KDTREE) cv::FindOneWayDescriptorEx(m_train_feature_count, m_descriptors, patch, - scale_min, scale_max, scale_step, desc_idx, pose_idx, distance, scale, + min, max, step, desc_idx, pose_idx, distance, scale, m_pca_avg, m_pca_eigenvectors); #else cv::FindOneWayDescriptorEx(m_pca_descriptors_tree, m_descriptors[0].GetPatchSize(), m_descriptors[0].GetPCADimLow(), m_pose_count, patch, - scale_min, scale_max, scale_step, desc_idx, pose_idx, distance, scale, + min, max, step, desc_idx, pose_idx, distance, scale, m_pca_avg, m_pca_eigenvectors); #endif @@ -1454,14 +1471,14 @@ namespace cv{ void OneWayDescriptorBase::FindDescriptor(IplImage* patch, int n, std::vector& desc_idxs, std::vector& pose_idxs, std::vector& distances, std::vector& _scales, float* scale_ranges) const { - float scale_min = 0.7f; - float scale_max = 2.5f; - float scale_step = 1.2f; + float min = scale_min; + float max = scale_max; + float step = scale_step; if (scale_ranges) { - scale_min = scale_ranges[0]; - scale_max = scale_ranges[1]; + min = scale_ranges[0]; + max = scale_ranges[1]; } distances.resize(n); @@ -1471,7 +1488,7 @@ namespace cv{ /*float scales = 1.0f;*/ cv::FindOneWayDescriptorEx(m_train_feature_count, m_descriptors, patch, - scale_min, scale_max, scale_step ,n, desc_idxs, pose_idxs, distances, _scales, + min, max, step ,n, desc_idxs, pose_idxs, distances, _scales, m_pca_avg, m_pca_eigenvectors); } @@ -1719,7 +1736,7 @@ namespace cv{ calcPCAFeatures(patches, fs, postfix, avg, eigenvectors); } - void OneWayDescriptorBase::GeneratePCA(const char* img_path, const char* images_list) + void OneWayDescriptorBase::GeneratePCA(const char* img_path, const char* images_list, int pose_count) { char pca_filename[1024]; sprintf(pca_filename, "%s/%s", img_path, GetPCAFilename().c_str()); @@ -1729,7 +1746,6 @@ namespace cv{ generatePCAFeatures(img_path, images_list, fs, "lr", cvSize(m_patch_size.width / 2, m_patch_size.height / 2), &m_pca_avg, &m_pca_eigenvectors); - const int pose_count = 500; OneWayDescriptorBase descriptors(m_patch_size, pose_count); descriptors.SetPCAHigh(m_pca_hr_avg, m_pca_hr_eigenvectors); descriptors.SetPCALow(m_pca_avg, m_pca_eigenvectors); @@ -1926,13 +1942,12 @@ namespace cv{ } OneWayDescriptorObject::OneWayDescriptorObject(CvSize patch_size, int pose_count, const string &pca_filename, - const string &train_path, const string &images_list, int pyr_levels) : - OneWayDescriptorBase(patch_size, pose_count, pca_filename, train_path, images_list, pyr_levels) + const string &train_path, const string &images_list, float _scale_min, float _scale_max, float _scale_step, int pyr_levels) : + OneWayDescriptorBase(patch_size, pose_count, pca_filename, train_path, images_list, _scale_min, _scale_max, _scale_step, pyr_levels) { m_part_id = 0; } - OneWayDescriptorObject::~OneWayDescriptorObject() { delete []m_part_id; diff --git a/tests/cv/src/adetectordescriptor_evaluation.cpp b/tests/cv/src/adetectordescriptor_evaluation.cpp index eb419da351..715c09cb6e 100644 --- a/tests/cv/src/adetectordescriptor_evaluation.cpp +++ b/tests/cv/src/adetectordescriptor_evaluation.cpp @@ -1461,6 +1461,7 @@ const string PRECISION = "precision"; const string KEYPOINTS_FILENAME = "keypointsFilename"; const string PROJECT_KEYPOINTS_FROM_1IMAGE = "projectKeypointsFrom1Image"; const string MATCH_FILTER = "matchFilter"; +const string RUN_PARAMS_IS_IDENTICAL = "runParamsIsIdentical"; const string ONE_WAY_TRAIN_DIR = "detectors_descriptors_evaluation/one_way_train_images/"; const string ONE_WAY_IMAGES_LIST = "one_way_train_images.txt"; @@ -1514,6 +1515,7 @@ protected: string keypontsFilename; bool projectKeypointsFrom1Image; int matchFilter; // not used now + bool runParamsIsIdentical; }; vector commRunParams; }; @@ -1565,6 +1567,7 @@ void DescriptorQualityTest::readDatasetRunParams( FileNode& fn, int datasetIdx ) commRunParams[datasetIdx].keypontsFilename = (string)fn[KEYPOINTS_FILENAME]; commRunParams[datasetIdx].projectKeypointsFrom1Image = (int)fn[PROJECT_KEYPOINTS_FROM_1IMAGE] != 0; commRunParams[datasetIdx].matchFilter = (int)fn[MATCH_FILTER]; + commRunParams[datasetIdx].runParamsIsIdentical = (int)fn[RUN_PARAMS_IS_IDENTICAL]; } void DescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int datasetIdx ) const @@ -1572,6 +1575,7 @@ void DescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int datasetI fs << KEYPOINTS_FILENAME << commRunParams[datasetIdx].keypontsFilename; fs << PROJECT_KEYPOINTS_FROM_1IMAGE << commRunParams[datasetIdx].projectKeypointsFrom1Image; fs << MATCH_FILTER << commRunParams[datasetIdx].matchFilter; + fs << RUN_PARAMS_IS_IDENTICAL << commRunParams[datasetIdx].runParamsIsIdentical; } void DescriptorQualityTest::setDefaultDatasetRunParams( int datasetIdx ) @@ -1579,6 +1583,7 @@ void DescriptorQualityTest::setDefaultDatasetRunParams( int datasetIdx ) commRunParams[datasetIdx].keypontsFilename = "surf_" + DATASET_NAMES[datasetIdx] + ".xml.gz"; commRunParams[datasetIdx].projectKeypointsFrom1Image = true; commRunParams[datasetIdx].matchFilter = NO_MATCH_FILTER; + commRunParams[datasetIdx].runParamsIsIdentical = true; } void DescriptorQualityTest::run( int ) @@ -1586,6 +1591,8 @@ void DescriptorQualityTest::run( int ) readAllDatasetsRunParams(); readResults(); + Ptr descMatch; + int notReadDatasets = 0; int progress = 0, progressCount = DATASETS_COUNT*TEST_CASE_COUNT; for(int di = 0; di < DATASETS_COUNT; di++ ) @@ -1608,6 +1615,12 @@ void DescriptorQualityTest::run( int ) vector keypoints1; vector ekeypoints1; readKeypoints( keypontsFS, keypoints1, 0); transformToEllipticKeyPoints( keypoints1, ekeypoints1 ); + + if (!commRunParams[di].runParamsIsIdentical) + { + descMatch = createDescriptorMatch (di); + } + for( int ci = 0; ci < TEST_CASE_COUNT; ci++ ) { progress = update_progress( progress, di*TEST_CASE_COUNT + ci, progressCount, 0 ); @@ -1624,7 +1637,6 @@ void DescriptorQualityTest::run( int ) readKeypoints( keypontsFS, keypoints2, ci+1 ); transformToEllipticKeyPoints( keypoints2, ekeypoints2 ); - Ptr descMatch = createDescriptorMatch(di); descMatch->add( imgs[ci+1], keypoints2 ); vector matches1to2; descMatch->match( imgs[0], keypoints1, matches1to2 ); @@ -1635,6 +1647,8 @@ void DescriptorQualityTest::run( int ) correctMatchCount, falseMatchCount, correspCount ); calcQuality[di][ci].recall = recall( correctMatchCount, correspCount ); calcQuality[di][ci].precision = precision( correctMatchCount, falseMatchCount ); + + descMatch->clear (); } } }