diff --git a/Code/FBSD/BSTools/bsdetectionwidget.cpp b/Code/FBSD/BSTools/bsdetectionwidget.cpp
index 130ddbc0762bb75f8e8fbf7b31ea48f67b7c827c..0d5fd2901e1a4f862ff248988187a8ef5239e3f6 100755
--- a/Code/FBSD/BSTools/bsdetectionwidget.cpp
+++ b/Code/FBSD/BSTools/bsdetectionwidget.cpp
@@ -1,8 +1,8 @@
-#include <QtGui>
 #include <iostream>
 #include <fstream>
 #include <cstdlib>
 #include <ctime>
+#include <cmath>
 #include "bsdetectionwidget.h"
 
 using namespace std;
@@ -35,10 +35,11 @@ BSDetectionWidget::BSDetectionWidget (QWidget *parent)
   strucview = NULL;
   profileview = NULL;
   idetview = NULL;
+  cannyview = NULL;
 
   // Sets initial user outputs parameters
   verbose = false;
-  stats = false;
+  statsOn = false;
   background = BACK_IMAGE;
   bsBoundsVisible = false;
   blevel = 0;
@@ -69,6 +70,7 @@ BSDetectionWidget::~BSDetectionWidget ()
   if (strucview != NULL) delete strucview;
   if (profileview != NULL) delete profileview;
   if (idetview != NULL) delete idetview;
+  if (cannyview != NULL) delete cannyview;
 }
 
 
@@ -392,13 +394,14 @@ void BSDetectionWidget::mouseMoveEvent (QMouseEvent *event)
 
 void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
 {
+  int count = 0;
   if (isActiveWindow ()) switch (event->key ())
   {
     case Qt::Key_A :
       // Registers the last extracted blurred segment
-      if (saveExtractedSegment ())
-        cout << "Last blurred segment(s) registered" << endl;
-      else cout << "No last segment(s) to register" << endl;
+      count = saveExtractedSegment ();
+      cout << count << " new segment(s) -> "
+           << extractedSegments.size () << " segments registered" << endl;
       break;
 
     case Qt::Key_B :
@@ -422,8 +425,8 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
 
     case Qt::Key_C :
       // Clears the registered blurred segments
+      cout << "Withdraws registered segments" << endl;
       clearSavedSegments ();
-      cout << "Registered segments withdrawn" << endl;
       break;
 
     case Qt::Key_D :
@@ -431,9 +434,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Switches density test at initial step
         detector.switchDensityTest ();
-        extract ();
         cout << "Density test : "
              << (detector.isDensityTestOn () ? "on" : "off") << endl;
+        extract ();
       }
       break;
 
@@ -474,9 +477,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Switches length test at final step
         detector.switchFinalLengthTest ();
-        extract ();
         cout << "Final length test : "
              << (detector.isFinalLengthTestOn () ? "on" : "off") << endl;
+        extract ();
       }
       else
       {
@@ -547,9 +550,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Switches density test at final step
         detector.switchFinalDensityTest ();
-        extract ();
         cout << "Final density test : "
              << (detector.isFinalDensityTestOn () ? "on" : "off") << endl;
+        extract ();
       }
       else
       {
@@ -575,8 +578,8 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         // Runs an automatic detection
         udef = false;
         detector.resetMaxDetections ();
+        cout << "Detects all segments" << endl;
         extract ();
-        cout << "All segments detected" << endl;
       }
       break;
 
@@ -585,9 +588,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Switches the initial detection extension limitation
         detector.switchInitialBounding ();
-        extract ();
         cout << "Initial step max extension = "
              << detector.initialDetectionMaxExtent () << endl;
+        extract ();
       }
       else
       {
@@ -596,9 +599,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         if (! bsl.empty ())
         {
           detector.incMaxDetections (event->modifiers () & Qt::ShiftModifier);
-          extract ();
           cout << "Selection of segment "
                << detector.getMaxDetections () << endl;
+          extract ();
         }
       }
       break;
@@ -615,15 +618,15 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       else
       {
         // Outputs the detected segment
+        cout << "Outputs detection result" << endl;
         writeDetectionResult ();
-        cout << "Detection result output" << endl;
       }
       break;
 
     case Qt::Key_P :
       if (event->modifiers () & Qt::ControlModifier)
       {
-        // Switches the preliminary detection
+        // Switchues the preliminary detection
         detector.switchPreliminary ();
         cout << "Initial detection duplication "
              << (detector.isPreliminary () ? "on" : "off") << endl;
@@ -632,8 +635,8 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       else
       {
         // Captures main window
+        cout << "Saves main window in capture.png" << endl;
         augmentedImage.save ("capture.png");
-        cout << "Main window shot in capture.png" << endl;
       }
       break;
 
@@ -649,8 +652,8 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       else
       {
         // Displays registered blurred segments
+        cout << "Displays all registered segments" << endl;
         displaySavedSegments ();
-        cout << "All registered segments displayed" << endl;
       }
       break;
 
@@ -659,9 +662,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Toggles the occupancy mask dilation type
         gMap->toggleMaskDilation ();
-        extract ();
         cout << "Occupancy mask dilation size : "
              << gMap->getMaskDilation () << endl;
+        extract ();
       }
       else
       {
@@ -678,18 +681,18 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Switches the interruption handling
         detector.switchAutoRestart ();
-        extract ();
         cout << "Segment continuation after = "
              << detector.getRestartOnLack () << " pixels" << endl;
+        extract ();
       }
       else
       {
         // Tunes the pixel lack tolerence value
         detector.setPixelLackTolerence (detector.getPixelLackTolerence () +
           (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
-        extract ();
         cout << "Tolerence to detection lacks = "
              << detector.getPixelLackTolerence () << " pixels" << endl;
+        extract ();
       }
       break;
 
@@ -700,9 +703,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         detector.toggleThinning ();
         if (detector.isThinningOn () && detector.isThickenningOn ())
           detector.toggleThickenning ();
-        extract ();
         cout << "Thinning "
              << (detector.isThinningOn () ? "on" : "off") << endl;
+        extract ();
       }
       break;
 
@@ -744,9 +747,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         // Tunes the assigned max width margin for fine tracks
         detector.setFastTracksMaxMargin (detector.fastTracksMaxMargin () +
           (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
-        extract ();
         cout << "Fast tracks max width margin = "
              << detector.fastTracksMaxMargin () << endl;
+        extract ();
       }
       break;
 
@@ -764,9 +767,9 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         // Tunes the assigned max width for fast tracks
         detector.setFineTracksMaxWidth (detector.fineTracksMaxWidth () +
           (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
-        extract ();
         cout << "Initial assigned width = "
              << detector.fineTracksMaxWidth () << endl;
+        extract ();
       }
       break;
 
@@ -783,8 +786,8 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Tunes the background image black level
         incBlackLevel ((event->modifiers () & Qt::ShiftModifier) ? -1 : 1);
-        displayDetectionResult ();
         cout << "Background black level = " << getBlackLevel () << endl;
+        displayDetectionResult ();
       }
       break;
 
@@ -795,38 +798,75 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         detector.toggleThickenning ();
         if (detector.isThickenningOn () && detector.isThinningOn ())
           detector.toggleThinning ();
-        extract ();
         cout << "Assigned width control "
              << (detector.isThickenningOn () ? "on" : "off") << endl;
+        extract ();
       }
       else
       {
         // Tunes the thickenning limit
         detector.incThickenningLimit (
           (event->modifiers () & Qt::ShiftModifier) ? -1 : 1);
-        extract ();
         cout << "Thickenning limit = " << detector.getThickenningLimit ()
              << " pixels" << endl;
+        extract ();
       }
       break;
 
     case Qt::Key_Exclam :
       switchHighlightColors ();
+      cout << "Highlight colors "
+           << (isHighlightColorsOn () ? "on" : "off") << endl;
       displayDetectionResult ();
       break;
 
     case Qt::Key_Equal :
       switchArlequin ();
+      cout << "Random coloring " << (isArlequinOn () ? "on" : "off") << endl;
       displayDetectionResult ();
       break;
 
     case Qt::Key_Asterisk :
       switchStats ();
+      cout << "Stats display " << (isStatsOn () ? "on" : "off") << endl;
       displayDetectionResult ();
       break;
 
     case Qt::Key_Dollar :
       writeTest ();
+      cout << "Selection stroke saved" << endl;
+      break;
+
+    case Qt::Key_Percent :
+/*
+      cout << "CannyLine compares BS" << endl;
+      detector.detectAll ();
+      if (cannyview == NULL)
+      {
+        cannyview = new BSCannyView (&loadedImage, &detector);
+      }
+      cannyview->testBS ();
+      cannyview->show ();
+      cannyview->update ();
+      displayDetectionResult ();
+      cout << "CannyLine compares BS" << endl;
+*/
+      break;
+
+    case Qt::Key_Ugrave :
+/*
+      cout << "CannyLine compares DSS" << endl;
+      detector.detectAll ();
+      if (cannyview == NULL)
+      {
+        cannyview = new BSCannyView (&loadedImage, &detector);
+      }
+      cannyview->testDSS ();
+      cannyview->show ();
+      cannyview->update ();
+      displayDetectionResult ();
+      cout << "CannyLine compares DSS" << endl;
+*/
       break;
 
     case Qt::Key_Plus :
@@ -835,6 +875,7 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         zoom /= 2;
         xShift = xShift * 2 - maxWidth / 2;
         yShift = yShift * 2 - maxHeight / 2;
+        cout << "Zoom : " << zoom << endl;
         displayDetectionResult ();
       }
       break;
@@ -851,6 +892,7 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
         if (yShift > 0) yShift = 0;
         if ((maxHeight - yShift) * zoom > height)
           yShift = maxHeight - height / zoom;
+        cout << "Zoom : " << zoom << endl;
         displayDetectionResult ();
       }
       break;
@@ -858,6 +900,7 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
     case Qt::Key_Left :
       xShift += 50;
       if (xShift > 0) xShift = 0;
+      cout << "X-shift : " << xShift << endl;
       displayDetectionResult ();
       break;
 
@@ -865,12 +908,14 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       xShift -= 50;
       if ((maxWidth - xShift) * zoom > width)
         xShift = maxWidth - width / zoom;
+      cout << "X-shift : " << xShift << endl;
       displayDetectionResult ();
       break;
 
     case Qt::Key_Up :
       yShift += 50;
       if (yShift > 0) yShift = 0;
+      cout << "Y-shift : " << yShift << endl;
       displayDetectionResult ();
       break;
 
@@ -878,6 +923,7 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       yShift -= 50;
       if ((maxHeight - yShift) * zoom > height)
         yShift = maxHeight - height / zoom;
+      cout << "Y-shift : " << yShift << endl;
       displayDetectionResult ();
       break;
 
@@ -1175,7 +1221,7 @@ void BSDetectionWidget::displayDetectionResult ()
       strucview->repaint ();
     }
     if (verbose) writeDetectionStatus ();
-    if (stats) writeStats ();
+    if (statsOn) writeStats ();
   }
 }
 
@@ -1202,12 +1248,26 @@ void BSDetectionWidget::displaySavedSegments ()
 }
 
 
-bool BSDetectionWidget::saveExtractedSegment ()
+int BSDetectionWidget::saveExtractedSegment ()
 {
-  if (detector.isMultiSelection ())
+  int count = 0;
+  vector<BlurredSegment *> bss = detector.getBlurredSegments ();
+  if (bss.empty ())
+  {
+    BlurredSegment *bs = detector.getBlurredSegment ();
+    if (bs != NULL)
+    {
+      ExtractedSegment es;
+      es.bs = bs;
+      es.p1 = p1;
+      es.p2 = p2;
+      extractedSegments.push_back (es);
+      detector.preserveFormerBlurredSegment ();
+      count = 1;
+    }
+  }
+  else
   {
-    vector<BlurredSegment *> bss = detector.getBlurredSegments ();
-    if (bss.empty ()) return false;
     vector<BlurredSegment *>::const_iterator it = bss.begin ();
     while (it != bss.end ())
     {
@@ -1218,19 +1278,9 @@ bool BSDetectionWidget::saveExtractedSegment ()
       extractedSegments.push_back (es);
     }
     detector.preserveFormerBlurredSegments ();
+    count = (int) (bss.size ());
   }
-  else
-  {
-    BlurredSegment *bs = detector.getBlurredSegment ();
-    if (bs == NULL) return false;
-    ExtractedSegment es;
-    es.bs = bs;
-    es.p1 = p1;
-    es.p2 = p2;
-    extractedSegments.push_back (es);
-    detector.preserveFormerBlurredSegment ();
-  }
-  return true;
+  return count;
 }
 
 
@@ -1334,6 +1384,9 @@ void BSDetectionWidget::writeDetectionStatus ()
   else if (res == BSDetector::RESULT_FINAL_TOO_SPARSE)
     cout << "Extraction : unsuccessful density test at final detection."
          << endl;
+  else if (res == BSDetector::RESULT_FINAL_TOO_SMALL)
+    cout << "Extraction : unsuccessful spread test at final detection."
+         << endl;
   else if (res == BSDetector::RESULT_FINAL_TOO_MANY_OUTLIERS)
     cout << "Extraction : unsuccessful filter test at final detection."
          << endl;
@@ -1493,13 +1546,36 @@ void BSDetectionWidget::performanceTest ()
 {
   if (p1.equals (p2))
   {
-    // No stroke -> automatic
-    cout << "Automatic extraction test" << endl;
-    clock_t start = clock ();
-    for (int i = 0; i < 100; i++) detector.detectAll ();
-    double diff = (clock () - start) / (double) CLOCKS_PER_SEC;
-    cout << "Test run : " << diff << endl;
-    extract ();
+/*
+    if (cannyview)
+    {
+      // Canny compare -> automatic
+      cout << "Automatic extraction test" << endl;
+      clock_t start = clock ();
+      for (int i = 0; i < 100; i++)
+      {
+        if (gMap != NULL) delete gMap;
+        gMap = new VMap (width, height, getBitmap (augmentedImage),
+                         VMap::TYPE_SOBEL_5X5);
+        detector.setGradientMap (gMap);
+        buildGradientImage (0);
+        detector.detectAll ();
+      }
+      double diff = (clock () - start) / (double) CLOCKS_PER_SEC;
+      cout << "Test run : " << diff << endl;
+      extract ();
+    }
+    else
+    {
+*/
+      // No stroke -> automatic
+      cout << "Automatic extraction test" << endl;
+      clock_t start = clock ();
+      for (int i = 0; i < 100; i++) detector.detectAll ();
+      double diff = (clock () - start) / (double) CLOCKS_PER_SEC;
+      cout << "Test run : " << diff << endl;
+      extract ();
+//    }
   }
   else
   {
diff --git a/Code/FBSD/BSTools/bsdetectionwidget.h b/Code/FBSD/BSTools/bsdetectionwidget.h
index c5b2775ff8a780881bb626b0a12b376a76ac3060..1cf240e6dccc5c239bdabe1684d587edb556b10e 100755
--- a/Code/FBSD/BSTools/bsdetectionwidget.h
+++ b/Code/FBSD/BSTools/bsdetectionwidget.h
@@ -12,6 +12,7 @@
 #include "bsstructureview.h"
 #include "bsprofileview.h"
 #include "bsidetview.h"
+#include "bscannyview.h"
 
 using namespace std;
 
@@ -117,20 +118,34 @@ public:
    */
   void switchIdetAnalyzer ();
 
+  /**
+   * \brief Return whether the blurred segment highlight colors are set.
+   */
+  inline bool isHighlightColorsOn () const { return darkHighlightOn; }
+
   /**
    * \brief Switches the blurred segment highlight colors.
    */
   void switchHighlightColors ();
 
+  /**
+   * \brief Returns whether random color display modality is set.
+   */
+  inline bool isArlequinOn () const { return arlequinOn; }
+
   /**
    * \brief Switches the random color display modality.
    */
   void switchArlequin ();
 
+  /**
+   * \brief Returns whether extraction stats are displayed. */
+  inline bool isStatsOn () const { return statsOn; }
+
   /**
    * \brief Switches the extraction stats display on or off.
    */
-  inline void switchStats () { stats = ! stats; }
+  inline void switchStats () { statsOn = ! statsOn; }
 
   /**
    * \brief Switches the extraction result display on or off.
@@ -246,7 +261,7 @@ private:
   /** Black level used to lighten background images. */
   int blevel;
   /** Flag indicating whether detection stats should be output. */
-  bool stats;
+  bool statsOn;
   /** Flag indicating whether detection result should be output. */
   bool verbose;
 
@@ -288,6 +303,8 @@ private:
   // BSAccumulatorView *accuview;
   /** Blurred segment contents view. */
   BSStructureView *strucview;
+  /** CannyLine comparator view. */
+  BSCannyView *cannyview;
 
   /** Aggregation of segment extraction results with initial conditions. */
   struct ExtractedSegment
@@ -403,9 +420,9 @@ private:
 
   /**
    * \brief Registers the last extracted blurred segment.
-   * Returns whether something is saved or not.
+   * Returns the count of registered segments more.
    */
-  bool saveExtractedSegment ();
+  int saveExtractedSegment ();
 
   /**
    * \brief Clears off the saved blurred segments.
diff --git a/Code/FBSD/BSTools/bsrandomtester.cpp b/Code/FBSD/BSTools/bsrandomtester.cpp
index 84551ec90920145b0eeeb31ad5c79c2045b268d6..ab2d4c5574df4b62a9fe6891564eed1adf58ccb4 100755
--- a/Code/FBSD/BSTools/bsrandomtester.cpp
+++ b/Code/FBSD/BSTools/bsrandomtester.cpp
@@ -52,10 +52,9 @@ BSRandomTester::BSRandomTester ()
   c_ldet = new int[nbt];
   c_unmatch = new int[nbt];
   c_undet = new int[nbt];
-  c_trueArea = new int[nbt];
-  c_falseArea = new int[nbt];
-  c_redetArea = new int[nbt];
+  c_true = new int[nbt];
   c_false = new int[nbt];
+  c_redet = new int[nbt];
 
   m_precision = new double[nbt];
   m_recall = new double[nbt];
@@ -69,6 +68,7 @@ BSRandomTester::BSRandomTester ()
   m_absadiff = new double[nbt];
   m_long_absadiff = new double[nbt];
 
+  gMap = NULL;
   detectors = new BSDetector[nbdets];
   for (int i = 0; i < nbdets; i++)
   {
@@ -103,10 +103,9 @@ BSRandomTester::~BSRandomTester ()
   delete [] m_fmeasure;
   delete [] m_recall;
   delete [] m_precision;
+  delete [] c_redet;
   delete [] c_false;
-  delete [] c_redetArea;
-  delete [] c_falseArea;
-  delete [] c_trueArea;
+  delete [] c_true;
   delete [] c_undet;
   delete [] c_unmatch;
   delete [] c_ldet;
@@ -166,7 +165,7 @@ void BSRandomTester::randomTest ()
       for (int i = 0; i < nbsegs; i++) rbs[i].clear ();
       c_unmatch[num] = 0;
       int nbdssnul = 0;
-      c_ldet[run] = 0;
+      c_ldet[num] = 0;
       double nomatchlength = 0.;
       vector<BlurredSegment *> bss = detectors[det].getBlurredSegments ();
       vector<BlurredSegment *>::iterator bsit = bss.begin ();
@@ -214,11 +213,13 @@ void BSRandomTester::randomTest ()
           {
             double denom = rdir[si].norm2 () * dssdir.norm2 ();
             score[si] = rdir[si].squaredScalarProduct (dssdir) / denom;
-            Vr2i bsac = rp1[si].vectorTo (bsc);
-            denom = rdir[si].norm2 () * bsac.norm2 ();
-            score[si] *= rdir[si].squaredScalarProduct (bsac) / denom;
-            if (rdir[si].scalarProduct (bsac) < 0) score[si] = 0.;
+            Vr2i bsca = rp1[si].vectorTo (bsc);
             Vr2i bscb = bsc.vectorTo (rp2[si]);
+            Vr2i *bsac = (rp1[si].chessboard (bsc) < sminlength / 2 ?
+                          &bscb : &bsca);
+            denom = rdir[si].norm2 () * bsac->norm2 ();
+            score[si] *= rdir[si].squaredScalarProduct (*bsac) / denom;
+            if (rdir[si].scalarProduct (bsca) < 0) score[si] = 0.;
             if (rdir[si].scalarProduct (bscb) < 0) score[si] = 0.;
             if (minscore < score[si])
             {
@@ -232,7 +233,7 @@ void BSRandomTester::randomTest ()
             c_unmatch[num] ++;
             nomatchlength += sqrt (bsl2);
           }
-          delete dss;
+          if (unbiasOn) delete dss;
         }
         else nbdssnul ++;
         bsit ++;
@@ -251,34 +252,39 @@ void BSRandomTester::randomTest ()
       }
       if (dispLast && run == nbruns - 1) createMap (names[det]);
       c_undet[num] = 0;
-      c_trueArea[num] = 0;
-      c_falseArea[num] = 0;
+      c_true[num] = 0;
+      c_false[num] = 0;
       for (int i = 0; i < width * height; i++)
       {
         if (stilltofind_map[i]) c_undet[num] ++;
-        if (foundin_map[i]) c_trueArea[num] ++;
-        if (foundout_map[i]) c_falseArea[num] ++;
+        if (foundin_map[i]) c_true[num] ++;
+        if (foundout_map[i]) c_false[num] ++;
       }
       if (dispEach)
         cout << (nbIniPts[run] - c_undet[num]) << " points detected on "
              << nbIniPts[run] << " ("
              << (nbIniPts[run] - c_undet[num]) * 100 / (double) nbIniPts[run]
              << " %)" << endl;
-      c_redetArea[num] = 0;
+      c_redet[num] = 0;
       for (int i = 0; i < width * height; i++)
-        if (hit_map[i] > 1) c_redetArea[num] += (hit_map[i] - 1);
+        if (hit_map[i] > 1) c_redet[num] += (hit_map[i] - 1);
       if (dispEach)
-        cout << c_redetArea[num] << " points redetected on " << nbIniPts[run]
-             << " (" << c_redetArea[num] * 100 / (double) nbIniPts[run]
+        cout << c_redet[num] << " points redetected on " << nbIniPts[run]
+             << " (" << c_redet[num] * 100 / (double) nbIniPts[run]
              << " %)" << endl;
-      c_false[num] = 0;
-      for (int i = 0; i < width * height; i++)
-        if (hit_map[i] < 0) c_false[num] ++;
       m_precision[num] = nbIniPts[run] - c_undet[num];
       m_recall[num] = m_precision[num] / nbIniPts[run];
-      m_precision[num] = m_precision[num] / (m_precision[num] + c_false[num]);
-      m_fmeasure[num] = 2 * m_precision[num] * m_recall[num]
-                      / (m_precision[num] + m_recall[num]);
+      if (m_precision[num] + c_false[num] != 0)
+      {
+        m_precision[num] = m_precision[num] / (m_precision[num] + c_false[num]);
+        m_fmeasure[num] = 2 * m_precision[num] * m_recall[num]
+                          / (m_precision[num] + m_recall[num]);
+      }
+      else
+      {
+        m_precision[num] = 0.;
+        m_fmeasure[num] = 0.;
+      }
       if (dispEach)
       {
         cout << c_false[num] << " false points detected on " << nbIniPts[run]
@@ -338,7 +344,7 @@ void BSRandomTester::randomTest ()
             m_adiff[num] += (onleft ? ang : -ang);
             if (bsl2 > longEdgeThreshold) m_long_absadiff[num] += ang;
           }
-          delete mydss;
+          if (unbiasOn) delete mydss;
           sit ++;
         }
       }
@@ -418,6 +424,7 @@ void BSRandomTester::randomTest ()
     cout << mean << " (pm " << sdev
          << ") undetected segments per image" << endl;
 
+    /*
     mean = 0.;
     sdev = 0.;
     for (int i = 0; i < nbruns; i++)
@@ -429,16 +436,17 @@ void BSRandomTester::randomTest ()
               * ((nbIniPts[i] - c_undet[det * nbruns + i])
                  / (double) nbIniPts[i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
-    cout << "Recall : " << 100 * mean << " (pm " << 100 * sdev
+    cout << "Weighted recall : " << 100 * mean << " (pm " << 100 * sdev
          << ") % of points found" << endl;
+    */
 
     mean = 0.;
     sdev = 0.;
-    for (int i = 0; i < nbruns; i++) mean += c_redetArea[det * nbruns + i];
+    for (int i = 0; i < nbruns; i++) mean += c_redet[det * nbruns + i];
     mean /= total_nbIniPts;
     for (int i = 0; i < nbruns; i++)
-      sdev += (c_redetArea[det * nbruns + i] / (double) nbIniPts[i] - mean)
-              * (c_redetArea[det * nbruns + i] / (double) nbIniPts[i] - mean);
+      sdev += (c_redet[det * nbruns + i] / (double) nbIniPts[i] - mean)
+              * (c_redet[det * nbruns + i] / (double) nbIniPts[i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
     cout << 100 * mean << " (pm " << 100 * sdev
          << ") % of points found more than once (redetections)" << endl;
@@ -454,6 +462,7 @@ void BSRandomTester::randomTest ()
     cout << 100 * mean << " (pm " << 100 * sdev
          << ") % false points produced" << endl;
 
+    /*
     mean = 0.;
     sdev = 0.;
     int numer = 0;
@@ -469,7 +478,8 @@ void BSRandomTester::randomTest ()
       sdev += (m_precision[det * nbruns + i] - mean)
               * (m_precision[det * nbruns + i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
-    cout << "Precision : " << mean << " (pm " << sdev << ")" << endl;
+    cout << "Weighted precision : " << mean << " (pm " << sdev << ")" << endl;
+    */
 
     mean = 0.;
     sdev = 0.;
@@ -479,8 +489,7 @@ void BSRandomTester::randomTest ()
       sdev += (m_precision[det * nbruns + i] - mean)
               * (m_precision[det * nbruns + i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
-    cout << "Statistical precision : " << mean
-         << " (pm " << sdev << ")" << endl;
+    cout << "Precision : " << mean << " (pm " << sdev << ")" << endl;
 
     mean = 0.;
     sdev = 0.;
@@ -490,7 +499,7 @@ void BSRandomTester::randomTest ()
       sdev += (m_recall[det * nbruns + i] - mean)
               * (m_recall[det * nbruns + i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
-    cout << "Statistical recall : " << mean << " (pm " << sdev << ")" << endl;
+    cout << "Recall : " << mean << " (pm " << sdev << ")" << endl;
 
     mean = 0.;
     sdev = 0.;
@@ -500,8 +509,7 @@ void BSRandomTester::randomTest ()
       sdev += (m_fmeasure[det * nbruns + i] - mean)
               * (m_fmeasure[det * nbruns + i] - mean);
     sdev = sqrt (sdev / (nbruns - 1));
-    cout << "Statistical F-measure : " << mean
-         << " (pm " << sdev << ")" << endl;
+    cout << "F-measure : " << mean << " (pm " << sdev << ")" << endl;
     total = 0;
     for (int i = 0; i < nbruns; i++) total += m_matched[det * nbruns + i];
 
@@ -610,39 +618,46 @@ void BSRandomTester::generateImage ()
       val = 255 - (rand () % 30);
       image.setPixel (i, j, val + val * 256 + val * 256 * 256);
     }
+
+  bool nok;
+  double score1, score2, score3;
+  Pt2i bsc1, bsc2;
+  Vr2i ali;
   for (int i = 0; i < nbsegs; i++)
   {
-    rp1[i].set (margin + rand () % swidth, margin + rand () % sheight);
-    bool nok = false;
     do
     {
       nok = false;
-      rp2[i].set (margin + rand () % swidth, margin + rand () % sheight);
+      rp1[i].set (margin + (rand () % swidth), margin + (rand () % sheight));
+      rp2[i].set (margin + (rand () % swidth), margin + (rand () % sheight));
       if (rp1[i].chessboard (rp2[i]) < sminlength) nok = true;
       else
       {
-        double score1, score2, score3;
         rdir[i] = rp1[i].vectorTo (rp2[i]);
-        Pt2i bsc ((rp1[i].x () + rp2[i].x ()) / 2,
+        bsc1.set ((rp1[i].x () + rp2[i].x ()) / 2,
                   (rp1[i].y () + rp2[i].y ()) / 2);
-        for (int si = 0; (! nok) && si < i - 1; si ++)
+        for (int si = 0; (! nok) && si < i; si ++)
         {
           score1 = rdir[si].squaredScalarProduct (rdir[i])
-                          / (rdir[si].norm2 () * rdir[i].norm2 ());
-          Vr2i ali = rp1[si].vectorTo (bsc);
+                          / (double) (rdir[si].norm2 () * rdir[i].norm2 ());
+          if (rp1[si].chessboard (bsc1) < sminlength / 2)
+            ali = bsc1.vectorTo (rp2[si]);
+          else ali = rp1[si].vectorTo (bsc1);
           score2 = rdir[si].squaredScalarProduct (ali)
-                   / (rdir[si].norm2 () * ali.norm2 ());
-          bsc.set ((rp1[si].x () + rp2[si].x ()) / 2,
-                   (rp1[si].y () + rp2[si].y ()) / 2);
-          ali = rp1[i].vectorTo (bsc);
+                   / (double) (rdir[si].norm2 () * ali.norm2 ());
+          bsc2.set ((rp1[si].x () + rp2[si].x ()) / 2,
+                    (rp1[si].y () + rp2[si].y ()) / 2);
+          if (rp1[i].chessboard (bsc2) < sminlength / 2)
+            ali = bsc2.vectorTo (rp2[i]);
+          else ali = rp1[i].vectorTo (bsc2);
           score3 = rdir[i].squaredScalarProduct (ali)
-                   / (rdir[i].norm2 () * ali.norm2 ());
-          if (score1 > 0.7 && (score2 > 0.7 || score3 > 0.7)) nok = true;
+                   / (double) (rdir[i].norm2 () * ali.norm2 ());
+          if (score1 > 0.9 && (score2 > 0.9 || score3 > 0.9)) nok = true;
         }
       }
     }
     while (nok);
-    rw[i] = sminwidth + rand () % (smaxwidth - sminwidth);
+    rw[i] = sminwidth + (rand () % (smaxwidth - sminwidth));
 
     DigitalStraightSegment dss (rp1[i], rp2[i], rw[i]);
     vector<Pt2i> pix;
@@ -663,6 +678,7 @@ void BSRandomTester::generateImage ()
       tofind_map[j * width + i] =
         QColor (image.pixel (i, height - 1 - j)).value () < 10;
         // QColor (image.pixel (i, height - 1 - j)).value () > 200; // ZZZ
+  if (dispEach) cout << "New segments generated" << endl;
 }
 
 
diff --git a/Code/FBSD/BSTools/bsrandomtester.h b/Code/FBSD/BSTools/bsrandomtester.h
index 5b162f5b1d4565ee58d7ebdcc8ad074ee35372ac..773b4b7dd19198a552c893c940914a5c78bb7244 100755
--- a/Code/FBSD/BSTools/bsrandomtester.h
+++ b/Code/FBSD/BSTools/bsrandomtester.h
@@ -79,15 +79,16 @@ private:
   int *rw;
   /** Occupancy map. */
   bool *tofind_map;
-  /** Detected points map. */
+  /** Amount of detected (positive) points.
+   * Negative sign for false positives, positive sign for true positives. */
   int *hit_map;
-  /** Undetected points map. */
+  /** Undetected points map (false negative points). */
   bool *stilltofind_map;
-  /** Found points map. */
+  /** Found points map (positive points). */
   bool *found_map;
-  /** Correct found points map. */
+  /** Correct found points map (true positive points). */
   bool *foundin_map;
-  /** Incorrect found points map. */
+  /** Incorrect found points map (false positive points). */
   bool *foundout_map;
 
   /** Per image results display modality. */
@@ -106,7 +107,7 @@ private:
   /** Gradient extraction bias value. */
   AbsRat biasVal;
 
-  /** ???. */
+  /** Amount of points to find (points of synthetized segments). */
   int *nbIniPts;
   /** Amount of tests on local minima per each detection. */
   int *c_trials;
@@ -116,16 +117,14 @@ private:
   int *c_ldet;
   /** Amount of unmatched segments per each detection. */
   int *c_unmatch;
-  /** Amount of ??? per each detection. */
+  /** Amount of undetected (false negative) points per each detection. */
   int *c_undet;
-  /** Amount of true area pixels per each detection. */
-  int *c_trueArea;
-  /** Amount of false area pixels per each detection. */
-  int *c_falseArea;
-  /** Amount of redetected area pixels per each detection. */
-  int *c_redetArea;
-  /** Amount of false pixels per each detection. */
+  /** Amount of trully detected (true positive) points per each detection. */
+  int *c_true;
+  /** Amount of wrongly detected (false positive) points per each detection. */
   int *c_false;
+  /** Amount of redetected points per each detection. */
+  int *c_redet;
 
   /** Measured precision per detector and per test. */
   double *m_precision;
diff --git a/Code/FBSD/BlurredSegment/bsdetector.cpp b/Code/FBSD/BlurredSegment/bsdetector.cpp
index a4b1b26e3851ed352e7f86e93a1d78b28da14751..9458174830fc808c7b4783bdadaeac534b8d3295 100755
--- a/Code/FBSD/BlurredSegment/bsdetector.cpp
+++ b/Code/FBSD/BlurredSegment/bsdetector.cpp
@@ -7,6 +7,7 @@ const int BSDetector::STEP_FINAL = 0;
 const int BSDetector::STEP_INITIAL = 1;
 const int BSDetector::STEP_PRELIM = 2;
 
+const int BSDetector::RESULT_VOID = -2;
 const int BSDetector::RESULT_UNDETERMINED = -1;
 const int BSDetector::RESULT_OK = 0;
 const int BSDetector::RESULT_PRELIM_NO_DETECTION = 1;
@@ -19,7 +20,8 @@ const int BSDetector::RESULT_INITIAL_CLOSE_ORIENTATION = 15;
 const int BSDetector::RESULT_FINAL_NO_DETECTION = 21;
 const int BSDetector::RESULT_FINAL_TOO_FEW = 22;
 const int BSDetector::RESULT_FINAL_TOO_SPARSE = 23;
-const int BSDetector::RESULT_FINAL_TOO_MANY_OUTLIERS = 24;
+const int BSDetector::RESULT_FINAL_TOO_SMALL = 24;
+const int BSDetector::RESULT_FINAL_TOO_MANY_OUTLIERS = 25;
 
 const int BSDetector::DEFAULT_FAST_TRACK_SCAN_WIDTH = 16;
 const int BSDetector::DEFAULT_FINE_TRACK_MAX_WIDTH = 3;
@@ -66,6 +68,9 @@ BSDetector::BSDetector ()
   densityTestOn = true;
   finalDensityTestOn = false;
   finalLengthTestOn = false;
+  finalSpreadTestOn = true;
+  finalSpreadMin = 30;
+  // nbSmallBS = 0;
   multiSelection = false;
   autodet = false;
   autoResol = DEFAULT_AUTO_RESOLUTION;
@@ -112,6 +117,7 @@ void BSDetector::detectAll ()
 
   bool isnext = true;
   nbtrials = 0;
+  // nbSmallBS = 0;
   int width = gMap->getWidth ();
   int height = gMap->getHeight ();
   for (int x = width / 2; isnext && x > 0; x -= autoResol)
@@ -123,6 +129,7 @@ void BSDetector::detectAll ()
   for (int y = height / 2 + autoResol; isnext && y < height - 1; y += autoResol)
     isnext = runMultiDetection (Pt2i (0, y), Pt2i (width - 1, y));
   if (maxtrials > (int) (mbsf.size ())) maxtrials = 0;
+  // cout << nbSmallBS << " petits BS elimines" << endl;
 
   gMap->setMasking (false);
 }
@@ -137,6 +144,7 @@ void BSDetector::detectAllWithBalancedXY ()
 
   bool isnext = true;
   nbtrials = 0;
+  // nbSmallBS = 0;
   int width = gMap->getWidth ();
   int height = gMap->getHeight ();
   int xg = width / 2, yb = height / 2;
@@ -170,6 +178,7 @@ void BSDetector::detectAllWithBalancedXY ()
     }
   }
   if (maxtrials > (int) (mbsf.size ())) maxtrials = 0;
+  // cout << nbSmallBS << " petits BS elimines" << endl;
   gMap->setMasking (false);
 }
 
@@ -183,13 +192,15 @@ void BSDetector::detectSelection (const Pt2i &p1, const Pt2i &p2)
     gMap->setMasking (true);
     gMap->clearMask ();
     nbtrials = 0;
+    // nbSmallBS = 0;
     runMultiDetection (p1, p2);
+    // cout << nbSmallBS << " petits BS elimines" << endl;
     if (maxtrials > (int) (mbsf.size ())) maxtrials = 0;
     gMap->setMasking (false);
   }
   else
-    if (oldp) olddetect (p1, p2);
-    else detect (p1, p2);
+    if (oldp) resultValue = olddetect (p1, p2);
+    else resultValue = detect (p1, p2);
 }
 
 
@@ -224,9 +235,10 @@ bool BSDetector::runMultiDetection (const Pt2i &p1, const Pt2i &p2)
       if (edgeDirection != 0) edgeDirection = 1;
       while (isnext && edgeDirection >= -1)
       {
-        if (oldp) olddetect (p1, p2, true, ptstart);
-        else detect (p1, p2, true, ptstart);
-        if (bsf != NULL)
+        int res = RESULT_VOID;
+        if (oldp) res = olddetect (p1, p2, true, ptstart);
+        else res = detect (p1, p2, true, ptstart);
+        if (res == RESULT_OK)
         {
           gMap->setMask (bsf->getAllPoints ());
           mbsf.push_back (bsf);
@@ -243,17 +255,17 @@ bool BSDetector::runMultiDetection (const Pt2i &p1, const Pt2i &p2)
 }
 
 
-void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
-                            bool centralp, const Pt2i &pc)
+int BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
+                           bool centralp, const Pt2i &pc)
 {
   // Entry check
   //------------
   if (p1.equals (p2)
-      || ((! centralp) && p1.chessboard (p2) < BSTracker::MIN_SCAN)) return;
+      || ((! centralp) && p1.chessboard (p2) < BSTracker::MIN_SCAN))
+    return RESULT_VOID;
 
   // Clearance
   //----------
-  resultValue = RESULT_UNDETERMINED;
   bst1->clear ();
   bst2->clear ();
   if (bsini != NULL) delete bsini;
@@ -271,11 +283,8 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
   bsini = bst1->fastTrack (DEFAULT_FAST_TRACK_SCAN_WIDTH / 4,
                            inip1, inip2, iniwidth, inipc);
   if (bsini == NULL || bsini->size () < bsMinSize)
-  {
-    resultValue = (bsini == NULL ? RESULT_INITIAL_NO_DETECTION
-                                 : RESULT_INITIAL_TOO_FEW);
-    return;
-  }
+    return (bsini == NULL ? RESULT_INITIAL_NO_DETECTION
+                          : RESULT_INITIAL_TOO_FEW);
 
   // Density test
   //-------------
@@ -288,10 +297,7 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
     if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2
     int expansion = 1 + mydrlf;
     if (bsini->size () < expansion / 2)
-    {
-      resultValue = RESULT_INITIAL_TOO_SPARSE;
-      return;
-    }
+      return RESULT_INITIAL_TOO_SPARSE;
   }
 */
 
@@ -299,10 +305,7 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
   //-------------------------------------------
   Vr2i bsinidir = bsini->getSupportVector();
   if (bsinidir.orientedAs (inip1.vectorTo (inip2)))
-  {
-    resultValue = RESULT_INITIAL_CLOSE_ORIENTATION;
-    return;
-  }
+    return RESULT_INITIAL_CLOSE_ORIENTATION;
 
   // Gradient reference selection
   //-----------------------------
@@ -320,11 +323,7 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
   bsf = bstold->fineTrack (fmaxWidth, pCenter, bsinidir,
                            4 * fmaxWidth, gRef);
   if (bsf == NULL || bsf->size () < bsMinSize)
-  {
-    resultValue = (bsf == NULL ? RESULT_FINAL_NO_DETECTION
-                               : RESULT_FINAL_TOO_FEW);
-    return;
-  }
+    return (bsf == NULL ? RESULT_FINAL_NO_DETECTION : RESULT_FINAL_TOO_FEW);
 
   // Scan recentering and fitting
   //-----------------------------
@@ -339,10 +338,12 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
                                             4 * fmaxWidth, gRef);
   if (bsf2 == NULL || bsf2->size () < bsMinSize)
   {
-    resultValue = (bsf2 == NULL ? RESULT_FINAL_NO_DETECTION
-                                : RESULT_FINAL_TOO_FEW);
-    if (bsf2 != NULL) delete bsf2;
-    return;
+    if (bsf2 != NULL)
+    {
+      delete bsf2;
+      return RESULT_FINAL_TOO_FEW;
+    }
+    else return RESULT_FINAL_NO_DETECTION;
   }
   else
   {
@@ -357,12 +358,7 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
     DigitalStraightSegment *dss = bsf->getSegment ();
     if (dss == NULL || (int) (bsf->getAllPoints().size ())
                        < (10 * dss->period ()) / dss->width ())
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
   }
 
   // New density test
@@ -375,12 +371,7 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
     if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2
     int expansion = 1 + mydrlf;
     if (bsf->size () < expansion / 2)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
   }
 
   // Connected components analysis
@@ -390,40 +381,30 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
     int bsccp = bsf->countOfConnectedPoints (ccMinSize);
     int bssize = bsf->getAllPoints().size ();
     if (bsccp < bssize / 2)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
 
 /*
     if (bssize < 20 || bsf->countOfConnectedComponents (bssize / 4) == 0)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
 */
   }
 
-  resultValue = RESULT_OK;
+  return RESULT_OK;
 }
 
 
-void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
-                         bool centralp, const Pt2i &pc)
+int BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
+                        bool centralp, const Pt2i &pc)
 {
   // Entry check
   //------------
   if (p1.equals (p2)
-      || ((! centralp) && p1.chessboard (p2) < BSTracker::MIN_SCAN)) return;
+      || ((! centralp) && p1.chessboard (p2) < BSTracker::MIN_SCAN))
+    return RESULT_VOID;
 
 
   // Clearance
   //----------
-  resultValue = RESULT_UNDETERMINED;
   if (prelimDetectionOn) bst0->clear ();
   bst1->clear ();
   bst2->clear ();
@@ -448,11 +429,8 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     bspre = bst0->fastTrack (fmaxWidth + imaxMargin,
                              prep1, prep2, prewidth, prepc);
     if (bspre == NULL || bspre->size () < bsMinSize)
-    {
-      resultValue = (bspre == NULL ? RESULT_PRELIM_NO_DETECTION
-                                   : RESULT_PRELIM_TOO_FEW);
-      return;
-    }
+      return (bspre == NULL ? RESULT_PRELIM_NO_DETECTION
+                            : RESULT_PRELIM_TOO_FEW);
 
     Vr2i v0 = bspre->getSupportVector ();
     int l = v0.chessboard ();
@@ -481,11 +459,8 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
   bsini = bst1->fastTrack (fmaxWidth + imaxMargin,
                            inip1, inip2, iniwidth, inipc);
   if (bsini == NULL || bsini->size () < bsMinSize)
-  {
-    resultValue = (bsini == NULL ? RESULT_INITIAL_NO_DETECTION
-                                 : RESULT_INITIAL_TOO_FEW);
-    return;
-  }
+    return (bsini == NULL ? RESULT_INITIAL_NO_DETECTION
+                          : RESULT_INITIAL_TOO_FEW);
 
   // Density test
   //-------------
@@ -497,10 +472,7 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2
     int expansion = 1 + mydrlf;
     if (bsini->size () < expansion / 2)
-    {
-      resultValue = RESULT_INITIAL_TOO_SPARSE;
-      return;
-    }
+      return RESULT_INITIAL_TOO_SPARSE;
   }
 
   // Filtering the initial segment
@@ -515,19 +487,13 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     }
   }
   if (bsini->size () < bsMinSize)
-  {
-    resultValue = RESULT_INITIAL_TOO_MANY_OUTLIERS;
-    return;
-  }
+    return RESULT_INITIAL_TOO_MANY_OUTLIERS;
 
   // Orientation test for automatic extractions
   //-------------------------------------------
   Vr2i bsinidir = bsini->getSupportVector();
   if (bsinidir.orientedAs (inip1.vectorTo (inip2)))
-  {
-    resultValue = RESULT_INITIAL_CLOSE_ORIENTATION;
-    return;
-  }
+    return RESULT_INITIAL_CLOSE_ORIENTATION;
   
   // Gradient reference selection
   //-----------------------------
@@ -551,10 +517,18 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
   //---------------------------------------------------------------------
   bsf = bst2->fineTrack (bswidth, pCenter, bsinidir, 2 * bswidth, gRef);
   if (bsf == NULL || bsf->size () < bsMinSize)
+    return (bsf == NULL ? RESULT_FINAL_NO_DETECTION : RESULT_FINAL_TOO_FEW);
+
+  // Spread test
+  //------------
+  if (finalSpreadTestOn)
   {
-    resultValue = (bsf == NULL ? RESULT_FINAL_NO_DETECTION
-                               : RESULT_FINAL_TOO_FEW);
-    return;
+    // DigitalStraightSegment *dss = bsf->getSegment ();
+    if ((int) (bsf->getAllPoints().size ()) < finalSpreadMin)
+    {
+      // nbSmallBS ++;
+      return RESULT_FINAL_TOO_SMALL;
+    }
   }
 
   // Length test
@@ -565,12 +539,7 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     if ((int) (bsf->getAllPoints().size ())
         < (3 * dss->width ()) / dss->period ())
     // if ((int) (bsf->getAllPoints().size ()) < 10)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
   }
 
   // New density test
@@ -583,12 +552,7 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2
     int expansion = 1 + mydrlf;
     if (expansion < 20 && bsf->size () < (expansion * 4) / 5)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
   }
 
   // Connected components analysis */
@@ -598,21 +562,11 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     int bsccp = bsf->countOfConnectedPoints (ccMinSize);
     int bssize = bsf->getAllPoints().size ();
     if (bsccp < bssize / 2)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
 
 /*
     if (bssize < 20 || bsf->countOfConnectedComponents (bssize / 2) == 0)
-    {
-      resultValue = RESULT_FINAL_TOO_SPARSE;
-      delete bsf;
-      bsf = NULL;
-      return;
-    }
+      return RESULT_FINAL_TOO_SPARSE;
 */
   }
 
@@ -624,13 +578,13 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     BlurredSegment *fbsf = lsf2->filter (bsf);
     if (fbsf != NULL)
     {
-      resultValue = RESULT_FINAL_TOO_MANY_OUTLIERS;
       delete bsf;
       bsf = fbsf;
     }
+    else return RESULT_FINAL_TOO_MANY_OUTLIERS;
   }
 
-  resultValue = RESULT_OK;
+  return RESULT_OK;
 }
 
 
diff --git a/Code/FBSD/BlurredSegment/bsdetector.h b/Code/FBSD/BlurredSegment/bsdetector.h
index 8d8581606e2b004f5b20e0a5549de4a4a70b06c2..24d4fd98a53f3768182c3b21c667baac6f74a33a 100755
--- a/Code/FBSD/BlurredSegment/bsdetector.h
+++ b/Code/FBSD/BlurredSegment/bsdetector.h
@@ -27,6 +27,8 @@ public:
   /** Identifier for the preliminary detection step. */
   static const int STEP_PRELIM;
 
+  /** Extraction result : void input. */
+  static const int RESULT_VOID;
   /** Extraction result : successful extraction. */
   static const int RESULT_UNDETERMINED;
   /** Extraction result : successful extraction. */
@@ -51,6 +53,8 @@ public:
   static const int RESULT_FINAL_TOO_FEW;
   /** Extraction result : unsuccessful connectivity test at final detection. */
   static const int RESULT_FINAL_TOO_SPARSE;
+  /** Extraction result : unsuccessful spread test at final detection. */
+  static const int RESULT_FINAL_TOO_SMALL;
   /** Extraction result : unsuccessful filter test at final detection. */
   static const int RESULT_FINAL_TOO_MANY_OUTLIERS;
 
@@ -109,13 +113,14 @@ public:
    *         The first candidates that prolongates the segment are retained.
    * Step 4: Outliers pruning based on parameter space filtering.
    * Note : Multi-detection along a stroke requires an initial start point.
+   * Returns the detection status (RESULT_OK if successfull).
    * @param p1 First input point.
    * @param p2 Second input point.
    * @param centralp Set to true if the central point is provided.
    * @param pc Initial central point.
    */
-  void detect (const Pt2i &p1, const Pt2i &p2,
-               bool centralp = false, const Pt2i &pc = Pt2i ());
+  int detect (const Pt2i &p1, const Pt2i &p2,
+              bool centralp = false, const Pt2i &pc = Pt2i ());
 
   /**
    * \brief Detects a blurred segment between two input points.
@@ -128,13 +133,14 @@ public:
    * Step 3: id. step 2.
    *         The directional scan is oriented on the segment of step 2.
    * Note : Multi-detection along a stroke requires an initial start point.
+   * Returns the detection status (RESULT_OK if successfull).
    * @param p1 First input point.
    * @param p2 Second input point.
    * @param centralp Set to true if the central point is provided.
    * @param pc Initial central point.
    */
-  void olddetect (const Pt2i &p1, const Pt2i &p2,
-                  bool centralp = false, const Pt2i &pc = Pt2i ());
+  int olddetect (const Pt2i &p1, const Pt2i &p2,
+                 bool centralp = false, const Pt2i &pc = Pt2i ());
 
   /**
    * \brief Returns the detected blurred segment at given step.
@@ -640,6 +646,12 @@ private :
   bool finalDensityTestOn;
   /** Length test modality after final detection. */
   bool finalLengthTestOn;
+  /** Spread test modality after final detection. */
+  bool finalSpreadTestOn;
+  /** Spread test min value. */
+  int finalSpreadMin;
+  /** Count of small BS eliminated by the spread test. */
+  int nbSmallBS;
   /** Segment multi-selection modality status. */
   bool multiSelection;
   /** Count of trials in a multi-detection. */
diff --git a/Code/FBSD/ImageTools/vmap.cpp b/Code/FBSD/ImageTools/vmap.cpp
index eb88b0796c6a8d15dd38589459c8436de66f5184..7f5afed6d04e08c2389aa748ddd676007fd45308 100755
--- a/Code/FBSD/ImageTools/vmap.cpp
+++ b/Code/FBSD/ImageTools/vmap.cpp
@@ -15,7 +15,7 @@ const int VMap::TYPE_FULL_BLACK_HAT = 6;
 const int VMap::TYPE_FULL_MORPHO = 7;
 
 const int VMap::NEAR_SQ_ANGLE = 80;  // 80% (roughly 25 degrees)
-const int VMap::DEFAULT_GRADIENT_THRESHOLD = 33;
+const int VMap::DEFAULT_GRADIENT_THRESHOLD = 20;
 const int VMap::DEFAULT_GRADIENT_RESOLUTION = 100;
 
 const int VMap::MAX_BOWL = 20;
@@ -109,7 +109,7 @@ VMap::VMap (int width, int height, int *data, int type)
       imap[i] = (int) sqrt (map[i].norm2 ());
     gmagThreshold *= gradientThreshold;
   }
-  else // type == TYPE_SOBEL_3X3
+  else if (type == TYPE_SOBEL_3X3)
   {
     buildGradientMap (data);
     for (int i = 0; i < width * height; i++)
@@ -205,7 +205,7 @@ VMap::VMap (int width, int height, int **data, int type)
       imap[i] = (int) sqrt (map[i].norm2 ());
     gmagThreshold *= gradientThreshold;
   }
-  else // type == TYPE_SOBEL_3X3
+  else if (type == TYPE_SOBEL_3X3)
   {
     buildGradientMap (data);
     for (int i = 0; i < width * height; i++)
@@ -234,7 +234,7 @@ void VMap::init ()
   for (int i = 0; i < width * height; i++) mask[i] = false;
   masking = false;
   angleThreshold = NEAR_SQ_ANGLE;
-  orientedGradient = false;
+  orientedGradient = true;
   bowl = new Vr2i[MAX_BOWL];
   bowl[0] = Vr2i (1, 0);
   bowl[1] = Vr2i (0, 1);