diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index 7155b6b8f9..02f17c2542 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1120,13 +1120,13 @@ public: void InitializeDescriptors(IplImage* train_image, const vector& features, const char* feature_label = "", int desc_start_idx = 0); - // SavePCAall: saves PCA components and descriptors to a file storage - // - fs: output file storage - void SavePCAall (FileStorage &fs) const; - - // LoadPCAall: loads PCA components and descriptors from a file node - // - fn: input file node - void LoadPCAall (const FileNode &fn); + // Write: writes this object to a file storage + // - fs: output filestorage + void Write (FileStorage &fs) const; + + // Read: reads OneWayDescriptorBase object from a file node + // - fn: input file node + void Read (const FileNode &fn); // LoadPCADescriptors: loads PCA descriptors from a file // - filename: input filename @@ -1191,9 +1191,17 @@ protected: int m_pca_dim_low; int m_pyr_levels; - const float scale_min; - const float scale_max; - const float scale_step; + float scale_min; + float scale_max; + float scale_step; + + // SavePCAall: saves PCA components and descriptors to a file storage + // - fs: output file storage + void SavePCAall (FileStorage &fs) const; + + // LoadPCAall: loads PCA components and descriptors from a file node + // - fn: input file node + void LoadPCAall (const FileNode &fn); }; class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase @@ -1748,9 +1756,12 @@ public: // Clears keypoints storing in collection virtual void clear(); - + // Reads match object from a file node virtual void read( const FileNode& fn ) {}; + + // Writes match object to a file storage virtual void write( FileStorage& fs ) const {}; + protected: KeyPointCollection collection; }; @@ -1817,15 +1828,16 @@ 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 ); + // Clears keypoints storing in collection and OneWayDescriptorBase + virtual void clear (); + + // Reads match object from a file node virtual void read (const FileNode &fn); + + // Writes match object to a file storage virtual void write (FileStorage& fs) const; - Params getParams () const {return params;} - - virtual void clear (); protected: - void readParams (const FileNode &fn); - void writeParams (FileStorage& fs) const; Ptr base; Params params; }; @@ -1882,6 +1894,12 @@ public: virtual void classify( const Mat& image, vector& keypoints ); + virtual void clear (); + + virtual void read( const FileNode &fn ); + + virtual void write( FileStorage& fs ) const; + protected: void trainRTreeClassifier(); Mat extractPatch( const Mat& image, const Point& pt, int patchSize ) const; @@ -1937,6 +1955,12 @@ public: virtual void classify( const Mat& image, vector& keypoints ); + virtual void clear (); + + virtual void read( const FileNode &fn ); + + virtual void write( FileStorage& fs ) const; + protected: void trainFernClassifier(); void calcBestProbAndMatchIdx( const Mat& image, const Point2f& pt, diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index dbb7a41c3f..a936787774 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -252,6 +252,10 @@ void OneWayDescriptorMatch::initialize( const Params& _params, OneWayDescriptorB 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.minScale, params.maxScale, params.stepScale); + size_t trainFeatureCount = keypoints.size(); base->Allocate( trainFeatureCount ); @@ -269,6 +273,10 @@ void OneWayDescriptorMatch::add( const Mat& image, vector& keypoints ) void OneWayDescriptorMatch::add( KeyPointCollection& keypoints ) { + if( base.empty() ) + base = new OneWayDescriptorObject( params.patchSize, params.poseCount, params.pcaFilename, + params.trainPath, params.trainImagesList, params.minScale, params.maxScale, params.stepScale); + size_t trainFeatureCount = keypoints.calcKeypointCount(); base->Allocate( trainFeatureCount ); @@ -306,39 +314,15 @@ void OneWayDescriptorMatch::match( const Mat& image, vector& points, v void OneWayDescriptorMatch::read( const FileNode &fn ) { - readParams (fn); - base = new OneWayDescriptorObject( params.patchSize, params.poseCount, string (), string (), string (), params.minScale, params.maxScale, params.stepScale ); - base->LoadPCAall (fn); + base->Read (fn); } -void OneWayDescriptorMatch::readParams ( const FileNode &fn ) -{ - params.poseCount = fn["poseCount"]; - int patchWidth = fn["patchWidth"]; - int patchHeight = fn["patchHeight"]; - params.patchSize = Size(patchWidth, patchHeight); - params.minScale = fn["minScale"]; - params.maxScale = fn["maxScale"]; - params.stepScale = fn["stepScale"]; -} void OneWayDescriptorMatch::write( FileStorage& fs ) const { -// fs << "algorithm" << getAlgorithmName (); - writeParams (fs); - base->SavePCAall (fs); -} - -void OneWayDescriptorMatch::writeParams( FileStorage& fs ) const -{ - fs << "poseCount" << params.poseCount; - fs << "patchWidth" << params.patchSize.width; - fs << "patchHeight" << params.patchSize.height; - fs << "minScale" << params.minScale; - fs << "maxScale" << params.maxScale; - fs << "stepScale" << params.stepScale; + base->Write (fs); } void OneWayDescriptorMatch::classify( const Mat& image, vector& points ) @@ -484,6 +468,34 @@ void CalonderDescriptorMatch::classify( const Mat& image, vector& keyp } } +void CalonderDescriptorMatch::clear () +{ + GenericDescriptorMatch::clear(); + classifier.release(); +} + +void CalonderDescriptorMatch::read( const FileNode &fn ) +{ + params.numTrees = fn["numTrees"]; + params.depth = fn["depth"]; + params.views = fn["views"]; + params.patchSize = fn["patchSize"]; + params.reducedNumDim = (int) fn["reducedNumDim"]; + params.numQuantBits = fn["numQuantBits"]; + params.printStatus = (int) fn["printStatus"]; +} + +void CalonderDescriptorMatch::write( FileStorage& fs ) const +{ + fs << "numTrees" << params.numTrees; + fs << "depth" << params.depth; + fs << "views" << params.views; + fs << "patchSize" << params.patchSize; + fs << "reducedNumDim" << (int) params.reducedNumDim; + fs << "numQuantBits" << params.numQuantBits; + fs << "printStatus" << params.printStatus; +} + /****************************************************************************************\ * FernDescriptorMatch * \****************************************************************************************/ @@ -597,3 +609,35 @@ void FernDescriptorMatch::classify( const Mat& image, vector& keypoint keypoints[pi].class_id = collection.getKeyPoint(bestMatchIdx).class_id; } } + +void FernDescriptorMatch::read( const FileNode &fn ) +{ + params.nclasses = fn["nclasses"]; + params.patchSize = fn["patchSize"]; + params.signatureSize = fn["signatureSize"]; + params.nstructs = fn["nstructs"]; + params.structSize = fn["structSize"]; + params.nviews = fn["nviews"]; + params.compressionMethod = fn["compressionMethod"]; + + //classifier->read(fn); +} + +void FernDescriptorMatch::write( FileStorage& fs ) const +{ + fs << "nclasses" << params.nclasses; + fs << "patchSize" << params.patchSize; + fs << "signatureSize" << params.signatureSize; + fs << "nstructs" << params.nstructs; + fs << "structSize" << params.structSize; + fs << "nviews" << params.nviews; + fs << "compressionMethod" << params.compressionMethod; + +// classifier->write(fs); +} + +void FernDescriptorMatch::clear () +{ + GenericDescriptorMatch::clear(); + classifier.release(); +} diff --git a/modules/features2d/src/oneway.cpp b/modules/features2d/src/oneway.cpp index 630bf77b29..97c401adf9 100644 --- a/modules/features2d/src/oneway.cpp +++ b/modules/features2d/src/oneway.cpp @@ -1332,19 +1332,26 @@ namespace cv{ } } - void OneWayDescriptorBase::LoadPCAall (const FileNode &fn) + void OneWayDescriptorBase::Read (const FileNode &fn) { -// m_pose_count = fn["pose_count"]; -// int patch_width = fn["patch_width"]; -// int patch_height = fn["patch_height"]; -// m_patch_size = cvSize (patch_width, patch_height); -// m_pyr_levels = fn["pyr_levels"]; -// m_pca_dim_high = fn["pca_dim_high"]; -// m_pca_dim_low = fn["pca_dim_low"]; -// scale_min = fn["scale_min"]; -// scale_max = fn["scale_max"]; -// scale_step = fn["scale_step"]; + clear (); + + m_pose_count = fn["poseCount"]; + int patch_width = fn["patchWidth"]; + int patch_height = fn["patchHeight"]; + m_patch_size = cvSize (patch_width, patch_height); + m_pyr_levels = fn["pyrLevels"]; + m_pca_dim_high = fn["pcaDimHigh"]; + m_pca_dim_low = fn["pcaDimLow"]; + scale_min = fn["minScale"]; + scale_max = fn["maxScale"]; + scale_step = fn["stepScale"]; + + LoadPCAall (fn); + } + void OneWayDescriptorBase::LoadPCAall (const FileNode &fn) + { readPCAFeatures(fn, &m_pca_avg, &m_pca_eigenvectors, "_lr"); readPCAFeatures(fn, &m_pca_hr_avg, &m_pca_hr_eigenvectors, "_hr"); m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1]; @@ -1855,17 +1862,23 @@ namespace cv{ fs.release(); } - void OneWayDescriptorBase::SavePCAall (FileStorage &fs) const + void OneWayDescriptorBase::Write (FileStorage &fs) const { -// fs << "pose_count" << m_pose_count; -// fs << "patch_width" << m_patch_size.width; -// fs << "patch_height" << m_patch_size.height; -// fs << "scale_min" << scale_min; -// fs << "scale_max" << scale_max; -// fs << "scale_step" << scale_step; -// fs << "pyr_levels" << m_pyr_levels; -// fs << "pca_dim_low" << m_pca_dim_low; + fs << "poseCount" << m_pose_count; + fs << "patchWidth" << m_patch_size.width; + fs << "patchHeight" << m_patch_size.height; + fs << "minScale" << scale_min; + fs << "maxScale" << scale_max; + fs << "stepScale" << scale_step; + fs << "pyrLevels" << m_pyr_levels; + fs << "pcaDimHigh" << m_pca_dim_high; + fs << "pcaDimLow" << m_pca_dim_low; + + SavePCAall (fs); + } + void OneWayDescriptorBase::SavePCAall (FileStorage &fs) const + { savePCAFeatures(fs, "hr", m_pca_hr_avg, m_pca_hr_eigenvectors); savePCAFeatures(fs, "lr", m_pca_avg, m_pca_eigenvectors); SavePCADescriptors(*fs); diff --git a/tests/cv/src/adetectordescriptor_evaluation.cpp b/tests/cv/src/adetectordescriptor_evaluation.cpp index 9755b49368..16d1223597 100644 --- a/tests/cv/src/adetectordescriptor_evaluation.cpp +++ b/tests/cv/src/adetectordescriptor_evaluation.cpp @@ -1431,6 +1431,27 @@ void DescriptorQualityTest::readAlgorithm( ) defaultDescMatch = new OneWayDescriptorMatch (); specificDescMatch = new OneWayDescriptorMatch (); } + else if (! algName.compare ("fern")) + { + FernDescriptorMatch::Params params; + params.nviews = 50; + params.signatureSize = 80; + params.nstructs = 20; + defaultDescMatch = new FernDescriptorMatch (params); + specificDescMatch = new FernDescriptorMatch (); + } + else if (! algName.compare ("calonder")) + { + CalonderDescriptorMatch::Params params; + params.numTrees = 20; + params.depth = 7; + params.views = 100; + params.reducedNumDim = 100; + params.patchSize = 20; + + defaultDescMatch = new CalonderDescriptorMatch (params); + specificDescMatch = new CalonderDescriptorMatch (); + } else { ts->printf(CvTS::LOG, "Algorithm can not be read\n"); @@ -1528,12 +1549,13 @@ void OneWayDescriptorQualityTest::processRunParamsFile () FileNode fn = fs.getFirstTopLevelNode(); fn = fn[DEFAULT_PARAMS]; - OneWayDescriptorMatch *match = new OneWayDescriptorMatch (); - match->read (fn); - string pcaFilename = string(ts->get_data_path()) + (string)fn["pcaFilename"]; string trainPath = string(ts->get_data_path()) + (string)fn["trainPath"]; string trainImagesList = (string)fn["trainImagesList"]; + int patch_width = fn["patchWidth"]; + int patch_height = fn["patchHeight"]; + Size patchSize = cvSize (patch_width, patch_height); + int poseCount = fn["poseCount"]; if (trainImagesList.length () == 0 ) { @@ -1544,11 +1566,11 @@ void OneWayDescriptorQualityTest::processRunParamsFile () readAllDatasetsRunParams(); - OneWayDescriptorBase *base = new OneWayDescriptorBase(match->getParams().patchSize, match->getParams().poseCount, pcaFilename, + OneWayDescriptorBase *base = new OneWayDescriptorBase(patchSize, poseCount, pcaFilename, trainPath, trainImagesList); - match->initialize( match->getParams(), base ); - + OneWayDescriptorMatch *match = new OneWayDescriptorMatch (); + match->initialize( OneWayDescriptorMatch::Params (), base ); defaultDescMatch = match; writeAllDatasetsRunParams(); } @@ -1563,3 +1585,6 @@ void OneWayDescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int da OneWayDescriptorQualityTest oneWayDescriptorQuality; + +DescriptorQualityTest fernDescriptorQualityTest( "fern", "quality-descriptor-fern"); +DescriptorQualityTest calonderDescriptorQualityTest( "calonder", "quality-descriptor-calonder");