From 452fae93e06855e92a522e49caf1354186fdedcb Mon Sep 17 00:00:00 2001 From: even <philippe.even@loria.fr> Date: Fri, 7 Dec 2018 15:42:52 +0100 Subject: [PATCH] Width control --- Article/method.tex | 16 ++++++++----- Article/notions.tex | 7 +++--- Code/Seg/BSTools/bsdetectionwidget.cpp | 24 +++++++++++++++++++ Code/Seg/BlurredSegment/bsdetector.h | 24 ++++++++++++++++++- Code/Seg/BlurredSegment/bstracker.cpp | 31 +++++++++++++++++++++---- Code/Seg/BlurredSegment/bstracker.h | 32 +++++++++++++++++++++++++- Methode/ctrl.tex | 6 +++-- Methode/methode.tex | 12 ++++++---- 8 files changed, 130 insertions(+), 22 deletions(-) diff --git a/Article/method.tex b/Article/method.tex index 9a0dde9..c2ce3b9 100755 --- a/Article/method.tex +++ b/Article/method.tex @@ -46,15 +46,19 @@ applied to decide of the detection poursuit. In case of positive response, the position $C$ and direction $\vec{D}$ of this initial blurred segment are extracted. -The fine track step consists on building and extending a blurred segment +The fine tracking step consists on building and extending a blurred segment $\mathcal{B}_2$ based on points that correspond to local maxima of the image gradient, ranked by magnitude order, and with gradient direction close to a reference gradient direction at the segment first point. -This step uses an adaptive directional scanner to extends the segment -in appropriate direction. -During that step a thinning procedure is run : -the assigned width is progressively brought to -the detected blurred segment minimal width. +This step uses an adaptive directional scanner based on the found +position $C$ direction $\vec{D}$ in order to extends the segment in the +appropriate direction. +After $N$ points are added without any augmentation of the segment minimal +width, this width becomes the new assigned width so that the segment +can not thicken any more. This procedure allows to control the blurred +segment width based on the observation of its evolution in the vicinity +of the input stroke. +Setting $N=20$ shows a good behaviour on tested images. The fine track output segment is finally filtered to remove artifacts and outliers, and a solution blurred segment $\mathcal{B}_3$ is provided. diff --git a/Article/notions.tex b/Article/notions.tex index 399f61e..ee859f5 100755 --- a/Article/notions.tex +++ b/Article/notions.tex @@ -46,10 +46,11 @@ the assigned width $\varepsilon$, then the new input point is rejected.} \label{fig:bs} \end{figure} -At the beginning, a large width $\varepsilon_{ini}$ is assigned to the +At the beginning, a large width $\varepsilon$ is assigned to the recognition problem to allow the detection of large blurred segments. -Then, when extending the blurred segment, this assigned width is -gradually decremented to reach the detected blurred segment minimal width. +Then, when no more aumentation of the minimal width is observed as the segment +grows, the assigned width is fixed to the observed minimal width in order to +avoid the incorporation of spurious outliers in further parts of the segment. \subsection{Directional scan} diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp index 8f0e344..e0de37e 100755 --- a/Code/Seg/BSTools/bsdetectionwidget.cpp +++ b/Code/Seg/BSTools/bsdetectionwidget.cpp @@ -614,6 +614,8 @@ cout << "AUTO" << endl; { // Switches the progressive thinning detector.toggleThinning (); + if (detector.isThinningActivated () && detector.isThickenningOn ()) + detector.toggleThickenning (); extract (); cout << "Thinning " << (detector.isThinningActivated () ? "on" : "off") << endl; @@ -695,6 +697,28 @@ cout << "AUTO" << endl; } break; + case Qt::Key_Z : + if (event->modifiers () & Qt::ControlModifier) + { + // Switches the thickenning control + detector.toggleThickenning (); + if (detector.isThickenningOn () && detector.isThinningActivated ()) + detector.toggleThinning (); + extract (); + cout << "Thickenning " + << (detector.isThickenningOn () ? "on" : "off") << endl; + } + else + { + // Tunes the thickenning limit + detector.incThickenningLimit ( + (event->modifiers () & Qt::ShiftModifier ? -1 : 1)); + extract (); + cout << "Thickenning limit = " << detector.getThickenningLimit () + << " pixels" << endl; + } + break; + case Qt::Key_1 : switchPixelAnalyzer (); break; diff --git a/Code/Seg/BlurredSegment/bsdetector.h b/Code/Seg/BlurredSegment/bsdetector.h index 95a38bb..c5444c0 100755 --- a/Code/Seg/BlurredSegment/bsdetector.h +++ b/Code/Seg/BlurredSegment/bsdetector.h @@ -349,10 +349,32 @@ public: */ void switchOrthoScans (); + /** + * \brief Returns if the thickenning control is activated. + */ + inline bool isThickenningOn () const { return bst2->isThickenningOn (); } + + /** + * \brief Toggles the thickenning control. + */ + inline void toggleThickenning () { bst2->toggleThickenning (); } + + /** + * \brief Returns the thickenning limit. + */ + inline int getThickenningLimit () const { + return bst2->getThickenningLimit (); } + + /** + * \brief Increments the thickenning limit. + */ + inline void incThickenningLimit (int val) { bst2->incThickenningLimit (val); } + /** * \brief Returns if the thinning is activated. */ - inline bool isThinningActivated () { return bst2->isThinningActivated (); } + inline bool isThinningActivated () const { + return bst2->isThinningActivated (); } /** * \brief Toggles the thinning strategy. diff --git a/Code/Seg/BlurredSegment/bstracker.cpp b/Code/Seg/BlurredSegment/bstracker.cpp index a5931ae..d76a5cd 100755 --- a/Code/Seg/BlurredSegment/bstracker.cpp +++ b/Code/Seg/BlurredSegment/bstracker.cpp @@ -12,6 +12,8 @@ const int BSTracker::MIN_SCAN = 8; const int BSTracker::DEFAULT_MAX_SCAN = 32; const int BSTracker::DEFAULT_FITTING_DELAY = 20; +const int BSTracker::DEFAULT_THICKENNING_LIMIT = 20; + const int BSTracker::DEFAULT_THINNING_DELAY = 20; const int BSTracker::DEFAULT_THINNING_SPEED = 2; const int BSTracker::DEFAULT_THINNING_REACH = 50; @@ -37,7 +39,10 @@ BSTracker::BSTracker () recordScans = false; orthoScan = false; - thinningOn = true; + thickenningOn = true; + thickenningLimit = DEFAULT_THICKENNING_LIMIT; + + thinningOn = false; thinningDelay = DEFAULT_THINNING_DELAY; thinningSpeed.set (DEFAULT_THINNING_SPEED, 100); thinningReach.set (100 + DEFAULT_THINNING_REACH, 100); @@ -241,6 +246,10 @@ BlurredSegment *BSTracker::fineTrack (const Pt2i ¢er, const Vr2i &scandir, BlurredSegmentProto bs (bswidth, pix[cand[0]]); + // Handles thickenning + bool thickenOn = thickenningOn; + int stableWidthCount = 0; + // Handles thinning int count = 0; AbsRat maxw (bswidth * DEFAULT_THINNING_RESOLUTION, @@ -261,19 +270,27 @@ BlurredSegment *BSTracker::fineTrack (const Pt2i ¢er, const Vr2i &scandir, while (scanningRight || scanningLeft) { count ++; + AbsRat sw = bs.segmentRationalWidth (); + + // Handles thickenning + if (thickenOn && stableWidthCount >= thickenningLimit) + { + bs.setMaxWidth (sw); + thickenOn = false; + } // Handles thinning if (thon) { if (count > thinningDelay) { - AbsRat sw = bs.segmentRationalWidth (); AbsRat oldmaxw (maxw); maxw.attractsTo (sw, thinningSpeed); - sw.mult (thinningReach); - if (maxw.lessThan (sw)) + AbsRat msw (sw); + msw.mult (thinningReach); + if (maxw.lessThan (msw)) { - maxw.sticksTo (sw); + maxw.sticksTo (msw); if (oldmaxw.lessThan (maxw)) maxw.set (oldmaxw); thon = false; // thinning deactivation } @@ -322,8 +339,10 @@ BlurredSegment *BSTracker::fineTrack (const Pt2i ¢er, const Vr2i &scandir, nbc = gMap->localMax (cand, pix, normal); for (int i = 0; ! added && i < nbc; i++) added = bs.addRight (pix[cand[i]]); + stableWidthCount ++; if (added) { + if (sw.lessThan (bs.segmentRationalWidth ())) stableWidthCount = 0; rscan = count; if (rstop == 0) rstart = 0; else @@ -368,8 +387,10 @@ BlurredSegment *BSTracker::fineTrack (const Pt2i ¢er, const Vr2i &scandir, nbc = gMap->localMax (cand, pix, normal); for (int i = 0; ! added && i < nbc; i++) added = bs.addLeft (pix[cand[i]]); + stableWidthCount ++; if (added) { + if (sw.lessThan (bs.segmentRationalWidth ())) stableWidthCount = 0; lscan = count; if (lstop == 0) lstart = 0; else diff --git a/Code/Seg/BlurredSegment/bstracker.h b/Code/Seg/BlurredSegment/bstracker.h index 58ce273..d4de005 100755 --- a/Code/Seg/BlurredSegment/bstracker.h +++ b/Code/Seg/BlurredSegment/bstracker.h @@ -189,10 +189,31 @@ public: */ inline void setDynamicScans (bool onOff) { dynamicScans = onOff; } + /** + * \brief Returns if the thickenning control is activated. + */ + inline bool isThickenningOn () const { return thickenningOn; } + + /** + * \brief Toggles the thickenning control. + */ + inline void toggleThickenning () { thickenningOn = ! thickenningOn; } + + /** + * \brief Returns the thickenning limit. + */ + inline int getThickenningLimit () const { return thickenningLimit; } + + /** + * \brief Increments the thickenning limit. + */ + inline void incThickenningLimit (int val) { + thickenningLimit += val; if (thickenningLimit < 1) thickenningLimit = 1; } + /** * \brief Returns if the thinning is activated. */ - inline bool isThinningActivated () { return thinningOn; } + inline bool isThinningActivated () const { return thinningOn; } /** * \brief Toggles the thinning strategy. @@ -238,6 +259,10 @@ private : /* Count of points before activating the fitting on the detected segment. */ static const int DEFAULT_FITTING_DELAY; + // Width thickenning default parameters. + /* Maximal count of points since last minimal width growing. */ + static const int DEFAULT_THICKENNING_LIMIT; + // Width thinning default parameters. /* Count of points before activating the width thinning. */ static const int DEFAULT_THINNING_DELAY; @@ -296,6 +321,11 @@ private : /** Minimal control width wrt detected segment width when thinning. */ AbsRat thinningReach; + /** Segment thickening control modality. */ + bool thickenningOn; + /** Count of expansion without width growing to stop the thickenning. */ + int thickenningLimit; + /** Gradient map. */ VMap *gMap; diff --git a/Methode/ctrl.tex b/Methode/ctrl.tex index eff09ff..b6596d1 100755 --- a/Methode/ctrl.tex +++ b/Methode/ctrl.tex @@ -39,7 +39,8 @@ s && Ajuste la longueur tol\'er\'ee pour les sauts de d\'etection \\ u && Relance la d\'etection sur la derni\`ere s\'election (update) \\ w && Ajuste la consigne d'\'epaisseur du segment flou pour le suivi fin \\ x && Ajuste la consigne d'\'epaisseur du segment flou pour le suivi rapide \\ -Ctrl-b && Commute le fond d'\'ecran de la fen\^etre principale. \\ +z && Ajuste le seuil du contr\^ole de la consigne d'\'epaisseur \\ +Ctrl-b && Commute le fond d'\'ecran de la fen\^etre principale \\ 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) \\ @@ -57,7 +58,8 @@ Ctrl-u && Commute l'affichage des bords des segments flous. \\ Ctrl-v && Commute l'affichage du r\'esultat de la d\'etection en console (verbose) \\ Ctrl-w && Commute l'ajustement de la consigne d'\'epaisseur sur le segment \\ Ctrl-x && Commute le recentrage du scan sur le segment d\'etect\'e \\ -Ctrl-y && Commute l'affichage des pixels des segments flous. \\ +Ctrl-y && Commute l'affichage des pixels des segments flous \\ +Ctrl-z && Commute le contr\^ole de la consigne d'\'epaisseur \\ 1 && Commute la visu des segments (pixels) \\ 2 && Commute la visu de l'accumulateur \\ 3 && Commute la visu des profils \\ diff --git a/Methode/methode.tex b/Methode/methode.tex index 7f4ed6d..9fccb59 100755 --- a/Methode/methode.tex +++ b/Methode/methode.tex @@ -189,10 +189,14 @@ un segment flou \`a partir des sommets de gradients, correctement orient\'es d\'ecroissantes, trouv\'es dans la barre. \item Aucun test de voisinage. \item Tol\'erance aux interruptions : 5 pixels. -\item Amincissement (activ\'e par d\'efaut) : \`a partir de 20 balayages, -la consigne d'\'epaisseur est r\'eduite de 2\% \`a chaque balayage -jusqu'\`a atteindre une valeur minimale de 150\% de l'\'epaisseur du segment -flou construit. +\item Amincissement progressif (d\'esactiv\'e par d\'efaut) : +\`a partir de 20 balayages, la consigne d'\'epaisseur est r\'eduite de 2\% +\`a chaque balayage jusqu'\`a atteindre une valeur minimale de 150\% de +l'\'epaisseur du segment flou construit. +\item Contr\^ole de la consigne d'\'epaisseur (activ\'e par d\'efaut) : +au bout de $N$ ($N=20$ par d\'efaut) ajouts de points sans influence sur la +largeur minimale du segment flou, la consigne d'\'epaisseur est fix\'ee +\`a la largeur minimale, de sorte que le segment ne peut plus s'\'epaissir. \end{itemize} \end{itemize} -- GitLab