Commit edfce723 for tesseract

commit edfce723409e8778d769892f03eae8ad92d94fe7
Author: Egor Pugin <egor.pugin@gmail.com>
Date:   Wed Apr 7 17:29:46 2021 +0300

    Refactor microfeatures a bit.

diff --git a/src/classify/mf.cpp b/src/classify/mf.cpp
index ac7e14bb..2570fdb6 100644
--- a/src/classify/mf.cpp
+++ b/src/classify/mf.cpp
@@ -51,14 +51,11 @@ FEATURE_SET ExtractMicros(TBLOB *Blob, const DENORM &cn_denorm) {

   for (auto &f : features) {
     auto Feature = new FEATURE_STRUCT(&MicroFeatureDesc);
-    Feature->Params[MFDirection] = f[ORIENTATION];
-    Feature->Params[MFXPosition] = f[XPOSITION];
-    Feature->Params[MFYPosition] = f[YPOSITION];
-    Feature->Params[MFLength] = f[MFLENGTH];
-
-    // Bulge features are deprecated and should not be used.  Set to 0.
-    Feature->Params[MFBulge1] = 0.0f;
-    Feature->Params[MFBulge2] = 0.0f;
+    for (int i = 0; i < (int)MicroFeatureParameter::MFCount; ++i)
+      Feature->Params[i] = f[i];
+    // Bulge features are deprecated and should not be used. Set to 0.
+    Feature->Params[(int)MicroFeatureParameter::MFBulge1] = 0.0f;
+    Feature->Params[(int)MicroFeatureParameter::MFBulge2] = 0.0f;

 #ifndef _WIN32
     // Assert that feature parameters are well defined.
diff --git a/src/classify/mf.h b/src/classify/mf.h
index 0eb5780e..b5a2fd82 100644
--- a/src/classify/mf.h
+++ b/src/classify/mf.h
@@ -23,20 +23,6 @@

 namespace tesseract {

-typedef enum {
-  MFXPosition,
-  MFYPosition,
-  MFLength,
-  MFDirection,
-  MFBulge1,
-  MFBulge2,
-  MFCount // For array sizes.
-} MF_PARAM_NAME;
-
-typedef float MicroFeature[MFCount];
-/*----------------------------------------------------------------------------
-          Private Function Prototypes
------------------------------------------------------------------------------*/
 FEATURE_SET ExtractMicros(TBLOB *Blob, const DENORM &cn_denorm);

 } // namespace tesseract
diff --git a/src/classify/mfdefs.h b/src/classify/mfdefs.h
index d6a7b3fd..e17c5017 100644
--- a/src/classify/mfdefs.h
+++ b/src/classify/mfdefs.h
@@ -18,29 +18,24 @@
 #ifndef MFDEFS_H
 #define MFDEFS_H

-/**----------------------------------------------------------------------------
-          Include Files and Type Defines
-----------------------------------------------------------------------------**/
-#include "matchdefs.h"
-#include "oldlist.h"
-
 #include <array>
 #include <forward_list>

 namespace tesseract {

-/* definition of a list of micro-features */
-using MICROFEATURE = float;
-using MFBLOCK = std::array<MICROFEATURE, 6>;
-using MICROFEATURES = std::forward_list<MFBLOCK>;
+enum class MicroFeatureParameter {
+  MFXPosition,
+  MFYPosition,
+  MFLength,
+  MFDirection,
+  MFBulge1,
+  MFBulge2,
+
+  MFCount // For array sizes.
+};

-/* definitions of individual micro-feature parameters */
-#define XPOSITION 0
-#define YPOSITION 1
-#define MFLENGTH 2
-#define ORIENTATION 3
-#define FIRSTBULGE 4
-#define SECONDBULGE 5
+using MicroFeature = std::array<float, (int)MicroFeatureParameter::MFCount>;
+using MICROFEATURES = std::forward_list<MicroFeature>;

 } // namespace tesseract

diff --git a/src/classify/mfx.cpp b/src/classify/mfx.cpp
index 39dd1df6..0ce5661a 100644
--- a/src/classify/mfx.cpp
+++ b/src/classify/mfx.cpp
@@ -36,7 +36,7 @@ double_VAR(classify_max_slope, 2.414213562, "Slope above which lines are called

 MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline, MICROFEATURES MicroFeatures);

-MFBLOCK ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End);
+MicroFeature ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End);

 /*----------------------------------------------------------------------------
             Public Code
@@ -125,19 +125,19 @@ MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline, MICROFEATURES MicroFeatu
  * @return New micro-feature or nullptr if the feature was rejected.
  * @note Globals: none
  */
-MFBLOCK ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End) {
+MicroFeature ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End) {
   MFEDGEPT *P1, *P2;

   P1 = PointAt(Start);
   P2 = PointAt(End);

-  MFBLOCK NewFeature;
-  NewFeature[XPOSITION] = AverageOf(P1->Point.x, P2->Point.x);
-  NewFeature[YPOSITION] = AverageOf(P1->Point.y, P2->Point.y);
-  NewFeature[MFLENGTH] = DistanceBetween(P1->Point, P2->Point);
-  NewFeature[ORIENTATION] = NormalizedAngleFrom(&P1->Point, &P2->Point, 1.0);
-  NewFeature[FIRSTBULGE] = 0.0f;  // deprecated
-  NewFeature[SECONDBULGE] = 0.0f; // deprecated
+  MicroFeature NewFeature;
+  NewFeature[(int)MicroFeatureParameter::MFXPosition] = AverageOf(P1->Point.x, P2->Point.x);
+  NewFeature[(int)MicroFeatureParameter::MFYPosition] = AverageOf(P1->Point.y, P2->Point.y);
+  NewFeature[(int)MicroFeatureParameter::MFLength] = DistanceBetween(P1->Point, P2->Point);
+  NewFeature[(int)MicroFeatureParameter::MFDirection] = NormalizedAngleFrom(&P1->Point, &P2->Point, 1.0);
+  NewFeature[(int)MicroFeatureParameter::MFBulge1] = 0.0f;  // deprecated
+  NewFeature[(int)MicroFeatureParameter::MFBulge2] = 0.0f; // deprecated

   return NewFeature;
 } /* ExtractMicroFeature */
diff --git a/src/classify/trainingsample.cpp b/src/classify/trainingsample.cpp
index ccbb84aa..ef255f94 100644
--- a/src/classify/trainingsample.cpp
+++ b/src/classify/trainingsample.cpp
@@ -263,7 +263,7 @@ void TrainingSample::ExtractCharDesc(int int_feature_type, int micro_type, int c
     num_micro_features_ = char_features->NumFeatures;
     micro_features_ = new MicroFeature[num_micro_features_];
     for (uint32_t f = 0; f < num_micro_features_; ++f) {
-      for (int d = 0; d < MFCount; ++d) {
+      for (int d = 0; d < (int)MicroFeatureParameter::MFCount; ++d) {
         micro_features_[f][d] = char_features->Features[f]->Params[d];
       }
     }
diff --git a/src/classify/trainingsample.h b/src/classify/trainingsample.h
index a833617d..5e4a943a 100644
--- a/src/classify/trainingsample.h
+++ b/src/classify/trainingsample.h
@@ -22,6 +22,7 @@
 #include "intmatcher.h"
 #include "matrix.h"
 #include "mf.h"
+#include "mfdefs.h"
 #include "picofeat.h"
 #include "shapetable.h"
 #include "unicharset.h"
diff --git a/src/training/common/mastertrainer.cpp b/src/training/common/mastertrainer.cpp
index 43eaf277..3ee28db7 100644
--- a/src/training/common/mastertrainer.cpp
+++ b/src/training/common/mastertrainer.cpp
@@ -576,7 +576,7 @@ CLUSTERER *MasterTrainer::SetupForClustering(const ShapeTable &shape_table,
                                              int *num_samples) {
   int desc_index = ShortNameToFeatureType(feature_defs, kMicroFeatureType);
   int num_params = feature_defs.FeatureDesc[desc_index]->NumParams;
-  ASSERT_HOST(num_params == MFCount);
+  ASSERT_HOST(num_params == (int)MicroFeatureParameter::MFCount);
   CLUSTERER *clusterer = MakeClusterer(num_params, feature_defs.FeatureDesc[desc_index]->ParamDesc);

   // We want to iterate over the samples of just the one shape.
@@ -596,7 +596,7 @@ CLUSTERER *MasterTrainer::SetupForClustering(const ShapeTable &shape_table,
     const TrainingSample *sample = sample_ptrs[i];
     uint32_t num_features = sample->num_micro_features();
     for (uint32_t f = 0; f < num_features; ++f) {
-      MakeSample(clusterer, sample->micro_features()[f], sample_id);
+      MakeSample(clusterer, sample->micro_features()[f].data(), sample_id);
     }
     ++sample_id;
   }