From 81cb7b2c5e04ba6597d09e309130bf566c87b805 Mon Sep 17 00:00:00 2001
From: Maria Dimashova <no@email>
Date: Wed, 10 Aug 2011 09:17:37 +0000
Subject: [PATCH] added read/write methods for SimpleBlobDetector and
 DenseFeatureDetector; added their creation to FeatureDetector::create method
 (#1290)

---
 .../include/opencv2/features2d/features2d.hpp | 12 +++-
 modules/features2d/src/blobdetector.cpp       | 68 +++++++++++++++++++
 modules/features2d/src/detectors.cpp          | 44 ++++++++++++
 3 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp
index 8ffae6180..b7281f8b6 100644
--- a/modules/features2d/include/opencv2/features2d/features2d.hpp
+++ b/modules/features2d/include/opencv2/features2d/features2d.hpp
@@ -1583,10 +1583,16 @@ public:
 
       bool filterByConvexity;
       float minConvexity, maxConvexity;
+
+      void read( const FileNode& fn );
+      void write( FileStorage& fs ) const;
   };
 
   SimpleBlobDetector(const SimpleBlobDetector::Params &parameters = SimpleBlobDetector::Params());
 
+  virtual void read( const FileNode& fn );
+  virtual void write( FileStorage& fs ) const;
+
 protected:
   struct CV_EXPORTS Center
   {
@@ -1618,11 +1624,15 @@ public:
 
         bool varyXyStepWithScale;
         bool varyImgBoundWithScale;
+
+        void read( const FileNode& fn );
+        void write( FileStorage& fs ) const;
     };
 
     DenseFeatureDetector( const DenseFeatureDetector::Params& params=DenseFeatureDetector::Params() );
     
-	// TODO implement read/write
+    virtual void read( const FileNode& fn );
+    virtual void write( FileStorage& fs ) const;
 
 protected:
     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp
index 124250754..4fa920787 100644
--- a/modules/features2d/src/blobdetector.cpp
+++ b/modules/features2d/src/blobdetector.cpp
@@ -84,11 +84,79 @@ SimpleBlobDetector::Params::Params()
 	maxConvexity = std::numeric_limits<float>::max();
 }
 
+void SimpleBlobDetector::Params::read(const cv::FileNode& fn )
+{
+    thresholdStep = fn["thresholdStep"];
+    minThreshold = fn["minThreshold"];
+    maxThreshold = fn["maxThreshold"];
+
+    minRepeatability = (size_t)(int)fn["minRepeatability"];
+    minDistBetweenBlobs = fn["minDistBetweenBlobs"];
+
+    filterByColor = (int)fn["filterByColor"] != 0 ? true : false;
+    blobColor = (uchar)(int)fn["blobColor"];
+
+    filterByArea = (int)fn["filterByArea"] != 0 ? true : false;
+    minArea = fn["minArea"];
+    maxArea = fn["maxArea"];
+
+    filterByCircularity = (int)fn["filterByCircularity"] != 0 ? true : false;
+    minCircularity = fn["minCircularity"];
+    maxCircularity = fn["maxCircularity"];
+
+    filterByInertia = (int)fn["filterByInertia"] != 0 ? true : false;
+    minInertiaRatio = fn["minInertiaRatio"];
+    maxInertiaRatio = fn["maxInertiaRatio"];
+
+    filterByConvexity = (int)fn["filterByConvexity"] != 0 ? true : false;
+    minConvexity = fn["minConvexity"];
+    maxConvexity = fn["maxConvexity"];
+}
+
+void SimpleBlobDetector::Params::write(cv::FileStorage& fs) const
+{
+    fs << "thresholdStep" << thresholdStep;
+    fs << "minThreshold" << minThreshold;
+    fs << "maxThreshold" << maxThreshold;
+
+    fs << "minRepeatability" << (int)minRepeatability;
+    fs << "minDistBetweenBlobs" << minDistBetweenBlobs;
+
+    fs << "filterByColor" << (int)filterByColor;
+    fs << "blobColor" << (int)blobColor;
+
+    fs << "filterByArea" << (int)filterByArea;
+    fs << "minArea" << minArea;
+    fs << "maxArea" << maxArea;
+
+    fs << "filterByCircularity" << (int)filterByCircularity;
+    fs << "minCircularity" << minCircularity;
+    fs << "maxCircularity" << maxCircularity;
+
+    fs << "filterByInertia" << (int)filterByInertia;
+    fs << "minInertiaRatio" << minInertiaRatio;
+    fs << "maxInertiaRatio" << maxInertiaRatio;
+
+    fs << "filterByConvexity" << (int)filterByConvexity;
+    fs << "minConvexity" << minConvexity;
+    fs << "maxConvexity" << maxConvexity;
+}
+
 SimpleBlobDetector::SimpleBlobDetector(const SimpleBlobDetector::Params &parameters) :
 params(parameters)
 {
 }
 
+void SimpleBlobDetector::read( const cv::FileNode& fn )
+{
+    params.read(fn);
+}
+
+void SimpleBlobDetector::write( cv::FileStorage& fs ) const
+{
+    params.write(fs);
+}
+
 void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, vector<Center> &centers) const
 {
 	(void)image;
diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp
index 120068122..80438f2c3 100644
--- a/modules/features2d/src/detectors.cpp
+++ b/modules/features2d/src/detectors.cpp
@@ -126,6 +126,14 @@ Ptr<FeatureDetector> FeatureDetector::create( const string& detectorType )
         params.useHarrisDetector = true;
         fd = new GoodFeaturesToTrackDetector(params);
     }
+    else if( !detectorType.compare( "Dense" ) )
+    {
+        fd = new DenseFeatureDetector();
+    }
+    else if( !detectorType.compare( "SimpleBlob" ) )
+    {
+        fd = new SimpleBlobDetector();
+    }
     else if( (pos=detectorType.find("Grid")) == 0 )
     {
         pos += string("Grid").size();
@@ -499,9 +507,45 @@ DenseFeatureDetector::Params::Params( float _initFeatureScale, int _featureScale
 	varyXyStepWithScale(_varyXyStepWithScale), varyImgBoundWithScale(_varyImgBoundWithScale)
 {}
 
+void DenseFeatureDetector::Params::read( const FileNode& fn )
+{
+    initFeatureScale = fn["initFeatureScale"];
+    featureScaleLevels = fn["featureScaleLevels"];
+    featureScaleMul = fn["featureScaleMul"];
+
+    initXyStep = fn["initXyStep"];
+    initImgBound = fn["initImgBound"];
+
+    varyXyStepWithScale = (int)fn["varyXyStepWithScale"] != 0 ? true : false;
+    varyImgBoundWithScale = (int)fn["varyImgBoundWithScale"] != 0 ? true : false;
+}
+
+void DenseFeatureDetector::Params::write( FileStorage& fs ) const
+{
+    fs << "initFeatureScale" << initFeatureScale;
+    fs << "featureScaleLevels" << featureScaleLevels;
+    fs << "featureScaleMul" << featureScaleMul;
+
+    fs << "initXyStep" << initXyStep;
+    fs << "initImgBound" << initImgBound;
+
+    fs << "varyXyStepWithScale" << (int)varyXyStepWithScale;
+    fs << "varyImgBoundWithScale" << (int)varyImgBoundWithScale;
+}
+
 DenseFeatureDetector::DenseFeatureDetector(const DenseFeatureDetector::Params &_params) : params(_params)
 {}
 
+void DenseFeatureDetector::read( const FileNode &fn )
+{
+    params.read(fn);
+}
+
+void DenseFeatureDetector::write( FileStorage &fs ) const
+{
+    params.write(fs);
+}
+
 void DenseFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
 {
     float curScale = params.initFeatureScale;