From eaaf8d667ab49ecafbc1ec8f1f0e3103b1e423ff Mon Sep 17 00:00:00 2001
From: even <philippe.even@loria.fr>
Date: Sun, 25 Nov 2018 17:35:24 +0100
Subject: [PATCH] Vicinity constraint released

---
 Code/Seg/BSTools/bsdetectionwidget.cpp | 46 +++++++++++++++++++++++---
 Code/Seg/BSTools/bsdetectionwidget.h   |  5 +++
 Code/Seg/BSTools/bswindow.cpp          |  2 +-
 Code/Seg/BlurredSegment/bsdetector.cpp | 18 +++++-----
 Code/Seg/BlurredSegment/bsdetector.h   | 26 +++++++++++++--
 Code/Seg/BlurredSegment/bstracker.cpp  |  9 ++---
 Code/Seg/BlurredSegment/bstracker.h    | 36 ++++++++++++++++----
 Code/Seg/ImageTools/absrat.h           |  6 ++++
 Code/Seg/ImageTools/vmap.h             |  2 +-
 Methode/ctrl.tex                       | 22 +++++++-----
 Methode/methode.tex                    | 10 +++---
 11 files changed, 143 insertions(+), 39 deletions(-)

diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp
index d2f8a6e..6ac098d 100755
--- a/Code/Seg/BSTools/bsdetectionwidget.cpp
+++ b/Code/Seg/BSTools/bsdetectionwidget.cpp
@@ -23,33 +23,33 @@ BSDetectionWidget::BSDetectionWidget (QWidget *parent)
 {
   Q_UNUSED (parent);
 
-  // Sets default user interface parameters
+  // Sets initial user inputs parameters
   setFocus ();
   grabKeyboard ();
   udef = false;
   nodrag = true;
 
-  // Sets initial values for the gradient map
+  // Initializes the gradient map and the auxiliary views
   gMap = NULL;
-
-  // Initializes the auxiliary views
   accuview = NULL;
   strucview = NULL;
   profileview = NULL;
   idetview = NULL;
 
+  // Sets initial user outputs parameters
   alternate = 0;
   verbose = false;
   background = BACK_IMAGE;
+  bsBoundsVisible = false;
   exam = -1;
 
+  // Sets display parameters
   selectionColor = Qt::red;
   bsColor = Qt::yellow;
   bsHighColor = Qt::blue;
   bsPointsVisible = true;
   boundColor = Qt::magenta;
   boundHighColor = Qt::green;
-  bsBoundsVisible = false;
 }
 
 
@@ -83,6 +83,19 @@ QSize BSDetectionWidget::openImage (const QString &fileName, int type)
 }
 
 
+void BSDetectionWidget::setDefaults ()
+{
+  ifstream input ("gradient.txt", ios::in);
+  if (input)
+  {
+    int gtval = gMap->getGradientThreshold ();
+    input >> gtval;
+    if (gtval >= 0 && gtval < 256)
+      gMap->incGradientThreshold (gtval - gMap->getGradientThreshold ());
+  }
+}
+
+
 int **BSDetectionWidget::getBitmap (const QImage &image)
 {
   int w = image.width ();
@@ -282,6 +295,8 @@ void BSDetectionWidget::mousePressEvent (QMouseEvent *event)
   oldp1.set (p1);
   oldp2.set (p2);
   p1 = Pt2i (event->pos().x (), height - 1 - event->pos().y());
+  if (p1.manhattan (p2) < 10) p1.set (oldp1);
+  else if (p1.manhattan (oldp1) < 10) p1.set (p2);
   udef = true;
 }
 
@@ -408,6 +423,27 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       }
       break;
 
+    case Qt::Key_J :
+      if (event->modifiers () & Qt::ControlModifier)
+      {
+        // Switches the vicinity constraint for fast tracks
+        detector.switchVicinityConstraint ();
+        cout << "Vicinity constraint "
+             << (detector.vicinityConstraintOn () ? "on" : "off")
+             << endl;
+        extract ();
+      }
+      else
+      {
+        // Tunes the vicinity threshold for fast tracks
+        detector.incVicinityThreshold(
+                    (event->modifiers () & Qt::ShiftModifier) == 0);
+        cout << "Vicinity threshold = "
+             << detector.getVicinityThreshold () << endl;
+        extract ();
+      }
+      break;
+
     case Qt::Key_K :
       if (event->modifiers () & Qt::ControlModifier)
       {
diff --git a/Code/Seg/BSTools/bsdetectionwidget.h b/Code/Seg/BSTools/bsdetectionwidget.h
index a8b1608..36c2994 100755
--- a/Code/Seg/BSTools/bsdetectionwidget.h
+++ b/Code/Seg/BSTools/bsdetectionwidget.h
@@ -45,6 +45,11 @@ public:
    */
   QSize openImage (const QString &fileName, int type = 0);
 
+  /**
+   * \brief Applies default options (read in defaults files).
+   */
+  void setDefaults ();
+
   /**
    * \brief Builds and returns the image bitmap.
    */
diff --git a/Code/Seg/BSTools/bswindow.cpp b/Code/Seg/BSTools/bswindow.cpp
index e5836fd..8d86ae5 100755
--- a/Code/Seg/BSTools/bswindow.cpp
+++ b/Code/Seg/BSTools/bswindow.cpp
@@ -1,6 +1,5 @@
 #include "bswindow.h"
 #include <QtGui>
-//#include <QtWidgets>
 #include <QFileDialog>
 #include <QMenuBar>
 #include <iostream>
@@ -44,6 +43,7 @@ BSWindow::BSWindow ()
 void BSWindow::setFile (QString fileName)
 {
   resize (detectionWidget->openImage (fileName, gradType));
+  detectionWidget->setDefaults ();
 }
 
 
diff --git a/Code/Seg/BlurredSegment/bsdetector.cpp b/Code/Seg/BlurredSegment/bsdetector.cpp
index 0c598e9..5bf61d3 100755
--- a/Code/Seg/BlurredSegment/bsdetector.cpp
+++ b/Code/Seg/BlurredSegment/bsdetector.cpp
@@ -23,7 +23,7 @@ const int BSDetector::DEFAULT_BS_MIN_SIZE = 5;
 const int BSDetector::ABSOLUTE_BS_MIN_SIZE = 3;
 const int BSDetector::DEFAULT_CONNECT_MIN_SIZE = 5;
 const int BSDetector::DEFAULT_AUTO_RESOLUTION = 10;
-const int BSDetector::PRELIM_SIZE = 10;
+const int BSDetector::PRELIM_MIN_HALF_WIDTH = 10;
 
 
 BSDetector::BSDetector ()
@@ -31,7 +31,7 @@ BSDetector::BSDetector ()
   gMap = NULL;
 
   bst1 = new BSTracker ();
-  bst1->setPixelLackTolerence (bst1->proximityThreshold ());
+  // bst1->setPixelLackTolerence (bst1->getVicinityThreshold ());
   bst2 = new BSTracker ();
 
   prefilteringOn = true;
@@ -39,7 +39,7 @@ BSDetector::BSDetector ()
   filteringOn = false;
   lsf2 = (filteringOn ? new LineSpaceFilter () : NULL);
 
-  edgeDirection = 0;   // detects line (not only edges)
+  edgeDirection = 0;   // detects strokes (not only edges)
   bsMinSize = DEFAULT_BS_MIN_SIZE;
   ccOn = true;
   ccMinSize = DEFAULT_CONNECT_MIN_SIZE;
@@ -183,13 +183,15 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0)
     }
 
     Vr2i v0 = bspre->getSupportVector ();
-    Pt2i pc = bspre->getSegment()->centerOfIntersection (p1, p2);
-    v0.setOrthog ();
     int l = v0.chessboard ();
-    int dx = (int) ((v0.x () * PRELIM_SIZE) / l);
-    int dy = (int) ((v0.y () * PRELIM_SIZE) / l);
-    if (dx * dy != 0)
+    if (l != 0)
     {
+      Pt2i pc = bspre->getSegment()->centerOfIntersection (p1, p2);
+      AbsRat sw = bspre->segmentRationalWidth ();
+      int detw = 2 * (1 + bspre->segmentRationalWidth().floor ());
+      if (detw < PRELIM_MIN_HALF_WIDTH) detw = PRELIM_MIN_HALF_WIDTH;
+      int dx = (int) ((v0.y () * detw) / l);
+      int dy = (int) (- (v0.x () * detw) / l);
       pt1 = Pt2i (pc.x () + dx, pc.y () + dy);
       pt2 = Pt2i (pc.x () - dx, pc.y () - dy);
       p0 = NULL;
diff --git a/Code/Seg/BlurredSegment/bsdetector.h b/Code/Seg/BlurredSegment/bsdetector.h
index b1301ae..746b4c9 100755
--- a/Code/Seg/BlurredSegment/bsdetector.h
+++ b/Code/Seg/BlurredSegment/bsdetector.h
@@ -326,6 +326,28 @@ public:
    */
   inline int initialDetectionMaxExtent () { return (bst1->maxScanExtent ()); }
 
+  /**
+   * \brief Returns the vicinity threshold used for fast tracking.
+   */
+  inline int getVicinityThreshold () { return (bst1->getVicinityThreshold ()); }
+
+  /**
+   * \brief Increments the vicinity threshold used for fast tracking.
+   * @param inc Increment value.
+   */
+  inline void incVicinityThreshold (int inc) {
+    bst1->incVicinityThreshold (inc); }
+    
+  /**
+   * \brief Returns the vicinity test status.
+   */
+  inline bool vicinityConstraintOn () { return (bst1->vicinityConstraintOn ()); }
+
+  /**
+   * \brief Switches the vicinity test used for fast tracking.
+   */
+  inline void switchVicinityConstraint () { bst1->switchVicinityConstraint (); }
+
   /**
    * \brief Returns if the dynamic scans modality is set.
    */
@@ -455,8 +477,8 @@ private :
   static const int DEFAULT_CONNECT_MIN_SIZE;
   /** Default value for the automatic detection grid resolution. */
   static const int DEFAULT_AUTO_RESOLUTION;
-  /** Default value for half the preliminary stroke size. */
-  static const int PRELIM_SIZE;
+  /** Default value for the preliminary stroke half length. */
+  static const int PRELIM_MIN_HALF_WIDTH;
 
 
   /** Gradient map. */
diff --git a/Code/Seg/BlurredSegment/bstracker.cpp b/Code/Seg/BlurredSegment/bstracker.cpp
index 676204e..ddd5a69 100755
--- a/Code/Seg/BlurredSegment/bstracker.cpp
+++ b/Code/Seg/BlurredSegment/bstracker.cpp
@@ -6,7 +6,8 @@
 const int BSTracker::DEFAULT_FAST_TRACK_MAX_WIDTH = 5;
 const int BSTracker::DEFAULT_FINE_TRACK_MAX_WIDTH = 8;
 const int BSTracker::DEFAULT_ACCEPTED_LACKS = 5;
-const int BSTracker::DEFAULT_PROXIMITY_THRESHOLD = 4;
+const int BSTracker::NO_VICINITY = 10000;
+const int BSTracker::DEFAULT_VICINITY_THRESHOLD = 10;
 const int BSTracker::MIN_SCAN = 8;
 const int BSTracker::DEFAULT_MAX_SCAN = 32;
 const int BSTracker::DEFAULT_FITTING_DELAY = 20;
@@ -25,7 +26,7 @@ const int BSTracker::FAILURE_LOST_ORIENTATION = 32;
 
 BSTracker::BSTracker ()
 {
-  proxThreshold = DEFAULT_PROXIMITY_THRESHOLD;
+  vicinityThreshold = NO_VICINITY + DEFAULT_VICINITY_THRESHOLD;
   imaxWidth = DEFAULT_FAST_TRACK_MAX_WIDTH;
   fmaxWidth = DEFAULT_FINE_TRACK_MAX_WIDTH;
   acceptedLacks = DEFAULT_ACCEPTED_LACKS;
@@ -146,7 +147,7 @@ BlurredSegment *BSTracker::fastTrack (const Pt2i &p1, const Pt2i &p2,
         candide = gMap->largestIn (pix);
         if (candide != -1)
         {
-          if (lastRight.manhattan (pix.at (candide)) <= proxThreshold)
+          if (lastRight.manhattan (pix.at (candide)) <= vicinityThreshold)
             added = bs.addRight (pix.at (candide));
         }
         if (added)
@@ -174,7 +175,7 @@ BlurredSegment *BSTracker::fastTrack (const Pt2i &p1, const Pt2i &p2,
         candide = gMap->largestIn (pix);
         if (candide != -1)
         {
-          if (lastLeft.manhattan (pix.at (candide)) < proxThreshold)
+          if (lastLeft.manhattan (pix.at (candide)) < vicinityThreshold)
             added = bs.addLeft (pix.at (candide));
         }
         if (added)
diff --git a/Code/Seg/BlurredSegment/bstracker.h b/Code/Seg/BlurredSegment/bstracker.h
index ff8893c..641c812 100755
--- a/Code/Seg/BlurredSegment/bstracker.h
+++ b/Code/Seg/BlurredSegment/bstracker.h
@@ -114,9 +114,31 @@ public:
   void setGradientMap (VMap *data);
 
   /**
-   * \brief Returns the proximity threshold.
+   * \brief Returns the vicinity threshold used for fast tracking.
    */
-  inline int proximityThreshold () { return proxThreshold; }
+  inline int getVicinityThreshold () { return vicinityThreshold; }
+
+  /**
+   * \brief Increments the vicinity threshold used for fast tracking.
+   * @param inc Increment value.
+   */
+  inline void incVicinityThreshold (int inc) {
+    if (vicinityThreshold < NO_VICINITY) {
+      vicinityThreshold += inc;
+      if (vicinityThreshold < 1) vicinityThreshold = 1; } }
+
+  /**
+   * \brief Returns the vicinity test status.
+   */
+  inline bool vicinityConstraintOn () {
+    return (vicinityThreshold < NO_VICINITY); }
+
+  /**
+   * \brief Switches the vicinity test used for fast tracking.
+   */
+  inline void switchVicinityConstraint () {
+    vicinityThreshold += (vicinityThreshold > NO_VICINITY ?
+                          - NO_VICINITY : NO_VICINITY); }
 
   /**
    * \brief Returns if the dynamic scans are used.
@@ -199,8 +221,10 @@ private :
   static const int DEFAULT_FINE_TRACK_MAX_WIDTH;
   /** Default value for the accepted number of successive lacks. */
   static const int DEFAULT_ACCEPTED_LACKS;
-  /** Default value for the proximity threshold used for fast tracking. */
-  static const int DEFAULT_PROXIMITY_THRESHOLD;
+  /** Default value for the vicinity test used for fast tracking. */
+  static const int DEFAULT_VICINITY_THRESHOLD;
+  /** Large value to release the vicinity constraint. */
+  static const int NO_VICINITY;
   /** Minimal length of scan length to be processed. */
   static const int MIN_SCAN;
   /** Default value for the maximal number of scans processed on each side. */
@@ -240,8 +264,8 @@ private :
   int minRestart;
   /** Accepted number of successive lacks (wrt restart points). */
   int acceptedLacks;
-  /** Proximity threshold used for fast tracking. */
-  int proxThreshold;
+  /** Vicinity threshold used for fast tracking. */
+  int vicinityThreshold;
 
   /** Orthogonal scanning modality status */
   bool orthoScan;
diff --git a/Code/Seg/ImageTools/absrat.h b/Code/Seg/ImageTools/absrat.h
index a52e710..410633e 100755
--- a/Code/Seg/ImageTools/absrat.h
+++ b/Code/Seg/ImageTools/absrat.h
@@ -59,6 +59,12 @@ public:
    */
   inline int denominator () const { return den; }
 
+  /**
+   * @fn int floor ()
+   * \brief Returns the nearest smaller integer value.
+   */
+  inline int floor () const { return (num / den); }
+
   /**
    * @fn void set (const AbsRat &val)
    * \brief Sets the value of the rational number.
diff --git a/Code/Seg/ImageTools/vmap.h b/Code/Seg/ImageTools/vmap.h
index ed6d09d..7ed1903 100755
--- a/Code/Seg/ImageTools/vmap.h
+++ b/Code/Seg/ImageTools/vmap.h
@@ -194,7 +194,7 @@ public:
   inline int getGradientThreshold () const { return (gradientThreshold); }
 
   /**
-   * \brief Returns the gradient threshold value used for maxima detection.
+   * \brief Increments the gradient threshold value used for maxima detection.
    */
   inline void incGradientThreshold (int inc) {
     gradientThreshold += inc;
diff --git a/Methode/ctrl.tex b/Methode/ctrl.tex
index 8194be6..481f53f 100755
--- a/Methode/ctrl.tex
+++ b/Methode/ctrl.tex
@@ -4,10 +4,10 @@
 \setlength{\unitlength}{1.0mm}
 \topmargin 0.0cm
 \headheight 0.0cm
-\headsep -1.5cm
+\headsep -0.5cm
 \oddsidemargin 0.5cm
 \evensidemargin 0.5cm
-\textheight 27.5cm
+\textheight 25.0cm
 \textwidth 15.0cm
 \footskip 1.5cm
 \parindent 0.0cm
@@ -27,6 +27,7 @@ a/q/c &\spa & Enregistre / Affiche / Supprime les segments \\
 e && Inverse la direction de r\'ef\'erence (autre bord) \\
 g && Ajuste le seuil du gradient \\
 n && Allume le segment suivant dans une d\'etection multiple \\
+j && Ajuste le seuil de voisinage pour les suivis rapides \\
 k && Ajuste la taille minimale des composantes connexes \\
 l && Ajuste la taille minimale du segment final \\
 m && D\'etection exhaustive de tous les segments \\
@@ -43,6 +44,7 @@ Ctrl-d && Commute le test de densit\'e \\
 Ctrl-e && Commute la prise en compte de la direction du bord (trait / contour) \\
 Ctrl-f && Commute le pr\'e-filtrage (segment initial) \\
 Ctrl-h && Commute le filtrage du segment final \\
+Ctrl-j && Commute la contrainte de voisinage pour les suivis rapides \\
 Ctrl-k && Commute la contrainte de konnectivit\'e \\
 Ctrl-m && Commute la d\'etection multiple \\
 Ctrl-n && Commute la limitation de l'extension de la d\'etection initiale \\
@@ -64,29 +66,33 @@ Ctrl-y && Commute l'affichage des pixels des segments flous. \\
 9 && Teste la performance sur la derni\`ere barre trac\'ee \\
 8 && Teste comparativement sur diff\'erents contextes de d\'etection \\
 7 && Enregistre la barre initiale dans test.txt \\
-\hline \hline
-\multicolumn{3}{|l|}{Fen\^etres d'analyse :} \\
+\hline
+\end{tabular}
+\newpage
+\begin{tabular}{|rcl|}
+\hline
+\multicolumn{3}{|l|}{Contr\^ole de l'extraction : \hspace{9.0cm} .} \\
 i && Changement d'info \\
 v && Commute l'affichage du texte \\
-\hline
+\hline \hline
 \multicolumn{3}{|l|}{Analyse des segments flous extraits :} \\
 Ctrl-i && Commute le type d'affichage des scans \\
 Ctrl-b && Commute le fond d'\'ecran de la fen\^etre principale. \\
 + -- && Zoom \\
 $< \wedge > \vee$ && D\'ecalage de l'observation \\
-\hline
+\hline \hline
 \multicolumn{3}{|l|}{Analyse des accumulateurs :} \\
 s && Taille de l'accumulateur (nombre de cellules) \\
 r && R\'esolution (espace couvert par une cellule) \\
 p && Sub-pixelisation (pour le vote) \\
 f && S\'electivit\'e du filtre \\
-\hline
+\hline \hline
 \multicolumn{3}{|l|}{Analyse des profils :} \\
 w && Largeur de correlation \\
 t && Epaisseur de correlation \\
 r && Taux de correlation \\
 $\wedge \vee$ && Parcours des bandes \\
-\hline
+\hline \hline
 \multicolumn{3}{|l|}{Analyse de la d\'etection initiale :} \\
 $< \wedge > \vee$ && D\'ecalage de l'observation \\
 \hline
diff --git a/Methode/methode.tex b/Methode/methode.tex
index ce9290f..7f4ed6d 100755
--- a/Methode/methode.tex
+++ b/Methode/methode.tex
@@ -64,8 +64,9 @@ sur sur le segment d\'etect\'e.
 \item Balayage directionnel statique pour cr\'eer et \'etendre un segment flou
 \`a partir du gradient maximal trouv\'e dans la barre.
 \item Consigne d'\'epaisseur : par d\'efaut 5 pixels, ajustable.
-\item En phase d'extension, on applique un test de voisinage par rapport au
-dernier pixel ins\'er\'e (4 pixels).
+\item La phase d'extension comporte un test de voisinage par rapport au
+dernier pixel ins\'er\'e (initialement 4 pixels, actuellement remont\'e
+\`a 10 pixels). Ce test est par d\'efaut d\'esactiv\'e.
 \item Aucun test angulaire.
 \item Tol\'erance aux interruptions : 5 pixels.
 \end{itemize}
@@ -94,8 +95,9 @@ l'\'etape pr\'ec\'edente. Sinon, par d\'efaut 8 pixels, ajustable.
 \item Centrage : si la modalit\'e {\tt scanRecentering} est active, le
 balayage est centr\'e sur le segment d\'etect\'e \`a l'\'etape pr\'ec\'edente.
 Sinon, il est centr\'e sur la barre utilisateur ($P_1P_2$).
-\item En phase d'extension, on applique un test de voisinage par rapport au
-dernier pixel ins\'er\'e (4 pixels).
+\item La phase d'extension comporte un test de voisinage par rapport au
+dernier pixel ins\'er\'e (initialement 4 pixels, actuellement remont\'e
+\`a 10 pixels). Ce test est par d\'efaut d\'esactiv\'e.
 \item Aucun test angulaire.
 \item Tol\'erance aux interruptions : 5 pixels.
 \end{itemize}
-- 
GitLab