From f4788b364525d5ec80bbed0bd9c7f2a037ccc4aa Mon Sep 17 00:00:00 2001 From: Ilya Lysenkov Date: Fri, 4 Jun 2010 05:30:09 +0000 Subject: [PATCH] Added read/write methods in detectors and some descriptors for XML/YAML persistence --- .../include/opencv2/features2d/features2d.hpp | 81 ++++- modules/features2d/src/descriptors.cpp | 97 ++++- modules/features2d/src/detectors.cpp | 137 +++++++ modules/features2d/src/oneway.cpp | 397 +++++++++++++-------- 4 files changed, 560 insertions(+), 152 deletions(-) diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index aeddafb..7155b6b 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -316,6 +316,10 @@ public: vector& keypoints, Mat& descriptors, bool useProvidedKeypoints=false) const; + + CommonParams getCommonParams () const { return commParams; } + DetectorParams getDetectorParams () const { return detectorParams; } + DescriptorParams getDescriptorParams () const { return descriptorParams; } protected: CommonParams commParams; DetectorParams detectorParams; @@ -969,6 +973,12 @@ public: // - return value: 1 if succeeded, 0 otherwise int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name); + // ReadByName: reads a descriptor from a file node + // - parent: parent node + // - name: node name + // - return value: 1 if succeeded, 0 otherwise + int ReadByName(const FileNode &parent, const char* name); + // Write: writes a descriptor into a file storage // - fs: file storage // - name: node name @@ -1110,17 +1120,29 @@ 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); + // LoadPCADescriptors: loads PCA descriptors from a file // - filename: input filename int LoadPCADescriptors(const char* filename); + // LoadPCADescriptors: loads PCA descriptors from a file node + // - fn: input file node + int LoadPCADescriptors(const FileNode &fn); + // SavePCADescriptors: saves PCA descriptors to a file // - filename: output filename void SavePCADescriptors(const char* filename); // SavePCADescriptors: saves PCA descriptors to a file storage // - fs: output file storage - void SavePCADescriptors(CvFileStorage* fs); + void SavePCADescriptors(CvFileStorage* fs) const; // GeneratePCA: calculate and save PCA components and descriptors // - img_path: path to training PCA images directory @@ -1254,6 +1276,9 @@ public: detectImpl( image, mask, keypoints ); } + virtual void read (const FileNode& fn) {}; + virtual void write (FileStorage& fs) const {}; + protected: /* * Detect keypoints; detect() calls this. Must be implemented by the subclass. @@ -1272,7 +1297,10 @@ protected: class CV_EXPORTS FastFeatureDetector : public FeatureDetector { public: - FastFeatureDetector( int _threshold, bool _nonmaxSuppression = true ); + FastFeatureDetector( int _threshold = 1, bool _nonmaxSuppression = true ); + + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1287,6 +1315,10 @@ class CV_EXPORTS GoodFeaturesToTrackDetector : public FeatureDetector public: GoodFeaturesToTrackDetector( int _maxCorners, double _qualityLevel, double _minDistance, int _blockSize=3, bool _useHarrisDetector=false, double _k=0.04 ); + + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; + protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1301,8 +1333,13 @@ protected: class CV_EXPORTS MserFeatureDetector : public FeatureDetector { public: + MserFeatureDetector( CvMSERParams params = cvMSERParams () ); MserFeatureDetector( int delta, int minArea, int maxArea, float maxVariation, float minDiversity, int maxEvolution, double areaThreshold, double minMargin, int edgeBlurSize ); + + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; + protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1315,6 +1352,9 @@ public: StarFeatureDetector( int maxSize=16, int responseThreshold=30, int lineThresholdProjected = 10, int lineThresholdBinarized=8, int suppressNonmaxSize=5 ); + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; + protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1330,6 +1370,10 @@ public: int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS, int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE, int angleMode=SIFT::CommonParams::FIRST_ANGLE ); + + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; + protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1341,6 +1385,9 @@ class CV_EXPORTS SurfFeatureDetector : public FeatureDetector public: SurfFeatureDetector( double hessianThreshold = 400., int octaves = 3, int octaveLayers = 4 ); + virtual void read (const FileNode& fn); + virtual void write (FileStorage& fs) const; + protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1375,6 +1422,9 @@ public: */ virtual void compute( const Mat& image, vector& keypoints, Mat& descriptors ) const = 0; + virtual void read (const FileNode &fn) {}; + virtual void write (FileStorage &fs) const {}; + protected: /* * Remove keypoints within border_pixels of an image edge. @@ -1394,6 +1444,8 @@ public: int angleMode=SIFT::CommonParams::FIRST_ANGLE ); virtual void compute( const Mat& image, vector& keypoints, Mat& descriptors) const; + virtual void read (const FileNode &fn); + virtual void write (FileStorage &fs) const; protected: SIFT sift; @@ -1406,6 +1458,8 @@ public: int nOctaveLayers=2, bool extended=false ); virtual void compute( const Mat& image, vector& keypoints, Mat& descriptors) const; + virtual void read (const FileNode &fn); + virtual void write (FileStorage &fs) const; protected: SURF surf; @@ -1693,6 +1747,10 @@ public: // Clears keypoints storing in collection virtual void clear(); + + + virtual void read( const FileNode& fn ) {}; + virtual void write( FileStorage& fs ) const {}; protected: KeyPointCollection collection; }; @@ -1740,7 +1798,7 @@ public: virtual ~OneWayDescriptorMatch(); // Sets one way descriptor parameters - void initialize( const Params& _params ); + void initialize( const Params& _params, OneWayDescriptorBase *_base = 0 ); // Calculates one way descriptors for a set of keypoints virtual void add( const Mat& image, vector& keypoints ); @@ -1759,9 +1817,15 @@ 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 read (const FileNode &fn); + 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; }; @@ -1927,6 +1991,17 @@ public: matcher.clear(); } + virtual void read (const FileNode& fn) + { + GenericDescriptorMatch::read(fn); + extractor.read (fn); + } + + virtual void write (FileStorage& fs) const + { + GenericDescriptorMatch::write(fs); + extractor.write (fs); + } protected: Extractor extractor; Matcher matcher; diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index e8fd15f..e570f0e 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -91,6 +91,34 @@ void SiftDescriptorExtractor::compute( const Mat& image, sift(image, 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; +} + /****************************************************************************************\ * SurfDescriptorExtractor * \****************************************************************************************/ @@ -114,6 +142,24 @@ void SurfDescriptorExtractor::compute( const Mat& image, std::copy(_descriptors.begin(), _descriptors.end(), descriptors.begin()); } +void SurfDescriptorExtractor::read( const FileNode &fn ) +{ + int nOctaves = fn["nOctaves"]; + int nOctaveLayers = fn["nOctaveLayers"]; + bool extended = (int)fn["extended"] != 0; + + surf = SURF( 0.0, nOctaves, nOctaveLayers, extended ); +} + +void SurfDescriptorExtractor::write( FileStorage &fs ) const +{ +// fs << "algorithm" << getAlgorithmName (); + + fs << "nOctaves" << surf.nOctaves; + fs << "nOctaveLayers" << surf.nOctaveLayers; + fs << "extended" << surf.extended; +} + /****************************************************************************************\ * GenericDescriptorMatch * \****************************************************************************************/ @@ -194,18 +240,18 @@ OneWayDescriptorMatch::OneWayDescriptorMatch( const Params& _params) OneWayDescriptorMatch::~OneWayDescriptorMatch() {} -void OneWayDescriptorMatch::initialize( const Params& _params) +void OneWayDescriptorMatch::initialize( const Params& _params, OneWayDescriptorBase *_base) { base.release(); + if (_base != 0) + { + base = _base; + } params = _params; } 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 ); @@ -223,10 +269,6 @@ 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 ); @@ -262,6 +304,43 @@ 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); +} + +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; +} + void OneWayDescriptorMatch::classify( const Mat& image, vector& points ) { IplImage _image = image; diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index b2ab08a..7f0178e 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -75,6 +75,18 @@ FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppressio : threshold(_threshold), nonmaxSuppression(_nonmaxSuppression) {} +void FastFeatureDetector::read (const FileNode& fn) +{ + threshold = fn["threshold"]; + nonmaxSuppression = (int)fn["nonmaxSuppression"] ? true : false; +} + +void FastFeatureDetector::write (FileStorage& fs) const +{ + fs << "threshold" << threshold; + fs << "nonmaxSuppression" << nonmaxSuppression; +} + void FastFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints) const { FAST( image, keypoints, threshold, nonmaxSuppression ); @@ -91,6 +103,26 @@ GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector( int _maxCorners, doubl blockSize(_blockSize), useHarrisDetector(_useHarrisDetector), k(_k) {} +void GoodFeaturesToTrackDetector::read (const FileNode& fn) +{ + maxCorners = fn["maxCorners"]; + qualityLevel = fn["qualityLevel"]; + minDistance = fn["minDistance"]; + blockSize = fn["blockSize"]; + useHarrisDetector = (int) fn["useHarrisDetector"]; + k = fn["k"]; +} + +void GoodFeaturesToTrackDetector::write (FileStorage& fs) const +{ + fs << "maxCorners" << maxCorners; + fs << "qualityLevel" << qualityLevel; + fs << "minDistance" << minDistance; + fs << "blockSize" << blockSize; + fs << "useHarrisDetector" << useHarrisDetector; + fs << "k" << k; +} + void GoodFeaturesToTrackDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const { @@ -117,6 +149,43 @@ MserFeatureDetector::MserFeatureDetector( int delta, int minArea, int maxArea, maxEvolution, areaThreshold, minMargin, edgeBlurSize ) {} +MserFeatureDetector::MserFeatureDetector( CvMSERParams params ) + : mser( params.delta, params.minArea, params.maxArea, params.maxVariation, params.minDiversity, + params.maxEvolution, params.areaThreshold, params.minMargin, params.edgeBlurSize ) +{} + +void MserFeatureDetector::read (const FileNode& fn) +{ + int delta = fn["delta"]; + int minArea = fn["minArea"]; + int maxArea = fn["maxArea"]; + float maxVariation = fn["maxVariation"]; + float minDiversity = fn["minDiversity"]; + int maxEvolution = fn["maxEvolution"]; + double areaThreshold = fn["areaThreshold"]; + double minMargin = fn["minMargin"]; + int edgeBlurSize = fn["edgeBlurSize"]; + + mser = MSER( delta, minArea, maxArea, maxVariation, minDiversity, + maxEvolution, areaThreshold, minMargin, edgeBlurSize ); +} + +void MserFeatureDetector::write (FileStorage& fs) const +{ + //fs << "algorithm" << getAlgorithmName (); + + fs << "delta" << mser.delta; + fs << "minArea" << mser.minArea; + fs << "maxArea" << mser.maxArea; + fs << "maxVariation" << mser.maxVariation; + fs << "minDiversity" << mser.minDiversity; + fs << "maxEvolution" << mser.maxEvolution; + fs << "areaThreshold" << mser.areaThreshold; + fs << "minMargin" << mser.minMargin; + fs << "edgeBlurSize" << mser.edgeBlurSize; +} + + void MserFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const { vector > msers; @@ -144,6 +213,29 @@ StarFeatureDetector::StarFeatureDetector(int maxSize, int responseThreshold, lineThresholdBinarized, suppressNonmaxSize) {} +void StarFeatureDetector::read (const FileNode& fn) +{ + int maxSize = fn["maxSize"]; + int responseThreshold = fn["responseThreshold"]; + int lineThresholdProjected = fn["lineThresholdProjected"]; + int lineThresholdBinarized = fn["lineThresholdBinarized"]; + int suppressNonmaxSize = fn["suppressNonmaxSize"]; + + star = StarDetector( maxSize, responseThreshold, lineThresholdProjected, + lineThresholdBinarized, suppressNonmaxSize); +} + +void StarFeatureDetector::write (FileStorage& fs) const +{ + //fs << "algorithm" << getAlgorithmName (); + + fs << "maxSize" << star.maxSize; + fs << "responseThreshold" << star.responseThreshold; + fs << "lineThresholdProjected" << star.lineThresholdProjected; + fs << "lineThresholdBinarized" << star.lineThresholdBinarized; + fs << "suppressNonmaxSize" << star.suppressNonmaxSize; +} + void StarFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints) const { star(image, keypoints); @@ -159,6 +251,33 @@ SiftFeatureDetector::SiftFeatureDetector(double threshold, double edgeThreshold, { } +void SiftFeatureDetector::read (const FileNode& fn) +{ + double threshold = fn["threshold"]; + double edgeThreshold = fn["edgeThreshold"]; + int nOctaves = fn["nOctaves"]; + int nOctaveLayers = fn["nOctaveLayers"]; + int firstOctave = fn["firstOctave"]; + int angleMode = fn["angleMode"]; + + sift = SIFT(threshold, edgeThreshold, nOctaves, nOctaveLayers, firstOctave, angleMode); +} + +void SiftFeatureDetector::write (FileStorage& fs) const +{ + //fs << "algorithm" << getAlgorithmName (); + + SIFT::CommonParams commParams = sift.getCommonParams (); + SIFT::DetectorParams detectorParams = sift.getDetectorParams (); + fs << "threshold" << detectorParams.threshold; + fs << "edgeThreshold" << detectorParams.edgeThreshold; + fs << "nOctaves" << commParams.nOctaves; + fs << "nOctaveLayers" << commParams.nOctaveLayers; + fs << "firstOctave" << commParams.firstOctave; + fs << "angleMode" << commParams.angleMode; +} + + void SiftFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints) const { @@ -172,6 +291,24 @@ SurfFeatureDetector::SurfFeatureDetector( double hessianThreshold, int octaves, : surf(hessianThreshold, octaves, octaveLayers) {} +void SurfFeatureDetector::read (const FileNode& fn) +{ + double hessianThreshold = fn["hessianThreshold"]; + int octaves = fn["octaves"]; + int octaveLayers = fn["octaveLayers"]; + + surf = SURF( hessianThreshold, octaves, octaveLayers ); +} + +void SurfFeatureDetector::write (FileStorage& fs) const +{ + //fs << "algorithm" << getAlgorithmName (); + + fs << "hessianThreshold" << surf.hessianThreshold; + fs << "octaves" << surf.nOctaves; + fs << "octaveLayers" << surf.nOctaveLayers; +} + void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints) const { diff --git a/modules/features2d/src/oneway.cpp b/modules/features2d/src/oneway.cpp index 63a9532..630bf77 100644 --- a/modules/features2d/src/oneway.cpp +++ b/modules/features2d/src/oneway.cpp @@ -139,7 +139,8 @@ namespace cv{ }*/ } - void readPCAFeatures(const char* filename, CvMat** avg, CvMat** eigenvectors, const char *postfix = ""); + void readPCAFeatures(const char *filename, CvMat** avg, CvMat** eigenvectors, const char *postfix = ""); + void readPCAFeatures(const FileNode &fn, CvMat** avg, CvMat** eigenvectors, const char* postfix = ""); void savePCAFeatures(FileStorage &fs, const char* postfix, CvMat* avg, CvMat* eigenvectors); void calcPCAFeatures(vector& patches, FileStorage &fs, const char* postfix, CvMat** avg, CvMat** eigenvectors); @@ -692,9 +693,9 @@ namespace cv{ cvReleaseMat(&mat); } - int OneWayDescriptor::ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name) + int OneWayDescriptor::ReadByName(const FileNode &parent, const char* name) { - CvMat* mat = (CvMat*)cvReadByName(fs, parent, name); + CvMat* mat = reinterpret_cast (parent[name].readObj ()); if(!mat) { return 0; @@ -716,6 +717,11 @@ namespace cv{ cvReleaseMat(&mat); return 1; } + + int OneWayDescriptor::ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name) + { + return ReadByName (FileNode (fs, parent), name); + } IplImage* OneWayDescriptor::GetPatch(int index) { @@ -1216,6 +1222,10 @@ namespace cv{ 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) { +#if defined(_KDTREE) + m_pca_descriptors_matrix = 0; + m_pca_descriptors_tree = 0; +#endif // m_pca_descriptors_matrix = 0; m_patch_size = patch_size; m_pose_count = pose_count; @@ -1276,7 +1286,10 @@ namespace cv{ 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; +#if defined(_KDTREE) + m_pca_descriptors_matrix = 0; + m_pca_descriptors_tree = 0; +#endif m_patch_size = patch_size; m_pose_count = pose_count; m_pyr_levels = pyr_levels; @@ -1291,6 +1304,12 @@ namespace cv{ m_descriptors = 0; + + if (pca_filename.length() == 0) + { + return; + } + CvFileStorage* fs = cvOpenFileStorage(pca_filename.c_str(), NULL, CV_STORAGE_READ); if (fs != 0) { @@ -1312,7 +1331,27 @@ namespace cv{ LoadPCADescriptors(pca_default_filename); } } - + + void OneWayDescriptorBase::LoadPCAall (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"]; + + 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]; +#if !defined(_GH_REGIONS) + LoadPCADescriptors(fn); +#endif //_GH_REGIONS + } OneWayDescriptorBase::~OneWayDescriptorBase() { @@ -1327,34 +1366,50 @@ namespace cv{ } - delete []m_descriptors; - delete []m_poses; + if(m_descriptors) + delete []m_descriptors; + + if(m_poses) + delete []m_poses; - for(int i = 0; i < m_pose_count; i++) + if (m_transforms) { - cvReleaseMat(&m_transforms[i]); + for(int i = 0; i < m_pose_count; i++) + { + cvReleaseMat(&m_transforms[i]); + } + delete []m_transforms; } - delete []m_transforms; - #if defined(_KDTREE) - // if (m_pca_descriptors_matrix) - // delete m_pca_descriptors_matrix; - cvReleaseMat(&m_pca_descriptors_matrix); - delete m_pca_descriptors_tree; + if (m_pca_descriptors_matrix) + { + cvReleaseMat(&m_pca_descriptors_matrix); + } + if (m_pca_descriptors_tree) + { + delete m_pca_descriptors_tree; + } #endif } void OneWayDescriptorBase::clear(){ - delete []m_descriptors; - m_descriptors = 0; + if (m_descriptors) + { + 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; + if (m_pca_descriptors_matrix) + { + cvReleaseMat(&m_pca_descriptors_matrix); + m_pca_descriptors_matrix = 0; + } + if (m_pca_descriptors_tree) + { + delete m_pca_descriptors_tree; + m_pca_descriptors_tree = 0; + } #endif } @@ -1545,79 +1600,75 @@ namespace cv{ int OneWayDescriptorBase::LoadPCADescriptors(const char* filename) { - CvMemStorage* storage = cvCreateMemStorage(); - CvFileStorage* fs = cvOpenFileStorage(filename, storage, CV_STORAGE_READ); - if(!fs) + FileStorage fs = FileStorage (filename, FileStorage::READ); + if(!fs.isOpened ()) { - cvReleaseMemStorage(&storage); printf("File %s not found...\n", filename); return 0; } + + LoadPCADescriptors (fs.root ()); + + printf("Successfully read %d pca components\n", m_pca_dim_high); + fs.release (); + return 1; + } + + int OneWayDescriptorBase::LoadPCADescriptors(const FileNode &fn) + { // read affine poses - CvFileNode* node = cvGetFileNodeByName(fs, 0, "affine poses"); - if(node != 0) - { - CvMat* poses = (CvMat*)cvRead(fs, node); - //if(poses->rows != m_pose_count) - //{ - // printf("Inconsistency in the number of poses between the class instance and the file! Exiting...\n"); - // cvReleaseMat(&poses); - // cvReleaseFileStorage(&fs); - // cvReleaseMemStorage(&storage); - //} - - if(m_poses) - { - delete m_poses; - } - m_poses = new CvAffinePose[m_pose_count]; - for(int i = 0; i < m_pose_count; i++) - { - m_poses[i].phi = (float)cvmGet(poses, i, 0); - m_poses[i].theta = (float)cvmGet(poses, i, 1); - m_poses[i].lambda1 = (float)cvmGet(poses, i, 2); - m_poses[i].lambda2 = (float)cvmGet(poses, i, 3); - } - cvReleaseMat(&poses); - - // now initialize pose transforms - InitializeTransformsFromPoses(); +// FileNode* node = cvGetFileNodeByName(fs, 0, "affine poses"); + CvMat* poses = reinterpret_cast (fn["affine_poses"].readObj ()); + if (poses == 0) + { + poses = reinterpret_cast (fn["affine poses"].readObj ()); + if (poses == 0) + return 0; } - else + + + if(m_poses) { - printf("Node \"affine poses\" not found...\n"); + delete m_poses; } - - node = cvGetFileNodeByName(fs, 0, "pca components number"); - if(node != 0) + m_poses = new CvAffinePose[m_pose_count]; + for(int i = 0; i < m_pose_count; i++) { - - m_pca_dim_high = cvReadInt(node); - if(m_pca_descriptors) - { - delete []m_pca_descriptors; - } - AllocatePCADescriptors(); - for(int i = 0; i < m_pca_dim_high + 1; i++) + m_poses[i].phi = (float)cvmGet(poses, i, 0); + m_poses[i].theta = (float)cvmGet(poses, i, 1); + m_poses[i].lambda1 = (float)cvmGet(poses, i, 2); + m_poses[i].lambda2 = (float)cvmGet(poses, i, 3); + } + cvReleaseMat(&poses); + + // now initialize pose transforms + InitializeTransformsFromPoses(); + + m_pca_dim_high = (int) fn["pca_components_number"]; + if (m_pca_dim_high == 0) + { + m_pca_dim_high = (int) fn["pca components number"]; + } + if(m_pca_descriptors) + { + delete []m_pca_descriptors; + } + AllocatePCADescriptors(); + for(int i = 0; i < m_pca_dim_high + 1; i++) + { + m_pca_descriptors[i].Allocate(m_pose_count, m_patch_size, 1); + m_pca_descriptors[i].SetTransforms(m_poses, m_transforms); + char buf[1024]; + sprintf(buf, "descriptor_for_pca_component_%d", i); + + if (! m_pca_descriptors[i].ReadByName(fn, buf)) { - m_pca_descriptors[i].Allocate(m_pose_count, m_patch_size, 1); - m_pca_descriptors[i].SetTransforms(m_poses, m_transforms); char buf[1024]; sprintf(buf, "descriptor for pca component %d", i); - m_pca_descriptors[i].ReadByName(fs, 0, buf); + m_pca_descriptors[i].ReadByName(fn, buf); } } - else - { - printf("Node \"pca components number\" not found...\n"); - } - - cvReleaseFileStorage(&fs); - cvReleaseMemStorage(&storage); - - printf("Successfully read %d pca components\n", m_pca_dim_high); - return 1; } @@ -1668,6 +1719,50 @@ namespace cv{ cvReleaseMat(&eigenvalues); } + void extractPatches (IplImage *img, vector& patches, CvSize patch_size) + { + vector features; + SURF surf_extractor(1.0f); + //printf("Extracting SURF features..."); + surf_extractor(img, Mat(), features); + //printf("done\n"); + + for (int j = 0; j < (int)features.size(); j++) + { + int patch_width = patch_size.width; + int patch_height = patch_size.height; + + CvPoint center = features[j].pt; + + CvRect roi = cvRect(center.x - patch_width / 2, center.y - patch_height / 2, patch_width, patch_height); + cvSetImageROI(img, roi); + roi = cvGetImageROI(img); + if (roi.width != patch_width || roi.height != patch_height) + { + continue; + } + + IplImage* patch = cvCreateImage(cvSize(patch_width, patch_height), IPL_DEPTH_8U, 1); + cvCopy(img, patch); + patches.push_back(patch); + cvResetImageROI(img); + } + //printf("Completed file, extracted %d features\n", (int)features.size()); + } + +/* + void loadPCAFeatures(const FileNode &fn, vector& patches, CvSize patch_size) + { + FileNodeIterator begin = fn.begin(); + for (FileNodeIterator i = fn.begin(); i != fn.end(); i++) + { + IplImage *img = reinterpret_cast ((*i).readObj()); + extractPatches (img, patches, patch_size); + cvReleaseImage(&img); + } + } +*/ + void loadPCAFeatures(const char* path, const char* images_list, vector& patches, CvSize patch_size) { char images_filename[1024]; @@ -1693,35 +1788,7 @@ namespace cv{ IplImage* img = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE); //printf("done\n"); - vector features; - SURF surf_extractor(1.0f); - //printf("Extracting SURF features..."); - surf_extractor(img, Mat(), features); - //printf("done\n"); - - for (int j = 0; j < (int)features.size(); j++) - { - int patch_width = patch_size.width; - int patch_height = patch_size.height; - - CvPoint center = features[j].pt; - - CvRect roi = cvRect(center.x - patch_width / 2, center.y - patch_height / 2, patch_width, patch_height); - cvSetImageROI(img, roi); - roi = cvGetImageROI(img); - if (roi.width != patch_width || roi.height != patch_height) - { - continue; - } - - IplImage* patch = cvCreateImage(cvSize(patch_width, patch_height), IPL_DEPTH_8U, 1); - cvCopy(img, patch); - patches.push_back(patch); - cvResetImageROI(img); - - } - - //printf("Completed file, extracted %d features\n", (int)features.size()); + extractPatches (img, patches, patch_size); cvReleaseImage(&img); } @@ -1736,6 +1803,35 @@ namespace cv{ calcPCAFeatures(patches, fs, postfix, avg, eigenvectors); } +/* + void generatePCAFeatures(const FileNode &fn, const char* postfix, + CvSize patch_size, CvMat** avg, CvMat** eigenvectors) + { + vector patches; + loadPCAFeatures(fn, patches, patch_size); + calcPCAFeatures(patches, fs, postfix, avg, eigenvectors); + } + + + void OneWayDescriptorBase::GeneratePCA(const FileNode &fn, int pose_count) + { + generatePCAFeatures(fn, "hr", m_patch_size, &m_pca_hr_avg, &m_pca_hr_eigenvectors); + generatePCAFeatures(fn, "lr", cvSize(m_patch_size.width / 2, m_patch_size.height / 2), + &m_pca_avg, &m_pca_eigenvectors); + + + 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); + + printf("Calculating %d PCA descriptors (you can grab a coffee, this will take a while)...\n", + descriptors.GetPCADimHigh()); + descriptors.InitializePoseTransforms(); + descriptors.CreatePCADescriptors(); + descriptors.SavePCADescriptors(*fs); + } +*/ + void OneWayDescriptorBase::GeneratePCA(const char* img_path, const char* images_list, int pose_count) { char pca_filename[1024]; @@ -1759,26 +1855,42 @@ namespace cv{ fs.release(); } + void OneWayDescriptorBase::SavePCAall (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; + + savePCAFeatures(fs, "hr", m_pca_hr_avg, m_pca_hr_eigenvectors); + savePCAFeatures(fs, "lr", m_pca_avg, m_pca_eigenvectors); + SavePCADescriptors(*fs); + } + void OneWayDescriptorBase::SavePCADescriptors(const char* filename) { CvMemStorage* storage = cvCreateMemStorage(); CvFileStorage* fs = cvOpenFileStorage(filename, storage, CV_STORAGE_WRITE); - - SavePCADescriptors (fs); - + + SavePCADescriptors (fs); + cvReleaseMemStorage(&storage); cvReleaseFileStorage(&fs); } - void OneWayDescriptorBase::SavePCADescriptors(CvFileStorage *fs) + void OneWayDescriptorBase::SavePCADescriptors(CvFileStorage *fs) const { - cvWriteInt(fs, "pca components number", m_pca_dim_high); + cvWriteInt(fs, "pca_components_number", m_pca_dim_high); cvWriteComment( fs, "The first component is the average Vector, so the total number of components is + 1", 0); - cvWriteInt(fs, "patch width", m_patch_size.width); - cvWriteInt(fs, "patch height", m_patch_size.height); + cvWriteInt(fs, "patch_width", m_patch_size.width); + cvWriteInt(fs, "patch_height", m_patch_size.height); // pack the affine transforms into a single CvMat and write them CvMat* poses = cvCreateMat(m_pose_count, 4, CV_32FC1); @@ -1789,13 +1901,13 @@ namespace cv{ cvmSet(poses, i, 2, m_poses[i].lambda1); cvmSet(poses, i, 3, m_poses[i].lambda2); } - cvWrite(fs, "affine poses", poses); + cvWrite(fs, "affine_poses", poses); cvReleaseMat(&poses); for (int i = 0; i < m_pca_dim_high + 1; i++) { char buf[1024]; - sprintf(buf, "descriptor for pca component %d", i); + sprintf(buf, "descriptor_for_pca_component_%d", i); m_pca_descriptors[i].Write(fs, buf); } } @@ -1950,7 +2062,8 @@ namespace cv{ OneWayDescriptorObject::~OneWayDescriptorObject() { - delete []m_part_id; + if (m_part_id) + delete []m_part_id; } vector OneWayDescriptorObject::_GetLabeledFeatures() const @@ -1990,31 +2103,35 @@ namespace cv{ } } } - + void readPCAFeatures(const char* filename, CvMat** avg, CvMat** eigenvectors, const char* postfix) { - CvMemStorage* storage = cvCreateMemStorage(); - CvFileStorage* fs = cvOpenFileStorage(filename, storage, CV_STORAGE_READ); - if (!fs) + FileStorage fs = FileStorage(filename, FileStorage::READ); + if (!fs.isOpened ()) { printf("Cannot open file %s! Exiting!", filename); - cvReleaseMemStorage(&storage); } - char buf[1024]; - sprintf(buf, "avg%s", postfix); - CvFileNode* node = cvGetFileNodeByName(fs, 0, buf); - CvMat* _avg = (CvMat*)cvRead(fs, node); - sprintf(buf, "eigenvectors%s", postfix); - node = cvGetFileNodeByName(fs, 0, buf); - CvMat* _eigenvectors = (CvMat*)cvRead(fs, node); - - *avg = cvCloneMat(_avg); - *eigenvectors = cvCloneMat(_eigenvectors); - - cvReleaseMat(&_avg); - cvReleaseMat(&_eigenvectors); - cvReleaseFileStorage(&fs); - cvReleaseMemStorage(&storage); + readPCAFeatures (fs.root (), avg, eigenvectors, postfix); + fs.release (); + } + + void readPCAFeatures(const FileNode &fn, CvMat** avg, CvMat** eigenvectors, const char* postfix) + { + std::string str = std::string ("avg") + postfix; + CvMat* _avg = reinterpret_cast (fn[str].readObj()); + if (_avg != 0) + { + *avg = cvCloneMat(_avg); + cvReleaseMat(&_avg); + } + + str = std::string ("eigenvectors") + postfix; + CvMat* _eigenvectors = reinterpret_cast (fn[str].readObj()); + if (_eigenvectors != 0) + { + *eigenvectors = cvCloneMat(_eigenvectors); + cvReleaseMat(&_eigenvectors); + } } } -- 2.7.4