diff --git a/Article/method.tex b/Article/method.tex
index a61e645f1b2227d7e7f850bea6011862b3e2374a..b07121d78e5b0ceb7e287fb6bff654efd0e3473d 100755
--- a/Article/method.tex
+++ b/Article/method.tex
@@ -372,8 +372,9 @@ of interfering outliers insertion.
 
 The automatic detection of blurred segments in a whole image is left
 available for testing in an online demonstration at the following address: \\
-  \href{http://ipol-geometry.loria.fr/~kerautre/ipol_demo/AdaptDirBS_IPOLDemo}{\small{\url{http://ipol-geometry.loria.fr/~kerautre/ipol_demo/AdaptDirBS_IPOLDemo}}}
-
+\href{http://ipol-geometry.loria.fr/~kerautre/ipol_demo/AdaptDirBS_IPOLDemo}{
+\small{\url{
+http://ipol-geometry.loria.fr/~kerautre/ipol_demo/AdaptDirBS_IPOLDemo}}}
 
 %The behavior of the unsupervised detection is depicted through the two
 %examples of \RefFig{fig:auto}.
diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp
index bd1b18a87fcc6dbeabfe057cbc28adee2a99f9f3..04ae746f654dd57f01e9b2b0d91aabc9cada9222 100755
--- a/Code/Seg/BSTools/bsdetectionwidget.cpp
+++ b/Code/Seg/BSTools/bsdetectionwidget.cpp
@@ -28,8 +28,6 @@ BSDetectionWidget::BSDetectionWidget (QWidget *parent)
   grabKeyboard ();
   udef = false;
   nodrag = true;
-  nbdettrials = 0;
-  nbmaxdettrials = 0;
 
   // Initializes the gradient map and the auxiliary views
   gMap = NULL;
@@ -46,13 +44,12 @@ BSDetectionWidget::BSDetectionWidget (QWidget *parent)
   blevel = 0;
 
   // Sets display parameters
+  darkHighlightOn = false;
   selectionColor = Qt::red;
   bsColor = Qt::blue;
-  //bsHighColor = Qt::black;
   bsHighColor = Qt::yellow;
   bsPointsVisible = true;
   boundColor = Qt::green;
-  //boundHighColor = Qt::black;
   boundHighColor = Qt::magenta;
 }
 
@@ -294,6 +291,22 @@ void BSDetectionWidget::switchIdetAnalyzer ()
 }
 
 
+void BSDetectionWidget::switchHighlightColors ()
+{
+  darkHighlightOn = ! darkHighlightOn;
+  if (darkHighlightOn)
+  {
+    bsHighColor = Qt::black;
+    boundHighColor = Qt::blue;
+  }
+  else
+  {
+    bsHighColor = Qt::yellow;
+    boundHighColor = Qt::magenta;
+  }
+}
+
+
 void BSDetectionWidget::mousePressEvent (QMouseEvent *event)
 {
   oldp1.set (p1);
@@ -320,14 +333,12 @@ void BSDetectionWidget::mouseReleaseEvent (QMouseEvent *event)
     alternate = 0;
     cerr << "p1 defined: " << p1.x () << " " << p1.y () << endl;
     cerr << "p2 defined: " << p2.x () << " " << p2.y () << endl;
-    detector.setMaxTrials (0);
+    detector.resetMaxDetections ();
     extract ();
-    nbdettrials = detector.countOfTrials ();
-    nbmaxdettrials = 0;
     if (detector.isMultiSelection ())
       cout << detector.getBlurredSegments().size ()
            << " blurred segments detected on "
-           << nbdettrials << " essais " << endl;
+           << detector.countOfTrials () << " essais " << endl;
   }
 }
 
@@ -530,13 +541,11 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       {
         // Runs an automatic detection
         udef = false;
-        detector.setMaxTrials (-1);
+        detector.resetMaxDetections ();
         extract ();
-        nbdettrials = detector.countOfTrials ();
-        nbmaxdettrials = 0;
-//        cout << detector.getBlurredSegments().size ()
-//             << " blurred segments detected on "
-//             << nbdettrials << " essais " << endl;
+        cout << detector.getBlurredSegments().size ()
+             << " blurred segments detected on "
+             << detector.countOfTrials () << " essais " << endl;
       }
       break;
 
@@ -552,14 +561,13 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       else
       {
         // Highlights the next segment in a multi-detection
-        if (! detector.getBlurredSegments().empty ())
+        vector<BlurredSegment *> bsl = detector.getBlurredSegments ();
+        if (! bsl.empty ())
         {
-          nbmaxdettrials += (event->modifiers () & Qt::ShiftModifier ? -1 : 1);
-          if (nbmaxdettrials < 0) nbmaxdettrials = nbdettrials;
-          else if (nbmaxdettrials > nbdettrials) nbmaxdettrials = 0;
-          detector.setMaxTrials (nbmaxdettrials);
-          cout << "Selection du segment " << nbmaxdettrials << endl;
+          detector.incMaxDetections (event->modifiers () & Qt::ShiftModifier);
           extract ();
+          cout << "Selection of segment "
+               << detector.getMaxDetections () << endl;
         }
       }
       break;
@@ -770,6 +778,11 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
       }
       break;
 
+    case Qt::Key_Exclam :
+      switchHighlightColors ();
+      displayDetectionResult ();
+      break;
+
     case Qt::Key_1 :
       switchPixelAnalyzer ();
       break;
@@ -989,8 +1002,8 @@ void BSDetectionWidget::displayDetectionResult ()
 //        if (dss == NULL) cout << "DSS null" << endl;
 //        else bsw += dss->width () / (double) dss->period ();
 //      }
-      drawBlurredSegment (painter, *it, nbmaxdettrials == 0 ||
-                          (*it == bss.back () && detector.isLastTrialOk ()));
+      drawBlurredSegment (painter, *it, detector.getMaxDetections () == 0
+                                        || *it == bss.back ());
       it++;
     }
 //    cout << bsc << " effective blurred segments" << endl;
@@ -1121,6 +1134,23 @@ void BSDetectionWidget::writeDetectionStatus ()
 }
 
 
+void BSDetectionWidget::saveMask ()
+{
+      QImage mim (width, height, QImage::Format_RGB32);
+      bool *mask = gMap->getMask ();
+      int nb = 0;
+      for (int j = 0; j < height; j++)
+        for (int i = 0; i < width; i++)
+        {
+          if (*mask) nb++;
+          mim.setPixel (i, height - 1 - j,
+                        *mask++ ? 0 : 255 + 255 * 256 + 255 * 256 * 256);
+        }
+      mim.save ("mask.png");
+      cout << "mask.png created with " << nb << " points" << endl;
+}
+
+
 void BSDetectionWidget::extract ()
 {
   if (udef)
@@ -1222,6 +1252,498 @@ void BSDetectionWidget::localTest ()
   }
   else cout << "Run autotest" << endl;
 
+  detector.resetMaxDetections ();
   extract ();
   cout << "Test run" << endl;
 }
+
+
+QSize BSDetectionWidget::setRandomImage (int type)
+{
+  width = 256;
+  height = 256;
+  loadedImage = QImage (width, height, QImage::Format_RGB32);
+  srand (time (NULL));
+  udef = false;
+  detector.setFineTracksMaxWidth (6);
+  if (! detector.isFinalLengthTestOn ()) detector.switchFinalLengthTest ();
+
+  int nbsegs = 10;
+  Pt2i rp1[nbsegs];
+  Pt2i rp2[nbsegs];
+  Vr2i rdir[nbsegs];
+  int rw[nbsegs];
+  vector<BlurredSegment *> rbs[nbsegs];
+   
+  bool dispEach = false;
+  int nbruns = 100;
+  int nbIniPts[nbruns];
+  int oldTrials[nbruns];
+  int newTrials[nbruns];
+  int oldDetections[nbruns];
+  int newDetections[nbruns];
+  int oldUndet[nbruns];
+  int newUndet[nbruns];
+  int oldRedet[nbruns];
+  int newRedet[nbruns];
+  int oldFalse[nbruns];
+  int newFalse[nbruns];
+  double oldNbMatched[nbruns];
+  double newNbMatched[nbruns];
+  double oldWidthDiff[nbruns];
+  double newWidthDiff[nbruns];
+  double oldAbsDiff[nbruns];
+  double newAbsDiff[nbruns];
+  double oldAngDiff[nbruns];
+  double newAngDiff[nbruns];
+
+  for (int run = 0; run < nbruns; run ++)
+  {
+    if (dispEach) cout << "Generating new segments" << endl;
+    int val;
+    for (int i = 0; i < width; i ++)
+      for (int j = 0; j < height; j ++)
+      {
+        val = 255 - (rand () % 30);
+        loadedImage.setPixel (i, j, val + val * 256 + val * 256 * 256);
+      }
+    for (int i = 0; i < nbsegs; i++)
+    {
+      rp1[i].set (rand () % width, rand () % height);
+      do rp2[i].set (rand () % width, rand () % height);
+      while (rp1[i].chessboard (rp2[i]) < 20);
+      rdir[i] = rp1[i].vectorTo (rp2[i]);
+      rw[i] = 1 + rand () % 3;
+
+      DigitalStraightSegment dss (rp1[i], rp2[i], rw[i]);
+      vector<Pt2i> pix;
+      dss.getPoints (pix);
+      vector<Pt2i>::iterator it = pix.begin ();
+      while (it != pix.end ())
+      {
+        Pt2i p = *it++;
+        if (p.x () >= 0 && p.x () < width && p.y () >= 0 && p.y () < height)
+          loadedImage.setPixel (p.x (), height - 1 - p.y (), 0);
+      }
+    }
+
+    if (dispEach) cout << "Initializing the detector" << endl;
+    if (gMap != NULL) delete gMap;
+    gMap = new VMap (width, height, getBitmap (loadedImage), type);
+    detector.setGradientMap (gMap);
+    buildGradientImage (0);
+    gMap->incGradientThreshold (50 - gMap->getGradientThreshold ());
+
+    if (dispEach) cout << "Preparing the result maps" << endl;
+    nbIniPts[run] = 0;
+    bool virgin[width * height];
+    for (int j = 0; j < height; j++)
+      for (int i = 0; i < width; i++)
+      {
+        virgin[j * width + i] = QColor(loadedImage.pixel(i,j)).value () < 10;
+        nbIniPts[run] ++;
+      }
+    int detmap[width * height];
+    int *dm = detmap;
+    for (int i = 0; i < width * height; i++) *dm++ = 0;
+
+    if (dispEach) cout << "Running the old detection" << endl;
+    if (! detector.oldDetectorOn ()) detector.switchDetector ();
+    extract ();
+
+    if (dispEach) cout << "Analyzing the old blurred segments" << endl;
+    for (int i = 0; i < nbsegs; i++) rbs[i].clear ();
+    int nbnomatch = 0;
+    int nbokortho = 0;
+    int nbokcolin = 0;
+    int nbokmid = 0;
+    int nbdssnul = 0;
+    double nomatchlength = 0.;
+    vector<BlurredSegment *> bss = detector.getBlurredSegments ();
+    vector<BlurredSegment *>::iterator bsit = bss.begin ();
+    while (bsit != bss.end ())
+    {
+      DigitalStraightSegment *dss = (*bsit)->getSegment ();
+      if (dss != NULL)
+      {
+        vector<Pt2i> dsspts;
+        dss->getPoints (dsspts);
+        vector<Pt2i>::iterator dssit = dsspts.begin ();
+        while (dssit != dsspts.end ())
+        {
+          Pt2i dsspt = *dssit++;
+          if (dsspt.x () >= 0 && dsspt.x () < width
+              && dsspt.y () >= 0 && dsspt.y () < height)
+          {
+            virgin[dsspt.y () * width + dsspt.x ()] = false;
+            detmap[dsspt.y () * width + dsspt.x ()] +=
+              (QColor(loadedImage.pixel(dsspt.x(),dsspt.y())) .value () < 10 ?
+              1 : -1);
+          }
+        }
+
+        Vr2i dssdir = dss->supportVector ();
+        Pt2i ptb = (*bsit)->getLastRight ();
+        Pt2i ptf = (*bsit)->getLastLeft ();
+        Pt2i bsc ((ptb.x () + ptf.x ()) / 2, (ptb.y () + ptf.y ()) / 2);
+        double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ())
+                      + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ());
+        bool searching = true;
+        for (int si = 0; searching && si < nbsegs; si++)
+        {
+          if (rdir[si].squaredVectorProduct (dssdir)
+              < 0.1 * rdir[si].norm2 () * dssdir.norm2 ())
+          {
+            nbokortho ++;
+            Vr2i bsac = rp1[si].vectorTo (bsc);
+            if (rdir[si].squaredVectorProduct (bsac)
+                < 0.1 * rdir[si].norm2 () * bsac.norm2 ())
+            {
+              nbokcolin ++;
+              if (rdir[si].scalarProduct (bsac) > 0)
+              {
+                Vr2i bscb = bsc.vectorTo (rp2[si]);
+                if (rdir[si].scalarProduct (bscb) > 0)
+                {
+                  nbokmid ++;
+                  rbs[si].push_back (*bsit);
+                  searching = false;
+                }
+              }
+            }
+          }
+        }
+        if (searching)
+        {
+          nbnomatch ++;
+          nomatchlength += sqrt (bsl2);
+        }
+      }
+      else nbdssnul ++;
+      bsit ++;
+    }
+
+    if (dispEach) cout << "  OLD DETECTOR :" << endl;
+    oldTrials[run] = detector.countOfTrials ();
+    oldDetections[run] = (int) (detector.getBlurredSegments().size ());
+    if (dispEach)
+      cout << oldDetections[run] << " blurred segments detected on "
+           << oldTrials[run] << " trials " << endl;
+    oldUndet[run] = 0;
+    for (int i = 0; i < width * height; i++) if (virgin[i]) oldUndet[run] ++;
+    if (dispEach)
+      cout << (nbIniPts[run] - oldUndet[run]) << " points detected on "
+           << nbIniPts[run] << " ("
+           << (nbIniPts[run] - oldUndet[run]) * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+    oldRedet[run] = 0;
+    for (int i = 0; i < width * height; i++)
+      if (detmap[i] > 1) oldRedet[run] += (detmap[i] - 1);
+    if (dispEach)
+      cout << oldRedet[run] << " points redetected on " << nbIniPts[run]
+           << " (" << oldRedet[run] * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+    oldFalse[run] = 0;
+    for (int i = 0; i < width * height; i++)
+      if (detmap[i] < 0) oldFalse[run] ++;
+    if (dispEach)
+    {
+      cout << oldFalse[run] << " false points detected on " << nbIniPts[run]
+           << " (" << oldFalse[run] * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+      cout << nbnomatch << " unmatched blurred segment (mean length : "
+           << (nbnomatch != 0 ? nomatchlength / nbnomatch : 0) << ")" << endl;
+      cout << nbokortho << " test ortho OK" << endl;
+      cout << nbokcolin << " test colin OK" << endl;
+      cout << nbokmid << " test mid OK" << endl;
+      cout << nbdssnul << " DSS nuls" << endl;
+    }
+
+    oldWidthDiff[run] = 0.;
+    oldAbsDiff[run] = 0.;
+    oldAngDiff[run] = 0.;
+    oldNbMatched[run] = 0;
+    for (int si = 0; si < nbsegs; si ++)
+    {
+      if (! rbs[si].empty ()) oldNbMatched[run] ++;
+      vector<BlurredSegment *>::iterator sit = rbs[si].begin ();
+      while (sit != rbs[si].end ())
+      {
+        Pt2i ptb = (*sit)->getLastRight ();
+        Pt2i ptf = (*sit)->getLastLeft ();
+        double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ())
+                      + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ());
+        DigitalStraightSegment *mydss = (*sit)->getSegment ();
+        double wd = (mydss->width () / (double) (mydss->period ()))
+                    * sqrt (bsl2) / sqrt (rdir[si].norm2 ()) - rw[si];
+        oldWidthDiff[run] += wd;
+        if (wd < 0) wd = -wd;
+        oldAbsDiff[run] += wd;
+        Vr2i mydir = mydss->supportVector ();
+        double ang = rdir[si].scalarProduct (mydir);
+        if (ang < 0.) ang = - ang;
+        double den = sqrt (rdir[si].norm2 ()) * sqrt (mydir.norm2 ());
+        if (den > ang)
+        {
+          ang = acos (ang / den) * 180 / M_PI;
+          oldAngDiff[run] += ang * sqrt (bsl2) / sqrt (rdir[si].norm2 ());
+        }
+        sit ++;
+      }
+    }
+    if (dispEach)
+    {
+      cout << "Width difference = "
+         << (oldNbMatched[run] != 0 ?
+             oldWidthDiff[run] / oldNbMatched[run] : 0) << endl;
+      cout << "Absolute width difference = "
+         << (oldNbMatched[run] != 0 ?
+             oldAbsDiff[run] / oldNbMatched[run] : 0) << endl;
+      cout << "Angle difference = "
+           << (oldNbMatched[run] != 0 ?
+               oldAngDiff[run] / oldNbMatched[run] : 0) << endl;
+    }
+
+    if (dispEach) cout << "Resetting the result maps" << endl;
+    for (int j = 0; j < height; j++)
+      for (int i = 0; i < width; i++)
+        virgin[j * width + i] = QColor(loadedImage.pixel(i,j)).value () < 10;
+    dm = detmap;
+    for (int i = 0; i < width * height; i++) *dm++ = 0;
+
+    if (dispEach) cout << "Running the new detection" << endl;
+    detector.switchDetector ();
+    extract ();
+
+    if (dispEach) cout << "Analyzing the new blurred segments" << endl;
+    for (int i = 0; i < nbsegs; i++) rbs[i].clear ();
+    nbnomatch = 0;
+    nomatchlength = 0.;
+    nbokortho = 0;
+    nbokcolin = 0;
+    nbokmid = 0;
+    nbdssnul = 0;
+    nomatchlength = 0.;
+    bss = detector.getBlurredSegments ();
+    bsit = bss.begin ();
+    while (bsit != bss.end ())
+    {
+      DigitalStraightSegment *dss = (*bsit)->getSegment ();
+      if (dss != NULL)
+      {
+        vector<Pt2i> dsspts;
+        dss->getPoints (dsspts);
+        vector<Pt2i>::iterator dssit = dsspts.begin ();
+        while (dssit != dsspts.end ())
+        {
+          Pt2i dsspt = *dssit++;
+          if (dsspt.x () >= 0 && dsspt.x () < width
+              && dsspt.y () >= 0 && dsspt.y () < height)
+          {
+            virgin[dsspt.y () * width + dsspt.x ()] = false;
+            detmap[dsspt.y () * width + dsspt.x ()] +=
+              (QColor(loadedImage.pixel(dsspt.x(),dsspt.y())).value () < 10 ?
+              1 : -1);
+          }
+        }
+
+        Vr2i dssdir = dss->supportVector ();
+        Pt2i ptb = (*bsit)->getLastRight ();
+        Pt2i ptf = (*bsit)->getLastLeft ();
+        Pt2i bsc ((ptb.x () + ptf.x ()) / 2, (ptb.y () + ptf.y ()) / 2);
+        double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ())
+                      + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ());
+        bool searching = true;
+        for (int si = 0; searching && si < nbsegs; si++)
+        {
+          if (rdir[si].squaredVectorProduct (dssdir)
+              < 0.1 * rdir[si].norm2 () * dssdir.norm2 ())
+          {
+            nbokortho ++;
+            Vr2i bsac = rp1[si].vectorTo (bsc);
+            if (rdir[si].squaredVectorProduct (bsac)
+                < 0.1 * rdir[si].norm2 () * bsac.norm2 ())
+            {
+              nbokcolin ++;
+              if (rdir[si].scalarProduct (bsac) > 0)
+              {
+                Vr2i bscb = bsc.vectorTo (rp2[si]);
+                if (rdir[si].scalarProduct (bscb) > 0)
+                {
+                  nbokmid ++;
+                  rbs[si].push_back (*bsit);
+                  searching = false;
+                }
+              }
+            }
+          }
+        }
+        if (searching)
+        {
+          nbnomatch ++;
+          nomatchlength += sqrt (bsl2);
+        }
+      }
+      else nbdssnul ++;
+      bsit ++;
+    }
+
+    if (dispEach) cout << "  NEW DETECTOR :" << endl;
+    newTrials[run] = detector.countOfTrials ();
+    newDetections[run] = (int) (detector.getBlurredSegments().size ());
+    if (dispEach)
+      cout << newDetections[run] << " blurred segments detected on "
+           << newTrials[run] << " trials " << endl;
+    newUndet[run] = 0;
+    for (int i = 0; i < width * height; i++) if (virgin[i]) newUndet[run] ++;
+    if (dispEach)
+      cout << (nbIniPts[run] - newUndet[run]) << " points detected on "
+           << nbIniPts[run] << " ("
+           << (nbIniPts[run] - newUndet[run]) * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+    newRedet[run] = 0;
+    for (int i = 0; i < width * height; i++)
+      if (detmap[i] > 1) newRedet[run] += (detmap[i] - 1);
+    if (dispEach)
+      cout << (newRedet[run]) << " points redetected on " << nbIniPts[run]
+           << " (" << newRedet[run] * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+    newFalse[run] = 0;
+    for (int i = 0; i < width * height; i++)
+      if (detmap[i] < 0) newFalse[run] ++;
+    if (dispEach)
+    {
+      cout << newFalse[run] << " false points detected on " << nbIniPts[run]
+           << " (" << newFalse[run] * 100 / (double) nbIniPts[run]
+           << " %)" << endl;
+      cout << nbnomatch << " unmatched blurred segment (mean length : "
+           << (nbnomatch != 0 ? nomatchlength / nbnomatch : 0) << ")" << endl;
+      cout << nbokortho << " test ortho OK" << endl;
+      cout << nbokcolin << " test colin OK" << endl;
+      cout << nbokmid << " test mid OK" << endl;
+      cout << nbdssnul << " DSS nuls" << endl;
+    }
+
+    newWidthDiff[run] = 0.;
+    newAbsDiff[run] = 0.;
+    newAngDiff[run] = 0.;
+    newNbMatched[run] = 0;
+    for (int si = 0; si < nbsegs; si ++)
+    {
+      if (! rbs[si].empty ()) newNbMatched[run] ++;
+      vector<BlurredSegment *>::iterator sit = rbs[si].begin ();
+      while (sit != rbs[si].end ())
+      {
+        Pt2i ptb = (*sit)->getLastRight ();
+        Pt2i ptf = (*sit)->getLastLeft ();
+        double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ())
+                      + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ());
+        DigitalStraightSegment *mydss = (*sit)->getSegment ();
+        double wd = (mydss->width () / (double) (mydss->period ()))
+                    * sqrt (bsl2) / sqrt (rdir[si].norm2 ()) - rw[si];
+        newWidthDiff[run] += wd;
+        if (wd < 0) wd = -wd;
+        newAbsDiff[run] += wd;
+        Vr2i mydir = mydss->supportVector ();
+        double ang = rdir[si].scalarProduct (mydir);
+        if (ang < 0.) ang = - ang;
+        double den = sqrt (rdir[si].norm2 ()) * sqrt (mydir.norm2 ());
+        if (den > ang)
+        {
+          ang = acos (ang / den) * 180 / M_PI;
+          newAngDiff[run] += ang * sqrt (bsl2) / sqrt (rdir[si].norm2 ());
+        }
+        sit ++;
+      }
+    }
+    if (dispEach)
+    {
+      cout << "Width difference = "
+           << (newNbMatched[run] != 0 ?
+               newWidthDiff[run] / newNbMatched[run] : 0) << endl;
+      cout << "Absolute width difference = "
+           << (newNbMatched[run] != 0 ?
+               newAbsDiff[run] / newNbMatched[run] : 0) << endl;
+      cout << "Angle difference = "
+           << (newNbMatched[run] != 0 ?
+               newAngDiff[run] / newNbMatched[run] : 0) << endl;
+    }
+  }
+
+  double total_nbIniPts = 0;
+  for (int i = 0; i < nbruns; i++) total_nbIniPts += nbIniPts[i];
+
+  cout << "  BILAN OLD" << endl;
+  double total_oldTrials = 0.;
+  for (int i = 0; i < nbruns; i++) total_oldTrials += oldTrials[i];
+  cout << total_oldTrials / nbruns << " trials" << endl;
+  double total_oldDetections = 0.;
+  for (int i = 0; i < nbruns; i++) total_oldDetections += oldDetections[i];
+  cout << total_oldDetections / nbruns << " detections" << endl;
+  double total_oldOkdet = 0;
+  for (int i = 0; i < nbruns; i++)
+    total_oldOkdet += nbIniPts[i] - oldUndet[i];
+  cout << 100 * total_oldOkdet / total_nbIniPts << " % success" << endl;
+  double total_oldRedet = 0;
+  for (int i = 0; i < nbruns; i++) total_oldRedet += oldRedet[i];
+  cout << 100 * total_oldRedet / total_nbIniPts << " % coverture" << endl;
+  double total_oldFalse = 0;
+  for (int i = 0; i < nbruns; i++) total_oldFalse += oldFalse[i];
+  cout << 100 * total_oldFalse / total_nbIniPts
+       << " % false detections" << endl;
+  int total_nbmatched = 0;
+  for (int i = 0; i < nbruns; i++) total_nbmatched += oldNbMatched[i];
+  double total_widthdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_widthdiff += oldWidthDiff[i];
+  cout << "Width difference : " << total_widthdiff / total_nbmatched
+       << " per matched segment" << endl;
+  double total_absdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_absdiff += oldAbsDiff[i];
+  cout << "Absolute width difference : " << total_absdiff / total_nbmatched
+       << " per matched segment" << endl;
+  double total_angdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_angdiff += oldAngDiff[i];
+  cout << "Angle difference : " << total_angdiff / total_nbmatched
+       << " degrees per matched segment" << endl;
+
+  cout << "  BILAN NEW" << endl;
+  double total_newTrials = 0.;
+  for (int i = 0; i < nbruns; i++) total_newTrials += newTrials[i];
+  cout << total_newTrials / nbruns << " trials" << endl;
+  double total_newDetections = 0;
+  for (int i = 0; i < nbruns; i++) total_newDetections += newDetections[i];
+  cout << total_newDetections / nbruns << " detections" << endl;
+  double total_newOkdet = 0;
+  for (int i = 0; i < nbruns; i++)
+    total_newOkdet += nbIniPts[i] - newUndet[i];
+  cout << 100 * total_newOkdet / total_nbIniPts << " % success" << endl;
+  double total_newRedet = 0;
+  for (int i = 0; i < nbruns; i++) total_newRedet += newRedet[i];
+  cout << 100 * total_newRedet / total_nbIniPts << " % coverture" << endl;
+  double total_newFalse = 0;
+  for (int i = 0; i < nbruns; i++) total_newFalse += newFalse[i];
+  cout << 100 * total_newFalse / total_nbIniPts
+       << " % false detections" << endl;
+  total_nbmatched = 0;
+  for (int i = 0; i < nbruns; i++) total_nbmatched += newNbMatched[i];
+  total_widthdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_widthdiff += newWidthDiff[i];
+  cout << "Width difference : " << total_widthdiff / total_nbmatched
+       << " per matched segment" << endl;
+  total_absdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_absdiff += newAbsDiff[i];
+  cout << "Absolute width difference : " << total_absdiff / total_nbmatched
+       << " per matched segment" << endl;
+  total_angdiff = 0;
+  for (int i = 0; i < nbruns; i++) total_angdiff += newAngDiff[i];
+  cout << "Angle difference : " << total_angdiff / total_nbmatched
+       << " degrees per matched segment" << endl;
+
+  cout << "Updating the displays" << endl;
+  augmentedImage = loadedImage;
+  update ();
+  if (idetview != NULL) idetview->setImage (&loadedImage, gMap);
+  if (profileview != NULL) profileview->setImage (&loadedImage, gMap);
+  if (strucview != NULL) strucview->setGradientImage (&gradImage);
+  return loadedImage.size ();
+}
diff --git a/Code/Seg/BSTools/bsdetectionwidget.h b/Code/Seg/BSTools/bsdetectionwidget.h
index fe937fdb3e53903486d33dea30b58fab04339a1c..5deb3759cb1475a4c03f6fea6013feafabae43e4 100755
--- a/Code/Seg/BSTools/bsdetectionwidget.h
+++ b/Code/Seg/BSTools/bsdetectionwidget.h
@@ -38,6 +38,12 @@ public:
    */
   ~BSDetectionWidget ();
 
+  /**
+   * \brief Creates and opens a random image to be processed.
+   * @param type Gradient extraction method.
+   */
+  QSize setRandomImage (int type = 0);
+
   /**
    * \brief Opens the image to be processed.
    * @param type Name of the image file to open.
@@ -117,6 +123,11 @@ public:
    */
   void switchIdetAnalyzer ();
 
+  /**
+   * \brief Switches the blurred segment highlight colors.
+   */
+  void switchHighlightColors ();
+
   /**
    * \brief Switches the extraction result display on or off.
    */
@@ -208,11 +219,9 @@ private:
   bool oldudef;
   /** Activation of alternate comparative tests (F8). */
   int alternate;
-  /** Count of trials in a multi_detection. */
-  int nbdettrials;
-  /** Maximum number of trials in a multi_detection. */
-  int nbmaxdettrials;
 
+  /** Kind of highlight colors. */
+  bool darkHighlightOn;
   /** Color of user selections. */
   QColor selectionColor;
   /** Color of blurred segments. */
@@ -369,6 +378,11 @@ private:
    */
   void writeDetectionStatus ();
 
+  /**
+   * \brief Stores the occupancy mask in a mask.png.
+   */
+  void saveMask ();
+
   /**
    * \brief Detects and displays a blurred segment under the selected stroke.
    */
diff --git a/Code/Seg/BSTools/bsidetitem.cpp b/Code/Seg/BSTools/bsidetitem.cpp
index 6304da85ba1959f0b4fb36e30288dd55d24ca53a..2fcb8b850adb99f61103a2b150d282f0d59c2e3f 100755
--- a/Code/Seg/BSTools/bsidetitem.cpp
+++ b/Code/Seg/BSTools/bsidetitem.cpp
@@ -50,7 +50,7 @@ void BSIdetItem::paint (QPainter *painter,
   Q_UNUSED (option);
   Q_UNUSED (widget);
 
-  if (det->getBlurredSegments().empty () || det->getMaxTrials () > 0)
+  if (det->getBlurredSegments().empty () || det->getMaxDetections () > 0)
   {
 //    buildScans ();
     paintStripes (painter);
@@ -70,7 +70,7 @@ void BSIdetItem::setImage (QImage *image, VMap *idata)
 
 void BSIdetItem::buildScans ()
 {
-  if ((! det->getBlurredSegments().empty ()) && det->getMaxTrials () <= 0)
+  if ((! det->getBlurredSegments().empty ()) && det->getMaxDetections () == 0)
     return;
 
   if (ds != NULL)
diff --git a/Code/Seg/BSTools/bswindow.cpp b/Code/Seg/BSTools/bswindow.cpp
index 8d86ae573742cceb643493ad446c1b7e6d9bce00..4eae19db40fd4d9317e4cb4ea29dbf7522a49fc6 100755
--- a/Code/Seg/BSTools/bswindow.cpp
+++ b/Code/Seg/BSTools/bswindow.cpp
@@ -40,6 +40,13 @@ BSWindow::BSWindow ()
 }
 
 
+void BSWindow::setRandom ()
+{
+  resize (detectionWidget->setRandomImage (gradType));
+  detectionWidget->setDefaults ();
+}
+
+
 void BSWindow::setFile (QString fileName)
 {
   resize (detectionWidget->openImage (fileName, gradType));
diff --git a/Code/Seg/BSTools/bswindow.h b/Code/Seg/BSTools/bswindow.h
index b5700167b9ff281404da4239a762973926a29103..6fd9e461bdd05faeb9ac8087bafa7c45a047000e 100755
--- a/Code/Seg/BSTools/bswindow.h
+++ b/Code/Seg/BSTools/bswindow.h
@@ -27,6 +27,11 @@ public:
    */
   BSWindow (int *val);
 
+  /**
+   * Sets a random processed image.
+   */
+  void setRandom ();
+
   /**
    * Sets the processed image.
    */
diff --git a/Code/Seg/BlurredSegment/bsdetector.cpp b/Code/Seg/BlurredSegment/bsdetector.cpp
index d39d0b0969c139a106ecb379e1a626207532dbdb..7b237096317460849fa43b2817c7a9ec588c42ca 100755
--- a/Code/Seg/BlurredSegment/bsdetector.cpp
+++ b/Code/Seg/BlurredSegment/bsdetector.cpp
@@ -20,7 +20,7 @@ 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::DEFAULT_FAST_TRACK_SCAN_WIDTH = 32;
+const int BSDetector::DEFAULT_FAST_TRACK_SCAN_WIDTH = 16;
 const int BSDetector::DEFAULT_FINE_TRACK_MAX_WIDTH = 3;
 const int BSDetector::DEFAULT_FAST_TRACK_MAX_MARGIN = 2;
 
@@ -66,7 +66,7 @@ BSDetector::BSDetector ()
   multiSelection = false;
   autodet = false;
   autoResol = DEFAULT_AUTO_RESOLUTION;
-  nbmaxtrials = 0;
+  maxtrials = 0;
   nbtrials = 0;
 
   bspre = NULL;
@@ -105,6 +105,7 @@ void BSDetector::detectAll ()
   autodet = true;
   freeMultiSelection ();
   gMap->setMasking (true);
+  gMap->clearMask ();
 
   bool isnext = true;
   nbtrials = 0;
@@ -118,8 +119,8 @@ void BSDetector::detectAll ()
     isnext = runMultiDetection (Pt2i (0, y), Pt2i (width - 1, y));
   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;
 
-  gMap->clearMask ();
   gMap->setMasking (false);
 }
 
@@ -129,6 +130,7 @@ void BSDetector::detectAllWithBalancedXY ()
   autodet = true;
   freeMultiSelection ();
   gMap->setMasking (true);
+  gMap->clearMask ();
 
   bool isnext = true;
   nbtrials = 0;
@@ -164,7 +166,7 @@ void BSDetector::detectAllWithBalancedXY ()
       if (yh >= height - 1) enhaut = false;
     }
   }
-  gMap->clearMask ();
+  if (maxtrials > (int) (mbsf.size ())) maxtrials = 0;
   gMap->setMasking (false);
 }
 
@@ -176,9 +178,10 @@ void BSDetector::detectSelection (const Pt2i &p1, const Pt2i &p2)
   if (multiSelection)
   {
     gMap->setMasking (true);
+    gMap->clearMask ();
     nbtrials = 0;
     runMultiDetection (p1, p2);
-    gMap->clearMask ();
+    if (maxtrials > (int) (mbsf.size ())) maxtrials = 0;
     gMap->setMasking (false);
   }
   else
@@ -216,7 +219,7 @@ bool BSDetector::runMultiDetection (const Pt2i &p1, const Pt2i &p2)
     {
       int oldEdgeDir = edgeDirection;
       if (edgeDirection != 0) edgeDirection = 1;
-      while (edgeDirection >= -1)
+      while (isnext && edgeDirection >= -1)
       {
         if (oldp) olddetect (p1, p2, true, ptstart);
         else detect (p1, p2, true, ptstart);
@@ -225,11 +228,12 @@ bool BSDetector::runMultiDetection (const Pt2i &p1, const Pt2i &p2)
           gMap->setMask (bsf->getAllPoints ());
           mbsf.push_back (bsf);
           bsf = NULL; // to avoid BS deletion
+          if ((int) (mbsf.size ()) == maxtrials) isnext = false;
         }
+        nbtrials ++;
         edgeDirection -= 2;
       }
       edgeDirection = oldEdgeDir;
-      if (++nbtrials == nbmaxtrials) isnext = false;
     }
   }
   return (isnext);
@@ -253,7 +257,6 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
   bsini = NULL;
   if (bsf != NULL) delete bsf;
   bsf = NULL;
-  lastTrialOk = false;
 
   inip1.set (p1);
   inip2.set (p2);
@@ -349,8 +352,8 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
   if (finalLengthTestOn)
   {
     DigitalStraightSegment *dss = bsf->getSegment ();
-    if ((int) (bsf->getAllPoints().size ())
-        < (10 * dss->period ()) / dss->width ())
+    if (dss == NULL || (int) (bsf->getAllPoints().size ())
+                       < (10 * dss->period ()) / dss->width ())
     {
       resultValue = RESULT_FINAL_TOO_SPARSE;
       delete bsf;
@@ -402,7 +405,6 @@ void BSDetector::olddetect (const Pt2i &p1, const Pt2i &p2,
 */
   }
 
-  lastTrialOk = true;
   resultValue = RESULT_OK;
 }
 
@@ -430,7 +432,6 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
   bsini = NULL;
   if (bsf != NULL) delete bsf;
   bsf = NULL;
-  lastTrialOk = false;
 
   prep1.set (p1);
   prep2.set (p2);
@@ -626,7 +627,6 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2,
     }
   }
 
-  lastTrialOk = true;
   resultValue = RESULT_OK;
 }
 
@@ -636,11 +636,18 @@ BlurredSegment *BSDetector::getBlurredSegment (int step) const
   if (step == STEP_PRELIM) return (bspre);
   else if (step == STEP_INITIAL) return (bsini);
   else if (mbsf.empty ()) return (bsf);
-  else if (lastTrialOk) return (mbsf.back ());
+  else return (mbsf.back ());
   return NULL;
 }
 
 
+void BSDetector::incMaxDetections (bool dir)
+{
+  maxtrials = maxtrials + (dir ? -1 : 1);
+  if (maxtrials < 0) maxtrials = (int) (mbsf.size ());
+}
+
+
 void BSDetector::getScanInput (int step,
                                Pt2i &p1, Pt2i &p2, int &swidth, Pt2i &pc) const
 {
diff --git a/Code/Seg/BlurredSegment/bsdetector.h b/Code/Seg/BlurredSegment/bsdetector.h
index 48e2a39a2c9b1c2d6d1857633b7704d2f7189a8f..bbfecdb1860b64bf9ce07fb5dc66d030b963d4d4 100755
--- a/Code/Seg/BlurredSegment/bsdetector.h
+++ b/Code/Seg/BlurredSegment/bsdetector.h
@@ -545,21 +545,28 @@ public:
    */
   inline int countOfTrials () const { return (nbtrials); }
 
+  /**
+   * \brief Returns the maximum number of detections set for a multi-detection.
+   */
+  inline int getMaxDetections () const { return maxtrials; }
+
   /**
    * \brief Sets the maximum number of trials in a multi-detection.
+   * Just kept for IPOL demo compatibility.
    * @param nb Number of trials (0 if illimited).
    */
-  inline void setMaxTrials (int nb) { nbmaxtrials = nb; }
+  inline void setMaxTrials (int nb) { maxtrials = nb; resetMaxDetections (); }
 
   /**
-   * \brief Returns the maximum number of trials for a multi-detection.
+   * \brief Increments the maximum number of detections in a multi-detection.
+   * @param dir Increments if true, otherwise decrements.
    */
-  inline int getMaxTrials () const { return nbmaxtrials; }
+  void incMaxDetections (bool dir);
 
   /**
-   * \brief Retuns whether the last trial was successful.
+   * \brief Resets the maximum number of detections set for a multi-detection.
    */
-  inline bool isLastTrialOk () { return lastTrialOk; }
+  inline void resetMaxDetections () { maxtrials = 0; }
 
   /**
    * \brief Gets the last detection inputs.
@@ -630,12 +637,10 @@ private :
   bool finalLengthTestOn;
   /** Segment multi-selection modality status. */
   bool multiSelection;
-  /** Flag indicating if the last trial was successful. */
-  bool lastTrialOk;
   /** Count of trials in a multi-detection. */
   int nbtrials;
   /** Maximum number of trials in a multi-detection. */
-  int nbmaxtrials;
+  int maxtrials;
   /** Automatic detection modality. */
   bool autodet;
   /** Grid resolution for the automatic extraction. */
diff --git a/Code/Seg/ImageTools/digitalstraightsegment.cpp b/Code/Seg/ImageTools/digitalstraightsegment.cpp
index 212aadc363bfba23462aa0f745a8abe1bd40f766..cbb53bd5d5aa2d6609a036c3fcbf71845eacda45 100755
--- a/Code/Seg/ImageTools/digitalstraightsegment.cpp
+++ b/Code/Seg/ImageTools/digitalstraightsegment.cpp
@@ -37,6 +37,24 @@ DigitalStraightSegment::DigitalStraightSegment (Pt2i p1, Pt2i p2, Pt2i p3,
 }
 
 
+DigitalStraightSegment::DigitalStraightSegment (Pt2i p1, Pt2i p2, int width)
+                      : DigitalStraightLine (p1, p2, DSL_THIN)
+{
+  nu = width * period ();
+  c = a * p1.x () + b * p1.y () - nu / 2;
+  if (a < (b < 0 ? -b : b))
+  {
+    min = (p1.x () < p2.x () ? p1.x () : p2.x ());
+    max = (p1.x () < p2.x () ? p2.x () : p1.x ());
+  }
+  else
+  {
+    min = (p1.y () < p2.y () ? p1.y () : p2.y ());
+    max = (p1.y () < p2.y () ? p2.y () : p1.y ());
+  }
+}
+
+
 Pt2i DigitalStraightSegment::getABoundingPoint (bool upper) const
 {
   int sa = a, sb = b, u1 = 1, v1 = 0, u2 = 0, v2 = 1;
@@ -101,3 +119,39 @@ void DigitalStraightSegment::adjustWorkArea (int &xmin, int &ymin,
     height = (ymin >= y2 ? 0 : y2 - ymin);
   }
 }
+
+
+void DigitalStraightSegment::getPoints (vector<Pt2i> &pts) const
+{
+  int xmin, ymin, w, h;
+  if (b > a || -b > a)
+  {
+    xmin = min;
+    w = max - min;
+    ymin = (b < 0 ? (c + nu - a * min) / b - 1 : (c - a * max) / b - 1);
+    h = (b < 0 ? (c - a * max) / b + 1 : (c + nu - a * min) / b + 1) - ymin;
+  }
+  else
+  {
+    ymin = min;
+    h = max - min;
+    xmin = (b < 0 ? (c - b * min) / a - 1 : (c - b * max) / a - 1);
+    w = (b < 0 ? (c + nu - b * max) / a : (c + nu - b * min) / a) + 1 - xmin;
+  }
+  vector<Pt2i> lowbound;
+  getBoundPoints (lowbound, false, xmin, ymin, w, h);
+  vector<Pt2i>::iterator it = lowbound.begin ();
+
+  while (it != lowbound.end ())
+  {
+    Pt2i p = *it;
+    while (owns (p))
+    {
+      pts.push_back (p);
+      if (b > a) p.set (p.x (), p.y () + 1);
+      else if (-b > a) p.set (p.x (), p.y () - 1);
+      else p.set (p.x () + 1, p.y ());
+    }
+    it ++;
+  }
+}
diff --git a/Code/Seg/ImageTools/digitalstraightsegment.h b/Code/Seg/ImageTools/digitalstraightsegment.h
index 21c2074532e9208b244abfd58680de8cf3af3894..8ab1ccc66d6e8e1d867747efcd9dcf6f2922e143 100755
--- a/Code/Seg/ImageTools/digitalstraightsegment.h
+++ b/Code/Seg/ImageTools/digitalstraightsegment.h
@@ -47,12 +47,26 @@ public:
   DigitalStraightSegment (Pt2i p1, Pt2i p2, Pt2i p3,
                           int xmin, int ymin, int xmax, int ymax);
 
+  /**
+   * Creates a digital straight segment from its end points and a width value.
+   * @param p1 First end point of the segment.
+   * @param p2 Second end point of the segment.
+   * @param width Width value.
+   */
+  DigitalStraightSegment (Pt2i p1, Pt2i p2, int width);
+
   /**
    * \brief Returns a bounding point of the digital line
    * @param upper true for a upper bounding point, false for a lower one.
    */
   Pt2i getABoundingPoint (bool upper) const;
 
+  /**
+   * \brief Returns the points of the segment.
+   * @param pts Vector of points to fill in.
+   */
+  void getPoints (vector<Pt2i> &pts) const;
+
 
 protected:
 
diff --git a/Code/Seg/ImageTools/vmap.cpp b/Code/Seg/ImageTools/vmap.cpp
index 42e97fb4d23d3dfdc67a987058763192ac6a939e..be16b2212514a6670f0b69252726d82d0cb0f203 100755
--- a/Code/Seg/ImageTools/vmap.cpp
+++ b/Code/Seg/ImageTools/vmap.cpp
@@ -218,7 +218,7 @@ VMap::VMap (int width, int height, int **data, int type)
 VMap::~VMap ()
 {
   delete [] map;
-  delete [] map;
+  delete [] imap;
   delete [] mask;
   delete [] dilations;
   delete [] bowl;
@@ -642,6 +642,10 @@ int VMap::localMax (int *lmax, const vector<Pt2i> &pix, const Vr2i &gref) const
   // Gets the local maxima
   int count = searchLocalMax (lmax, n, gn);
 
+  // Prunes the already selected candidates
+  if (masking)
+    count = keepFreeElementsIn (pix, count, lmax);
+
   // Prunes the candidates with opposite gradient
   if (orientedGradient)
     count = keepDirectedElementsAs (pix, count, lmax, gref);
@@ -688,7 +692,8 @@ int VMap::searchLocalMax (int *lmax, int n, int *in) const
         up = false;
         int k = i;
         while (in[k - 1] == in[i]) k--;
-        lmax[count++] = k + (i - k) / 2;
+        if (in[k + (i - k) / 2] > gmagThreshold)
+          lmax[count++] = k + (i - k) / 2;
       }
     }
     else
diff --git a/Code/Seg/ImageTools/vmap.h b/Code/Seg/ImageTools/vmap.h
index 06671ce2f0774a980ae9e2ba143ebc6aab381693..54236e2079f2bff180cb02a9cc190eaac3c615b8 100755
--- a/Code/Seg/ImageTools/vmap.h
+++ b/Code/Seg/ImageTools/vmap.h
@@ -241,6 +241,11 @@ public:
   inline void switchOrientationConstraint () {
     orientedGradient = ! orientedGradient; }
 
+  /**
+   * \brief Returns the occupancy mask contents.
+   */
+  inline bool *getMask () const { return (mask); }
+
   /**
    * \brief Clears the occupancy mask.
    */
diff --git a/Code/Seg/ImageTools/vr2i.h b/Code/Seg/ImageTools/vr2i.h
index cac1af7dd1b85a151609f2aeb215935d66e96409..5fc99ef15dda3db918812269775ab66e0b2bc33c 100755
--- a/Code/Seg/ImageTools/vr2i.h
+++ b/Code/Seg/ImageTools/vr2i.h
@@ -73,18 +73,29 @@ public:
    * \brief Returns the scalar product with the given vector.
    * If intensity value holds on a byte, scalar product (SP) holds on a short
    *   and squared SP holds on a int.
+   * @param vec The given vector.
    */
   inline int scalarProduct (Vr2i vec) const {
     return (xv * vec.xv + yv * vec.yv); }
 
   /**
    * @fn int squaredScalarProduct (Vr2i vec)
-   * \brief Returns the sqaured scalar product with the given vector.
+   * \brief Returns the squared scalar product with the given vector.
+   * @param vec The given vector.
    */
   inline int squaredScalarProduct (Vr2i vec) const {
     return ((xv * vec.xv + yv * vec.yv)
             * (xv * vec.xv + yv * vec.yv)); }
 
+  /**
+   * @fn int squaredVectorProduct (Vr2i vec)
+   * \brief Returns the squared norm of the vector product with given vector.
+   * @param vec The given vector.
+   */
+  inline int squaredVectorProduct (Vr2i vec) const {
+    return ((xv * vec.yv - yv * vec.xv)
+            * (xv * vec.yv - yv * vec.xv)); }
+
   /**
    * @fn bool equals (Vr2i p)
    * \brief Checks equivalence to the given vector.
diff --git a/Code/Seg/main.cpp b/Code/Seg/main.cpp
index 30aa3b5762a312a42e2619f011719ae08b44af89..d48471616aceb542fe3b84aedaa76aef6e564a26 100755
--- a/Code/Seg/main.cpp
+++ b/Code/Seg/main.cpp
@@ -8,7 +8,7 @@ int main (int argc, char *argv[])
 {
   int val = 0;
   int imageName = 0;
-  bool testing = false;
+  bool random = false, testing = false;
   QApplication app (argc, argv);
 
 /*
@@ -32,6 +32,7 @@ int main (int argc, char *argv[])
       else if (string(argv[i]) == string ("-idet")) window.toggleIdetWindow ();
       // Test command : time ./Seg -test ../Images/couloir.jpg
       else if (string(argv[i]) == string ("-test")) testing = true;
+      else if (string(argv[i]) == string ("-random")) random = true;
       else if (string(argv[i]) == string ("-sobel3x3"))
         window.useGradient (VMap::TYPE_SOBEL_3X3);
       else if (string(argv[i]) == string ("-sobel5x5"))
@@ -63,7 +64,8 @@ int main (int argc, char *argv[])
     }
     else imageName = i;
   }
-  if (imageName != 0) window.setFile (QString (argv[imageName]));
+  if (random) window.setRandom ();
+  else if (imageName != 0) window.setFile (QString (argv[imageName]));
   else window.setFile (QString ("../couloir.gif"));
   if (testing)
   {
diff --git a/Methode/ctrl.tex b/Methode/ctrl.tex
index 76475029b60bd070f78d691c22b67d8c753e2923..f11906425aed9f485a2bcdaa7f6aea33a8d93aaf 100755
--- a/Methode/ctrl.tex
+++ b/Methode/ctrl.tex
@@ -62,6 +62,7 @@ Ctrl-w && Commute le recentrage du scan sur le segment d\'etect\'e \\
 Ctrl-x && Commute l'ajustement de la consigne d'\'epaisseur sur le segment d\'etect\'e \\
 Ctrl-y && Commute l'affichage des pixels des segments flous \\
 Ctrl-z && Commute le contr\^ole de la consigne d'\'epaisseur \\
+Ctrl-! && Commute la couleur de s\'election des segments flous \\
 1 && Commute la visu des segments (pixels) \\
 2 && Commute la visu de l'accumulateur \\
 3 && Commute la visu des profils \\