diff --git a/Code/Seg/BSTools/bsaccumulatoritem.cpp b/Code/Seg/BSTools/bsaccumulatoritem.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..3ecf8c027892b6a754b2b1bf000a7b6e65d5bb70
--- /dev/null
+++ b/Code/Seg/BSTools/bsaccumulatoritem.cpp
@@ -0,0 +1,168 @@
+#include <QtGui>
+#include <iostream>
+#include <cmath>
+#include "bsaccumulatoritem.h"
+
+using namespace std;
+
+
+
+const int BSAccumulatorItem::DEFAULT_PEN_WIDTH = 1;
+const int BSAccumulatorItem::LEFT_MARGIN = 16;
+const int BSAccumulatorItem::TEXT_HEIGHT = 16;
+
+
+BSAccumulatorItem::BSAccumulatorItem (BSDetector *sd, int w, int h)
+{
+  detector = sd;
+  width = w;
+  height = h;
+  selaccu = 1;
+  map[0] = NULL;
+  map[1] = NULL;
+  solution[0] = -1;
+  solution[1] = -1;
+  resol[0] = 1.;
+  resol[1] = 1.;
+  mask = NULL;
+  verbose = true;
+  infoPen = QPen (Qt::red, DEFAULT_PEN_WIDTH, Qt::SolidLine,
+                  Qt::RoundCap, Qt::RoundJoin);
+  scalePen = QPen (Qt::red, 2);
+  markPen = QPen (Qt::blue, 4);
+}
+
+
+BSAccumulatorItem::~BSAccumulatorItem ()
+{
+  delete [] map[0];
+  delete [] map[1];
+}
+
+
+QRectF BSAccumulatorItem::boundingRect () const
+{
+  return QRectF (0, 0, width, height);
+}
+
+
+void BSAccumulatorItem::paint (QPainter *painter,
+                               const QStyleOptionGraphicsItem *option,
+                               QWidget *widget)
+{
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+
+  if (! detector->isFiltering (selaccu))
+  {
+    painter->fillRect (0, 0, width, height, QBrush (Qt::black));
+    return;
+  }
+
+  // Updates the grid
+  LineSpaceFilter *hugues = detector->getFilter (selaccu);
+  int nbc = hugues->width ();
+  int nbl = hugues->height ();
+  int cw = width / nbc;
+  int ch = height / nbl;
+
+  // Updates the accumulator
+  if (map[selaccu] == NULL) map[selaccu] = new uchar[nbc * nbl];
+  hugues->getAccumulator (map[selaccu], solution);
+  resol[0] = hugues->angularResolution () * 180. / M_PI;
+  resol[1] = hugues->distanceResolution ();
+  mask = hugues->getMask ();
+
+  // Draws the accumulator
+  if (solution[0] >= 0)
+  {
+    uchar *pix = map[selaccu];
+    for (int i = 0; i < nbc * nbl; i++, pix++)
+      painter->fillRect ((i % nbc) * cw, (nbl - 1 - i / nbc) * ch, cw, ch,
+                         QBrush (QColor ((int) *pix, (int) *pix, (int) *pix)));
+
+    // Marks the filtering cells
+    if (mask != NULL)
+    {
+      painter->setPen (markPen);
+      bool *maski = mask;
+      for (int j = 0; j < nbl; j++)
+        for (int i = 0; i < nbc; i++)
+          if (*maski++)
+            painter->drawPoint ((i + 0.5) * cw, (nbl - j - 0.5) * ch);
+    }
+
+    if (verbose)
+    {
+      // Displays the scale (one radian / one pixel)
+      painter->setPen (scalePen);
+      int sh = (int) (ch / resol[1] + 0.5);
+      painter->drawRect (0, height - 1 - sh, (int) (cw / resol[0] + 0.5), sh);
+
+      // Displays information
+      initText (painter);
+      addText (painter, QString ("S size : ") + QString::number (nbc)
+                        + QString ("x") + QString::number (nbl));
+      addText (painter, QString ("R resolution : ")
+                        + QString::number (resol[0]) + QString (" pixels x ")
+                        + QString::number (resol[1]) + QString (" degrees"));
+      addText (painter, QString ("P sub-pixellisation level : ")
+                        + QString::number (hugues->getSubpix ()));
+      addText (painter, QString ("F selectivity : ")
+                        + QString::number (hugues->getSelectionThreshold ())
+                        + QString ("% of max vote"));
+    }
+  }
+}
+
+
+bool BSAccumulatorItem::resizeAccumulator (bool larger)
+{
+  if (! detector->isFiltering (selaccu)) return false;
+  LineSpaceFilter *hugues = detector->getFilter (selaccu);
+  bool res = hugues->resize (larger);
+  if (res)
+  {
+    delete [] map[selaccu];
+    map[selaccu] = new uchar[hugues->width () * hugues->height ()];
+  }
+  return (res);
+}
+
+
+bool BSAccumulatorItem::zoomAccumulator (bool in)
+{
+  if (! detector->isFiltering (selaccu)) return false;
+  LineSpaceFilter *hugues = detector->getFilter (selaccu);
+  return (hugues->zoom (in));
+}
+
+
+bool BSAccumulatorItem::subpixellise (bool larger)
+{
+  if (! detector->isFiltering (selaccu)) return false;
+  LineSpaceFilter *hugues = detector->getFilter (selaccu);
+  return (hugues->subpixellise (larger));
+}
+
+
+bool BSAccumulatorItem::setFilterSelectivity (bool larger)
+{
+  if (! detector->isFiltering (selaccu)) return false;
+  LineSpaceFilter *hugues = detector->getFilter (selaccu);
+  return (hugues->setSelectivity (larger));
+}
+
+
+void BSAccumulatorItem::initText (QPainter *painter)
+{
+  painter->setPen (infoPen);
+  textOffset = 0;
+}
+
+
+void BSAccumulatorItem::addText (QPainter *painter, const QString &text)
+{
+  textOffset += TEXT_HEIGHT;
+  painter->drawText (LEFT_MARGIN, textOffset, text);
+}
diff --git a/Code/Seg/BSTools/bsaccumulatoritem.h b/Code/Seg/BSTools/bsaccumulatoritem.h
new file mode 100755
index 0000000000000000000000000000000000000000..25368fb65b8f12233563c7745040b703ed1e1287
--- /dev/null
+++ b/Code/Seg/BSTools/bsaccumulatoritem.h
@@ -0,0 +1,130 @@
+#ifndef BS_ACCUMULATOR_ITEM_H
+#define BS_ACCUMULATOR_ITEM_H
+
+#include <QGraphicsItem>
+#include "bsdetector.h"
+
+
+/** 
+ * @class BSAccumulatorItem bsaccumulatoritem.h
+ * \brief Hough accumulator grid display and control.
+ * \author {P. Even}
+ */
+class BSAccumulatorItem : public QGraphicsItem
+{
+
+public:
+
+  /**
+   * \brief Creates a Hough accumulator grid.
+   * @param sd Associated blurred segment detector.
+   * @param w Accumulator width.
+   * @param h Accumulator height.
+   */
+  BSAccumulatorItem (BSDetector *sd, int w, int h);
+
+  /** Deletes the Hough accumulator grid.
+   */
+  ~BSAccumulatorItem ();
+
+  /** \brief Inquires if the pre-filter accumulator is displayed.
+   */
+  inline bool isPrefilterDisplayed () const {return (selaccu == 0); }
+
+  /** \brief Switches the displayed accumulator filter.
+   */
+  inline void switchAccumulator () { selaccu = (selaccu != 0 ? 0 : 1); }
+
+  /** \brief Returns the size of the filter accumulator graphics item.
+   */
+  QRectF boundingRect () const;
+
+  /** \brief Draws the accumulator of the selected filter.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+  /**
+   * \brief Switches on or off the information text display modality.
+   */
+  inline void switchInfoDisplay () { verbose = ! verbose; }
+
+  /** \brief Resizes the accumulator array.
+   * @param larger Sets larger if true, smaller otherwise.
+   */
+  bool resizeAccumulator (bool larger);
+
+  /** \brief Zooms in or out the accumulator array.
+   * @param in Zooms in if true, out otherwise.
+   */
+  bool zoomAccumulator (bool in);
+
+  /** \brief Modifies the subpixellisation of the accumulator array.
+   * @param in Sets larger if true, smaller otherwise.
+   */
+  bool subpixellise (bool larger);
+
+  /** \brief Modifies the filter selectivity.
+   * @param larger Makes the filter more selective if true, less otherwise.
+   */
+  bool setFilterSelectivity (bool larger);
+
+
+private:
+
+  /** Default value for pen width. */
+  static const int DEFAULT_PEN_WIDTH;
+  /** Left margin for information text. */
+  static const int LEFT_MARGIN;
+  /** Information text height. */
+  static const int TEXT_HEIGHT;
+
+
+  /** Blurred segment detector. */
+  BSDetector *detector;
+  /** Accumulator displayed (0 = prefilter, 1 = final filter). */
+  int selaccu;
+
+  /** Accumulator width. */
+  int width;
+  /** Accumulator height. */
+  int height;
+  /** Contents of the accumulator.
+    * The array of vote counts for each cell. */
+  uchar *map[2];
+  /** Coordinates of the cell with the highest vote. */
+  int solution[2];
+  /** Accumulator scale in pixels.
+    * One radian for the angles, and one pixel for the distances. */
+  double resol[2];
+  /** Contents of the applied accumulator mask.
+    * An array of booleans values for each cell,
+    * that are set to true if the cell belongs to the mask. */
+  bool *mask;
+
+  /** Information text modality. */
+  bool verbose;
+  /** Information text style. */
+  QPen infoPen;
+  /** Information text vertical offset. */
+  int textOffset;
+  /** Scale display style. */
+  QPen scalePen;
+  /** Mark display style. */
+  QPen markPen;
+
+
+  /**
+   * \brief Initializes the text display (color and position).
+   * @param painter : Painter to be decorated.
+   */
+  void initText (QPainter *painter);
+
+  /**
+   * \brief Paints a new text in the graphics item (updates text position).
+   * @param painter : Painter to be decorated.
+   * @param text : Text to be displayed.
+   */
+  void addText (QPainter *painter, const QString &text);
+};
+#endif
diff --git a/Code/Seg/BSTools/bsaccumulatorview.cpp b/Code/Seg/BSTools/bsaccumulatorview.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..4610b547726b700fc5d75e4a891bdea85ce73a92
--- /dev/null
+++ b/Code/Seg/BSTools/bsaccumulatorview.cpp
@@ -0,0 +1,79 @@
+#include <QtGui>
+#include <iostream>
+#include "bsaccumulatorview.h"
+
+using namespace std;
+
+
+const int BSAccumulatorView::CELL_SIZE = 12;
+
+
+BSAccumulatorView::BSAccumulatorView (BSDetector *sd)
+{
+  int w = LineSpaceFilter::DEFAULT_NB_ANG_CELLS * CELL_SIZE;
+  int h = LineSpaceFilter::DEFAULT_NB_DIST_CELLS * CELL_SIZE;
+  setBackgroundBrush (QBrush (Qt::yellow));
+  setScene (new QGraphicsScene (0, 0, w, h));
+  grid = new BSAccumulatorItem (sd, w, h);
+  scene()->addItem (grid);
+  setWindowTitle (grid->isPrefilterDisplayed () ?
+                  "Pre-filter accumulator" : "Final filter accumulator");
+}
+
+
+BSAccumulatorView::~BSAccumulatorView ()
+{
+  scene()->removeItem (grid);
+  delete grid;
+}
+
+
+void BSAccumulatorView::paint (QPainter *painter,
+                               const QStyleOptionGraphicsItem *option,
+                               QWidget *widget)
+{
+  Q_UNUSED (painter);
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+}
+
+
+bool BSAccumulatorView::processKeyEvent (QKeyEvent *event)
+{
+  bool processed = false;
+  switch (event->key ())
+  {
+    case Qt::Key_I :
+      grid->switchAccumulator ();
+      setWindowTitle (grid->isPrefilterDisplayed () ?
+                      "Pre-filter accumulator" : "Final filter accumulator");
+      processed = true;
+      break;
+
+    case Qt::Key_V :
+      grid->switchInfoDisplay ();
+      processed = true;
+      break;
+
+    case Qt::Key_S :
+      processed = grid->resizeAccumulator (
+                          (event->modifiers () & Qt::ShiftModifier) == 0);
+      break;
+
+    case Qt::Key_R :
+      processed = grid->zoomAccumulator (
+                          (event->modifiers () & Qt::ShiftModifier) == 0);
+      break;
+
+    case Qt::Key_P :
+      processed = grid->subpixellise (
+                          (event->modifiers () & Qt::ShiftModifier) != 0);
+      break;
+
+    case Qt::Key_F :
+      processed = grid->setFilterSelectivity (
+                          (event->modifiers () & Qt::ShiftModifier) == 0);
+      break;
+  }
+  return processed;
+}
diff --git a/Code/Seg/BSTools/bsaccumulatorview.h b/Code/Seg/BSTools/bsaccumulatorview.h
new file mode 100755
index 0000000000000000000000000000000000000000..75ccfebed3120a1a9cd19fcc9bc3b1a47b55e021
--- /dev/null
+++ b/Code/Seg/BSTools/bsaccumulatorview.h
@@ -0,0 +1,42 @@
+#ifndef BS_ACCUMULATOR_H
+#define BS_ACCUMULATOR_H
+
+#include <QGraphicsView>
+#include "bsaccumulatoritem.h"
+
+
+class BSAccumulatorView : public QGraphicsView
+{
+
+public:
+
+  /**
+   * \brief Creates an accumulator analyzer.
+   */
+  BSAccumulatorView (BSDetector *sd);
+
+  /**
+   * \brief Deletes the accumulator analyzer.
+   */
+  ~BSAccumulatorView ();
+
+  /**
+   * \brief Redraws the accumulator analyzer.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+  /**
+   * \brief Processes key pressed events.
+   */
+  bool processKeyEvent (QKeyEvent *event);
+
+protected:
+
+private:
+  static const int CELL_SIZE;
+  BSAccumulatorItem *grid;
+
+};
+
+#endif
diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..375f19a803388e2b4f99e4791cb82d5a5e21b4d4
--- /dev/null
+++ b/Code/Seg/BSTools/bsdetectionwidget.cpp
@@ -0,0 +1,762 @@
+#include <QtGui>
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+#include "bsdetectionwidget.h"
+
+using namespace std;
+
+
+
+const int BSDetectionWidget::MAX_WIDTH_TUNING = 400;
+const int BSDetectionWidget::DETECTION_LACKS_TUNING = 20;
+const int BSDetectionWidget::DEFAULT_PEN_WIDTH = 1;
+
+
+
+BSDetectionWidget::BSDetectionWidget (QWidget *parent)
+{
+  Q_UNUSED (parent);
+
+  // Sets default user interface parameters
+  setFocus ();
+  grabKeyboard ();
+  fixed = false;
+
+  // Sets initial values for the gradient map
+  gMap = NULL;
+
+  // Initializes the auxiliary views
+  accuview = NULL;
+  strucview = NULL;
+  profileview = NULL;
+
+  alternate = 0;
+  verbose = false;
+
+  instanceOfAll = 0;
+}
+
+
+BSDetectionWidget::~BSDetectionWidget ()
+{
+  if (accuview != NULL) delete accuview;
+  if (strucview != NULL) delete strucview;
+}
+
+
+QSize BSDetectionWidget::openImage (const QString &fileName, int type)
+{
+  QSize newSize (0, 0);
+  loadedImage.load (fileName);
+  width = loadedImage.width ();
+  height = loadedImage.height ();
+  newSize = loadedImage.size ();
+ 
+  augmentedImage = loadedImage;
+  if (gMap != NULL) delete gMap;
+  gMap = new VMap (width, height, getBitmap (augmentedImage), type);
+  detector.setGradientMap (gMap);
+ 
+  update ();
+  if (profileview != NULL) profileview->setImage (&loadedImage, gMap);
+  if (strucview != NULL) strucview->setGradientImage (gMap);
+
+  return newSize;
+}
+
+
+int **BSDetectionWidget::getBitmap (const QImage &image)
+{
+  int w = image.width ();
+  int h = image.height ();
+  
+  int **tabImage = new int*[h];
+  for (int i = 0; i < h; i++)
+  {
+    tabImage[i] = new int[w];
+    for(int j = 0; j < w; j++)
+    {
+      QColor c = QColor (image.pixel (j, h - i - 1));
+      tabImage[i][j] = c.value ();
+    }
+  }
+  return tabImage;
+}
+
+
+bool BSDetectionWidget::saveAugmentedImage (const QString &fileName,
+                                            const char *fileFormat)
+{
+  QImage aImage = augmentedImage;
+  return (aImage.save (fileName, fileFormat));
+}
+
+
+void BSDetectionWidget::clearImage ()
+{
+  augmentedImage.fill (qRgb (255, 255, 255));
+  update ();
+}
+
+
+void BSDetectionWidget::paintEvent (QPaintEvent *)
+{
+  QPainter painter (this);
+  painter.drawImage (QPoint (0, 0), augmentedImage);
+}
+
+
+void BSDetectionWidget::storeExtractedSegment ()
+{
+  BlurredSegment *bs = detector.getBlurredSegment (1);
+  if (bs != NULL)
+  {
+    ExtractedSegment es;
+    es.bs = bs;
+    es.p1 = p1;
+    es.p2 = p2;
+    extractedSegments.push_back (es);
+    detector.preserveFormerBlurredSegment ();
+  }
+}
+
+
+void BSDetectionWidget::displayExtractedSegments ()
+{
+  augmentedImage = loadedImage;
+  QPainter painter (&augmentedImage);
+  if (! extractedSegments.empty ())
+  {
+    vector<ExtractedSegment>::iterator it = extractedSegments.begin ();
+    while (it != extractedSegments.end ())
+    {
+      vector<Pt2i> bnd;
+      DigitalStraightSegment *dss = it->bs->getSegment ();
+      dss->getBoundPoints (bnd, false, 0, 0, width, height);
+      drawListOfPixels (bnd, Qt::green, painter);
+      dss->getBoundPoints (bnd, true, 0, 0, width, height);
+      drawListOfPixels (bnd, Qt::green, painter);
+      bnd = it->bs->getAllPoints ();
+      drawListOfPixels (bnd, Qt::blue, painter);
+      drawLine (it->p1, it->p2, Qt::white, painter);
+      it ++;
+    }
+  }
+  update (QRect (QPoint (0, 0), QPoint (width, height)));
+}
+
+
+void BSDetectionWidget::clearExtractedSegments ()
+{
+  vector<ExtractedSegment>::iterator it = extractedSegments.begin ();
+  while (it != extractedSegments.end ())
+    delete ((it++)->bs->getSegment ());
+  extractedSegments.clear ();
+}
+
+
+void BSDetectionWidget::closeAccuAnalyzer ()
+{
+  if (accuview != NULL)
+  {
+    accuview->close ();
+    delete accuview;
+    accuview = NULL;
+  }
+}
+
+
+void BSDetectionWidget::closePixelAnalyzer ()
+{
+  if (strucview != NULL)
+  {
+    strucview->close ();
+    delete strucview;
+    strucview = NULL;
+  }
+}
+
+
+void BSDetectionWidget::closeProfileAnalyzer ()
+{
+  if (profileview != NULL)
+  {
+    profileview->close ();
+    delete profileview;
+    profileview = NULL;
+  }
+}
+
+
+void BSDetectionWidget::switchAccuAnalyzer ()
+{
+  if (accuview != NULL)
+  {
+    accuview->close ();
+    delete accuview;
+    accuview = NULL;
+  }
+  else
+  {
+    accuview = new BSAccumulatorView (&detector);
+    accuview->show ();
+  }
+}
+
+
+void BSDetectionWidget::switchPixelAnalyzer ()
+{
+  if (strucview != NULL)
+  {
+    strucview->close ();
+    delete strucview;
+    strucview = NULL;
+  }
+  else
+  {
+    strucview = new BSStructureView (&loadedImage, &detector);
+    strucview->setGradientImage (gMap);
+    strucview->show ();
+  }
+}
+
+
+void BSDetectionWidget::switchProfileAnalyzer ()
+{
+  if (profileview != NULL)
+  {
+    profileview->close ();
+    delete profileview;
+    profileview = NULL;
+  }
+  else
+  {
+    profileview = new BSProfileView ();
+    profileview->setImage (&loadedImage, gMap);
+    if (! p1.equals (p2)) profileview->buildScans (p1, p2);
+    profileview->show ();
+  }
+}
+
+
+void BSDetectionWidget::mousePressEvent (QMouseEvent *event)
+{
+  this->p1 = Pt2i (event->pos().x (), height - 1 - event->pos().y());
+}
+
+
+void BSDetectionWidget::mouseReleaseEvent (QMouseEvent *event)
+{
+  fixed = true;
+  this->p2 = Pt2i (event->pos().x (), height - 1 - event->pos().y());
+alternate = 0;
+  cerr << "p1 defined: " << p1.x () << " " << p1.y () << endl;
+  cerr << "p2 defined: " << p2.x () << " " << p2.y () << endl;
+  extract ();
+}
+
+
+void BSDetectionWidget::mouseMoveEvent (QMouseEvent *event)
+{
+  fixed = false;
+  this->p2 = Pt2i (event->pos().x (), height - 1 - event->pos().y ());
+  if (verbose) cerr << "(" << p1.x () << ", " << p1.y () << ") ("
+                    << p2.x () << ", " << p2.y () << ")" << endl;
+  if (p1.manhattan (p2) > 5
+      && (width > p2.x() && height > p2.y()
+          && p2.x() > 0 && p2.y() > 0))
+  {
+    extract ();
+  }
+}
+
+
+void BSDetectionWidget::keyPressEvent (QKeyEvent *event)
+{
+  if (isActiveWindow ()) switch (event->key ())
+  {
+    case Qt::Key_U :
+      cerr << "p1 update: " << p1.x () << " " << p1.y () << endl;
+      cerr << "p2 update: " << p2.x () << " " << p2.y () << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_M : // Multi-selection switch
+      detector.switchMultiSelection ();
+      cout << "Multi-selection "
+           << (detector.isMultiSelection () ? "on" : "off") << endl;
+      break;
+
+    case Qt::Key_Y : // Initial detection extension limitation
+      detector.switchInitialBounding ();
+      extract (true);
+      cout << "Initial step max extension = "
+           << detector.initialDetectionMaxExtent () << endl;
+      break;
+
+    case Qt::Key_D : // Density test at initial step
+      detector.switchDensityTest ();
+      extract (true);
+      cout << "Density test : "
+           << (detector.isSetDensityTest () ? "on" : "off") << endl;
+      break;
+
+    case Qt::Key_W : // Input max width
+      detector.setInputMaxWidth (detector.getInputMaxWidth () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      extract (true);
+      cout << "Input max width = " << detector.getInputMaxWidth () << endl;
+      break;
+
+    case Qt::Key_L : // Output blurred segment min size
+      detector.setBSminSize (detector.getBSminSize () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      extract (true);
+      cout << "Output BS min size = " << detector.getBSminSize () << endl;
+      break;
+
+    case Qt::Key_H : // Pixel lack tolerence
+      detector.setPixelLackTolerence (detector.getPixelLackTolerence () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      extract (true);
+      cout << "Lack tolerence = " << detector.getPixelLackTolerence ()
+           << " pixels" << endl;
+      break;
+
+    case Qt::Key_N : // Automatic detection grid resolution
+      detector.setAutoGridResolution (detector.getAutoGridResolution () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      cout << "Auto grid resolution = "
+           << detector.getAutoGridResolution () << " pixels" << endl;
+      break;
+
+    case Qt::Key_Q :
+      detector.switchAutoRestart ();
+      extract (true);
+      cout << "Segment continuation after = "
+           << detector.getRestartOnLack () << " pixels" << endl;
+      break;
+
+    case Qt::Key_T :
+      detector.toggleThinning ();
+      extract (true);
+      cout << "Thinning "
+           << (detector.isThinningActivated () ? "on" : "off") << endl;
+      break;
+
+    case Qt::Key_X :
+      detector.switchAutoWidth ();
+      cout << "Final step max width " << (detector.autoWidthOn () ?
+              "fitted to initial segment" : "left unchanged") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_S :
+      detector.switchDynamicScans ();
+      cout << (detector.dynamicScansOn () ?
+               "Dynamic scans" : "Static scans") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_O :
+      detector.switchOrthoScans ();
+      cout << (detector.orthoScansOn () ?
+               "Orthographic scans" : "Directional scans") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_F :
+      detector.switchFiltering (1);
+      cout << "Final filtering "
+           << (detector.isFiltering (1) ? "on" : "off") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_P :
+      detector.switchFiltering (0);
+      cout << "Pre-filtering "
+           << (detector.isFiltering (0) ? "on" : "off") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_G :
+      detector.switchConnectivityConstraint ();
+      cout << "Connectivity constraint "
+           << (detector.isSetConnectivityConstraint () ? "on" : "off") << endl;
+      extract (true);
+      break;
+
+    case Qt::Key_C :
+      if (event->modifiers () & Qt::ControlModifier)
+        storeExtractedSegment ();
+      break;
+
+    case Qt::Key_V :
+      if (event->modifiers () & Qt::ControlModifier)
+        displayExtractedSegments ();
+      else switchVerbose ();
+      break;
+
+    case Qt::Key_Z :
+      if (event->modifiers () & Qt::ControlModifier)
+        clearExtractedSegments ();
+      break;
+
+    case Qt::Key_E :
+      if (event->modifiers () & Qt::ShiftModifier)
+        detector.invertEdgeDirection ();
+      else detector.switchEdgeDirectionConstraint ();
+      switch (detector.edgeDirectionConstraint ())
+      {
+        case 0 :
+          cout << "Stroke detection" << endl;
+          break;
+        case 1 :
+          cout << "Edge detection" << endl;
+          break;
+        case -1 :
+          cout << "Opposite edge detection" << endl;
+          break;
+      }
+      extract (true);
+      break;
+
+    case Qt::Key_1 :
+      switchPixelAnalyzer ();
+      break;
+
+    case Qt::Key_2 :
+      switchAccuAnalyzer ();
+      break;
+
+    case Qt::Key_3 :
+      switchProfileAnalyzer ();
+      break;
+
+    case Qt::Key_6 :
+      displayNextOfAll ();
+      break;
+
+    case Qt::Key_7 :
+      extractAll ();
+      break;
+
+    case Qt::Key_8 :
+      alternateTest ();
+      break;
+
+    case Qt::Key_9 :
+      performanceTest ();
+      break;
+
+    case Qt::Key_0 :
+      localTest ();
+      break;
+  }
+  else if (strucview != NULL && strucview->isActiveWindow ())
+  {
+    if (strucview->processKeyEvent (event)) extract (true);
+  }
+  else if (accuview != NULL && accuview->isActiveWindow ())
+  {
+    if (accuview->processKeyEvent (event)) extract (true);
+  }
+  else if (profileview != NULL && profileview->isActiveWindow ())
+  {
+    if (profileview->processKeyEvent (event)) extract (true);
+  }
+}
+
+
+void BSDetectionWidget::drawListOfPixels (vector<Pt2i> vectPixels,
+                                          QColor color, QPainter &painter)
+{
+  vector<Pt2i>::iterator iter = vectPixels.begin ();
+  while (iter != vectPixels.end ())
+  {
+    Pt2i p = *iter;
+    painter.setPen (QPen (color, DEFAULT_PEN_WIDTH, Qt::SolidLine,
+                          Qt::RoundCap, Qt::RoundJoin));
+    if (p.x() < width && p.y() < height && p.x() >= 0 && p.y() >= 0)
+      painter.drawPoint (QPoint (p.x(), height - 1 - p.y()));  // dec 1
+    iter ++;
+   }
+}
+
+
+void BSDetectionWidget::drawListOfPixels (vector<Pt2i> vectPixels,
+                                          QPainter &painter)
+{
+  vector<Pt2i>::iterator iter = vectPixels.begin ();
+  while (iter != vectPixels.end ())
+  {
+    Pt2i p = *iter;
+    painter.setPen (QPen (QBrush (loadedImage.pixel (p.x (),
+                                  loadedImage.height () - 1 - p.y ())),
+                          DEFAULT_PEN_WIDTH, Qt::SolidLine,
+                          Qt::RoundCap, Qt::RoundJoin));
+    if (p.x() < width && p.y() < height && p.x() >= 0 && p.y() >= 0)
+      painter.drawPoint (QPoint (p.x(), height - 1 - p.y()));  // dec 1
+    iter ++;
+   }
+}
+
+
+void BSDetectionWidget::drawLine (const Pt2i from, const Pt2i to,
+                                  QColor color, QPainter &painter)
+{
+  int n;
+  Pt2i *pts = from.drawing (to, &n);
+  painter.setPen (QPen (color, DEFAULT_PEN_WIDTH, Qt::SolidLine,
+                        Qt::RoundCap, Qt::RoundJoin));
+  for (int i = 0; i < n; i++)
+    painter.drawPoint (QPoint (pts[i].x (),
+                               height - 1 - pts[i].y ()));  // dec 1
+  delete [] pts;
+}
+
+
+void BSDetectionWidget::extract (bool withAllDisplay)
+{
+  if (! p1.equals (p2))
+  {
+    fixed = withAllDisplay;
+    extract ();
+  }
+}
+
+
+void BSDetectionWidget::extract ()
+{
+  augmentedImage = loadedImage;
+  QPainter painter (&augmentedImage);
+  if (p1.equals (p2))
+  {
+    update (QRect (QPoint (0, 0), QPoint (width, height)));
+    fixed = false;
+    return;
+  }
+  drawLine (p1, p2, Qt::red, painter);
+
+  if (detector.isMultiSelection ()) detector.multidetect (p1, p2);
+  else detector.detect (p1, p2);
+
+  // Update auxiliary view if not dragging
+  if (fixed)
+  {
+    if (profileview != NULL)
+    {
+      profileview->buildScans (p1, p2);
+      profileview->scene()->update ();
+    }
+    if (accuview != NULL) accuview->scene()->update ();
+    if (strucview != NULL) strucview->scene()->update ();
+  }
+
+  if (detector.isMultiSelection ())
+  {
+    vector<BlurredSegment *> mbs = detector.getBlurredSegments ();
+    vector<BlurredSegment *>::iterator it = mbs.begin ();
+    while (it != mbs.end ())
+    {
+      DigitalStraightSegment *dss = (*it)->getSegment ();
+      if (dss != NULL) 
+      {
+        vector<Pt2i> bnd;
+        dss->getBounds (bnd, 0, 0, width, height);
+        drawListOfPixels (bnd, Qt::green, painter);
+      }
+      it++;
+    }
+  }
+  else
+  {
+    BlurredSegment *bs = detector.getBlurredSegment (1);
+    if (bs != NULL)
+    {
+      DigitalStraightSegment *dss = bs->getSegment ();
+      if (dss != NULL) 
+      {
+        vector<Pt2i> bnd;
+        dss->getBounds (bnd, 0, 0, width, height);
+        drawListOfPixels (bnd, Qt::green, painter);
+      }
+    }
+  }
+
+  update (QRect (QPoint (0, 0), QPoint (width, height)));
+  if (verbose && fixed) displayExtractionResult ();
+  fixed = false;
+}
+
+
+void BSDetectionWidget::extractAll ()
+{
+  bool formerMultiMode = detector.isMultiSelection ();
+  if (! formerMultiMode) detector.switchMultiSelection ();
+  augmentedImage = loadedImage;
+  QPainter painter (&augmentedImage);
+
+  detector.detectAll ();
+
+  // Update auxiliary view if not dragging
+  if (fixed)
+  {
+    if (profileview != NULL)
+    {
+      profileview->buildScans (p1, p2);
+      profileview->scene()->update ();
+    }
+    if (accuview != NULL) accuview->scene()->update ();
+    if (strucview != NULL) strucview->scene()->update ();
+  }
+
+  vector<BlurredSegment *> mbs = detector.getBlurredSegments ();
+  instanceOfAll = mbs.size ();
+  cout << instanceOfAll << " blurred segments detected" << endl;
+  vector<BlurredSegment *>::iterator it = mbs.begin ();
+  while (it != mbs.end ())
+  {
+/*
+    DigitalStraightSegment *dss = (*it)->getSegment ();
+    if (dss != NULL) 
+    {
+      vector<Pt2i> bnd;
+      dss->getBounds (bnd, 0, 0, width, height);
+      drawListOfPixels (bnd, Qt::green, painter);
+    }
+*/
+    drawListOfPixels ((*it)->getAllPoints (), Qt::green, painter);
+    it++;
+  }
+
+  update (QRect (QPoint (0, 0), QPoint (width, height)));
+  if (verbose && fixed) displayExtractionResult ();
+  fixed = false;
+  if (! formerMultiMode) detector.switchMultiSelection ();
+}
+
+
+void BSDetectionWidget::displayNextOfAll ()
+{
+  augmentedImage = loadedImage;
+  QPainter painter (&augmentedImage);
+
+  vector<BlurredSegment *> mbs = detector.getBlurredSegments ();
+  if (++instanceOfAll > (int) (mbs.size ())) instanceOfAll = 0;
+  vector<BlurredSegment *>::iterator it = mbs.begin ();
+  QColor bsCol = Qt::blue;
+  int index = 0;
+  while (index <= instanceOfAll && it != mbs.end ())
+  {
+    if (index++ == instanceOfAll) bsCol = Qt::green;
+/*
+    DigitalStraightSegment *dss = (*it)->getSegment ();
+    if (dss != NULL) 
+    {
+      vector<Pt2i> bnd;
+      dss->getBounds (bnd, 0, 0, width, height);
+      drawListOfPixels (bnd, Qt::green, painter);
+    }
+*/
+    drawListOfPixels ((*it)->getAllPoints (), bsCol, painter);
+    it++;
+  }
+  update (QRect (QPoint (0, 0), QPoint (width, height)));
+}
+
+
+void BSDetectionWidget::displayExtractionResult ()
+{
+  int res = detector.result ();
+  if (res == BSDetector::RESULT_UNDETERMINED)
+    cout << "Extraction : undetermined." << endl;
+  else if (res == BSDetector::RESULT_OK)
+    cout << "Extraction : OK." << endl;
+  else if (res == BSDetector::RESULT_INITIAL_NO_DETECTION)
+    cout << "Extraction : no initial detection (bsini == NULL)." << endl;
+  else if (res == BSDetector::RESULT_INITIAL_TOO_FEW)
+    cout << "Extraction : two few points at initial detection." << endl;
+  else if (res == BSDetector::RESULT_INITIAL_TOO_SPARSE)
+    cout << "Extraction : unsuccessful density test at initial detection."
+         << endl;
+  else if (res == BSDetector::RESULT_INITIAL_TOO_MANY_OUTLIERS)
+    cout << "Extraction : unsuccessful filter test at initial detection."
+         << endl;
+  else if (res == BSDetector::RESULT_FINAL_NO_DETECTION)
+    cout << "Extraction : no final detection (bsini == NULL)." << endl;
+  else if (res == BSDetector::RESULT_FINAL_TOO_FEW)
+    cout << "Extraction : two few points at final detection." << endl;
+  else if (res == BSDetector::RESULT_FINAL_TOO_SPARSE)
+    cout << "Extraction : unsuccessful density test at final detection."
+         << endl;
+  else if (res == BSDetector::RESULT_FINAL_TOO_MANY_OUTLIERS)
+    cout << "Extraction : unsuccessful filter test at final detection."
+         << endl;
+}
+
+
+void BSDetectionWidget::alternateTest ()
+{
+  if (p1.equals (p2))
+  {
+    cout << "Stroke undefined" << endl;
+    return;
+  }
+
+  if (++alternate == 3) alternate = 0;
+  if (alternate == 0)
+  {
+  }
+  else if (alternate == 1)
+  {
+  }
+  else if (alternate == 2)
+  {
+  }
+//  extract (true);
+} 
+
+
+
+void BSDetectionWidget::performanceTest ()
+{
+/*
+  if (p1.equals (p2))
+  {
+    cout << "Stroke undefined" << endl;
+    return;
+  }
+  cout << "Run test" << endl;
+  clock_t start = clock ();
+  for (int i = 0; i < 1000; i++) detector.detect (p1, p2);
+  double diff = (clock () - start) / (double) CLOCKS_PER_SEC;
+  cout << "Test run : " << diff << endl;
+  extract (true);
+*/
+
+  cout << "Complete extractions 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 (true);
+}
+
+
+void BSDetectionWidget::localTest ()
+{
+  cout << "Run test" << endl;
+
+/*
+  p1 = Pt2i (212, 169);
+  p2 = Pt2i (232, 152);
+*/
+
+  p1 = Pt2i (298, 199);
+  p2 = Pt2i (279, 173);
+
+  extract (true);
+  cout << "Test run" << endl;
+}
diff --git a/Code/Seg/BSTools/bsdetectionwidget.h b/Code/Seg/BSTools/bsdetectionwidget.h
new file mode 100755
index 0000000000000000000000000000000000000000..f459a9316ceaa8585f2ccec191880c56dc98d1f0
--- /dev/null
+++ b/Code/Seg/BSTools/bsdetectionwidget.h
@@ -0,0 +1,270 @@
+#ifndef BS_DETECTION_WIDGET_H
+#define BS_DETECTION_WIDGET_H
+
+#include <QGraphicsView>
+#include <QColor>
+#include <QImage>
+#include <QWidget>
+#include <QVector>
+#include <fstream>
+#include "bsdetector.h"
+#include "bsaccumulatorview.h"
+#include "bsstructureview.h"
+#include "bsprofileview.h"
+
+using namespace std;
+
+
+/** 
+ * @class BSDetectionWidget bsdetectionwidget.h
+ * \brief Segment extraction view and controller.
+ * \author {P. Even and B. Kerautret}
+ */
+class BSDetectionWidget : public QWidget 
+{
+  Q_OBJECT
+
+
+public:
+
+  /**
+   * \brief Creates a segment extraction widget.
+   */
+  BSDetectionWidget (QWidget *parent = 0);
+
+  /**
+   * \brief Deletes the segment extraction widget.
+   */
+  ~BSDetectionWidget ();
+
+  /**
+   * \brief Opens the image to be processed.
+   * @param type Name of the image file to open.
+   * @param type Gradient extraction method.
+   */
+  QSize openImage (const QString &fileName, int type = 0);
+
+  /**
+   * \brief Builds and returns the image bitmap.
+   */
+  int **getBitmap (const QImage &image);
+  
+  /**
+   * \brief Updates the Qt widget display.
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+   */
+
+  /**
+   * \brief Saves the augmented image with extraction results.
+   */
+  bool saveAugmentedImage (const QString &fileName, const char *fileFormat);
+
+  /**
+   * \brief Requires the accumulation window closure.
+   */
+  void closeAccuAnalyzer ();
+
+  /**
+   * \brief Requires the pixel analysis window closure.
+   */
+  void closePixelAnalyzer ();
+
+  /**
+   * \brief Requires the profile analysis window closure.
+   */
+  void closeProfileAnalyzer ();
+
+  /**
+   * \brief Switches the pixel display window on or off.
+   */
+  void switchPixelAnalyzer ();
+
+  /**
+   * \brief Switches the accumulator display window on or off.
+   */
+  void switchAccuAnalyzer ();
+
+  /**
+   * \brief Switches the profile display window on or off.
+   */
+  void switchProfileAnalyzer ();
+
+  /**
+   * \brief Switches the extraction result display on or off.
+   */
+  inline void switchVerbose () { verbose = ! verbose; }
+
+  /**
+   * \brief Runs a comparative test.
+   */
+  void alternateTest ();
+
+  /**
+   * \brief Runs a performance test.
+   * Displays the time spent for 1000 detections under the present stroke.
+   */
+  void performanceTest ();
+
+  /**
+   * \brief Runs a local test (to be adapted).
+   */
+  void localTest ();
+
+
+public slots:
+  /**
+   * \brief Clears the widget drawing.
+   */
+  void clearImage ();
+
+
+protected:
+  /**
+   * \brief Updates the widget drawing.
+   */
+  void paintEvent (QPaintEvent *event);
+
+  /**
+   * \brief Processes mouse press events.
+   */
+  void mousePressEvent (QMouseEvent *event);
+
+  /**
+   * \brief Processes mouse release events.
+   */
+  void mouseReleaseEvent (QMouseEvent *event);
+
+  /**
+   * \brief Processes move release events.
+   */
+  void mouseMoveEvent (QMouseEvent *event);
+
+  /**
+   * \brief Processes key press events.
+   */
+  void keyPressEvent (QKeyEvent *event);
+
+
+private:
+ 
+  /** Sensitiveness of segment max width parameter. */
+  static const int MAX_WIDTH_TUNING;
+  /** Sensitiveness of detection lacks parameter. */
+  static const int DETECTION_LACKS_TUNING;
+  /** Default value for pen width. */
+  static const int DEFAULT_PEN_WIDTH;
+
+
+  /** Initial scan end points */
+  Pt2i p1, p2;
+  /** Flag indicating if the stroke is completely defined. */
+  bool fixed;
+  /** Flag indicating whether extraction result should be displayed. */
+  bool verbose;
+
+  /** Activation of alternate comparative tests (F8). */
+  int alternate;
+
+  /** Index of the last blurred segment displayed in a multi-selection. */
+  int instanceOfAll;
+
+
+  /** Presently loaded image. */
+  QImage loadedImage;
+  /** Present image augmented with processed data. */
+  QImage augmentedImage;
+  /** Gradient map of the loaded picture. */
+  VMap *gMap;
+  /** Width of the present image. */
+  int width;
+  /** Height of the present image. */
+  int height;
+  /** Blurred segment detector. */
+  BSDetector detector;
+
+  /** Aggregation of segment extraction results with initial conditions. */
+  struct ExtractedSegment
+  {
+    /** Extracted blurred segment. */
+    BlurredSegment *bs;
+    /** Selected strock start point. */
+    Pt2i p1;
+    /** Selected stroke end point. */
+    Pt2i p2;
+  };
+
+  /** List of registred blurred segments. */
+  vector<ExtractedSegment> extractedSegments;
+
+  /** Scanned profile graphics view. */
+  BSProfileView *profileview;
+  /** Filter accumulator view. */
+  BSAccumulatorView *accuview;
+  /** Blurred segment contents view. */
+  BSStructureView *strucview;
+
+
+
+  /**
+   * \brief Draws a list of points with the given color.
+   */
+  void drawListOfPixels (vector<Pt2i> vectPixels,
+                         QColor color, QPainter &painter);
+
+  /**
+   * \brief Draws a list of image pixels.
+   */
+  void drawListOfPixels (vector<Pt2i> vectPixels,
+                       QPainter &painter);
+
+  /**
+   * \brief Draws the line joining two points.
+   */
+  void drawLine (const Pt2i from, const Pt2i to,
+                 QColor color, QPainter &painter);
+
+  /**
+   * \brief Registers the last extracted blurred segment.
+   */
+  void storeExtractedSegment ();
+
+  /**
+   * \brief Displays the registred blurred segments.
+   */
+  void displayExtractedSegments ();
+
+  /**
+   * \brief Clears off the already extracted segments.
+   */
+  void clearExtractedSegments ();
+
+  /**
+   * \brief Displays the last extraction result.
+   */
+  void displayExtractionResult ();
+
+  /**
+   * \brief Detects a blurred segment under the selected stroke.
+   * @param withAllDisplay Indicates if all information about the extraction
+   *                       should be displayed.
+   */
+  void extract (bool withAllDisplay);
+
+  /**
+   * \brief Detects and displays a blurred segment under the selected stroke.
+   */
+  void extract ();
+
+  /**
+   * \brief Detects and displays all the blurred segment in the picture.
+   */
+  void extractAll ();
+
+  /**
+   * \brief Highlights the next blurred segment in multi-selection mode.
+   */
+  void displayNextOfAll ();
+
+};
+#endif
diff --git a/Code/Seg/BSTools/bsprofileitem.cpp b/Code/Seg/BSTools/bsprofileitem.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..29d183264734f9b7ac1f508c9f9bb531fb19fdc5
--- /dev/null
+++ b/Code/Seg/BSTools/bsprofileitem.cpp
@@ -0,0 +1,912 @@
+#include <cstdlib>
+#include <iostream>
+#include <QtGui>
+#include "bsprofileitem.h"
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+const int BSProfileItem::DISPLAY_INTENSITY = 1;
+const int BSProfileItem::DISPLAY_GRADIENT = 2;
+const int BSProfileItem::DISPLAY_CORRELATION_MEAN_1D = 3;
+const int BSProfileItem::DISPLAY_CORRELATION_FULL_2D = 4;
+const int BSProfileItem::DISPLAY_CORRELATION_MEAN_2D = 5;
+const int BSProfileItem::DISPLAY_MIN = DISPLAY_INTENSITY;
+const int BSProfileItem::DISPLAY_MAX = DISPLAY_CORRELATION_MEAN_2D;
+
+const int BSProfileItem::MIN_SCAN = 8;
+
+
+
+BSProfileItem::BSProfileItem ()
+{
+  profileWidth = 400;
+  profileRatio = 3;
+  gradientUnRatio = 40;
+  gradientLow = 0;
+
+  stripeWidth = 200;
+  stripeMargin = 5;
+  stripeResol = 4;
+
+  widWidth = profileWidth + stripeWidth + 2 * stripeMargin;
+  widHeight = 610;
+  profileLow = (256 - (widHeight / profileRatio)) / 2;
+
+  image = NULL;
+  imageWidth = 0;
+  imageHeight = 0;
+  gMap = NULL;
+
+  displayItem = DISPLAY_INTENSITY;
+  stripe = 0;
+  correlWidth = 7;
+  correlThick = 3;
+  correlRatio = 4;
+}
+
+
+QRectF BSProfileItem::boundingRect () const
+{
+  return QRectF (0, 0, widWidth, widHeight);
+}
+
+
+void BSProfileItem::paint (QPainter *painter,
+                           const QStyleOptionGraphicsItem *option,
+                           QWidget *widget)
+{
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+
+  paintStripes (painter);
+  switch (displayItem)
+  {
+    case DISPLAY_INTENSITY :
+      paintIntensityProfile (painter);
+      break;
+
+    case DISPLAY_GRADIENT :
+      paintGradientProfile (painter);
+      break;
+
+    case DISPLAY_CORRELATION_MEAN_1D :
+      if (setMeanCorrelationStripes ())
+        paintCorrelationProfile (painter);
+      painter->drawText (100, 20, QString ("W : Correl width = ")
+                                  + QString::number (correlWidth));
+      painter->drawText (100, 40, QString ("T : Correl thick = ")
+                                  + QString::number (correlThick));
+      break;
+
+    case DISPLAY_CORRELATION_FULL_2D :
+      if (setFull2dCorrelationStripes ())
+        paintCorrelationProfile (painter);
+      painter->drawText (100, 20, QString ("W : Correl width = ")
+                                  + QString::number (correlWidth));
+      painter->drawText (100, 40, QString ("T : Correl thick = ")
+                                  + QString::number (correlThick));
+      break;
+
+    case DISPLAY_CORRELATION_MEAN_2D :
+      if (setMean2dCorrelationStripes ())
+        paintCorrelationProfile (painter);
+      painter->drawText (100, 20, QString ("W : Correl width = ")
+                                  + QString::number (correlWidth));
+      painter->drawText (100, 40, QString ("T : Correl thick = ")
+                                  + QString::number (correlThick));
+      break;
+  }
+}
+
+
+void BSProfileItem::setImage (QImage *image, VMap *idata)
+{
+  this->image = image;
+  this->gMap = idata;
+  this->imageWidth = image->width ();
+  this->imageHeight = image->height ();
+}
+
+
+void BSProfileItem::buildScans (Pt2i p1, Pt2i p2)
+{
+  // Updates the central scan end points for parallel display
+  this->pt1 = p1;
+  this->pt2 = p2;
+
+  // Resets the profiles
+  rightscan.clear ();
+  leftscan.clear ();
+  rightCorrel.clear ();
+  leftCorrel.clear ();
+  rightReCorrel.clear ();
+  leftReCorrel.clear ();
+  stripe = 0;
+
+  // Gets a scan iterator
+  DirectionalScanner *ds = scanp.getScanner (p1, p2,
+                                             0, 0, imageWidth, imageHeight);
+
+  // Extracts the left scan (with central one)
+  vector<Pt2i> pix;
+  if (ds->first (pix) < MIN_SCAN) { delete ds; return;}
+  leftscan.push_back (pix);
+
+  bool leftScanOn = true;
+  maxStripe = 0;
+  while (leftScanOn)
+  {
+    vector<Pt2i> scan;
+    if (ds->nextOnLeft (scan) < MIN_SCAN) leftScanOn = false;
+    else
+    {
+      leftscan.push_back (scan);
+      maxStripe ++;
+    }
+  }
+
+  // Extracts the right scans
+  bool rightScanOn = true;
+  minStripe = 1;
+  while (rightScanOn)
+  {
+    vector<Pt2i> scan;
+    if (ds->nextOnRight (scan) < MIN_SCAN) rightScanOn = false;
+    else
+    {
+      rightscan.push_back (scan);
+      minStripe --;
+    }
+  }
+
+  // Frees the scan iterator
+  delete ds;
+}
+
+
+void BSProfileItem::incStripe (int inc)
+{
+  stripe += inc;
+  if (stripe > maxStripe) stripe = maxStripe;
+  else if (stripe < minStripe) stripe = minStripe;
+}
+
+
+void BSProfileItem::incCorrelWidth (int down)
+{
+  if (displayItem <= DISPLAY_CORRELATION_MEAN_2D
+          && displayItem >= DISPLAY_CORRELATION_MEAN_1D)
+  {
+    if (down)
+    {
+      if (correlWidth >= 5) correlWidth -= 2;
+    }
+    else if (correlWidth <= 19) correlWidth += 2;
+  }
+}
+
+
+void BSProfileItem::incCorrelThick (int down)
+{
+  if (displayItem <= DISPLAY_CORRELATION_MEAN_2D
+          && displayItem >= DISPLAY_CORRELATION_MEAN_1D)
+  {
+    if (down)
+    {
+      if (correlThick >= 3) correlThick -= 2;
+    }
+    else if (correlThick <= 17) correlThick += 2;
+  }
+}
+
+
+void BSProfileItem::incCorrelRatio (int down)
+{
+  if (displayItem <= DISPLAY_CORRELATION_MEAN_2D
+          && displayItem >= DISPLAY_CORRELATION_MEAN_1D)
+  {
+    if (down)
+    {
+      if (correlRatio > 1) correlRatio /= 2;
+    }
+    else correlRatio *= 2;
+  }
+}
+
+
+void BSProfileItem::toggleDisplay (bool next)
+{
+  if (displayItem == DISPLAY_CORRELATION_FULL_2D) correlRatio *= 4;
+  displayItem += (next ? 1 : -1);
+  if (displayItem > DISPLAY_MAX) displayItem = DISPLAY_MIN;
+  else if (displayItem < DISPLAY_MIN) displayItem = DISPLAY_MAX;
+  if (displayItem == DISPLAY_CORRELATION_FULL_2D) correlRatio /= 4;
+}
+
+
+
+
+/**
+ * Correlation calculation (first release).
+ * Compares portions of scan bars with a profile extracted at
+ * the first scan centered on the blurred segment.
+ */
+void BSProfileItem::setCorrelationStripes (Pt2i p1, Pt2i p2, int segwidth)
+{
+  leftCorrel.clear ();
+  rightCorrel.clear ();
+  leftReCorrel.clear ();
+  rightReCorrel.clear ();
+  int correlWidth = segwidth;
+  if (correlWidth > (int) leftscan.at(0).size ())
+  {
+    cerr << "Can't get correlation stripes" << endl;
+    return;
+  }
+
+  // Gets the central index
+  Pt2i pc ((p1.x () + p2.x ()) / 2, (p1.y () + p2.y ()) / 2);
+  vector<Pt2i>::iterator it = leftscan.at(0).begin ();
+  int dist, pos = 0, minPos = 0;
+  int minDist = (pc.x() - (*it).x()) * (pc.x() - (*it).x())
+                + (pc.y() - (*it).y()) * (pc.y() - (*it).y());
+  it ++;
+  while (it != leftscan.at(0).end ())
+  {
+    dist = (pc.x() - (*it).x()) * (pc.x() - (*it).x())
+           + (pc.y() - (*it).y()) * (pc.y() - (*it).y());
+    if (dist < minDist)
+    {
+      minDist = dist;
+      minPos = pos;
+    }
+    it ++;
+    pos ++;
+  }
+  if (minPos - correlWidth / 2 < 0
+      || minPos + correlWidth / 2 >= (int) leftscan.size ())
+  {
+    cerr << "Excentred stripe" << endl;
+    return;
+  }
+
+  // Gets the central template
+  int *centralShape = new int[correlWidth];
+  for (int i = 0; i < correlWidth; i++)
+  {
+    Pt2i pix = leftscan.at(0).at(minPos-correlWidth/2+i);
+    centralShape[i] = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ();
+  }
+
+  // Computes the left correlation stripes
+  vector <vector <Pt2i> >::iterator scit = leftscan.begin ();
+  while (scit != leftscan.end ())
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((*scit).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          Pt2i pix = (*scit).at(j+k);
+          int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ()
+                     - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    leftCorrel.push_back (corr);
+    leftReCorrel.push_back (recorr);
+    scit ++;
+  }
+
+  // Computes the right correlation stripes
+  scit = rightscan.begin ();
+  while (scit != rightscan.end ())
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((*scit).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          Pt2i pix = (*scit).at(j+k);
+          int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ()
+                     - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    rightCorrel.push_back (corr);
+    rightReCorrel.push_back (recorr);
+    scit ++;
+  }
+}
+
+
+/** Correlation calculation (second release).
+ * Compares portions of scan bars with a mean profile extracted at
+ * the center of the first Nth scans (N = correlThick).
+ */
+bool BSProfileItem::setMeanCorrelationStripes ()
+{
+  leftCorrel.clear ();
+  rightCorrel.clear ();
+  leftReCorrel.clear ();
+  rightReCorrel.clear ();
+  int minPos = (int) leftscan.at(0).size () / 2;
+  if (correlWidth > (int) leftscan.at(0).size ())
+  {
+    cerr << "Can't get correlation stripes" << endl;
+    return false;
+  }
+
+  // Gets the central template
+  int *centralShape = new int[correlWidth];
+  for (int i = 0; i < correlWidth; i++)
+  {
+    centralShape[i] = 0;
+    for (int j = 0; j < correlThick; j++)
+    {
+      Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i);
+      centralShape[i] += ((QColor) image->pixel (QPoint (pix.x (),
+                                    imageHeight - 1 - pix.y ()))).value ();
+    }
+    centralShape[i] /= correlThick;
+  }
+
+  // Computes the left correlation stripes
+  vector <vector <Pt2i> >::iterator scit = leftscan.begin ();
+  while (scit != leftscan.end ())
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((*scit).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          Pt2i pix = (*scit).at(j+k);
+          int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ()
+                     - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    leftCorrel.push_back (corr);
+    leftReCorrel.push_back (recorr);
+    scit ++;
+  }
+
+  // Computes the right correlation stripes
+  scit = rightscan.begin ();
+  while (scit != rightscan.end ())
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((*scit).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          Pt2i pix = (*scit).at(j+k);
+          int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ()
+                     - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    rightCorrel.push_back (corr);
+    rightReCorrel.push_back (recorr);
+    scit ++;
+  }
+  return true;
+}
+
+
+/** Correlation calculation (third release).
+ * Compares 2D portions of scan bars (N = correlThick) with a 2D profile
+ * extracted at the center of the first Nth scans (N = correlThick).
+ */
+bool BSProfileItem::setFull2dCorrelationStripes ()
+{
+  leftCorrel.clear ();
+  rightCorrel.clear ();
+  leftReCorrel.clear ();
+  rightReCorrel.clear ();
+  if ((int) leftscan.size () <= correlThick)
+  {
+    cerr << "Can't get correlation stripes : not enough left scans" << endl;
+    return false;
+  }
+  int minPos = (int) leftscan.at(0).size () / 2;
+  if (correlWidth > (int) leftscan.at(0).size ())
+  {
+    cerr << "Can't get correlation stripes : scans too narrow" << endl;
+    return false;
+  }
+
+  // Gets the central template
+  int *centralShape = new int[correlThick * correlWidth];
+  for (int i = 0; i < correlWidth; i++)
+    for (int j = 0; j < correlThick; j++)
+    {
+      Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i);
+      centralShape[j * correlWidth + i] = ((QColor) image->pixel (
+               QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value ();
+    }
+
+  // Computes the left correlation stripes
+  for (int i = 0; i < (int) leftscan.size () - correlThick - 2; i++)
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((leftscan.at(i)).size ()) >= correlWidth)
+      for (int j = 0; j < ((int) (leftscan.at(i)).size ()) - correlWidth; j++)
+      {
+        int val = 0;
+        for (int cw = 0; cw < correlThick; cw ++)
+          for (int k = 0; k < correlWidth; k++)
+            if ((int) leftscan.at(i+cw).size () > j+k)
+            {
+              Pt2i pix = (leftscan.at(i+cw)).at(j+k);
+              int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                    imageHeight - 1 - pix.y ()))).value ()
+                       - centralShape[cw * correlWidth + k];
+              val += (diff < 0 ? - diff : diff);
+            }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    leftCorrel.push_back (corr);
+    leftReCorrel.push_back (recorr);
+  }
+
+  // Computes the right correlation stripes
+  for (int i = correlThick - 1; i < (int) rightscan.size () - 1; i++)
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((rightscan.at(i)).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (rightscan.at(i)).size ()) - correlWidth; j++)
+      {
+        int val = 0;
+        for (int cw = 0; cw < correlThick; cw ++)
+          for (int k = 0; k < correlWidth; k++)
+            if ((int) rightscan.at(i-cw).size () > j+k)
+            {
+              Pt2i pix = (rightscan.at(i-cw)).at(j+k);
+              int diff = ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ()
+                     - centralShape[cw * correlWidth + k];
+              val += (diff < 0 ? - diff : diff);
+            }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    rightCorrel.push_back (corr);
+    rightReCorrel.push_back (recorr);
+  }
+  return true;
+}
+
+
+
+
+/** Correlation calculation (ourth release).
+ * Compares mean portions of scan bars (N = correlThick) with a mean
+ * profile extracted at the center of the first Nth scans (N = correlThick).
+ */
+bool BSProfileItem::setMean2dCorrelationStripes ()
+{
+  leftCorrel.clear ();
+  rightCorrel.clear ();
+  leftReCorrel.clear ();
+  rightReCorrel.clear ();
+  if ((int) leftscan.size () <= correlThick)
+  {
+    cerr << "Can't get correlation stripes : not enough left scans" << endl;
+    return false;
+  }
+  int minPos = (int) leftscan.at(0).size () / 2;
+  if (correlWidth > (int) leftscan.at(0).size ())
+  {
+    cerr << "Can't get correlation stripes : scans too narrow" << endl;
+    return false;
+  }
+
+  // Gets the central template
+  int *centralShape = new int[correlWidth];
+  for (int i = 0; i < correlWidth; i++)
+  {
+    centralShape[i] = 0;
+    for (int j = 0; j < correlThick; j++)
+    {
+      Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i);
+      centralShape[i] += ((QColor) image->pixel (
+               QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value ();
+    }
+    centralShape[i] /= correlThick;
+  }
+
+  // Computes the left correlation stripes
+  for (int i = 0; i < (int) leftscan.size () - correlThick - 2; i++)
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((leftscan.at(i)).size ()) >= correlWidth)
+      for (int j = 0; j < ((int) (leftscan.at(i)).size ()) - correlWidth; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          int nbval = 0;
+          int locval = 0;
+          for (int cw = 0; cw < correlThick; cw ++)
+          {
+            if ((int) leftscan.at(i+cw).size () > j+k)
+            {
+              nbval ++;
+              Pt2i pix = (leftscan.at(i+cw)).at(j+k);
+              locval += ((QColor) image->pixel (QPoint (pix.x (),
+                                    imageHeight - 1 - pix.y ()))).value ();
+            }
+          }
+          int diff = locval / nbval - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    leftCorrel.push_back (corr);
+    leftReCorrel.push_back (recorr);
+  }
+
+  // Computes the right correlation stripes
+  for (int i = correlThick - 1; i < (int) rightscan.size () - 1; i++)
+  {
+    vector<int> corr;
+    vector<int> recorr;
+    if ((int) ((rightscan.at(i)).size ()) >= correlWidth)
+    {
+      for (int j = 0; j < ((int) (rightscan.at(i)).size ()) - correlWidth; j++)
+      {
+        int val = 0;
+        for (int k = 0; k < correlWidth; k++)
+        {
+          int nbval = 0;
+          int locval = 0;
+          for (int cw = 0; cw < correlThick; cw ++)
+          {
+            if ((int) rightscan.at(i-cw).size () > j+k)
+            {
+              nbval ++;
+              Pt2i pix = (rightscan.at(i-cw)).at(j+k);
+              locval += ((QColor) image->pixel (QPoint (pix.x (),
+                                  imageHeight - 1 - pix.y ()))).value ();
+            }
+          }
+          int diff = locval / nbval - centralShape[k];
+          val += (diff < 0 ? - diff : diff);
+        }
+        corr.push_back (val);
+        recorr.push_back ((int) val);
+      }
+    }
+    rightCorrel.push_back (corr);
+    rightReCorrel.push_back (recorr);
+  }
+  return true;
+}
+
+
+void BSProfileItem::getLocalMinimaIndices (vector<int> &indices,
+                                     const vector<int> &signal) const
+{
+  int ng = signal.size ();
+  int offset = 0;
+  bool up = true;
+
+  // Gets the first distinct value from start
+  while (offset < ng - 1 && signal.at (offset) == signal.at (0))
+  {
+    if (signal.at (offset) - signal.at (offset + 1) < 0)
+    {
+      up = true;
+      break;
+    }
+    if (signal.at (offset) - signal.at (offset + 1) > 0)
+    {
+      up = false;
+      break;
+    }
+    offset++;
+  }
+
+  for(int i = offset; i < ng - 1; i++)
+  {
+    if (up)
+    {
+      if ((signal.at (i + 1) - signal.at (i)) < 0) up = false;
+    }
+    else
+    {
+      if (signal.at (i + 1) - signal.at (i) > 0)
+      {
+        up = true;
+        int k = i;
+        while (signal.at (k) == signal.at (i)) k--;
+        indices.push_back (k + 1 + (i - k - 1) / 2);
+      }
+    }
+  }
+}
+
+
+
+
+void BSProfileItem::paintStripes (QPainter *painter)
+{
+  int lx = 80;
+  int cx, cy = widHeight / 2;
+  vector <vector <Pt2i> >::iterator bigit;
+
+  if (rightscan.size ())
+    lx = profileWidth + stripeMargin + stripeWidth / 2
+             - stripeResol / 2 - rightscan.at(0).size () * stripeResol / 2;
+  else if (leftscan.size ())
+    lx = profileWidth + stripeMargin + stripeWidth / 2
+             - stripeResol / 2 - leftscan.at(0).size () * stripeResol / 2;
+  painter->setPen (QPen (Qt::red, 2));
+  painter->drawRect (profileWidth + stripeMargin - 1, stripeMargin - 1,
+                     stripeWidth + 2, widHeight - 2 * stripeMargin + 2);
+
+  // Lower part (right side)
+  if (rightscan.size ())
+  {
+    bigit = rightscan.begin ();
+    while (cy <= widWidth - stripeMargin - stripeResol
+           && bigit != rightscan.end ())
+    {
+      cx = lx;
+      vector<Pt2i> scan = *bigit;
+      vector<Pt2i>::iterator it = scan.begin ();
+      while (cx < widWidth - stripeMargin - stripeResol && it != scan.end ())
+      {
+        if (cx >= profileWidth + stripeMargin)
+          painter->fillRect (cx, cy, stripeResol, stripeResol,
+             QBrush (image->pixel ((*it).x (), imageHeight - 1 - (*it).y ())));
+        it ++;
+        cx += stripeResol;
+      }
+      bigit ++;
+      cy += stripeResol;
+    }
+  }
+  
+  // Upper part (left side)
+  if (leftscan.size ())
+  {
+    cy = widHeight / 2 - 2 * stripeResol;
+    bigit = leftscan.begin ();
+    while (cy >= 5 && bigit != leftscan.end ())
+    {
+      cx = lx;
+      vector<Pt2i> scan = *bigit;
+      vector<Pt2i>::iterator it = scan.begin ();
+      while (cx < widHeight - stripeMargin - stripeResol && it != scan.end ())
+      {
+        if (cx >= profileWidth + stripeMargin)
+          painter->fillRect (cx, cy, stripeResol, stripeResol,
+             QBrush (image->pixel ((*it).x (), imageHeight - 1 - (*it).y ())));
+        it ++;
+        cx += stripeResol;
+      }
+      bigit ++;
+      cy -= stripeResol;
+    }
+  }
+
+  // Enclosing the central scan
+  if (stripe >= 0)
+    cy = widHeight / 2 - 1 - 2 * stripeResol - stripe * stripeResol;
+  else cy = widHeight / 2 - 1 - (1 + stripe) * stripeResol;
+  painter->setPen (QPen (Qt::green, 2));
+  painter->drawRect (profileWidth + stripeMargin - 1, cy,
+                     stripeWidth + 2, stripeResol + 2);
+}
+
+
+void BSProfileItem::paintIntensityProfile (QPainter *painter)
+{
+  if (rightscan.size () || leftscan.size ())
+  {
+    vector<Pt2i> scan;
+    if (stripe >= 0) scan = leftscan.at (stripe);
+    else scan = rightscan.at (- stripe - 1);
+    int h, cx = 0, w = profileWidth / (leftscan.at(0)).size ();
+    vector<Pt2i>::iterator it = scan.begin ();
+    while (it != scan.end ())
+    {
+      if ((*it).x () < 0 || (*it).x () >= imageWidth
+          || (*it).y () < 0 || (*it).y () >= imageHeight)
+        cerr << "OUT OF IMAGE BOUNDS : (" << (*it).x () << ","
+             << imageHeight - 1 - (*it).y () << ")" << endl;
+      else
+      {
+        h = ((QColor) image->pixel (QPoint ((*it).x (),
+                                    imageHeight - 1 - (*it).y ()))).value ();
+        h = (h - profileLow) * profileRatio;
+        if (h < 0) h = 0;
+        else if (h > widHeight) h = widHeight;
+        if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue));
+        it ++;
+        cx += w;
+      }
+    }
+
+    painter->setPen (QPen (Qt::black, 2));
+    scan = leftscan.at (0);
+    it = scan.begin ();
+    int prevh = ((QColor) image->pixel (QPoint ((*it).x (),
+                                  imageHeight - 1 - (*it).y ()))).value ();
+    prevh = (prevh - profileLow) * profileRatio;
+    if (prevh < 0) prevh = 0;
+    else if (prevh > widWidth) prevh = widWidth;
+    cx = 0;
+    while (it != scan.end ())
+    {
+      h = ((QColor) image->pixel (QPoint ((*it).x (),
+                                  imageHeight - 1 - (*it).y ()))).value ();
+      h = (h - profileLow) * profileRatio;
+      if (h < 0) h = 0;
+      else if (h > widWidth) h = widWidth;
+      painter->drawLine (cx, widWidth - prevh, cx, widWidth - h);
+      painter->drawLine (cx, widWidth - h, cx + w, widWidth - h);
+      prevh = h;
+      it ++;
+      cx += w;
+    }
+  }
+}
+
+
+void BSProfileItem::paintGradientProfile (QPainter *painter)
+{
+  if (rightscan.size () || leftscan.size ())
+  {
+    vector<Pt2i> scan;
+    if (stripe >= 0) scan = leftscan.at (stripe);
+    else scan = rightscan.at (- stripe - 1);
+    int cx = 0, w = profileWidth / (leftscan.at(0)).size ();
+    int h, prevh;
+    vector<Pt2i>::iterator it = scan.begin ();
+    while (it != scan.end ())
+    {
+      if ((*it).x () < 0 || (*it).x () >= imageWidth
+          || (*it).y () < 0 || (*it).y () >= imageHeight)
+        cerr << "OUT OF IMAGE BOUNDS : (" << (*it).x () << ","
+             << imageHeight - 1 - (*it).y () << ")" << endl;
+      else
+      {
+        h = (gMap->sqNorm ((*it).x (), (*it).y ()) - gradientLow)
+            / gradientUnRatio;
+        if (h < 0) h = 0;
+        else if (h > widHeight) h = widHeight;
+        if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue));
+        it ++;
+        cx += w;
+      }
+    }
+
+    painter->setPen (QPen (Qt::black, 2));
+    scan = leftscan.at (0);
+    it = scan.begin ();
+    prevh = (gMap->sqNorm ((*it).x (), (*it).y ()) - gradientLow)
+            / gradientUnRatio;
+    if (prevh < 0) prevh = 0;
+    else if (prevh > widWidth) prevh = widWidth;
+    cx = 0;
+    while (it != scan.end ())
+    {
+      h = (gMap->sqNorm ((*it).x (), (*it).y ()) - gradientLow)
+          / gradientUnRatio;
+      if (h < 0) h = 0;
+      else if (h > widWidth) h = widWidth;
+      painter->drawLine (cx, widWidth - prevh, cx, widWidth - h);
+      painter->drawLine (cx, widWidth - h, cx + w, widWidth - h);
+      prevh = h;
+      it ++;
+      cx += w;
+    }
+  }
+}
+
+
+
+void BSProfileItem::paintCorrelationProfile (QPainter *painter)
+{
+  if (rightCorrel.size () || leftCorrel.size ())
+  {
+    Pt2i gr;
+    vector<int> scan;
+    vector<int> rescan;
+    if (stripe >= 0)
+    {
+      scan = leftCorrel.at (stripe);
+      rescan = leftReCorrel.at (stripe);
+    }
+    else
+    {
+      scan = rightCorrel.at (- stripe - 1);
+      rescan = rightReCorrel.at (- stripe - 1);
+    }
+
+    int h, cx = 0, w = profileWidth / (leftscan.at(0)).size ();
+    vector<int>::iterator it = scan.begin ();
+    while (it != scan.end ())
+    {
+      h = (*it) * correlRatio;
+      if (h > widHeight) h = widHeight;
+      if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue));
+      it ++;
+      cx += w;
+    }
+
+    vector<int> locs;
+    getLocalMinimaIndices (locs, rescan);
+    it = locs.begin ();
+    while (it != locs.end ())
+    {
+      h = scan.at(*it) * correlRatio;
+      painter->fillRect ((*it) * w + 4, widHeight - h - 14, w - 8, 10,
+                         QBrush (Qt::red));
+      it ++;
+    }
+
+    painter->setPen (QPen (Qt::black, 2));
+    scan = leftCorrel.at (0);
+    it = scan.begin ();
+    int prevh = (*it) * correlRatio;
+    if (prevh > widWidth) prevh = widWidth;
+    cx = 0;
+    while (it != scan.end ())
+    {
+      h = (*it) * correlRatio;
+      if (h > widWidth) h = widWidth;
+      painter->drawLine (cx, widWidth - prevh, cx, widWidth - h);
+      painter->drawLine (cx, widWidth - h, cx + w, widWidth - h);
+      prevh = h;
+      it ++;
+      cx += w;
+    }
+  }
+}
diff --git a/Code/Seg/BSTools/bsprofileitem.h b/Code/Seg/BSTools/bsprofileitem.h
new file mode 100755
index 0000000000000000000000000000000000000000..3ca04bca9178bc1c8394b0757599e293f51b8410
--- /dev/null
+++ b/Code/Seg/BSTools/bsprofileitem.h
@@ -0,0 +1,249 @@
+#ifndef BS_PROFILE_ITEM_H
+#define BS_PROFILE_ITEM_H
+
+#include <QGraphicsItem>
+#include <QImage>
+#include <QKeyEvent>
+#include "vmap.h"
+#include "scannerprovider.h"
+
+
+/** 
+ * @class BSProfileItem bsprofileitem.h
+ * \brief Scan intensity profile view and controller.
+ * \author {P. Even}
+ */
+class BSProfileItem : public QGraphicsItem
+{
+
+public:
+
+
+  /**
+   * \brief Creates a profile analysis widget.
+   */
+  BSProfileItem ();
+
+  /**
+   * \brief Declares the image to be analysed.
+   */
+  void setImage (QImage *image, VMap *idata);
+
+  /**
+   * \brief Sets the image scan area from an initial scan.
+   * The initial scan is a straight segment from p1 to p2.
+   */
+  void buildScans (Pt2i p1, Pt2i p2);
+
+  /**
+   * \brief Returns the widget size.
+   * Nominally the image size.
+   */
+  QRectF boundingRect () const;
+
+  /**
+   * \brief Updates the widget display.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+  /**
+   * \brief Returns the displayed information title.
+   */
+  inline QString itemTitle () const
+  {
+    if (displayItem == DISPLAY_INTENSITY)
+      return ("Intensity profiles");
+    else if (displayItem == DISPLAY_GRADIENT)
+      return ("Gradient profiles");
+    else if (displayItem == DISPLAY_CORRELATION_MEAN_1D)
+      return ("Correlation profiles (mean 1D)");
+    else if (displayItem == DISPLAY_CORRELATION_FULL_2D)
+      return ("Correlation profiles (full 2D)");
+    else if (displayItem == DISPLAY_CORRELATION_MEAN_2D)
+      return ("Correlation profiles (mean 2D)");
+    else return ("No profile");
+  }
+
+  /**
+   * \brief Increments the current stripe index.
+   * @param inc Direction (1 for leftwards, -1 for rightwards)
+   */
+  void incStripe (int inc);
+
+  /**
+   * \brief Increments or decrements the scan correlation width.
+   * @param down Direction (1 to increment, -1 to decrement)
+   */
+  void incCorrelWidth (int down);
+
+  /**
+   * \brief Increments or decrements the scan correlation thickness.
+   * @param down Direction (1 to increment, -1 to decrement)
+   */
+  void incCorrelThick (int down);
+
+  /**
+   * \brief Increments or decrements the scan correlation ratio.
+   * @param down Direction (1 to increment, -1 to decrement)
+   */
+  void incCorrelRatio (int down);
+
+  /**
+   * \brief Toggles the displayed information.
+   * @param next Get next information if true, previous on otherwise.
+   */
+  void toggleDisplay (bool next);
+
+
+protected:
+
+private:
+
+  /** Available information : intensity profiles. */
+  static const int DISPLAY_INTENSITY;
+  /** Available information : gradient profiles. */
+  static const int DISPLAY_GRADIENT;
+  /** Available information : 1D mean correlation profiles. */
+  static const int DISPLAY_CORRELATION_MEAN_1D;
+  /** Available information : 2D full correlation profiles. */
+  static const int DISPLAY_CORRELATION_FULL_2D;
+  /** Available information : 1D full correlation profiles. */
+  static const int DISPLAY_CORRELATION_MEAN_2D;
+  /** Number of the first information. */
+  static const int DISPLAY_MIN;
+  /** Number of the last information. */
+  static const int DISPLAY_MAX;
+
+  /** Analysis widget height. */
+  int widHeight;
+  /** Analysis widget width. */
+  int widWidth;
+
+  /** Profile area width. */
+  int profileWidth;
+  /** Intensity profile vertical zoom factor. */
+  int profileRatio;
+  /** Intensity profile lowest visible value. */
+  int profileLow;
+
+  /** Gradient profile vertical unzoom factor. */
+  int gradientUnRatio;
+  /** Gradient profile lowest visible value. */
+  int gradientLow;
+
+  /** Correlation profile vertical zoom factor (power of 2). */
+  int correlRatio;
+  /** Correlation profile width. */
+  int correlWidth;
+  /** Correlation profile scan thickness. */
+  int correlThick;
+
+  /** Stripe area width. */
+  int stripeWidth;
+  /** Stripe area margin width. */
+  int stripeMargin;
+  /** Stripe points zoom factor. */
+  int stripeResol;
+
+  /** Analysed image. */
+  QImage *image;
+  /* Analysed image width. */
+  int imageWidth;
+  /** Analyzed image height. */
+  int imageHeight;
+  /** Gradient map. */
+  VMap *gMap;
+
+  /** Central scan start point. */
+  Pt2i pt1;
+  /** Central scan start point. */
+  Pt2i pt2;
+  /** Central and left scans. */
+  vector <vector <Pt2i> > leftscan;
+  /** Right scans. */
+  vector <vector <Pt2i> > rightscan;
+  /** Minimum scan length allowed. */
+  static const int MIN_SCAN;
+
+  // Just for local minima extraction.
+  vector <vector <int> > leftCorrel;
+  vector <vector <int> > rightCorrel;
+  vector <vector <int> > leftReCorrel;
+  vector <vector <int> > rightReCorrel;
+
+  /** Displayed information (intensity, gradient, correlation). */
+  int displayItem;
+  /** Current stripe index. */
+  int stripe;
+  /** Min stripe index (right scan size). */
+  int minStripe;
+  /** Max stripe index (left scan size). */
+  int maxStripe;
+
+  /** Scanner provider (that selects the appropriate octant) */
+  ScannerProvider scanp;
+
+
+  /**
+   * \brief Correlation calculation (first release).
+   * \author {B. Kerautret}
+   * Compares portions of scan bars with a profile extracted at
+   * the first scan centered on the blurred segment.
+   */
+  void setCorrelationStripes (Pt2i p1, Pt2i p2, int segwidth);
+
+  /**
+   * \brief Correlation calculation (second release).
+   * \author {B. Kerautret}
+   * Compares portions of scan bars with a mean profile extracted at
+   * the center of the first Nth scans (N = correlThick).
+   */
+  bool setMeanCorrelationStripes ();
+
+  /**
+   * \brief Correlation calculation (third release).
+   * \author {B. Kerautret}
+   * Compares 2D portions of scan bars (N = correlThick) with a 2D profile
+   * extracted at the center of the first Nth scans (N = correlThick).
+   */
+  bool setFull2dCorrelationStripes ();
+
+  /**
+   * \brief Correlation calculation (fourth release).
+   * \author {B. Kerautret}
+   * Compares mean portions of scan bars (N = correlThick) with a mean
+   * profile extracted at the center of the first Nth scans (N = correlThick).
+   */
+  bool setMean2dCorrelationStripes ();
+
+  /**
+   * \brief Extract local minima from given signal.
+   * @param indices List of indices of the signal local minima.
+   * @param signal Input signal.
+   */
+  void getLocalMinimaIndices (vector<int> &indices,
+                              const vector<int> &signal) const;
+
+  /**
+   * \brief Draws the scan strip.
+   */
+  void paintStripes (QPainter *painter);
+
+  /**
+   * \brief Draws the intensity profile.
+   */
+  void paintIntensityProfile (QPainter *painter);
+
+  /**
+   * \brief Draws the gradient profile.
+   */
+  void paintGradientProfile (QPainter *painter);
+
+  /**
+   * \brief Draws the correlation profile.
+   */
+  void paintCorrelationProfile (QPainter *painter);
+};
+
+#endif
diff --git a/Code/Seg/BSTools/bsprofileview.cpp b/Code/Seg/BSTools/bsprofileview.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..e20f8b7ab5233a40bd34160b306c2940e7db6c65
--- /dev/null
+++ b/Code/Seg/BSTools/bsprofileview.cpp
@@ -0,0 +1,87 @@
+#include <QtGui>
+#include <iostream>
+#include <cstdlib>
+#include "bsprofileview.h"
+
+using namespace std;
+
+
+
+BSProfileView::BSProfileView ()
+{
+  // CAUTION : don't activate antialiasing here !!!
+  setBackgroundBrush (QBrush (Qt::white));
+  setScene (new QGraphicsScene (0, 0, 610, 610));
+  prof = new BSProfileItem ();
+  scene()->addItem (prof);
+  setWindowTitle (prof->itemTitle ());
+  resize (QSize (616, 616));
+}
+
+
+BSProfileView::~BSProfileView ()
+{
+  scene()->removeItem (prof);
+  delete prof;
+}
+
+
+void BSProfileView::paint (QPainter *painter,
+                           const QStyleOptionGraphicsItem *option,
+                           QWidget *widget)
+{
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+  Q_UNUSED (painter);
+}
+
+
+void BSProfileView::setImage (QImage *image, VMap *idata)
+{
+  prof->setImage (image, idata);
+}
+
+
+void BSProfileView::buildScans (Pt2i p1, Pt2i p2)
+{
+  prof->buildScans (p1, p2);
+}
+
+
+bool BSProfileView::processKeyEvent (QKeyEvent *event)
+{
+  switch (event->key ())
+  {
+    case Qt::Key_W : // Width of correlation measure
+      prof->incCorrelWidth (event->modifiers () & Qt::ShiftModifier);
+      prof->update ();
+      break;
+
+    case Qt::Key_T : // Thickness of correlation measure
+      prof->incCorrelThick (event->modifiers () & Qt::ShiftModifier);
+      prof->update ();
+      break;
+
+    case Qt::Key_R : // Ratio of correlation measure
+      prof->incCorrelRatio (event->modifiers () & Qt::ShiftModifier);
+      prof->update ();
+      break;
+
+    case Qt::Key_I :
+      prof->toggleDisplay ((event->modifiers () & Qt::ShiftModifier) == 0);
+      setWindowTitle (prof->itemTitle ());
+      prof->update ();
+      break;
+
+    case Qt::Key_Up :
+      prof->incStripe (1);
+      prof->update ();
+      break;
+
+    case Qt::Key_Down :
+      prof->incStripe (-1);
+      prof->update ();
+      break;
+  }
+  return false;
+}
diff --git a/Code/Seg/BSTools/bsprofileview.h b/Code/Seg/BSTools/bsprofileview.h
new file mode 100755
index 0000000000000000000000000000000000000000..462648cf02106121b3205c7344ed76b32466fded
--- /dev/null
+++ b/Code/Seg/BSTools/bsprofileview.h
@@ -0,0 +1,58 @@
+#ifndef BS_PROFILE_VIEW_H
+#define BS_PROFILE_VIEW_H
+
+#include <QGraphicsView>
+#include "bsprofileitem.h"
+
+
+/** 
+ * @class BSProfileView bsprofileview.h
+ * \brief A Qt window containing informations about scanned profiles.
+ * \author {P. Even}
+ */
+class BSProfileView : public QGraphicsView
+{
+
+public:
+
+  /**
+   * \brief Creates a profile analysis window.
+   */
+  BSProfileView ();
+
+  /**
+   * \brief Deletes the profile analysis window.
+   */
+  ~BSProfileView ();
+
+  /**
+   * \brief Updates the profile analysis window display.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+  /**
+   * \brief Declares the image to be analysed.
+   */
+  void setImage (QImage *image, VMap *idata);
+
+  /**
+   * \brief Sets the image scan area from an initial scan.
+   * The initial scan is a straight segment from p1 to p2.
+   */
+  void buildScans (Pt2i p1, Pt2i p2);
+
+  /**
+   * \brief Processes key pressed events.
+   */
+  bool processKeyEvent (QKeyEvent *event);
+
+
+private:
+
+  /** Profile analysis widget. */
+  BSProfileItem *prof;
+
+};
+
+#endif
diff --git a/Code/Seg/BSTools/bsstructureitem.cpp b/Code/Seg/BSTools/bsstructureitem.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..c4cf2947f1fc77e56b26d6d0d47ae733349b0745
--- /dev/null
+++ b/Code/Seg/BSTools/bsstructureitem.cpp
@@ -0,0 +1,326 @@
+#include <QtGui>
+#include <iostream>
+#include "bsstructureitem.h"
+
+using namespace std;
+
+
+const int BSStructureItem::DISPLAY_FINAL_BLURRED_SEGMENT = 1;
+const int BSStructureItem::DISPLAY_FINAL_CONNECTED_COMPONENTS = 2;
+const int BSStructureItem::DISPLAY_FINAL_SCANS_AND_FILTER = 3;
+const int BSStructureItem::DISPLAY_INITIAL_BLURRED_SEGMENT = 4;
+const int BSStructureItem::DISPLAY_INITIAL_CONNECTED_COMPONENTS = 5;
+const int BSStructureItem::DISPLAY_INITIAL_SCANS_AND_FILTER = 6;
+const int BSStructureItem::DISPLAY_MIN = DISPLAY_FINAL_BLURRED_SEGMENT;
+const int BSStructureItem::DISPLAY_MAX = DISPLAY_INITIAL_SCANS_AND_FILTER;
+
+const int BSStructureItem::DEFAULT_PEN_WIDTH = 1;
+const int BSStructureItem::LEFT_MARGIN = 16;
+const int BSStructureItem::TEXT_HEIGHT = 16;
+
+const int BSStructureItem::MAX_ZOOM = 16;
+
+
+
+BSStructureItem::BSStructureItem (int width, int height, const QImage *im,
+                                  BSDetector *detector)
+{
+  w = width;
+  h = height;
+  zoom = 1;
+  focx = 0;
+  focy = 0;
+  det = detector;
+  displayItem = DISPLAY_MIN;
+  displayScanLines = false;
+  this->im = im;
+  verbose = true;
+  infoPen = QPen (Qt::red, DEFAULT_PEN_WIDTH, Qt::SolidLine,
+                  Qt::RoundCap, Qt::RoundJoin);
+}
+
+
+BSStructureItem::~BSStructureItem ()
+{
+}
+
+
+void BSStructureItem::zoomIn ()
+{
+  if (zoom < MAX_ZOOM) zoom *= 2;
+}
+
+
+void BSStructureItem::zoomOut ()
+{
+  if (zoom > 1)
+  {
+    int w2 = w / 2;
+    int h2 = h / 2;
+    zoom /= 2;
+    if (focx < w2 / zoom - w2) focx = w2 / zoom - w2;
+    if (focx > w2 - w2 / zoom) focx = w2 - w2 / zoom;
+    if (focy < h2 / zoom - h2) focy = h2 / zoom - h2;
+    if (focy > h2 - h2 / zoom) focy = h2 - h2 / zoom;
+  }
+}
+
+
+void BSStructureItem::shift (int dx, int dy)
+{
+  int w2 = w / 2;
+  int h2 = h / 2;
+  focx += zoom * dx;
+  focy += zoom * dy;
+  if (focx < w2 / zoom - w2) focx = w2 / zoom - w2;
+  if (focx > w2 - w2 / zoom) focx = w2 - w2 / zoom;
+  if (focy < h2 / zoom - h2) focy = h2 / zoom - h2;
+  if (focy > h2 - h2 / zoom) focy = h2 - h2 / zoom;
+}
+
+
+QRectF BSStructureItem::boundingRect () const
+{
+  return QRectF (0, 0, w - 1, h - 1); // ZZZ
+}
+
+
+void BSStructureItem::paint(QPainter *painter,
+                            const QStyleOptionGraphicsItem *option,
+                            QWidget *widget)
+{
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+
+  if (displayItem == DISPLAY_FINAL_BLURRED_SEGMENT)
+    paintBlurredSegment (painter, 1);
+  else if (displayItem == DISPLAY_FINAL_CONNECTED_COMPONENTS)
+    paintConnectedComponents (painter, 1);
+  else if (displayItem == DISPLAY_FINAL_SCANS_AND_FILTER)
+    paintScansAndFilter (painter, 1);
+  if (displayItem == DISPLAY_INITIAL_BLURRED_SEGMENT)
+    paintBlurredSegment (painter, 0);
+  else if (displayItem == DISPLAY_INITIAL_CONNECTED_COMPONENTS)
+    paintConnectedComponents (painter, 0);
+  else if (displayItem == DISPLAY_INITIAL_SCANS_AND_FILTER)
+    paintScansAndFilter (painter, 0);
+}
+
+
+void BSStructureItem::paintBlurredSegment (QPainter *painter, int step)
+{
+  BlurredSegment *bs = det->getBlurredSegment (step);
+  if (bs != NULL)
+  {
+    DigitalStraightSegment *dss = bs->getSegment ();
+    if (dss != NULL)
+    {
+      vector<Pt2i> bnd;
+      dss->getBounds (bnd, 0, 0, w, h);
+      paintPixels (painter, bnd, Qt::green);
+    }
+    paintPixels (painter, bs->getAllPoints (), Qt::blue);
+
+    if (verbose)
+    {
+      initText (painter);
+      if (dss != NULL)
+        addText (painter, QString ("Segment width = ")
+                 + QString::number (dss->width ()) + QString ("/")
+                 + QString::number (dss->period ()) + QString (" = ")
+                 + QString::number (dss->width () / (double) dss->period ()));
+      else addText (painter, QString ("Segment width = 0"));
+      addText (painter, QString ("W : input max width = ")
+               + QString::number (det->getInputMaxWidth ()));
+      addText (painter, QString ("L : output BS min size = ")
+               + QString::number (det->getBSminSize ()));
+      addText (painter, QString ("H : pixel lack tolerence = ")
+               + QString::number (det->getPixelLackTolerence ()));
+      if (step == 0)
+      {
+        addText (painter, QString ("D : extension limit = ")
+                 + QString::number (det->initialDetectionMaxExtent ()));
+        addText (painter, QString ("P : Prefiltering ")
+                 + (det->isFiltering (step) ?
+                    (QString ("on : ")
+                     + QString::number (det->prefilteringInputSize ())
+                     + QString (" -> ")
+                     + QString::number (det->prefilteringOutputSize ())
+                     + QString (" pixels")) :
+                    QString ("off")));
+      }
+    }
+  }
+}
+
+
+void BSStructureItem::paintConnectedComponents (QPainter *painter, int step)
+{
+  BlurredSegment *bs = det->getBlurredSegment (step);
+  if (bs != NULL)
+  {
+    QColor cols[] = {Qt::blue, Qt::red, Qt::green};
+    int col = 0;
+    vector < vector <Pt2i> > cc = bs->getConnectedComponents ();
+    vector < vector <Pt2i> >::const_iterator it = cc.begin ();
+    while (it != cc.end ())
+    {
+      paintPixels (painter, *it, cols[col]);
+      if (++col == 3) col = 0;
+      it++;
+    }
+  }
+
+  if (verbose)
+  {
+    initText (painter);
+    int ccs = det->connectedComponentMinSize ();
+    if (bs != NULL)
+    {
+      int bsccp = bs->countOfConnectedPoints (ccs);
+      int bssize = bs->getAllPoints().size ();
+      addText (painter, QString ("G connectivity constraint ")
+                        + (det->isSetConnectivityConstraint () ?
+                           QString ("on") : QString ("off")));
+      addText (painter, QString ("C connected components min size = ")
+                        + QString::number (ccs) + QString (" points"));
+      addText (painter, QString::number (bssize) + QString (" points"));
+      addText (painter, QString::number (bs->countOfConnectedComponents ())
+                        + QString (" connected components"));
+      addText (painter, QString::number (bs->countOfConnectedPoints ())
+                        + QString (" connected points"));
+      addText (painter, QString::number (bs->countOfConnectedComponents (ccs))
+                        + QString (" connected components with min size ")
+                        + QString::number (ccs));
+      addText (painter, QString::number (bsccp)
+                        + QString (" connected points with min size ")
+                        + QString::number (ccs));
+      if (bsccp < bssize / 2)
+        addText (painter, QString ("BS too sparse !"));
+    }
+  }
+}
+
+
+void BSStructureItem::paintScansAndFilter (QPainter *painter, int step)
+{
+  if (det->scanRecordOn (step))
+  {
+    if (displayScanLines)
+    {
+      QColor col[] = {Qt::blue, Qt::red, Qt::green};
+      int i = 0;
+      vector < vector <Pt2i> > scns = det->getScans (step);
+      if (scns.size () > 0)
+      {
+        vector <vector <Pt2i> >::const_iterator it = scns.begin ();
+        paintPixel (painter, it->front (), col[2]);
+        paintPixel (painter, it->back (), col[2]);
+        it++;  // Displays only the bounds of the central scan
+        while (it != scns.end ())
+        {
+          paintPixels (painter, *it, col[i]);
+          it++;
+          if (++i == 3) i = 0;
+        }
+      }
+    }
+    else
+    {
+      // Displays scan bounds
+      paintPixels (painter, det->getScanBound1 (step), Qt::blue);
+      paintPixels (painter, det->getScanBound2 (step), Qt::blue);
+
+      // Displays filter
+      if (det->isFiltering (step))
+      {
+        paintPixels (painter, det->getAccepted (step), Qt::green);
+        paintPixels (painter, det->getRejected (step), Qt::red);
+        BlurredSegment *bs = det->getBlurredSegment (step);
+        if (bs != NULL) paintPixels (painter, bs->getStartPt (), Qt::yellow);
+      }
+    }
+  }
+
+  if (verbose)
+  {
+    initText (painter);
+    addText (painter,
+             QString ("S : ") + (det->dynamicScansOn () ?
+               QString ("dynamic scans") : QString ("static scans")));
+    addText (painter,
+             QString ("O : ") + (det->orthoScansOn () ?
+               QString ("vert/horiz scans") : QString ("directional scans")));
+  }
+}
+
+
+void BSStructureItem::toggleDisplay (bool next)
+{
+  displayItem += (next ? 1 : -1);
+  if (displayItem > DISPLAY_MAX) displayItem = DISPLAY_MIN;
+  else if (displayItem < DISPLAY_MIN) displayItem = DISPLAY_MAX;
+  det->setScanRecord (1, displayItem == DISPLAY_FINAL_SCANS_AND_FILTER);
+  det->setScanRecord (0, displayItem == DISPLAY_INITIAL_SCANS_AND_FILTER);
+}
+
+
+void BSStructureItem::paintPixels (QPainter *painter,
+                                   const vector<Pt2i> &pix, const QColor col)
+{
+  QBrush brush (col);
+  vector<Pt2i>::const_iterator iter = pix.begin ();
+  while (iter != pix.end ())
+  {
+    Pt2i p = *iter;
+    int dx = w / 2 + focx - p.x ();
+    int dy = h / 2 - focy - p.y ();
+    painter->fillRect (w / 2 - zoom * dx,
+                      (h / 2 + zoom * dy),
+                       zoom, zoom, brush);
+    iter++;
+  }
+}
+
+
+void BSStructureItem::paintPixels (QPainter *painter,
+                                   const vector<Pt2i> &pix)
+{
+  vector<Pt2i>::const_iterator iter = pix.begin ();
+  while (iter != pix.end ())
+  {
+    Pt2i p = *iter;
+    int dx = w / 2 + focx - p.x ();
+    int dy = h / 2 - focy - p.y ();
+    QBrush brush (im->pixel (p.x (), im->height () - 1 - p.y ()));
+    painter->fillRect (w / 2 - zoom * dx,
+                      (h / 2 + zoom * dy),
+                       zoom, zoom, brush);
+    iter++;
+  }
+}
+
+
+void BSStructureItem::paintPixel (QPainter *painter,
+                                  const Pt2i &pix, const QColor col)
+{
+  QBrush brush (col);
+  int dx = w / 2 + focx - pix.x ();
+  int dy = h / 2 - focy - pix.y ();
+  painter->fillRect (w / 2 - zoom * dx, (h / 2 + zoom * dy), // dec 1
+                     zoom, zoom, brush);
+}
+
+
+void BSStructureItem::initText (QPainter *painter)
+{
+  painter->setPen (infoPen);
+  textOffset = 0;
+}
+
+
+void BSStructureItem::addText (QPainter *painter, const QString &text)
+{
+  textOffset += TEXT_HEIGHT;
+  painter->drawText (LEFT_MARGIN, textOffset, text);
+}
diff --git a/Code/Seg/BSTools/bsstructureitem.h b/Code/Seg/BSTools/bsstructureitem.h
new file mode 100755
index 0000000000000000000000000000000000000000..d8ea16f85eed6dbab71cc68816e19a3ac14a624b
--- /dev/null
+++ b/Code/Seg/BSTools/bsstructureitem.h
@@ -0,0 +1,218 @@
+#ifndef BS_STRUCTURE_ITEM_H
+#define BS_STRUCTURE_ITEM_H
+
+#include <QGraphicsItem>
+#include <vector>
+#include "bsdetector.h"
+
+
+class BSStructureItem : public QGraphicsItem
+{
+public:
+
+  /**
+   * \brief Creates a pixel analysis grid.
+   */
+  BSStructureItem (int width, int height,
+                   const QImage *im, BSDetector *detector);
+
+  /**
+   * \brief Deletes the pixel analysis grid.
+   */
+  ~BSStructureItem ();
+
+  /**
+   * \brief Return the zoom factor.
+   */
+  inline int zoomFactor () const { return zoom; }
+
+  /**
+   * \brief Zooms the grid in.
+   */
+  void zoomIn ();
+
+  /**
+   * \brief Zooms the grid out.
+   */
+  void zoomOut ();
+
+  /**
+   * \brief Return the focus point abscissae.
+   */
+  inline int focusX () const { return focx; }
+
+  /**
+   * \brief Return the focus point ordinate.
+   */
+  inline int focusY () const { return focy; }
+
+  /**
+   * \brief Shifts the grid.
+   * @param dx shift X value.
+   * @param dy shift Y value.
+   */
+  void shift (int dx, int dy);
+
+  /**
+   * \brief Toggles the displayed information.
+   * @param next Get next information if true, previous on otherwise.
+   */
+  void toggleDisplay (bool next);
+
+  /**
+   * \brief Switches on or off the information text display modality.
+   */
+  inline void switchInfoDisplay () { verbose = ! verbose; }
+
+  /**
+   * \brief Switches on or off the scan line display modality.
+   * @param next Get next information if true, previous on otherwise.
+   */
+  inline void switchScanDisplay () { displayScanLines = ! displayScanLines; }
+
+  /**
+   * \brief Returns the displayed information title.
+   */
+  inline QString itemTitle () const
+  {
+    if (displayItem == DISPLAY_FINAL_BLURRED_SEGMENT)
+      return ("Final blurred segment");
+    else if (displayItem == DISPLAY_FINAL_CONNECTED_COMPONENTS)
+      return ("Final connected components");
+    else if (displayItem == DISPLAY_FINAL_SCANS_AND_FILTER)
+      return ("Final scans and filter");
+    else if (displayItem == DISPLAY_INITIAL_BLURRED_SEGMENT)
+      return ("Initial blurred segment");
+    else if (displayItem == DISPLAY_INITIAL_CONNECTED_COMPONENTS)
+      return ("Initial connected components");
+    else if (displayItem == DISPLAY_INITIAL_SCANS_AND_FILTER)
+      return ("Initial scans and filter");
+    else return ("No info");
+  }
+
+  /**
+   * \brief Returns the grid area.
+   */
+  QRectF boundingRect () const;
+
+  /**
+   * \brief Redraws the pixel analysis grid.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+
+private:
+
+  /** Available information : final blurred segment pixels and bounds. */
+  static const int DISPLAY_FINAL_BLURRED_SEGMENT;
+  /** Available information : final connected components. */
+  static const int DISPLAY_FINAL_CONNECTED_COMPONENTS;
+  /** Available information : final scans and filter output. */
+  static const int DISPLAY_FINAL_SCANS_AND_FILTER;
+  /** Available information : initial blurred segment points and bounds. */
+  static const int DISPLAY_INITIAL_BLURRED_SEGMENT;
+  /** Available information : initial connected components. */
+  static const int DISPLAY_INITIAL_CONNECTED_COMPONENTS;
+  /** Available information : initial scans and filter output. */
+  static const int DISPLAY_INITIAL_SCANS_AND_FILTER;
+  /** Number of the first information. */
+  static const int DISPLAY_MIN;
+  /** Number of the last information. */
+  static const int DISPLAY_MAX;
+
+  /** Default value for pen width. */
+  static const int DEFAULT_PEN_WIDTH;
+  /** Left margin for information text. */
+  static const int LEFT_MARGIN;
+  /** Information text height. */
+  static const int TEXT_HEIGHT;
+
+  const QImage *im;
+  /** Grid width. */
+  int w;
+  /** Grid height. */
+  int h;
+  /** Zoom factor. */
+  static const int MAX_ZOOM;
+  /** Zoom factor. */
+  int zoom;
+  /** Focus point abscissae. */
+  int focx;
+  /** Focus point ordinate. */
+  int focy;
+  /** Segment detector. */
+  BSDetector *det;
+  /** Displayed information. */
+  int displayItem;
+  /** Scan display modality. */
+  bool displayScanLines;
+  /** Information text modality. */
+  bool verbose;
+  /** Information text style. */
+  QPen infoPen;
+  /** Information text vertical offset. */
+  int textOffset;
+
+
+  /**
+   * \brief Draws blurred segment structure information for the given step.
+   * @param painter : Painter to be decorated.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  void paintBlurredSegment (QPainter *painter, int step);
+
+  /**
+   * \brief Draws connected components information for the given step.
+   * @param painter : Painter to be decorated.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  void paintConnectedComponents (QPainter *painter, int step);
+
+  /**
+   * \brief Draws scans and filter information for the given step.
+   * @param painter : Painter to be decorated.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  void paintScansAndFilter (QPainter *painter, int step);
+
+  /**
+   * \brief Draws a vector of pixels with given color.
+   * @param painter : Painter to be decorated.
+   * @param pix : Pixels to display.
+   * @param col : Pixels color.
+   */
+  void paintPixels (QPainter *painter,
+                    const vector<Pt2i> &pix, const QColor col);
+
+  /**
+   * \brief Draws a list of image pixels.
+   * @param painter : Painter to be decorated.
+   * @param pix : List of pixels to display.
+   * @param col : Pixels color.
+   */
+  void paintPixels (QPainter *painter, const vector<Pt2i> &pix);
+
+  /**
+   * \brief Draws a pixel with given color.
+   * @param painter : Painter to be decorated.
+   * @param pix : Pixel to display.
+   * @param col : Color to apply.
+   */
+  void paintPixel (QPainter *painter, const Pt2i &pix, const QColor col);
+
+  /**
+   * \brief Initializes the text display (color and position).
+   * @param painter : Painter to be decorated.
+   */
+  void initText (QPainter *painter);
+
+  /**
+   * \brief Paints a new text in the graphics item (updates text position).
+   * @param painter : Painter to be decorated.
+   * @param text : Text to be displayed.
+   */
+  void addText (QPainter *painter, const QString &text);
+};
+
+#endif
diff --git a/Code/Seg/BSTools/bsstructureview.cpp b/Code/Seg/BSTools/bsstructureview.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..81ce0b946e5641f187850af4a5570b56796556d8
--- /dev/null
+++ b/Code/Seg/BSTools/bsstructureview.cpp
@@ -0,0 +1,234 @@
+#include <QtGui>
+#include <iostream>
+#include "bsstructureview.h"
+#include "math.h"
+
+using namespace std;
+
+
+BSStructureView::BSStructureView (QImage *im, BSDetector *sd)
+{
+  graylevelImage = im;
+  currentImage = im;
+  det = sd;
+  int w = im->width ();
+  int h = im->height ();
+  imageInBack = true;
+  gradImage = NULL;
+  gradInBack = false;
+  setBackgroundBrush (QBrush (*currentImage));
+  setScene (new QGraphicsScene (0, 0, w, h));
+  grid = new BSStructureItem (w, h, im, sd);
+  scene()->addItem (grid);
+  setWindowTitle (grid->itemTitle ());
+}
+
+
+BSStructureView::~BSStructureView ()
+{
+  scene()->removeItem (grid);
+  delete grid;
+  delete gradImage;
+}
+
+
+void BSStructureView::setGradientImage (VMap *gMap)
+{
+  if (gradImage != NULL) delete gradImage;
+  int w = gMap->getWidth ();
+  int h = gMap->getHeight ();
+  double gn[w * h];
+  for (int j = 0; j < h; j++)
+    for (int i = 0; i < w; i++)
+      gn[j * w + i] = gMap->cmpNorm (i, j);
+      // gn[j * w + i] = sqrt (gMap->sqNorm (i, j));
+  double max = 0;
+  for (int i = 0; i < w * h; i++) if (max < gn[i]) max = gn[i];
+  gradImage = new QImage (w, h, QImage::Format_RGB32);
+  for (int j = 0; j < h; j++)
+    for (int i = 0; i < w; i++)
+    {
+      uint val = (uint) (gn[(h - 1 - j) * w + i] * 255 / max);
+      gradImage->setPixel (i, j, val + val * 256 + val * 256 * 256);
+    }
+  // gradImage->save ("gradient.png");
+}
+
+
+void BSStructureView::updateBackground (bool zoomChanged)
+{
+  if (imageInBack)
+  {
+    int w = currentImage->width ();
+    int h = currentImage->height ();
+    int zf = grid->zoomFactor ();
+    if (zoomChanged) image = currentImage->scaled (w * zf, h * zf);
+    QBrush qb (image);
+    qb.setTransform (QTransform::fromTranslate (
+          w / 2 - zf * (w / 2 + grid->focusX ()),
+          h / 2 - zf * (h / 2 + grid->focusY ())));
+    setBackgroundBrush (qb);
+  }
+}
+
+
+void BSStructureView::toggleBackground ()
+{
+  imageInBack = ! imageInBack;
+  if (imageInBack) setBackgroundBrush (QBrush (image));
+  else setBackgroundBrush (QBrush (Qt::white));
+}
+
+
+void BSStructureView::toggleGradient ()
+{
+  if (currentImage == gradImage) currentImage = graylevelImage;
+  else if (gradImage != NULL) currentImage = gradImage;
+}
+
+
+void BSStructureView::paint (QPainter *painter,
+                             const QStyleOptionGraphicsItem *option,
+                             QWidget *widget)
+{
+  Q_UNUSED (painter);
+  Q_UNUSED (option);
+  Q_UNUSED (widget);
+}
+
+
+bool BSStructureView::processKeyEvent (QKeyEvent *event)
+{
+  bool processed = false;
+  switch (event->key ())
+  {
+    case Qt::Key_I : // Info
+      if (event->modifiers () & Qt::ControlModifier) grid->switchScanDisplay ();
+      else grid->toggleDisplay ((event->modifiers () & Qt::ShiftModifier) == 0);
+      setWindowTitle (grid->itemTitle ());
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_V : // Info display
+      grid->switchInfoDisplay ();
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_B : // Background
+      if (event->modifiers () & Qt::ShiftModifier) toggleGradient ();
+      else toggleBackground ();
+      updateBackground (true);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Plus : // Zoom in
+      grid->zoomIn ();
+      updateBackground (true);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Minus : // Zoom out
+      grid->zoomOut ();
+      updateBackground (true);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Left : // Go leftwards
+      grid->shift (-1, 0);
+      updateBackground (false);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Right : // Go rightwards
+      grid->shift (1, 0);
+      updateBackground (false);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Up : // Go upwards
+      grid->shift (0, -1);
+      updateBackground (false);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_Down : // Go downwards
+      grid->shift (0, 1);
+      updateBackground (false);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_C : // Increments the connected components min size
+      det->incConnectedComponentMinSize (
+            (event->modifiers () & Qt::ShiftModifier) == 0);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_G : // Increments the connected components min size
+      det->switchConnectivityConstraint ();
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_S : // Switch dynamic scans
+      det->switchDynamicScans ();
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_O : // Switch orthographic scans
+      det->switchOrthoScans ();
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_P : // Switch pre-filtering
+      det->switchFiltering (0);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_F : // Switch final filtering
+      det->switchFiltering (1);
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_D : // Initial detection extension limitation
+      det->switchInitialBounding ();
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_W : // Input max width
+      det->setInputMaxWidth (det->getInputMaxWidth () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_L : // Output blurred segment min size
+      det->setBSminSize (det->getBSminSize () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      update ();
+      processed = true;
+      break;
+
+    case Qt::Key_H : // Pixel lack tolerence
+      det->setPixelLackTolerence (det->getPixelLackTolerence () +
+        (event->modifiers () & Qt::ShiftModifier ? -1 : 1));
+      update ();
+      processed = true;
+      break;
+  }
+  return processed;
+}
diff --git a/Code/Seg/BSTools/bsstructureview.h b/Code/Seg/BSTools/bsstructureview.h
new file mode 100755
index 0000000000000000000000000000000000000000..6f6dce8cd82ee41ab354ae57e436922a5e9867c6
--- /dev/null
+++ b/Code/Seg/BSTools/bsstructureview.h
@@ -0,0 +1,80 @@
+#ifndef BS_STRUCTURE_VIEW_H
+#define BS_STRUCTURE_VIEW_H
+
+#include <QGraphicsView>
+#include <QImage>
+#include "bsstructureitem.h"
+
+
+class BSStructureView : public QGraphicsView
+{
+
+public:
+
+  /**
+   * \brief Creates a pixel analyzer.
+   */
+  BSStructureView (QImage *im, BSDetector *sd);
+
+  /**
+   * \brief Deletes the pixel analyzer.
+   */
+  ~BSStructureView ();
+
+  /**
+   * Sets the gradient image.
+   */
+  void setGradientImage (VMap *gMap);
+
+  /**
+   * Toggles the window background between the current image or plain white.
+   */
+  void toggleBackground ();
+
+  /**
+   * Toggles the current image between gray level or gradient image.
+   */
+  void toggleGradient ();
+
+  /**
+   * \brief Redraws the pixel analyzer.
+   */
+  void paint (QPainter *painter,
+              const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+  /**
+   * \brief Processes key pressed events.
+   */
+  bool processKeyEvent (QKeyEvent *event);
+
+protected:
+
+private:
+
+
+  /** Pointer to the blurred segment detector. */
+  BSDetector *det;
+  /** Pointer to the raw image. */
+  QImage *graylevelImage;
+  /** Pointer to the blurred segment structure graphics item. */
+  BSStructureItem *grid;
+  /** Background image. */
+  QImage image;
+  /** Background image display modality. */
+  bool imageInBack;
+  /** Pointer to the gradient image. */
+  QImage *currentImage;
+  /** Pointer to the currently displayed image. */
+  QImage *gradImage;
+  /** Gradient image display modality. */
+  bool gradInBack;
+
+  /**
+   * Updates the background image.
+   * @param zoomChanged If 'true', the zoom factorshould be taken into account
+   */
+  void updateBackground (bool zoomChanged);
+
+};
+
+#endif
diff --git a/Code/Seg/BSTools/bswindow.cpp b/Code/Seg/BSTools/bswindow.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..5c848f9339f57b3a09ab31f9bb5a41f22af4f0be
--- /dev/null
+++ b/Code/Seg/BSTools/bswindow.cpp
@@ -0,0 +1,140 @@
+#include "bswindow.h"
+#include <QtGui>
+//#include <QtWidgets>
+#include <QFileDialog>
+#include <QMenuBar>
+#include <iostream>
+
+
+BSWindow::BSWindow (int *val)
+{
+  Q_UNUSED (val);
+  showProf = false;
+  showAccu = false;
+  showSeg = false;
+  gradType = VMap::TYPE_SOBEL_5X5;
+  detectionWidget = new BSDetectionWidget;
+  setCentralWidget (detectionWidget);
+  // setFocus();  
+  // createActions ();
+  // createMenus ();
+  setWindowTitle (tr ("Blurred Segments"));
+  resize (400, 400);
+}
+
+
+BSWindow::BSWindow ()
+{
+  showProf = false;
+  showAccu = false;
+  showSeg = false;
+  gradType = 0;
+  detectionWidget = new BSDetectionWidget;
+  setCentralWidget (detectionWidget);
+  // setFocus ();
+  // createActions ();
+  // createMenus ();
+  setWindowTitle (tr ("Blurred Segments"));
+  resize (400, 400);
+}
+
+
+void BSWindow::setFile (QString fileName)
+{
+  resize (detectionWidget->openImage (fileName, gradType));
+}
+
+
+void BSWindow::runOptions ()
+{
+  if (showProf) detectionWidget->switchProfileAnalyzer ();
+  if (showAccu) detectionWidget->switchAccuAnalyzer ();
+  if (showSeg) detectionWidget->switchPixelAnalyzer ();
+}
+
+
+void BSWindow::runTest ()
+{
+  detectionWidget->localTest ();
+}
+
+
+void BSWindow::closeEvent (QCloseEvent *event)
+{
+  detectionWidget->closeProfileAnalyzer ();
+  detectionWidget->closeAccuAnalyzer ();
+  detectionWidget->closePixelAnalyzer ();
+  event->accept ();
+}
+
+
+void BSWindow::open ()
+{
+  QSize windowSize;
+  QString fileName = QFileDialog::getOpenFileName (this,
+                                     tr ("Open File"), QDir::currentPath ());
+  if (! fileName.isEmpty ())
+  {
+    windowSize = detectionWidget->openImage (fileName, gradType);
+    updateActions ();
+  }
+  resize (windowSize);
+}
+
+
+void BSWindow::save ()
+{
+  QAction *action = qobject_cast < QAction *> (sender ());
+  QByteArray fileFormat = action->data().toByteArray ();
+  saveFile (fileFormat);
+}
+
+
+void BSWindow::updateActions ()
+{
+}
+
+
+void BSWindow::createActions ()
+{
+  openAct = new QAction (tr ("&Open..."), this);
+  openAct->setShortcut (tr ("Ctrl+O"));
+  connect (openAct, SIGNAL (triggered ()), this, SLOT (open()));
+
+  foreach (QByteArray format, QImageWriter::supportedImageFormats ())
+  {
+    QString text = tr("%1...").arg (QString(format).toUpper ());
+    QAction *action = new QAction (text, this);
+    action->setData (format);
+    connect (action, SIGNAL (triggered ()), this, SLOT (save ()));
+    saveAsActs.append (action);
+  }
+  exitAct = new QAction (tr ("E&xit"), this);
+  exitAct->setShortcut (tr ("Ctrl+Q"));
+  connect (exitAct, SIGNAL (triggered ()), this, SLOT (close ()));
+}
+
+
+void BSWindow::createMenus ()
+{
+  saveAsMenu = new QMenu (tr ("&Save As"), this);
+  foreach (QAction *action, saveAsActs) saveAsMenu->addAction (action);
+  fileMenu = new QMenu (tr ("&File"), this);
+  fileMenu->addAction (openAct);
+  fileMenu->addMenu (saveAsMenu);
+  fileMenu->addSeparator ();
+  fileMenu->addAction (exitAct);
+  menuBar()->addMenu (fileMenu);
+}
+
+
+bool BSWindow::saveFile (const QByteArray &fileFormat)
+{
+  QString initialPath = QDir::currentPath () + "/untitled." + fileFormat;
+  QString fileName = QFileDialog::getSaveFileName (this, tr ("Save As"),
+                       initialPath, tr ("%1 Files (*.%2);;All Files (*)")
+                           .arg(QString(fileFormat.toUpper()))
+                           .arg(QString(fileFormat)));
+  if (fileName.isEmpty ()) return false;
+  else return detectionWidget->saveAugmentedImage (fileName, fileFormat);
+}
diff --git a/Code/Seg/BSTools/bswindow.h b/Code/Seg/BSTools/bswindow.h
new file mode 100755
index 0000000000000000000000000000000000000000..c9afa16d0ed1ef3176dfb455805d8fd684f5bd67
--- /dev/null
+++ b/Code/Seg/BSTools/bswindow.h
@@ -0,0 +1,96 @@
+#ifndef BS_WINDOW_H
+#define BS_WINDOW_H
+
+#include <QList>
+#include <QMainWindow>
+#include "bsdetectionwidget.h"
+
+
+/** 
+ * @class BSWindow bswindow.h
+ * \brief Blurred segment extraction Qt window.
+ * \author {P. Even and B. Kerautret}
+ */
+class BSWindow : public QMainWindow
+{
+    Q_OBJECT
+    
+public:
+
+  /**
+   * \brief Creates a blurred segment extraction window.
+   */
+  BSWindow ();
+
+  /**
+   * \brief Creates a segment extraction window.
+   */
+  BSWindow (int *val);
+
+  /**
+   * Sets the processed image.
+   */
+  void setFile (QString fileName);
+
+  /**
+   * Switches the profile analysis window on or off.
+   */
+  inline void toggleProfWindow () { showProf = ! showProf; }
+
+  /**
+   * Switches the accumulator analysis window on or off.
+   */
+  inline void toggleAccuWindow () { showAccu = ! showAccu; }
+
+  /**
+   * Switches the segment analysis window on or off.
+   */
+  inline void toggleSegWindow () { showSeg= ! showSeg; }
+
+  /**
+   * Sets the gradient extraction method to be used.
+   */
+  inline void useGradient (int type) { gradType = type; }
+
+  /**
+   * Takes into account the option (after image load).
+   */
+  void runOptions ();
+
+  /**
+   * Performs a simple test.
+   */
+  void runTest ();
+
+
+protected:
+  void closeEvent (QCloseEvent *event);
+
+
+private slots:
+  void open ();
+  void save ();
+  void updateActions ();
+
+
+private:
+
+  /** Blurred segment detection widget. */
+  BSDetectionWidget *detectionWidget;
+  bool showProf;
+  bool showAccu;
+  bool showSeg;
+  int gradType;
+
+  void createActions ();
+  void createMenus ();
+  bool saveFile (const QByteArray &fileFormat);
+  QMenu *saveAsMenu;
+  QMenu *fileMenu;
+
+  QAction *openAct;
+  QList<QAction *> saveAsActs;
+  QAction *exitAct;
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/biptlist.cpp b/Code/Seg/BlurredSegment/biptlist.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..233932bd8f3196653272295ed44104247de0f96c
--- /dev/null
+++ b/Code/Seg/BlurredSegment/biptlist.cpp
@@ -0,0 +1,103 @@
+#include "biptlist.h"
+#include <iostream>
+
+
+BiPtList::BiPtList (Pt2i pt)
+{
+  pts.push_back (pt);
+  start = 0;
+  cpt = 1;
+}
+
+
+BiPtList::~BiPtList ()
+{
+}
+
+
+void BiPtList::addFront (Pt2i pt)
+{
+  pts.push_front (pt);
+  start++;
+  cpt++;
+}
+
+
+void BiPtList::addBack (Pt2i pt)
+{
+  pts.push_back (pt);
+  cpt++;
+}
+
+
+void BiPtList::removeFront (int n)
+{
+  if (n >= frontSize ()) n = frontSize () - 1; // We keep at least one point
+  for (int i = 0; i < n; i++) pts.pop_front ();
+  cpt -= n;
+  start -= n;
+  if (start < 0) start = 0; // Theoretically impossible
+}
+
+
+void BiPtList::removeBack (int n)
+{
+  if (n >= backSize ()) n = backSize () - 1;  // We keep at least one point
+  for (int i = 0; i < n; i++) pts.pop_back ();
+  cpt -= n;
+  if (start >= cpt) start = cpt - 1;  // Theoretically impossible
+}
+
+
+void BiPtList::findExtrema (int &xmin, int &ymin, int &xmax, int &ymax) const
+{
+  deque<Pt2i>::const_iterator it = pts.begin ();
+  xmin = it->x ();
+  ymin = it->y ();
+  xmax = it->x ();
+  ymax = it->y ();
+  while (it != pts.end ())
+  {
+    if (xmin > it->x ()) xmin = it->x ();
+    if (xmax < it->x ()) xmax = it->x ();
+    if (ymin > it->y ()) ymin = it->y ();
+    if (ymax < it->y ()) ymax = it->y ();
+    it++;
+  }
+}
+
+
+vector<Pt2i> BiPtList::frontToBackPoints () const
+{
+  vector<Pt2i> res;
+  for (deque<Pt2i>::const_iterator it = pts.begin ();
+       it != pts.end (); it++)
+    res.push_back (*it);
+  return (res);
+}
+
+
+vector<Pt2i> *BiPtList::vide () const
+{
+  return (new vector<Pt2i> ());
+}
+
+
+vector<Pt2i> *BiPtList::frontPoints () const
+{
+  // Fournis du bord au centre : pertinent ?
+  vector<Pt2i> *res = new vector<Pt2i> ();
+  deque<Pt2i>::const_iterator it = pts.begin ();
+  for (int i = 0; i < start; i++) res->push_back (*it++);
+  return res;
+}
+
+
+vector<Pt2i> *BiPtList::backPoints () const
+{
+  vector<Pt2i> *res = new vector<Pt2i> ();
+  deque<Pt2i>::const_iterator it = pts.begin ();
+  it += start + 1;
+  for (int i = 0; i < cpt - start - 1; i++) res->push_back (*it++);
+  return res;
+}
diff --git a/Code/Seg/BlurredSegment/biptlist.h b/Code/Seg/BlurredSegment/biptlist.h
new file mode 100755
index 0000000000000000000000000000000000000000..be01993e2553f7a34c0bf98f700e34b289666beb
--- /dev/null
+++ b/Code/Seg/BlurredSegment/biptlist.h
@@ -0,0 +1,132 @@
+#ifndef BIPT_LIST_H
+#define BIPT_LIST_H
+
+#include "pt2i.h"
+#include <deque>
+
+using namespace std;
+
+
+/** 
+ * @class BiPtList biptlist.h
+ * \brief Bi-directional list of points.
+ * \author {P. Even}
+ */
+class BiPtList
+{
+public:
+
+  /**
+   * Creates a extendable bi-directional list with one point.
+   * @param pt Initial point of the list.
+   */
+  BiPtList (Pt2i pt);
+
+  /**
+   * Deletes the bi-directional list.
+   */
+  ~BiPtList ();
+
+  /**
+   * Returns the count of point in the bi-directional list.
+   */
+  inline int size () const { return (cpt); }
+
+  /**
+   * Returns the count of point on the back part of the bi-directional list.
+   */
+  inline int backSize () const { return (cpt - start - 1); }
+
+  /**
+   * Returns the count of point on the back part of the bi-directional list.
+   */
+  inline int frontSize () const { return (start); }
+
+  /**
+   * Returns the initial point of the bi-directional list.
+   */
+  inline Pt2i initialPoint () const { return (pts[start]); }
+
+  /**
+   * Returns the back end point of the bi-directional list.
+   */
+  inline Pt2i backPoint () const { return (pts.back ()); }
+
+  /**
+   * Returns the front end point of the bi-directional list.
+   */
+  inline Pt2i frontPoint () const { return (pts.front ()); }
+
+  /**
+   * Returns the height of the point to the line between the list end points..
+   */
+  inline AbsRat heightToEnds (const Pt2i &pt) const {
+    return (pt.triangleRationalHeight (pts.front (), pts.back ())); }
+
+  /**
+   * Adds the point on front side.
+   * @param pt The point to add.
+   */
+  void addFront (Pt2i pt);
+
+  /**
+   * Adds the point on back side.
+   * @param pt The point to add.
+   */
+  void addBack (Pt2i pt);
+
+  /**
+   * Removes n point on front side.
+   * @param n The count of points to remove.
+   */
+  void removeFront (int n);
+
+  /**
+   * Removes n point on back side.
+   * @param n The count of points to remove.
+   */
+  void removeBack (int n);
+
+  /**
+   * Fills in the given parameters with the point min and max coordinates.
+   * @param xmin Minimum X value.
+   * @param ymin Minimum Y value.
+   * @param xmax Maximum X value.
+   * @param ymax Maximum Y value.
+   */
+  void findExtrema (int &xmin, int &ymin, int &xmax, int &ymax) const;
+
+  /**
+   * Returns front to back points in a vector.
+   */
+  vector<Pt2i> frontToBackPoints () const;
+
+  /**
+   * Returns a pointer to a empty vector.
+   */
+  vector<Pt2i> *vide () const;
+
+  /**
+   * Returns a pointer to a vector filled in with front points.
+   * Front points are entered from segment edge to the initial point excluded.
+   */
+  vector<Pt2i> *frontPoints () const;
+
+  /**
+   * Returns a pointer to a vector filled in with back points.
+   * Back points are entered from initial point excluded to segment edge.
+   */
+  vector<Pt2i> *backPoints () const;
+
+
+private:
+
+  /** List of points. */
+  deque<Pt2i> pts;
+  /** Index of the initial point. */
+  int start;
+  /** Length of the point list. */
+  int cpt;
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/blurredsegment.cpp b/Code/Seg/BlurredSegment/blurredsegment.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..7dcc136d266d9a8bf825f83f55b91e3b9744c284
--- /dev/null
+++ b/Code/Seg/BlurredSegment/blurredsegment.cpp
@@ -0,0 +1,260 @@
+#include "blurredsegment.h"
+
+
+BlurredSegment::BlurredSegment ()
+{
+  plist = NULL;
+  dss = NULL;
+}
+
+
+BlurredSegment::BlurredSegment (BiPtList *ptlist, DigitalStraightSegment *seg)
+{
+  plist = ptlist;
+  dss = seg;
+}
+
+
+BlurredSegment::~BlurredSegment ()
+{
+  if (plist != NULL) delete plist;
+  if (dss != NULL) delete dss;
+}
+
+
+AbsRat BlurredSegment::segmentRationalWidth () const
+{
+  return (AbsRat (dss->width (), dss->period ()));
+}
+
+
+vector<Pt2i> BlurredSegment::getAllPoints () const
+{
+  return (plist->frontToBackPoints ());
+}
+
+
+vector<Pt2i> *BlurredSegment::getAllRight () const
+{
+  return (plist->backPoints ());
+}
+
+
+vector<Pt2i> *BlurredSegment::getAllLeft () const
+{
+  return (plist->frontPoints ());
+}
+
+
+int BlurredSegment::size () const
+{
+  return (plist->size ());
+}
+
+
+vector<Pt2i> BlurredSegment::getStartPt () const
+{
+  vector<Pt2i> res;
+  res.push_back (plist->initialPoint ());
+  return res;
+}
+
+
+const Pt2i BlurredSegment::getLastRight () const
+{
+  return (plist->backPoint ());
+}
+
+
+const Pt2i BlurredSegment::getLastLeft () const
+{
+  return (plist->frontPoint ());
+}
+
+
+Vr2i BlurredSegment::getSupportVector ()
+{
+  return (dss->supportVector ());
+}
+
+
+Vr2i BlurredSegment::boundingBoxSize () const
+{
+  int xmin, ymin, xmax, ymax;
+  plist->findExtrema (xmin, ymin, xmax, ymax);
+  return (Vr2i (xmax - xmin, ymax - ymin));
+}
+
+
+vector <vector <Pt2i> > BlurredSegment::connectedComponents () const
+{
+  vector <vector <Pt2i> > ccs;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    vector <Pt2i> cc;
+    bool started = false;
+    vector <Pt2i>::const_iterator it = pts.begin ();
+    Pt2i pix = *it++;
+    while (it != pts.end ())
+    {
+      if (it->isConnectedTo (pix))
+      {
+        if (! started)
+        {
+          cc.push_back (pix);
+          started = true;
+        }
+        cc.push_back (*it);
+      }
+      else
+      {
+        if (started)
+        {
+          ccs.push_back (cc);
+          cc.clear ();
+          started = false;;
+        }
+      }
+      pix = *it++;
+    }
+  }
+  return ccs;
+}
+
+
+int BlurredSegment::countOfConnectedPoints () const
+{
+  int count = 0;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    bool started = false;
+    vector <Pt2i>::const_iterator it = pts.begin ();
+    Pt2i pix = *it++;
+    while (it != pts.end ())
+    {
+      if (it->isConnectedTo (pix))
+      {
+        if (started) count ++;
+        else
+        {
+          count += 2;
+          started = true;
+        }
+      }
+      else
+      {
+        if (started) started = false;;
+      }
+      pix = *it++;
+    }
+  }
+  return count;
+}
+
+
+int BlurredSegment::countOfConnectedComponents () const
+{
+  int count = 0;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    bool started = false;
+    vector <Pt2i>::const_iterator it = pts.begin ();
+    Pt2i pix = *it++;
+    while (it != pts.end ())
+    {
+      if (it->isConnectedTo (pix))
+      {
+        if (! started)
+        {
+          count ++;
+          started = true;
+        }
+      }
+      else
+      {
+        if (started) started = false;;
+      }
+      pix = *it++;
+    }
+  }
+  return count;
+}
+
+
+int BlurredSegment::countOfConnectedPoints (int min) const
+{
+  int count = 0;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    int cpt = 1;
+    vector <Pt2i>::const_iterator it = pts.begin ();
+    Pt2i pix = *it++;
+    while (it != pts.end ())
+    {
+      if (it->isConnectedTo (pix))
+      {
+        if (++cpt == min) count += min;
+        else if (cpt > min) count ++;
+      }
+      else cpt = 1;
+      pix = *it++;
+    }
+  }
+  return count;
+}
+
+
+int BlurredSegment::countOfConnectedComponents (int min) const
+{
+  int count = 0;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    int cpt = 1;
+    vector <Pt2i>::const_iterator it = pts.begin ();
+    Pt2i pix = *it++;
+    while (it != pts.end ())
+    {
+      if (it->isConnectedTo (pix))
+      {
+        if (++cpt == min) count ++;
+      }
+      else cpt = 1;;
+      pix = *it++;
+    }
+  }
+  return count;
+}
+
+
+vector <vector <Pt2i> >
+BlurredSegment::getConnectedComponents () const
+{
+  vector < vector <Pt2i> > res;
+  vector <Pt2i> pts = getAllPoints ();
+  if (pts.size () > 1)
+  {
+    vector <Pt2i>::const_iterator bit = pts.begin ();
+    vector <Pt2i>::const_iterator eit = pts.end ();
+    while (bit != eit)
+    {
+      vector <Pt2i> lres;
+      Pt2i pix = *bit++;
+      bool compose = true;
+      do
+      {
+        lres.push_back (pix);
+        compose = bit->isConnectedTo (pix);
+        if (compose) pix = *bit++;
+      }
+      while (compose && bit != eit);
+      if (compose) lres.push_back (pix);
+      res.push_back (lres);
+    }
+  }
+  return res;
+}
diff --git a/Code/Seg/BlurredSegment/blurredsegment.h b/Code/Seg/BlurredSegment/blurredsegment.h
new file mode 100755
index 0000000000000000000000000000000000000000..0395e78a75033268afc98cdbd4024448e2714c7f
--- /dev/null
+++ b/Code/Seg/BlurredSegment/blurredsegment.h
@@ -0,0 +1,171 @@
+#ifndef BLURRED_SEGMENT_H
+#define BLURRED_SEGMENT_H
+
+
+#include "convexhull.h"
+#include "digitalstraightsegment.h"
+#include "biptlist.h"
+
+using namespace std;
+
+
+/** 
+ * @class BlurredSegment blurredsegment.h
+ * \brief A list of 2D points lying inside a digital straight line.
+ * \author {P. Even}
+ */
+class BlurredSegment
+{
+
+public:
+
+  /**
+   * Creates a blurred segment from nothing.
+   */
+  BlurredSegment ();
+
+  /**
+   * Creates a blurred segment from a list of points.
+   * @param ptlist List of points of the blurred segment to build.
+   * @param seg Bounding digital straight segment.
+   */
+  BlurredSegment (BiPtList *ptlist, DigitalStraightSegment *seg);
+
+  /**
+   * \brief Deletes the blurred segment.
+   */
+  virtual ~BlurredSegment ();
+
+  /**
+   * \brief Returns the minimal vertical or horizontal width.
+   */
+  virtual AbsRat segmentRationalWidth () const;
+
+  /**
+   * \brief Returns if the segment has non null thickness (not aligned points).
+   */
+  inline bool isThick () const { return (dss->width () < 2); }
+
+  /**
+   * \brief Returns the underlying digital straight segment.
+   */
+  inline DigitalStraightSegment *getSegment () { return dss; }
+
+  /**
+   * \brief Returns the count of points of the blurred segment.
+   */
+  int size () const;
+
+  /**
+   * \brief Returns the start point of the blurred segment.
+   */
+  inline const Pt2i getCenter () const { return plist->initialPoint (); }
+
+  /**
+   * \brief Returns the colinear points at the left of the start point.
+   */
+  inline const vector<Pt2i> *getLeftLine () const { return plist->vide (); }
+
+  /**
+   * \brief Returns the colinear points at the right of the start point.
+   */
+  inline const vector<Pt2i> *getRightLine () const { return plist->vide (); }
+
+  /**
+   * \brief Returns the left points added to the blurred segment start point.
+   */
+  inline const vector<Pt2i> *getLeftPoints () const {
+    return plist->frontPoints (); }
+
+  /**
+   * \brief Returns the right points added to the blurred segment start point.
+   */
+  inline const vector<Pt2i> *getRightPoints () const {
+    return plist->backPoints (); }
+
+  /**
+   * \brief Returns the set of all the points on the blurred segment.
+   * Points are ordered from the left end point up to the right end point.
+   */
+  vector<Pt2i> getAllPoints () const;
+
+  /**
+   * \brief Returns the set of points on the left part of the blurred segment.
+   * Points are ordered from the furthest to the nearest to the start point.
+   */
+  vector<Pt2i> *getAllLeft () const;
+
+  /**
+   * \brief Returns the set of points on the left part of the blurred segment.
+   * Points are ordered from the nearest to the furthest to the start point.
+   */
+  vector<Pt2i> *getAllRight () const;
+
+  /**
+   * \brief Returns a vector containing the start point of the blurred segment.
+   */
+  vector<Pt2i> getStartPt () const;
+
+  /**
+   * \brief Returns the last accepted point on the right side. 
+   */
+  const Pt2i getLastRight () const;
+
+  /**
+   * \brief Returns the last accepted point on the left side. 
+   */
+  const Pt2i getLastLeft () const;
+
+  /**
+   * \brief Returns the support vector of the blurred segment.
+   */
+  virtual Vr2i getSupportVector ();
+
+  /**
+   * \brief Returns the size of the segment bounding box in a vector 2D.
+   */
+  Vr2i boundingBoxSize () const;
+
+  /**
+   * \brief Returns the connected components of the blurred segment.
+   */
+  vector <vector <Pt2i> > connectedComponents () const;
+
+  /**
+   * \brief Returns the count of connected points in the blurred segment.
+   */
+  int countOfConnectedPoints () const;
+
+  /**
+   * \brief Returns the count of connected components in the blurred segment.
+   */
+  int countOfConnectedComponents () const;
+
+  /**
+   * \brief Returns the count of connected points of given minimal size.
+   * @param min Minimal size of the connected components.
+   */
+  int countOfConnectedPoints (int min) const;
+
+  /**
+   * \brief Returns the count of connected components of given minimal size.
+   * @param min Minimal size of the connected components.
+   */
+  int countOfConnectedComponents (int min) const;
+
+  /**
+   * \brief Returns the connected components of the blurred segment.
+   */
+  vector <vector <Pt2i> > getConnectedComponents () const;
+
+
+protected:
+
+  /** Bounding straight segment. */
+  DigitalStraightSegment *dss;
+
+  /** Bi-directional list of points. */
+  BiPtList *plist;
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/blurredsegmentproto.cpp b/Code/Seg/BlurredSegment/blurredsegmentproto.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2354df5d1ed901d2386dbb1a0c0254d12e532968
--- /dev/null
+++ b/Code/Seg/BlurredSegment/blurredsegmentproto.cpp
@@ -0,0 +1,284 @@
+#include "blurredsegmentproto.h"
+
+
+BlurredSegmentProto::BlurredSegmentProto (int maxWidth, Pt2i pix)
+{
+  this->maxWidth.set (maxWidth);
+  plist = new BiPtList (pix);
+  leftOK = false;
+  rightOK = false;
+  bsFlat = false;
+  bsOK = false;
+  convexhull = NULL;
+  chChanged = false;
+  dss = NULL;
+}
+
+
+BlurredSegmentProto::BlurredSegmentProto (int maxWidth, Pt2i center,
+                  const vector<Pt2i> &leftPts, const vector<Pt2i> &rightPts)
+{
+  this->maxWidth.set (maxWidth);
+  plist = new BiPtList (center);
+  leftOK = false;
+  rightOK = false;
+  bsFlat = false;
+  bsOK = false;
+  convexhull = NULL;
+  chChanged = false;
+  dss = NULL;
+
+  vector<Pt2i>::const_iterator itr = rightPts.begin ();
+  vector<Pt2i>::const_iterator itl = leftPts.begin ();
+  bool scanningRight = true;
+  bool scanningLeft = true;
+  while (scanningRight || scanningLeft)
+  {
+    if (scanningRight)
+    {
+      if (itr == rightPts.end ())
+      {
+        scanningRight = false;
+        rightOK = true;
+      }
+      else plist->addBack (*itr++);
+    }
+    if (scanningLeft)
+    {
+      if (itl == leftPts.end ()) scanningLeft = false;
+      else
+      {
+        plist->addFront (*itl++);
+        leftOK = true;
+      }
+    }
+    if (! bsOK && plist->size () > 2)
+    {
+      if (! plist->backPoint().colinearTo (plist->frontPoint (),
+                                           plist->initialPoint ()))
+        bsOK = true;
+    }
+  }
+}
+
+
+BlurredSegmentProto::~BlurredSegmentProto ()
+{
+  if (convexhull != NULL) delete convexhull;
+}
+
+
+AbsRat BlurredSegmentProto::segmentRationalWidth () const
+{
+  return (convexhull != NULL ? convexhull->rationalThickness ()
+                             : AbsRat (0, 1));
+}
+
+
+DigitalStraightLine *BlurredSegmentProto::getLine () const
+{
+  if (bsOK)
+  {
+    Pt2i s, e, v;
+    convexhull->antipodalEdgeAndVertex (s, e, v);
+    return (new DigitalStraightLine (s, e, v));
+  }
+  if (bsFlat) return (new DigitalStraightLine (getLastLeft (), getLastRight (),
+                                               DigitalStraightLine::DSL_THIN));
+  return (NULL);
+}
+
+
+bool BlurredSegmentProto::addLeft (Pt2i pix)
+{
+  if (bsOK)     // convexhull defined
+  {
+    bool res = addPoint (pix, true);
+    return (res);
+  }
+
+  else if (bsFlat)    // leftOK && rightOK
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () != 0)
+    {
+      convexhull = new ConvexHull (pix, plist->frontPoint (),
+                                        plist->backPoint ());
+      bsOK = true;
+    }
+    plist->addFront (pix);
+  }
+
+  else if (leftOK)    // thus ! rightOK
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () == 0) bsFlat = true;
+    else
+    {
+      convexhull = new ConvexHull (pix, plist->frontPoint (),
+                                        plist->backPoint ());
+      bsOK = true;
+    }
+    plist->addFront (pix);
+  }
+
+  else if (rightOK)
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () == 0) bsFlat = true;
+    else
+    {
+      convexhull = new ConvexHull (pix, plist->frontPoint (),
+                                        plist->backPoint ());
+      bsOK = true;
+    }
+    plist->addFront (pix);
+  }
+
+  else   // only the central point is ok
+  {
+    plist->addFront (pix);
+    leftOK = true;
+  }
+
+  chChanged = true;
+  return true;
+}
+
+
+bool BlurredSegmentProto::addRight (Pt2i pix)
+{
+  if (bsOK)     // bs != NULL
+  {
+    bool res = addPoint (pix, false);
+    return (res);
+  }
+
+  else if (bsFlat)    // leftOK && rightOK
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () != 0)
+    {
+      convexhull = new ConvexHull (plist->frontPoint (),
+                                   plist->backPoint (), pix);
+      bsOK = true;
+    }
+    plist->addBack (pix);
+  }
+
+  else if (rightOK)    // thus ! leftOK
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () == 0) bsFlat = true;
+    else
+    {
+      convexhull = new ConvexHull (plist->frontPoint (),
+                                   plist->backPoint (), pix);
+      bsOK = true;
+    }
+    plist->addBack (pix);
+  }
+
+  else if (leftOK)
+  {
+    AbsRat height = plist->heightToEnds (pix);
+    if (height.greaterThan (maxWidth)) return false;
+    if (height.numerator () == 0) bsFlat = true;
+    else
+    {
+      convexhull = new ConvexHull (plist->frontPoint (),
+                                   plist->backPoint (), pix);
+      bsOK = true;
+    }
+    plist->addBack (pix);
+  }
+
+  else   // only the central point is ok
+  {
+    plist->addBack (pix);
+    rightOK = true;
+  }
+
+  chChanged = true;
+  return true;
+}
+
+
+bool BlurredSegmentProto::addPoint (Pt2i p, bool onleft)
+{
+  bool inserted = convexhull->addPointDS (p, onleft);
+  if ((segmentRationalWidth ()).greaterThan (maxWidth))
+  {
+    if (inserted) convexhull->restore ();
+    return false;
+  }
+ 
+  if (onleft) plist->addFront (p);
+  else plist->addBack (p);
+  chChanged = true;
+  return true;
+}
+
+
+void BlurredSegmentProto::removeLeft (int n)
+{
+  if (bsOK) plist->removeFront (n);
+}
+
+
+void BlurredSegmentProto::removeRight (int n)
+{
+  if (bsOK) plist->removeBack (n);
+}
+ 
+
+Vr2i BlurredSegmentProto::getSupportVector ()
+{
+  if (bsOK)
+  {
+    Pt2i s, e, v;
+    convexhull->antipodalEdgeAndVertex (s, e, v);
+    return (s.vectorTo (e));
+  }
+  if (bsFlat || leftOK || rightOK)
+    return (getLastLeft().vectorTo (getLastRight ()));
+  return (Vr2i (1, 0));    // hardly better with only one point !
+}
+
+
+BlurredSegment *BlurredSegmentProto::endOfBirth ()
+{
+  DigitalStraightSegment *seg = NULL;
+  if (bsOK)
+  {
+    int xmin, ymin, xmax, ymax;
+    plist->findExtrema (xmin, ymin, xmax, ymax);
+    Pt2i s, e, v;
+    convexhull->antipodalEdgeAndVertex (s, e, v);
+    seg = new DigitalStraightSegment (s, e, v, xmin, ymin, xmax, ymax);
+  }
+  else if (bsFlat || rightOK || leftOK)
+  {
+    Pt2i llast = plist->frontPoint ();
+    Pt2i rlast = plist->backPoint ();
+    int xmin = llast.x ();
+    if (rlast.x () < llast.x ()) xmin = rlast.x ();
+    int ymin = llast.y ();
+    if (rlast.y () < llast.y ()) ymin = rlast.y ();
+    int xmax = llast.x ();
+    if (rlast.x () > llast.x ()) xmax = rlast.x ();
+    int ymax = llast.y ();
+    if (rlast.y () > llast.y ()) ymax = rlast.y ();
+    seg = new DigitalStraightSegment (llast, rlast,
+                                      DigitalStraightLine::DSL_THIN,
+                                      xmin, ymin, xmax, ymax);
+  }
+  BlurredSegment *bbs = new BlurredSegment (plist, seg);
+  plist = NULL;  // NECESSARY TO AVOID CONTENTS CLEARANCE !!!
+  return (bbs);
+}
diff --git a/Code/Seg/BlurredSegment/blurredsegmentproto.h b/Code/Seg/BlurredSegment/blurredsegmentproto.h
new file mode 100755
index 0000000000000000000000000000000000000000..ba2b51da4632340040c54928a6dbe2b69e970237
--- /dev/null
+++ b/Code/Seg/BlurredSegment/blurredsegmentproto.h
@@ -0,0 +1,131 @@
+#ifndef BLURRED_SEGMENT_PROTO_H
+#define BLURRED_SEGMENT_PROTO_H
+
+
+#include "blurredsegment.h"
+
+using namespace std;
+
+
+/** 
+ * @class BlurredSegmentProto blurredsegmentproto.h
+ * \brief A prototype of blurred segment, untill complete specification.
+ * It is mostly based on a evolving list of points, its convex hull and
+ * the successive states of the blurred segment construction.
+ * \author {P. Even}
+ */
+class BlurredSegmentProto : public BlurredSegment
+{
+
+public:
+
+  /**
+   * Creates a blurred segment prototype.
+   * @param maxWidth Maximal width of the blurred segment to build
+   * @param pix Central point of the blurred segment to build
+   */
+  BlurredSegmentProto (int maxWidth, Pt2i pix);
+
+  /**
+   * Creates a blurred segment prototype with lists of points.
+   * @param maxWidth Maximal width of the blurred segment to build.
+   * @param center Central point of the blurred segment to build.
+   * @param leftPts Points to add on left side
+   * @param rightPts Points to add on right side.
+   */
+  BlurredSegmentProto (int maxWidth, Pt2i center,
+                  const vector<Pt2i> &leftPts, const vector<Pt2i> &rightPts);
+
+  /**
+   * \brief Deletes the blurred segment prototype.
+   */
+  ~BlurredSegmentProto ();
+
+  /**
+   * \brief Returns the minimal vertical or horizontal width.
+   */
+  AbsRat segmentRationalWidth () const;
+
+  /**
+   * \brief Returns the requested max width of the segment.
+   */
+  inline const AbsRat getMaxWidth () const { return maxWidth; }
+
+  /**
+   * \brief Sets the requested max width of the segment.
+   * @param maxwidth The new vaue for the requested max width.
+   */
+  inline void setMaxWidth (const AbsRat &val) { maxWidth.set (val); }
+
+  /**
+   * \brief Returns the underlying digital straight line.
+   */
+  DigitalStraightLine *getLine () const;
+
+  /**
+   * Adds a new point on the left.
+   * @param pix point to be added.
+   * Returns true if the point is accepted.
+   */
+  bool addLeft (Pt2i pix);
+
+  /**
+   * Adds a new point on the right.
+   * @param pix point to be added.
+   * Returns true if the point is accepted.
+   */
+  bool addRight (Pt2i pix);
+
+  /**
+   * \brief Remove last points on the left side.
+   * @param n Number of points to remove.
+   */
+  void removeLeft (int n);
+
+  /**
+   * \brief Remove last points on the right side.
+   * @param n Number of points to remove.
+   */
+  void removeRight (int n);
+
+  /**
+   * \brief Returns the support vector of the blurred segment.
+   */
+  Vr2i getSupportVector ();
+
+  /**
+   * \brief Returns a stable blurred segment from available information.
+   */
+  BlurredSegment *endOfBirth ();
+
+
+protected:
+
+  /** Maximal width of the blurred segment. */
+  AbsRat maxWidth;
+
+  /** Maintained convex hull of the blurred segment. */
+  ConvexHull *convexhull;
+
+  /** Indicates if the blurred segment is constructed. */
+  bool bsOK;
+  /** Indicates if the points are aligned. */
+  bool bsFlat;
+  /** Indicates if the left point is defined. */
+  bool leftOK;
+  /** Indicates if the right point is defined. */
+  bool rightOK;
+
+  /** Flag indicating if the convex hull changed since last DSS extraction. */
+  bool chChanged;
+
+
+  /**
+   * \brief Submits a new point to extend the blurred segment.
+   * @param p Submitted point.
+   * @param onleft Adding direction (true for LEFT, false for RIGHT).
+   */
+  bool addPoint (Pt2i p, bool onleft);
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/bsdetector.cpp b/Code/Seg/BlurredSegment/bsdetector.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..b52db0ef9ec62490c2d2e57f075117502c5519ec
--- /dev/null
+++ b/Code/Seg/BlurredSegment/bsdetector.cpp
@@ -0,0 +1,289 @@
+#include "bsdetector.h"
+
+
+
+const int BSDetector::RESULT_UNDETERMINED = -1;
+const int BSDetector::RESULT_OK = 0;
+const int BSDetector::RESULT_INITIAL_NO_DETECTION = 11;
+const int BSDetector::RESULT_INITIAL_TOO_FEW = 12;
+const int BSDetector::RESULT_INITIAL_TOO_SPARSE = 13;
+const int BSDetector::RESULT_INITIAL_TOO_MANY_OUTLIERS = 14;
+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::DEFAULT_BS_MIN_SIZE = 5;
+const int BSDetector::ABSOLUTE_BS_MIN_SIZE = 3;
+const int BSDetector::DEFAULT_CONNECT_MIN_SIZE = 5;
+const int BSDetector::DEFAULT_AUTO_RESOLUTION = 10;
+
+
+BSDetector::BSDetector ()
+{
+  gMap = NULL;
+
+  bst1 = new BSTracker ();
+  bst1->setPixelLackTolerence (bst1->proximityThreshold ());
+  bst2 = new BSTracker ();
+
+  prefilteringOn = true;
+  lsf1 = (prefilteringOn ? new LineSpaceFilter () : NULL);
+  filteringOn = false;
+  lsf2 = (filteringOn ? new LineSpaceFilter () : NULL);
+
+  edgeDirection = 0;   // detects line (not only edges)
+  bsMinSize = DEFAULT_BS_MIN_SIZE;
+  connectMinSize = DEFAULT_CONNECT_MIN_SIZE;
+  minScanLength = bst1->defaultMinScan ();
+  autowidth = true;
+  ccOn = true;
+  densityTestOn = true;
+  multiSelection = false;
+  autoResol = DEFAULT_AUTO_RESOLUTION;
+
+  bsini = NULL;
+  bsf = NULL;
+  tempo = true;
+  resultValue = RESULT_UNDETERMINED;
+}
+
+
+BSDetector::~BSDetector ()
+{
+  delete bst1;
+  delete bst2;
+  if (lsf1 != NULL) delete lsf1;
+  if (lsf2 != NULL) delete lsf2;
+}
+
+
+void BSDetector::setGradientMap (VMap *data)
+{
+  gMap = data;
+  bst1->setGradientMap (data);
+  bst2->setGradientMap (data);
+}
+
+
+void BSDetector::detectAll ()
+{
+  // Deletes former blurred segments
+  vector<BlurredSegment *>::iterator it = mbsf.begin ();
+  while (it != mbsf.end ()) delete (*it++);
+  mbsf.clear ();
+
+  gMap->setMasking (true);
+
+  int width = gMap->getWidth ();
+  int height = gMap->getHeight ();
+  for (int x = width / 2; x > 0; x -= autoResol)
+    runMultiDetection (Pt2i (x, 0), Pt2i (x, height - 1), Vr2i (0, 1));
+  for (int x = width / 2 + autoResol; x < width - 1; x += autoResol)
+    runMultiDetection (Pt2i (x, 0), Pt2i (x, height - 1), Vr2i (0, 1));
+  for (int y = height / 2; y > 0; y -= autoResol)
+    runMultiDetection (Pt2i (0, y), Pt2i (width - 1, y), Vr2i (1, 0));
+  for (int y = height / 2 + autoResol; y < height - 1; y += autoResol)
+    runMultiDetection (Pt2i (0, y), Pt2i (width - 1, y), Vr2i (1, 0));
+
+  gMap->clearMask ();
+  gMap->setMasking (false);
+}
+
+
+void BSDetector::multidetect (const Pt2i &p1, const Pt2i &p2)
+{
+  // Deletes former blurred segments
+  vector<BlurredSegment *>::iterator it = mbsf.begin ();
+  while (it != mbsf.end ()) delete (*it++);
+  mbsf.clear ();
+
+  gMap->setMasking (true);
+  runMultiDetection (p1, p2, p1.vectorTo (p2));
+  gMap->clearMask ();
+  gMap->setMasking (false);
+}
+
+
+void BSDetector::runMultiDetection (const Pt2i &p1, const Pt2i &p2,
+                                    const Vr2i &dir)
+{
+  vector<Pt2i> pts;
+  p1.draw (pts, p2);
+  int locmax[pts.size ()];
+  gMap->releaseOrientationConstraint ();
+  int nlm = gMap->localMax (locmax, pts, dir);
+  gMap->restoreOrientationConstraint ();
+  for (int i = 0; i < nlm; i++)
+  {
+    detect (p1, p2, &(pts.at (locmax[i])));
+    if (bsf != NULL)
+    {
+      gMap->setMask (bsf->getAllPoints ());
+      mbsf.push_back (bsf);
+      tempo = false; // to avoid former BS deletion
+    }
+  }
+}
+
+
+void BSDetector::detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0)
+{
+  // Clearance
+  //----------
+  resultValue = RESULT_UNDETERMINED;
+  bst1->clear ();
+  bst2->clear ();
+  if (prefilteringOn) lsf1->clear ();
+  if (filteringOn) lsf2->clear ();
+  if (bsini != NULL) delete bsini;
+  if (tempo && bsf != NULL) delete bsf;
+  bsf = NULL;
+  tempo = true;
+  if (p1.equals (p2)) return;
+
+  // Initial detection based on highest gradient without orientation constraint
+  //---------------------------------------------------------------------------
+  bsini = bst1->fastTrack (p1, p2, p0);
+  if (bsini == NULL || bsini->size () < bsMinSize)
+  {
+    resultValue = (bsini == NULL ? RESULT_INITIAL_NO_DETECTION
+                                 : RESULT_INITIAL_TOO_FEW);
+    return;
+  }
+
+  // Density test
+  //-------------
+  if (densityTestOn)
+  {
+    DigitalStraightLine mydsl (p1, p2, DigitalStraightLine::DSL_NAIVE);
+    int mydrlf = mydsl.manhattan (bsini->getLastRight ())
+                 - mydsl.manhattan (bsini->getLastLeft ());
+    if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2
+    int expansion = 1 + mydrlf;
+    if (bsini->size () < expansion / 2)
+    {
+      resultValue = RESULT_INITIAL_TOO_SPARSE;
+      return;
+    }
+  }
+
+  // Hough filtering on the initial segment
+  //---------------------------------------
+  if (prefilteringOn)
+  {
+    BlurredSegment *fbs = lsf1->filter (bsini);
+    if (fbs != NULL)
+    {
+      delete bsini;
+      bsini = fbs;
+    }
+  }
+  if (bsini->size () < bsMinSize)
+  {
+    resultValue = RESULT_INITIAL_TOO_MANY_OUTLIERS;
+    return;
+  }
+
+  // Finer detection based on gradient maxima with orientation constraint
+  //---------------------------------------------------------------------
+  Pt2i pCenter = bsini->getCenter ();
+  Vr2i gRef = gMap->getValue (pCenter.x (), pCenter.y ());
+  if (edgeDirection == -1) gRef.invert ();
+  int bswidth = bst1->inputMaxWidth ();
+  int scanwidth2 = 4 * bswidth;
+  if (autowidth)
+  {
+    bswidth = minScanLength;
+    DigitalStraightSegment *dss = bsini->getSegment ();
+    if (dss != NULL)
+    {
+      bswidth = (dss->width () / dss->period ());
+      if (bswidth < minScanLength) bswidth = minScanLength;
+    }
+    scanwidth2 = bswidth;
+    pCenter = bsini->getSegment()->centerOfIntersection (p1, p2);
+  }
+  bsf = bst2->fineTrack (pCenter, bsini->getSupportVector(),
+                         scanwidth2, bswidth, gRef);
+
+  if (bsf == NULL || bsf->size () < bsMinSize)
+  {
+    resultValue = (bsf == NULL ? RESULT_FINAL_NO_DETECTION
+                               : RESULT_FINAL_TOO_FEW);
+    return;
+  }
+
+  // Connected components analysis */
+  //------------------------------*/
+  if (ccOn)
+  {
+    int bsccp = bsf->countOfConnectedPoints (connectMinSize);
+    int bssize = bsf->getAllPoints().size ();
+    if (bsccp < bssize / 2)
+    {
+      resultValue = RESULT_FINAL_TOO_SPARSE;
+      delete bsf;
+      bsf = NULL;
+      return;
+    }
+  }
+
+  // Line space filtering
+  //---------------------
+  if (filteringOn)
+  {
+    BlurredSegment *fbsf = lsf2->filter (bsf);
+    if (fbsf != NULL)
+    {
+      resultValue = RESULT_FINAL_TOO_MANY_OUTLIERS;
+      delete bsf;
+      bsf = fbsf;
+    }
+  }
+
+  resultValue = RESULT_OK;
+}
+
+
+
+void BSDetector::switchOrthoScans ()
+{
+  bst1->switchOrthoScans ();
+  bst2->switchOrthoScans ();
+}
+
+
+vector<Pt2i> BSDetector::getRejected (int step) const
+{
+  vector<Pt2i> res;
+  if (step != 0)
+  {
+    if (filteringOn) res = lsf2->getAccepted ();
+  }
+  else if (prefilteringOn) res = lsf1->getAccepted ();
+  return res;
+}
+
+
+void BSDetector::switchFiltering (int step)
+{
+  if (step != 0)
+  {
+    filteringOn = ! filteringOn;
+    if (filteringOn && lsf2 == NULL) lsf2 = new LineSpaceFilter ();
+  }
+  else
+  {
+    prefilteringOn = ! prefilteringOn;
+    if (prefilteringOn && lsf1 == NULL) lsf1 = new LineSpaceFilter ();
+  }
+}
+
+
+bool BSDetector::incConnectedComponentMinSize (bool increase)
+{
+  if ((! increase) && connectMinSize <= 1) return false;
+  connectMinSize += (increase ? 1 : -1);
+  return true;
+}
diff --git a/Code/Seg/BlurredSegment/bsdetector.h b/Code/Seg/BlurredSegment/bsdetector.h
new file mode 100755
index 0000000000000000000000000000000000000000..f30bc183d9682c48b4dfa65c3c88c868473b41b7
--- /dev/null
+++ b/Code/Seg/BlurredSegment/bsdetector.h
@@ -0,0 +1,453 @@
+#ifndef BLURRED_SEGMENT_DETECTOR_H
+#define BLURRED_SEGMENT_DETECTOR_H
+
+#include "bstracker.h"
+#include "linespacefilter.h"
+
+using namespace std;
+
+
+/** 
+ * @class BSDetector bsdetector.h
+ * \brief Blurred segment detector in grey level images.
+ * \author {P. Even}
+ */
+class BSDetector
+{
+
+public:
+
+  /** Extraction result : successful extraction. */
+  static const int RESULT_UNDETERMINED;
+  /** Extraction result : successful extraction. */
+  static const int RESULT_OK;
+  /** Extraction result : no initial detection (bsini == NULL). */
+  static const int RESULT_INITIAL_NO_DETECTION;
+  /** Extraction result : too few points at initial detection. */
+  static const int RESULT_INITIAL_TOO_FEW;
+  /** Extraction result : unsuccessful density test at initial detection. */
+  static const int RESULT_INITIAL_TOO_SPARSE;
+  /** Extraction result : unsuccessful filter test at initial detection. */
+  static const int RESULT_INITIAL_TOO_MANY_OUTLIERS;
+  /** Extraction result : no final detection (bsf == NULL). */
+  static const int RESULT_FINAL_NO_DETECTION;
+  /** Extraction result : too few points at final detection. */
+  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 filter test at final detection. */
+  static const int RESULT_FINAL_TOO_MANY_OUTLIERS;
+
+  
+  /**
+   * \brief Creates a segment detector.
+   */
+  BSDetector ();
+
+  /**
+   * \brief Deletes the segment detector.
+   */
+  ~BSDetector ();
+
+  /**
+   * \brief Returns the minimal vertical or horizontal width.
+   */
+  inline int result () const { return resultValue; }
+
+  /**
+   * \brief Sets the gradient map.
+   */
+  void setGradientMap (VMap *data);
+
+  /**
+   * \brief Detects all blurred segments in the picture.
+   */
+  void detectAll ();
+
+  /**
+   * \brief Detects all blurred segments between two input points.
+   * @param p1 First input point.
+   * @param p2 Second input point.
+   */
+  void multidetect (const Pt2i &p1, const Pt2i &p2);
+
+  /**
+   * \brief Detects a blurred segment between two input points.
+   * Step 1: For each scan line, one candidate is selected
+   *         based on the gradient norm only (no direction test).
+   * Step 2: Outliers pruning based on parameter space pre-filtering.
+   * Step 3: For each scan line, local candidates are detected
+   *         on top of gradient ridges with closest direction.
+   *         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.
+   * @param p1 First input point.
+   * @param p2 Second input point.
+   * @param p0 Initial segment start point (if different from NULL).
+   */
+  void detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0 = NULL);
+
+  /**
+   * \brief Returns the last detected blurred segment at given step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline BlurredSegment *getBlurredSegment (int step) {
+    return (step == 0 ? bsini : bsf); }
+
+  /**
+   * \brief Returns the list of detected blurred segments.
+   */
+  inline vector<BlurredSegment *> getBlurredSegments () { return (mbsf); }
+
+  /**
+   * \brief Avoids the deletion of the last extracted blurred segent.
+   */
+  inline void preserveFormerBlurredSegment () { tempo = false; }
+
+  /**
+   * \brief Returns the input maximal width of the initial segment.
+   */
+  inline int getInputMaxWidth () const { return bst1->inputMaxWidth (); }
+
+  /**
+   * \brief Sets the maximal width of the initial segment.
+   */
+  inline void setInputMaxWidth (int value) {
+    bst1->setInputMaxWidth (value); }
+
+  /**
+   * \brief Returns the output blurred segment minimal size.
+   */
+  inline int getBSminSize () const { return bsMinSize; }
+
+  /**
+   * \brief Sets the output blurred segment minimal size.
+   */
+  inline void setBSminSize (int value) {
+    if (value >= ABSOLUTE_BS_MIN_SIZE) bsMinSize = value; }
+
+  /**
+   * \brief Returns the automatic detection grid resolution.
+   */
+  inline int getAutoGridResolution () const { return autoResol; }
+
+  /**
+   * \brief Sets the automatic detection grid resolution.
+   */
+  inline void setAutoGridResolution (int number) {
+    if (number > 0 && number < gMap->getWidth () / 8) autoResol = number; }
+
+  /**
+   * \brief Returns the pixel lack tolerence.
+   */
+  inline int getPixelLackTolerence () const {
+    return bst2->pixelLackTolerence (); }
+
+  /**
+   * \brief Sets the pixel lack tolerence.
+   */
+  inline void setPixelLackTolerence (int number) {
+    bst2->setPixelLackTolerence (number); }
+
+  /**
+   * \brief Returns the count of accepted points to release a failure.
+   */
+  inline int getRestartOnLack () { return bst2->getRestartOnLack (); }
+
+  /**
+   * \brief Switches on or off the automatic restart after failure.
+   */
+  inline void switchAutoRestart () { bst2->switchAutoRestart (); }
+
+  /**
+   * \brief Returns the edge direction constraint status.
+   *    +1 : Edge direction constrained to the initial direction.
+   *    -1 : Edge direction constrained to the initial direction opposite.
+   *     0 : Edge constraint free (detects lines as well as edges).
+   */
+  inline int edgeDirectionConstraint ()
+  {
+    return (edgeDirection);
+  }
+
+  /**
+   * \brief Inverts the edge direction for detection stage.
+   */
+  inline void invertEdgeDirection ()
+  {
+    edgeDirection = - edgeDirection;
+  }
+
+  /**
+   * \brief Switches the edge direction constraint.
+   */
+  inline void switchEdgeDirectionConstraint ()
+  {
+    edgeDirection = (edgeDirection == 0 ? 1 : 0);
+    gMap->switchOrientationConstraint ();
+  }
+
+  /**
+   * \brief Returns true if the automatic width selection is set.
+   */
+  inline bool autoWidthOn () { return autowidth; }
+
+  /**
+   * \brief Switches on or off the automatic width selection.
+   */
+  inline void switchAutoWidth () { autowidth = ! autowidth; }
+
+  /**
+   * \brief Returns true if the multi-selection modality is set.
+   */
+  inline bool isMultiSelection () { return multiSelection; }
+
+  /**
+   * \brief Switches on or off the multi-selection modality.
+   */
+  inline void switchMultiSelection () { multiSelection = ! multiSelection; }
+
+  /**
+   * \brief Returns the upper bound of the final scan of the given step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline vector<Pt2i> getScanBound1 (int step) const {
+    return (step != 0 ? bst2->getScanBound1 () : bst1->getScanBound1 ()); }
+
+  /**
+   * \brief Returns the lower bound of the final scan of the given step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline vector<Pt2i> getScanBound2 (int step) const {
+    return (step != 0 ? bst2->getScanBound2 () : bst1->getScanBound2 ()); }
+
+  /**
+   * \brief Returns the scan lines of the given step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline vector <vector <Pt2i> > getScans (int step) const {
+    return (step != 0 ? bst2->getScans () : bst1->getScans ()); }
+
+  /**
+   * \brief Returns whether the scan record modality is set for the given step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline bool scanRecordOn (int step) {
+    return (step != 0 ? bst2->scanRecordOn () : bst1->scanRecordOn ()); }
+
+  /**
+   * \brief Sets the scan record modality of initial or final step.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   * @param status Sets on if true, off otherwise.
+   */
+  inline void setScanRecord (int step, bool status) {
+    if (step != 0) bst2->setScanRecord (status);
+    else bst1->setScanRecord (status); }
+
+  /**
+   * \brief Toggles the initial step bounding.
+   */
+  inline void switchInitialBounding () { bst1->switchScanExtent (); }
+
+  /**
+   * \brief Returns the maximal scan extent of the initial detection.
+   */
+  inline int initialDetectionMaxExtent () { return (bst1->maxScanExtent ()); }
+
+  /**
+   * \brief Returns if the dynamic scans modality is set.
+   */
+  inline bool dynamicScansOn () { return bst2->dynamicScansOn (); }
+
+  /**
+   * \brief Switches on or off the dynamic scans modality.
+   */
+  inline void switchDynamicScans () { bst2->toggleDynamicScans (); }
+
+  /**
+   * \brief Sets the dynamic scans modality on or off.
+   */
+  inline void setDynamicScans (bool onOff) { bst2->setDynamicScans (onOff); }
+
+  /**
+   * \brief Returns if the orthographic scans modality set.
+   */
+  inline bool orthoScansOn () { return bst1->orthoScansOn (); }
+
+  /**
+   * \brief Switches on or off the orthogonal scans modality.
+   */
+  void switchOrthoScans ();
+
+  /**
+   * \brief Returns if the thinning is activated.
+   */
+  inline bool isThinningActivated () { return bst2->isThinningActivated (); }
+
+  /**
+   * \brief Toggles the thinning strategy.
+   */
+  inline void toggleThinning () { bst2->toggleThinning (); }
+
+  /**
+   * \brief Returns if one of the filter is activated.
+   */
+  inline bool isOneFilterSet () { return (filteringOn || prefilteringOn); }
+
+  /**
+   * \brief Returns the line space based filter.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline LineSpaceFilter *getFilter (int step) const {
+    return (step != 0 ? lsf2 : lsf1); }
+
+  /**
+   * \brief Returns the accepted points by the line space based filter.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline vector<Pt2i> getAccepted (int step) const {
+    return (step != 0 ?
+      (filteringOn ? lsf2->getAccepted () : bsf->getAllPoints ()) :
+      (prefilteringOn ? lsf1->getAccepted () : bsini->getAllPoints ())); }
+
+  /**
+   * \brief Returns the rejected points by the line space based filter.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  vector<Pt2i> getRejected (int step) const;
+
+  /**
+   * \brief Returns if the given line space based filter is activated.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  inline bool isFiltering (int step) const {
+    return (step != 0 ? filteringOn : prefilteringOn); }
+
+  /**
+   * \brief Toggles the use of the given line space based filter.
+   * @param step Initial step addressed if set to 0, final step otherwise.
+   */
+  void switchFiltering (int step);
+
+  /**
+   * \brief Returns the blurred segment size before pre-filtering.
+   */
+  inline int prefilteringInputSize () {
+    return (prefilteringOn ? lsf1->blurredSegmentInitialSize () : 0); }
+
+  /**
+   * \brief Returns the blurred segment size after pre-filtering.
+   */
+  inline int prefilteringOutputSize () {
+    return (prefilteringOn ? lsf1->blurredSegmentFinalSize () : 0); }
+
+  /**
+   * \brief Returns whether the density test at initial step is set.
+   */
+  inline bool isSetDensityTest () { return (densityTestOn); }
+
+  /**
+   * \brief Switches on or off the density test modality.
+   */
+  inline void switchDensityTest () { densityTestOn = ! densityTestOn; }
+
+  /**
+   * \brief Switches on or off the connectivity constraint.
+   */
+  inline void switchConnectivityConstraint () { ccOn = ! ccOn; }
+
+  /**
+   * \brief Returns the connectivity constraint status.
+   */
+  inline bool isSetConnectivityConstraint () { return (ccOn); }
+
+  /**
+   * \brief Returns the minimal size of the segment connected components.
+   */
+  inline int connectedComponentMinSize () { return connectMinSize; }
+
+  /**
+   * \brief Increments the minimal size of the connected components.
+   * @param increase Positive increment if true, negative otherwise.
+   */
+  bool incConnectedComponentMinSize (bool increase);
+
+
+private :
+
+  /** Default value for the minimal size of the detected blurred segment. */
+  static const int DEFAULT_BS_MIN_SIZE;
+  /** Absolute value for the minimal size of the detected blurred segment. */
+  static const int ABSOLUTE_BS_MIN_SIZE;
+  /** Default value for the minimal size of connected components. */
+  static const int DEFAULT_CONNECT_MIN_SIZE;
+  /** Default value for the automatic detection grid resolution. */
+  static const int DEFAULT_AUTO_RESOLUTION;
+
+
+  /** Direction constraint of the detected edge :
+   *    +1 : complies to initial direction
+   *    -1 : complies to initial direction opposite
+   *     0 : no direction condition (detects lines as well as edges)
+   */
+  int edgeDirection;
+  /** Minimal length of scan lines. */
+  int minScanLength;
+  /** Connectivity constraint status. */
+  bool ccOn;
+  /** Minimal size of the detected blurred segment. */
+  int bsMinSize;
+  /** Minimal size of the connected components to validate a blurred segment. */
+  int connectMinSize;
+  /** Automatic width selection (based on previous detection). */
+  bool autowidth;
+  /** Density test modality after initial detection. */
+  bool densityTestOn;
+  /** Segment multi-selection modality status. */
+  bool multiSelection;
+  /** Grid resolution for the automatic extraction. */
+  int autoResol;
+
+
+  /** Gradient map. */
+  VMap *gMap;
+
+  /** Initially detected blurred segment (initial step result). */
+  BlurredSegment *bsini;
+  /** Initial rough tracker */
+  BSTracker *bst1;
+  /** Flag indicating whether the blurred segment is not registred. */
+  bool tempo;
+
+  /** Fine tracker */
+  BSTracker *bst2;
+  /** Detected blurred segment (final result). */
+  BlurredSegment *bsf;
+  /** Detected blurred segments (in case of multi-detection). */
+  vector<BlurredSegment *> mbsf;
+
+  /** Initial segment filtering modality. */
+  bool prefilteringOn;
+  /** Line space based pre-filter. */
+  LineSpaceFilter *lsf1;
+
+  /** Detected segment filtering modality. */
+  bool filteringOn;
+  /** Line space based post-filter. */
+  LineSpaceFilter *lsf2;
+
+  /** Result of the blurred segment extraction */
+  int resultValue;
+
+
+  /**
+   * \brief Detects all blurred segments between two input points.
+   * @param p1 First input point.
+   * @param p2 Second input point.
+   * @param dir Direction of the selection (factored P1P2).
+   */
+  void runMultiDetection (const Pt2i &p1, const Pt2i &p2,
+                          const Vr2i &dir);
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/bstracker.cpp b/Code/Seg/BlurredSegment/bstracker.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..e1c5991b4d2b9322a3541680d202c21b070e4a18
--- /dev/null
+++ b/Code/Seg/BlurredSegment/bstracker.cpp
@@ -0,0 +1,412 @@
+#include "bstracker.h"
+#include "blurredsegmentproto.h"
+
+
+
+const int BSTracker::DEFAULT_MAX_WIDTH = 5;
+const int BSTracker::DEFAULT_ACCEPTED_LACKS = 5;
+const int BSTracker::DEFAULT_PROXIMITY_THRESHOLD = 4;
+const int BSTracker::MIN_SCAN = 8;
+const int BSTracker::DEFAULT_MAX_SCAN = 32;
+const int BSTracker::DEFAULT_FITTING_DELAY = 20;
+
+const int BSTracker::DEFAULT_THINNING_DELAY = 20;
+const int BSTracker::DEFAULT_THINNING_SPEED = 2;
+const int BSTracker::DEFAULT_THINNING_REACH = 50;
+const int BSTracker::DEFAULT_THINNING_RESOLUTION = 1000;
+
+const int BSTracker::FAILURE_NO_START = 1;
+const int BSTracker::FAILURE_IMAGE_BOUND_ON_RIGHT = 2;
+const int BSTracker::FAILURE_IMAGE_BOUND_ON_LEFT = 4;
+const int BSTracker::FAILURE_LOST_ORIENTATION = 32;
+
+
+
+BSTracker::BSTracker ()
+{
+  proxThreshold = DEFAULT_PROXIMITY_THRESHOLD;
+  maxWidth = DEFAULT_MAX_WIDTH;
+  acceptedLacks = DEFAULT_ACCEPTED_LACKS;
+  minRestart = acceptedLacks;
+
+  dynamicScans = true;
+  fittingDelay = DEFAULT_FITTING_DELAY;
+  recordScans = false;
+  orthoScan = false;
+
+  thinningOn = true;
+  thinningDelay = DEFAULT_THINNING_DELAY;
+  thinningSpeed.set (DEFAULT_THINNING_SPEED, 100);
+  thinningReach.set (100 + DEFAULT_THINNING_REACH, 100);
+  gMap = NULL;
+
+  maxScan = DEFAULT_MAX_SCAN;
+
+  fail = 0;
+
+  cand = new int[1]; // to avoid systematic tests
+  lscan = 0;
+  rscan = 0;
+}
+
+
+BSTracker::~BSTracker ()
+{
+  delete cand;
+}
+
+
+void BSTracker::clear ()
+{
+  scanBound1.clear ();
+  scanBound2.clear ();
+  scanLine.clear ();
+}
+
+
+void BSTracker::setGradientMap (VMap *data)
+{
+  gMap = data;
+  delete cand;
+  cand = new int[data->getHeightWidthMax ()];
+}
+
+
+BlurredSegment *BSTracker::fastTrack (const Pt2i &p1, const Pt2i &p2,
+                                      Pt2i *p0)
+{
+  // Creates the scanner
+  DirectionalScanner *ds = NULL;
+  if (p0 != NULL)
+    ds = scanp.getScanner (*p0, p1.vectorTo (p2), 4 * maxWidth, false,
+                           0, 0, gMap->getWidth (), gMap->getHeight ());
+  else ds = scanp.getScanner (p1, p2,
+                              0, 0, gMap->getWidth (), gMap->getHeight ());
+  if (ds == NULL) return NULL;
+
+  // Builds a BS builder around a central point
+  vector<Pt2i> pix;
+  if (ds->first (pix) < MIN_SCAN)
+  {
+    delete ds;
+    return NULL;
+  }
+
+  if (recordScans)
+  {
+    scanBound1.push_back (pix.front ());
+    scanBound2.push_back (pix.back ());
+    scanLine.push_back (pix);
+  }
+  int candide;
+  Pt2i pfirst;
+  if (p0 != NULL) pfirst.set (p0->x (), p0->y ());
+  else
+  {
+    candide = gMap->largestIn (pix);
+    if (candide == -1)
+    {
+      delete ds;
+      return NULL;
+    }
+    pfirst.set (pix.at (candide));
+  }
+
+  BlurredSegmentProto bs (maxWidth, pfirst);
+  Pt2i lastLeft (pfirst);
+  Pt2i lastRight (pfirst);
+  
+  // Extends the segment
+  int lstop = 0;
+  int rstop = 0;
+  int lstart = 0;
+  int rstart = 0;
+  bool added = false;
+  bool scanningRight = true;
+  bool scanningLeft = true;
+  int fsCount = maxScan;
+
+  while ((scanningRight || scanningLeft) && (fsCount--))
+  {
+    // Extends on right
+    if (scanningRight)
+    {
+      if (ds->nextOnRight (pix) < MIN_SCAN) scanningRight = false;
+      else
+      {
+        if (recordScans)
+        {
+          scanBound1.push_back (pix.front ());
+          scanBound2.push_back (pix.back ());
+          scanLine.push_back (pix);
+        }
+        added = false;
+        candide = gMap->largestIn (pix);
+        if (candide != -1)
+        {
+          if (lastRight.manhattan (pix.at (candide)) <= proxThreshold)
+            added = bs.addRight (pix.at (candide));
+        }
+        if (added)
+        {
+          lastRight = pix.at (candide);
+          if (rstop != 0) rstop = 0;
+        }
+        else if (++rstop > acceptedLacks)
+          scanningRight = false;
+      }
+    }
+    // Extends on left
+    if (scanningLeft)
+    {
+      if (ds->nextOnLeft (pix) < MIN_SCAN) scanningLeft = false;
+      else
+      {
+        if (recordScans)
+        {
+          scanBound1.push_back (pix.front ());
+          scanBound2.push_back (pix.back ());
+          scanLine.push_back (pix);
+        }
+        added = false;
+        candide = gMap->largestIn (pix);
+        if (candide != -1)
+        {
+          if (lastLeft.manhattan (pix.at (candide)) < proxThreshold)
+            added = bs.addLeft (pix.at (candide));
+        }
+        if (added)
+        {
+          lastLeft = pix.at (candide);
+          if (lstop != 0) lstop = 0;
+        }
+        else if (++lstop > acceptedLacks)
+          scanningLeft = false;
+      }
+    }
+  }
+  if (rstart) bs.removeRight (rstart);
+  if (lstart) bs.removeLeft (lstart);
+  delete ds;
+  return (bs.endOfBirth ());
+}
+
+
+
+BlurredSegment *BSTracker::fineTrack (const Pt2i &center, const Vr2i &scandir,
+                                      int scanwidth2, int bswidth,
+                                      const Vr2i &gref)
+{
+  // Gets detected segment normal vector
+  Vr2i normal = scandir.orthog ();
+  if (! normal.orientedAs (gref)) normal.invert ();
+
+  fail = 0;
+
+  // Creation of the directional scanner and the array of candidates
+  DirectionalScanner *ds = scanp.getScanner (
+                 center, normal, scanwidth2, dynamicScans,
+                 0, 0, gMap->getWidth (), gMap->getHeight ());
+  if (ds == NULL)
+  {
+    fail = FAILURE_NO_START;
+    return NULL;
+  }
+
+  // Looking for a central point
+  vector<Pt2i> pix;
+  if (ds->first (pix) < MIN_SCAN)
+  {
+    delete ds;
+    fail = FAILURE_NO_START;
+    return NULL;
+  }
+  if (recordScans)
+  {
+    scanBound1.push_back (pix.front ());
+    scanBound2.push_back (pix.back ());
+    scanLine.push_back (pix);
+  }
+  int nbc = gMap->localMax (cand, pix, normal);
+  if (nbc == 0)
+  {
+    delete ds;
+    fail = FAILURE_NO_START;
+    return NULL;
+  }
+
+  BlurredSegmentProto bs (bswidth, pix[cand[0]]);
+
+  // Handles thinning
+  int count = 0;
+  AbsRat maxw (bswidth * DEFAULT_THINNING_RESOLUTION,
+               DEFAULT_THINNING_RESOLUTION);
+
+  // Extends the segment
+  lscan = 0;
+  rscan = 0;
+  int lstop = 0;
+  int rstop = 0;
+  int lstart = 0;
+  int rstart = 0;
+  bool added = false;
+  bool scanningRight = true;
+  bool scanningLeft = true;
+  bool thon = thinningOn;
+
+  while (scanningRight || scanningLeft)
+  {
+    count ++;
+
+    // Handles thinning
+    if (thon)
+    {
+      if (count > thinningDelay)
+      {
+        AbsRat sw = bs.segmentRationalWidth ();
+        AbsRat oldmaxw (maxw);
+        maxw.attractsTo (sw, thinningSpeed);
+        sw.mult (thinningReach);
+        if (maxw.lessThan (sw))
+        {
+          maxw.sticksTo (sw);
+          if (oldmaxw.lessThan (maxw)) maxw.set (oldmaxw);
+          thon = false;  // thinning deactivation
+        }
+        bs.setMaxWidth (maxw);
+      }
+    }
+
+    // Resets the scan stripe
+    if (dynamicScans && count > fittingDelay && bs.getLine () != NULL)
+    {
+      // Stops the detection if the segment gets crosswise
+      if (count == fittingDelay + 1)
+      {
+        Vr2i dirn = bs.getSupportVector ();
+        if (4 * dirn.squaredScalarProduct (scandir)
+            < dirn.norm2 () * scandir.norm2 ())
+        {
+          scanningLeft = false;
+          scanningRight = false;
+          fail += FAILURE_LOST_ORIENTATION;
+        }
+      }
+      int ppa, ppb, ppc;
+      bs.getLine()->getMedialAxis (ppa, ppb, ppc);
+      ds->bindTo (ppa, ppb, ppc);
+    }
+
+    // Extends on right
+    if (scanningRight)
+    {
+      added = false;
+      if (ds->nextOnRight (pix) < MIN_SCAN)
+      {
+        fail += FAILURE_IMAGE_BOUND_ON_RIGHT;
+        scanningRight = false;
+      }
+      else
+      {
+        if (recordScans)
+        {
+          scanBound1.push_back (pix.front ());
+          scanBound2.push_back (pix.back ());
+          scanLine.push_back (pix);
+        }
+        added = false;
+        nbc = gMap->localMax (cand, pix, normal);
+        for (int i = 0; ! added && i < nbc; i++)
+          added = bs.addRight (pix[cand[i]]);
+        if (added)
+        {
+          rscan = count;
+          if (rstop == 0) rstart = 0;
+          else
+          {
+            rstart ++;
+            //if (rstart >= minRestart || rstart >= rstop)
+            if (rstart >= rstop)
+            {
+              rstop = 0;
+              rstart = 0;
+            }
+          }
+        }
+        else
+        {
+          if (++rstop - rstart > acceptedLacks)
+          {
+            if (bs.size () <= 3) fail = FAILURE_NO_START;
+            scanningRight = false;
+          }
+        }
+      }
+    }
+
+    // Extends on left
+    if (scanningLeft)
+    {
+      if (ds->nextOnLeft (pix) < MIN_SCAN)
+      {
+        fail += FAILURE_IMAGE_BOUND_ON_LEFT;
+        scanningLeft = false;
+      }
+      else
+      {
+        if (recordScans)
+        {
+          scanBound1.push_back (pix.front ());
+          scanBound2.push_back (pix.back ());
+          scanLine.push_back (pix);
+        }
+        added = false;
+        nbc = gMap->localMax (cand, pix, normal);
+        for (int i = 0; ! added && i < nbc; i++)
+          added = bs.addLeft (pix[cand[i]]);
+        if (added)
+        {
+          lscan = count;
+          if (lstop == 0) lstart = 0;
+          else
+          {
+            lstart ++;
+            //if (lstart >= minRestart || lstart >= lstop)
+            if (lstart >= lstop)
+            {
+              lstop = 0;
+              lstart = 0;
+            }
+          }
+        }
+        else
+        {
+          if (++lstop - lstart > acceptedLacks)
+          {
+            if (bs.size () <= 3) fail = FAILURE_NO_START;
+            scanningLeft = false;
+          }
+        }
+      }
+    }
+  }
+  if (rstart) bs.removeRight (rstart);
+  if (lstart) bs.removeLeft (lstart);
+  delete ds;
+  return (bs.endOfBirth ());
+}
+
+
+void BSTracker::switchOrthoScans ()
+{
+  orthoScan = ! orthoScan;
+  scanp.setOrtho (orthoScan);
+  cout << "OrthoScan is " << (orthoScan ? "on" : "off") << endl;
+}
+
+
+void BSTracker::switchScanExtent ()
+{
+  maxScan = (maxScan == gMap->getHeightWidthMax () ?
+             DEFAULT_MAX_SCAN : gMap->getHeightWidthMax ());
+}
diff --git a/Code/Seg/BlurredSegment/bstracker.h b/Code/Seg/BlurredSegment/bstracker.h
new file mode 100755
index 0000000000000000000000000000000000000000..9d1aeded1ab8688b276bcd1b8c169c3442432231
--- /dev/null
+++ b/Code/Seg/BlurredSegment/bstracker.h
@@ -0,0 +1,282 @@
+#ifndef BLURRED_SEGMENT_TRACKER_H
+#define BLURRED_SEGMENT_TRACKER_H
+
+#include <vector>
+#include "scannerprovider.h"
+#include "blurredsegment.h"
+#include "vmap.h"
+
+using namespace std;
+
+
+/** 
+ * @class BSTracker bstracker.h
+ * \brief Blurred segment tracker in grey level images.
+ * \author {P. Even and B. Kerautret}
+ */
+class BSTracker
+{
+
+public:
+  
+  /**
+   * \brief Creates a blurred segment tracker.
+   */
+  BSTracker ();
+
+  /**
+   * \brief Deletes the blurred segment tracker.
+   */
+  ~BSTracker ();
+
+  /**
+   * \brief Clears off stored information.
+   */
+  void clear ();
+
+  /**
+   * \brief Builds and returns a blurred segment from only gradient maximum.
+   * @param p1 Initial stroke start point.
+   * @param p2 Initial stroke end point.
+   * @param p0 Initial segment start point (if different from NULL).
+   */
+  BlurredSegment *fastTrack (const Pt2i &p1, const Pt2i &p2,
+                             Pt2i *p0 = NULL);
+
+  /**
+   * \brief Builds and returns a blurred segment from local gradient maxima.
+   * Finer detection using gradient ridges and direction input.
+   * @param center Central point of the scan.
+   * @param scandir Scan direction
+   * @param scanwidth2 Half width of the scan strip.
+   * @param bswidth Initial maximal width of the blurred segment to build.
+   * @param gref Gradient vector reference to select candidates.
+   */
+  BlurredSegment *fineTrack (const Pt2i &center, const Vr2i &scandir,
+                             int scanwidth2, int bswidth,
+                             const Vr2i &gref);
+
+  /**
+   * \brief Returns the input maximal width of the blurred segment.
+   */
+  inline int inputMaxWidth () const { return maxWidth; }
+
+  /**
+   * \brief Sets the input maximal width of the blurred segment.
+   */
+  inline void setInputMaxWidth (int value) {
+    if (value > 0) maxWidth = value; }
+
+  /**
+   * \brief Returns the default minimal length of scan lines.
+   */
+  inline int defaultMinScan () const { return MIN_SCAN; }
+
+  /**
+   * \brief Returns the pixel lack tolerence for exdending the blurred segment..
+   */
+  inline int pixelLackTolerence () const { return acceptedLacks; }
+
+  /**
+   * \brief Sets the pixel lack tolerence for extending the blurred segment.
+   */
+  inline void setPixelLackTolerence (int number)
+  {
+    if (number >= 0)
+    {
+      acceptedLacks = number;
+      if (minRestart != 1) minRestart = number;
+    }
+  }
+
+  /**
+   * \brief Returns the count of accepted points to release a failure.
+   */
+  inline int getRestartOnLack () { return minRestart; }
+
+  /**
+   * \brief Switches on or off the automatic restart after failure.
+   */
+  inline void switchAutoRestart ()
+  {
+    minRestart = (minRestart == 1 ? acceptedLacks : 1);
+  }
+
+  /**
+   * \brief Sets the image data.
+   */
+  void setGradientMap (VMap *data);
+
+  /**
+   * \brief Returns the proximity threshold.
+   */
+  inline int proximityThreshold () { return proxThreshold; }
+
+  /**
+   * \brief Returns if the dynamic scans are used.
+   */
+  inline bool dynamicScansOn () { return dynamicScans; }
+
+  /**
+   * \brief Returns the upper bound of the final scan.
+   */
+  inline vector<Pt2i> getScanBound1 () const { return scanBound1; }
+
+  /**
+   * \brief Returns the lower bound of the final scan.
+   */
+  inline vector<Pt2i> getScanBound2 () const { return scanBound2; }
+
+  /**
+   * \brief Returns the scan lines.
+   */
+  inline vector <vector <Pt2i> > getScans () const { return scanLine; }
+
+  /**
+   * \brief Returns whether the scan record modality is set.
+   */
+  inline bool scanRecordOn () { return recordScans; }
+
+  /**
+   * \brief Sets the scan record modality.
+   * @param status Sets on if true, off otherwise.
+   */
+  inline void setScanRecord (bool status) { recordScans = status; }
+
+  /**
+   * \brief Toggles the dynamic scans use.
+   */
+  inline void toggleDynamicScans () { dynamicScans = ! dynamicScans; }
+
+  /**
+   * \brief Switches the scan extent limitation..
+   */
+  void switchScanExtent ();
+
+  /**
+   * \brief Returns the scan extent limit.
+   */
+  inline int maxScanExtent () { return (maxScan); }
+
+  /**
+   * \brief Sets the dynamic scans on or off.
+   */
+  inline void setDynamicScans (bool onOff) { dynamicScans = onOff; }
+
+  /**
+   * \brief Returns if the thinning is activated.
+   */
+  inline bool isThinningActivated () { return thinningOn; }
+
+  /**
+   * \brief Toggles the thinning strategy.
+   */
+  inline void toggleThinning () { thinningOn = ! thinningOn; }
+
+  /**
+   * \brief Switches on or off the orthogonal scanning modality.
+   */
+  void switchOrthoScans ();
+
+  /**
+   * \brief Switches on or off the orthogonal scanning modality.
+   */
+  inline bool orthoScansOn () { return orthoScan; }
+
+
+private :
+
+  // Segment detection default parameters.
+  /** Default value for the initial max segment width. */
+  static const int DEFAULT_MAX_WIDTH;
+  /** Default value forr the accepted number of successive lacks. */
+  static const int DEFAULT_ACCEPTED_LACKS;
+  /** Default value for the proximity threshold used for fast tracking. */
+  static const int DEFAULT_PROXIMITY_THRESHOLD;
+  /** Minimal length of scan length to be processed. */
+  static const int MIN_SCAN;
+  /** Default value for the maximal number of scans processed on each side. */
+  static const int DEFAULT_MAX_SCAN;
+
+  // Dynamical scan default parameters.
+  /* Count of points before activating the fitting on the detected segment. */
+  static const int DEFAULT_FITTING_DELAY;
+
+  // Width thinning default parameters.
+  /* Count of points before activating the width thinning. */
+  static const int DEFAULT_THINNING_DELAY;
+  /** Value which controls the width thinning speed.
+   * It is the percentage of width offset withdrawn from the width tolerence.
+   * Width offset = width tolerence - blurred segment width. */
+  static const int DEFAULT_THINNING_SPEED;
+  /** Minimal value of the percentage of width offset wrt segment width. */
+  static const int DEFAULT_THINNING_REACH;
+  /** Resolution of the max segment width when thinning. */
+  static const int DEFAULT_THINNING_RESOLUTION;
+
+  /** Segment stop information : no start point found. */
+  static const int FAILURE_NO_START;
+  /** Segment stop information : image bound reached on the right. */
+  static const int FAILURE_IMAGE_BOUND_ON_RIGHT;
+  /** Segment stop information : image bound reached on the left. */
+  static const int FAILURE_IMAGE_BOUND_ON_LEFT;
+  /** Segment stop information : lost orientation at dynamical reset start. */
+  static const int FAILURE_LOST_ORIENTATION;
+
+
+  /** Blurred segment max half-width. */
+  int maxWidth;
+  /** Number of awaited points after each failure. */
+  int minRestart;
+  /** Accepted number of successive lacks (wrt restart points). */
+  int acceptedLacks;
+  /** Proximity threshold used for fast tracking. */
+  int proxThreshold;
+
+  /** Orthogonal scanning modality status */
+  bool orthoScan;
+  /** Kind of scans used : dynamic if true. */
+  bool dynamicScans;
+  /** Minimal detection width before activating the dynamical scans. */
+  int fittingDelay;
+
+  /** Segment thinning strategy. */
+  bool thinningOn;
+  /** Width thinning delay. */
+  int thinningDelay;
+  /** Width thinning speed : amount of thinning offset withdrawn. */
+  AbsRat thinningSpeed;
+  /** Minimal control width wrt detected segment width when thinning. */
+  AbsRat thinningReach;
+
+  /** Gradient map. */
+  VMap *gMap;
+
+  /** Maximum number of scans. */
+  int maxScan;
+
+  /** Failure cause. */
+  int fail;
+
+  /** Candidates array for internal use. */
+  int *cand;
+  /** Index of the last successful scan on right side. */
+  int rscan;
+  /** Index of the last successful scan on left side. */
+  int lscan;
+
+
+  /** Directional scanner provider.
+   * Automatically selects the appropriate octant. */
+  ScannerProvider scanp;
+  /** Upper bound of the scan. */
+  vector<Pt2i> scanBound1;
+  /** Lower bound of the scan. */
+  vector<Pt2i> scanBound2;
+  /** Scan lines. */
+  vector <vector <Pt2i> > scanLine;
+  /** Dynamical scanner record modality. */
+  bool recordScans;
+
+};
+#endif
diff --git a/Code/Seg/BlurredSegment/linespacefilter.cpp b/Code/Seg/BlurredSegment/linespacefilter.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2745c38396846d385cb1c615955e050a0e9450a8
--- /dev/null
+++ b/Code/Seg/BlurredSegment/linespacefilter.cpp
@@ -0,0 +1,688 @@
+#include <cmath>
+#include "linespacefilter.h"
+#include "blurredsegmentproto.h"
+
+
+
+const int LineSpaceFilter::DEFAULT_NB_ANG_CELLS = 32;
+const int LineSpaceFilter::DEFAULT_NB_DIST_CELLS = 32;
+const int LineSpaceFilter::MIN_NB_ANG_CELLS = 8;
+const int LineSpaceFilter::MAX_NB_ANG_CELLS = 64;
+const int LineSpaceFilter::MIN_NB_DIST_CELLS = 8;
+const int LineSpaceFilter::MAX_NB_DIST_CELLS = 64;
+const int LineSpaceFilter::DEFAULT_SELECTION_THRESHOLD = 75;
+const int LineSpaceFilter::MIN_SELECTION_THRESHOLD = 20;
+const int LineSpaceFilter::MAX_SELECTION_THRESHOLD = 90;
+const int LineSpaceFilter::INC_SELECTION_THRESHOLD = 5;
+const int LineSpaceFilter::NO_SUBPIXEL = 1;
+const int LineSpaceFilter::MAX_SUBPIXEL = 64;
+const int LineSpaceFilter::ANG_DEF_ZOOM = 8;
+const int LineSpaceFilter::ANG_MIN_ZOOM = 2;
+const int LineSpaceFilter::ANG_MAX_ZOOM = 32;
+const int LineSpaceFilter::DIST_DEF_ZOOM = 4;
+const int LineSpaceFilter::DIST_MIN_ZOOM = 1;
+const int LineSpaceFilter::DIST_MAX_ZOOM = 16;
+
+
+LineSpaceFilter::LineSpaceFilter ()
+{
+  nt = DEFAULT_NB_ANG_CELLS;
+  nr = DEFAULT_NB_DIST_CELLS;
+  acc = new int[nt*nr];
+  ncos = new double[nt];
+  nsin = new double[nt];
+  mask = new bool[nt*nr];
+  cellMax = -1;
+  minsel = DEFAULT_SELECTION_THRESHOLD;
+  azoom = ANG_DEF_ZOOM;
+  dzoom = DIST_DEF_ZOOM;
+  nbSubpix = NO_SUBPIXEL;
+}
+
+
+LineSpaceFilter::~LineSpaceFilter ()
+{
+  delete [] acc;
+  delete [] ncos;
+  delete [] nsin;
+  delete [] mask;
+}
+
+
+void LineSpaceFilter::clear ()
+{
+  leftIn.clear ();
+  rightIn.clear ();
+  out.clear ();
+}
+
+
+BlurredSegment *LineSpaceFilter::filter (BlurredSegment *bs)
+{
+  bsInitialSize = 0;
+  bsFinalSize = 0;
+  if (bs == NULL || ! bs->isThick ()) return NULL;
+  bsInitialSize = bs->size ();
+  if (bsInitialSize < 10) return NULL;
+
+  // Gets the line spacefilter
+  const Pt2i bsstart = bs->getCenter ();
+  const vector<Pt2i> *bslineleft = bs->getLeftLine ();
+  const vector<Pt2i> *bsleft = bs->getLeftPoints ();
+  const vector<Pt2i> *bslineright = bs->getRightLine ();
+  const vector<Pt2i> *bsright = bs->getRightPoints ();
+  Vr2i sv = bs->getSupportVector ();
+  AbsRat segwidth = bs->segmentRationalWidth ();
+  Vr2i bbs = bs->boundingBoxSize ();
+  init (bsstart.x (), bsstart.y (), -sv.y (), sv.x (),
+        sqrt (bbs.x () * bbs.x () + bbs.y () * bbs.y ()),
+        segwidth.numerator () / (double) segwidth.denominator ());
+  vote (bsstart);
+  for (vector<Pt2i>::const_iterator it = bslineleft->begin ();
+       it != bslineleft->end (); it ++)
+    vote (*it);
+  for (vector<Pt2i>::const_iterator it = bsleft->begin ();
+       it != bsleft->end (); it ++)
+    vote (*it);
+  for (vector<Pt2i>::const_iterator it = bslineright->begin ();
+       it != bslineright->end (); it ++)
+    vote (*it);
+  for (vector<Pt2i>::const_iterator it = bsright->begin ();
+       it != bsright->end (); it ++)
+    vote (*it);
+  findMaxThroughOrigin ();
+  fitMask ();
+
+  // Filters the previous points
+  for (vector<Pt2i>::const_iterator it = bsleft->begin ();
+       it != bsleft->end (); it ++)
+  {
+    if (voteInMask (*it)) leftIn.push_back (Pt2i (*it));
+    else out.push_back (Pt2i (*it));
+  }
+  for (vector<Pt2i>::const_iterator it = bsright->begin ();
+       it != bsright->end (); it ++)
+  {
+    if (voteInMask (*it)) rightIn.push_back (Pt2i (*it));
+    else out.push_back (Pt2i (*it));
+  }
+
+  // Returns a blurred segment with the accepted points
+  int mw = 1;
+  AbsRat sw = bs->segmentRationalWidth ();
+  if (sw.denominator () != 0) mw += sw.numerator () / sw.denominator ();
+  BlurredSegmentProto resbs (mw, bsstart, leftIn, rightIn);
+  bsFinalSize = resbs.size ();
+  return (resbs.endOfBirth ());
+}
+
+
+void LineSpaceFilter::getAccumulator (unsigned char *map, int *solution)
+{
+  if (cellMax != -1)
+  {
+    int max = 0;
+    for (int i = 0; i < nt * nr; i++) if (acc[i] > max) max = acc[i];
+    for (int i = 0; i < nt * nr; i++)
+      map[i] = (unsigned char) ((acc[i] * 255) / max);
+    solution[0] = cellMax % nt;
+    solution[1] = cellMax / nt;
+  }
+}
+
+
+bool LineSpaceFilter::resize (bool larger)
+{
+  bool ok = false;
+  if (larger)
+  {
+    if (nt > MIN_NB_ANG_CELLS)
+    {
+      nt /= 2;
+      nr /= 2;
+      ok = true;
+    }
+  }
+  else
+  {
+    if (nt < MAX_NB_ANG_CELLS)
+    {
+      nt *= 2;
+      nr *= 2;
+      ok = true;
+    }
+  }
+  if (ok)
+  {
+    delete [] acc;
+    delete [] ncos;
+    delete [] nsin;
+    delete [] mask;
+    acc = new int[nt*nr];
+    ncos = new double[nt];
+    nsin = new double[nt];
+    mask = new bool[nt*nr];
+  }
+  return (ok);
+}
+
+
+bool LineSpaceFilter::zoom (bool in)
+{
+  bool ok = false;
+  if (in)
+  {
+    if (dzoom > DIST_MIN_ZOOM) 
+    {
+      dzoom /= 2;
+      azoom /= 2;
+      ok = true;
+    }
+  }
+  else
+  {
+    if (dzoom < DIST_MAX_ZOOM)
+    {
+      dzoom *= 2;
+      azoom *= 2;
+      ok = true;
+    }
+  }
+  return (ok);
+}
+
+
+bool LineSpaceFilter::subpixellise (bool larger)
+{
+  bool ok = false;
+  if (larger)
+  {
+    if (nbSubpix < MAX_SUBPIXEL)
+    {
+      nbSubpix *= 2;
+      ok = true;
+    }
+  }
+  else
+  {
+    if (nbSubpix > NO_SUBPIXEL)
+    {
+      nbSubpix /= 2;
+      ok = true;
+    }
+  }
+  return (ok);
+}
+
+
+bool LineSpaceFilter::setSelectivity (bool larger)
+{
+  bool ok = false;
+  if (larger)
+  {
+    if (minsel < MAX_SELECTION_THRESHOLD)
+    {
+      minsel += INC_SELECTION_THRESHOLD;
+      ok = true;
+    }
+  }
+  else
+  {
+    if (minsel > MIN_SELECTION_THRESHOLD)
+    {
+      minsel -= INC_SELECTION_THRESHOLD;
+      ok = true;
+    }
+  }
+  return (ok);
+}
+
+
+vector<Pt2i> LineSpaceFilter::getAccepted ()
+{
+  vector<Pt2i> res;
+  for (vector<Pt2i>::iterator it = leftIn.begin ();
+       it != leftIn.end (); it ++)
+    res.push_back (*it);
+  for (vector<Pt2i>::iterator it = rightIn.begin ();
+       it != rightIn.end (); it ++)
+    res.push_back (*it);
+  return res;
+}
+
+
+void LineSpaceFilter::checkManhattanScan ()
+{
+  if (cellMax == -1) findMax (); // default choice if not already done
+  int cell0 = cellMax;
+  int x0 = cell0 % nt;
+  int y0 = cell0 / nt;
+  int nrt = nr * nt;
+  bool poursuite = true;
+  int tour = 1;
+int val = 1;
+int vtour = 6;
+
+  while (poursuite)
+  {
+    // bottom cell first
+    int cell = cell0 - nt * tour;
+    if (cell < 0)
+    {
+      // first cell on the diagonal inside the accumulator
+      cell += (nt + 1) * (1 + (-cell) / nt);
+      if (cell >= nt) cell = cell0;
+    }
+    while (cell < cell0)
+    {
+      // process cell HERE
+if (tour == vtour) acc[cell] = val++;
+      cell += nt + 1;
+      if (cell % nt == 0) cell = cell0;
+    }
+
+    // right cell next
+    cell = cell0 + tour;
+    if (cell % nt <= x0)
+    {
+      // first cell on the diagonal inside the accumulator
+      cell += (nt - 1) * (x0 + tour + 1 - nt);
+      if (cell >= nrt) cell = cell0;
+    }
+    while (cell % nt > x0)
+    {
+      // process cell HERE
+if (tour == vtour) acc[cell] = val++;
+      cell += nt - 1;
+      if (cell >= nrt) cell = cell0;
+    }
+
+    // top cell next
+    cell = cell0 + nt * tour;
+    if (cell >= nrt)
+    {
+      // first cell on the diagonal inside the accumulator
+      cell -= (nt + 1) * (y0 + tour + 1 - nr);
+      if (cell % nt >= x0) cell = cell0;
+    }
+    while (cell / nt > y0)
+    {
+      // process cell HERE
+if (tour == vtour) acc[cell] = val++;
+      cell -= nt + 1;
+      if (cell % nt >= x0) cell = cell0;
+    }
+
+    // left cell next
+    cell = cell0 - tour;
+    if (tour > x0)
+    {
+      // first cell on the diagonal inside the accumulator
+      cell -= (nt - 1) * (tour - x0);
+      if (cell < 0) cell = cell0;
+    }
+    while (cell % nt < x0)
+    {
+      // process cell HERE
+if (tour == vtour) acc[cell] = val++;
+      cell -= nt - 1;
+      if (cell < 0) cell = cell0;
+    }
+
+    tour ++;
+    poursuite = (tour != 12);
+  }
+}
+
+
+void LineSpaceFilter::init (double x0, double y0, int a, int b,
+                            double length, double width)
+{
+  // Clears the accumulator
+  int *ac = acc;
+  bool *m = mask;
+  for (int i = 0; i < nt * nr; i++)
+  {
+    *ac++ = 0;
+    *m++ = false;
+  }
+  cellMax = -1;
+
+  // Computes the column values (normal vector deviations)
+  double w = azoom * width / nt;
+  double hyp = sqrt (w * w + length * length);
+  double dcos = length / hyp;
+  da = acos (dcos);
+  double dsin = w / hyp;
+  double n = sqrt (a * a + b * b);
+  ncos[nt/2] = a / n;
+  nsin[nt/2] = b / n;
+  for (int i = nt / 2; i > 0; i--)
+  {
+    ncos[i-1] = ncos[i] * dcos + nsin[i] * dsin;
+    nsin[i-1] = nsin[i] * dcos - ncos[i] * dsin;
+  }
+  for (int i = nt / 2 + 1; i < nt; i++)
+  {
+    ncos[i] = ncos[i-1] * dcos - nsin[i-1] * dsin;
+    nsin[i] = nsin[i-1] * dcos + ncos[i-1] * dsin;
+  }
+
+  // Computes the row values (distance parameter)
+  cx = x0;
+  cy = y0;
+  dr = dzoom * width / nr;
+  r0 = - ((nr / 2) + 0.5) * dr;
+}
+
+
+void LineSpaceFilter::vote (int i, int j)
+{
+  acc[i + j * nt] ++;
+}
+
+
+void LineSpaceFilter::vote (Pt2i pix)
+{
+  int x = pix.x () - cx;
+  int y = pix.y () - cy;
+  for (int i = 0; i < nt; i++)
+  {
+    if (nbSubpix == 1)
+    {
+      double d = x * ncos[i] + y * nsin[i];
+      if (d >= r0)
+      {
+        int rho = (int) ((d - r0) / dr);
+        if (rho < nr) acc[i + rho * nt] ++;
+      }
+    }
+    else
+    {
+      for (int ix = 0; ix < nbSubpix; ix ++)
+        for (int jy = 0; jy < nbSubpix; jy ++)
+        {
+          double d = (x + (2 * ix - 15) / 32.) * ncos[i]
+                     + (y + (2 * jy - 15) / 32.) * nsin[i];
+          if (d >= r0)
+          {
+            int rho = (int) ((d - r0) / dr);
+            if (rho < nr) acc[i + rho * nt] ++;
+          }
+        }
+    }
+  }
+}
+
+
+void LineSpaceFilter::vote (const vector<Pt2i>& pts)
+{
+  vector<Pt2i>::const_iterator it = pts.begin ();
+  while (it != pts.end ())
+  {
+    int x = it->x () - cx;
+    int y = it->y () - cy;
+    for (int i = 0; i < nt; i++)
+    {
+      if (nbSubpix == 1)
+      {
+        double d = x * ncos[i] + y * nsin[i];
+        if (d >= r0)
+        {
+          int rho = (int) ((d - r0) / dr);
+          if (rho < nr) acc[i + rho * nt] ++;
+        }
+      }
+      else
+      {
+        for (int ix = 0; ix < nbSubpix; ix ++)
+          for (int jy = 0; jy < nbSubpix; jy ++)
+          {
+            double d = (x + (2 * ix - 15) / 32.) * ncos[i]
+                       + (y + (2 * jy - 15) / 32.) * nsin[i];
+            if (d >= r0)
+            {
+              int rho = (int) ((d - r0) / dr);
+              if (rho < nr) acc[i + rho * nt] ++;
+            }
+          }
+      }
+    }
+    it ++;
+  }
+}
+
+
+bool LineSpaceFilter::voteInMask (Pt2i pix)
+{
+  int x = pix.x () - cx;
+  int y = pix.y () - cy;
+  for (int i = 0; i < nt; i++)
+  {
+    if (nbSubpix == 1)
+    {
+      double d = x * ncos[i] + y * nsin[i];
+      if (d >= r0)
+      {
+        int rho = (int) ((d - r0) / dr);
+        if (rho < nr && mask[i + rho * nt]) return true;
+      }
+    }
+    else
+    {
+      for (int ix = 0; ix < nbSubpix; ix ++)
+        for (int jy = 0; jy < nbSubpix; jy ++)
+        {
+          double d = (x + (2 * ix - 15) / 32.) * ncos[i]
+                     + (y + (2 * jy - 15) / 32.) * nsin[i];
+          if (d >= r0)
+          {
+            int rho = (int) ((d - r0) / dr);
+            if (rho < nr && mask[i + rho * nt]) return true;
+          }
+        }
+    }
+  }
+  return false;
+}
+
+
+vector<Pt2i> LineSpaceFilter::voteInMask (vector<Pt2i>& pts)
+{
+  vector<Pt2i> vpix;
+  vector<Pt2i>::iterator it = pts.begin ();
+  while (it != pts.end ())
+  {
+    int x = it->x () - cx;
+    int y = it->y () - cy;
+    for (int i = 0; i < nt; i++)
+    {
+      double d = x * ncos[i] + y * nsin[i];
+      if (d >= r0)
+      {
+        int rho = (int) ((d - r0) / dr);
+        if (rho < nr && mask[i + rho * nt]) vpix.push_back (*it);
+      }
+    }
+    it ++;
+  }
+  return (vpix);
+}
+
+
+void LineSpaceFilter::findMax ()
+{
+  cellMax = 0;
+  for (int i = 1; i < nt * nr; i++)
+    if (acc[i] > acc[cellMax]) cellMax = i;
+}
+
+
+void LineSpaceFilter::findMaxThroughOrigin ()
+{
+  cellMax = (nr / 2) * nt;
+  for (int i = 1; i < nt; i++)
+    if (acc[cellMax + i] > acc[cellMax]) cellMax = cellMax + i;
+}
+
+
+void LineSpaceFilter::fitMask ()
+{
+  if (cellMax == -1) findMax ();
+  int cell0 = cellMax;
+  int x0 = cell0 % nt;
+  int y0 = cell0 / nt;
+  int nrt = nr * nt;
+  bool rt = true, tl = true, lb = true, br = true;
+  int tour = 1;
+  int cell;
+
+  mask[cellMax] = true;
+  while (br || rt || tl || lb)
+  {
+    // bottom cell first
+    if (br)
+    {
+      br = false;
+      cell = cell0 - nt * tour;
+      if (cell < 0)
+      {
+        // first cell on the diagonal inside the accumulator
+        cell += (nt + 1) * (1 + (-cell) / nt);
+        if (cell >= nt) cell = cell0;
+      }
+      else
+      {
+        // process bottom cell HERE
+        if (mask[cell+nt] && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          br = true;
+        }
+        cell += nt + 1;
+        if (cell % nt == 0) cell = cell0;
+      }
+      while (cell < cell0)
+      {
+        // process cell HERE
+        if ((mask[cell+nt] || mask[cell-1])
+            && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          br = true;
+        }
+        cell += nt + 1;
+        if (cell % nt == 0) cell = cell0;
+      }
+    }
+
+    // right cell next
+    if (rt)
+    {
+      rt = false;
+      cell = cell0 + tour;
+      if (cell % nt <= x0)
+      {
+        // first cell on the diagonal inside the accumulator
+        cell += (nt - 1) * (x0 + tour + 1 - nt);
+        if (cell >= nrt) cell = cell0;
+      }
+      else
+      {
+        // process left cell HERE
+        if (mask[cell-1] && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          rt = true;
+        }
+        cell += nt - 1;
+        if (cell >= nrt) cell = cell0;
+      }
+      while (cell % nt > x0)
+      {
+        // process cell HERE
+        if ((mask[cell-1] || mask[cell-nt])
+            && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          rt = true;
+        }
+        cell += nt - 1;
+        if (cell >= nrt) cell = cell0;
+      }
+    }
+  
+    // top cell next
+    if (tl)
+    {
+      tl = false;
+      cell = cell0 + nt * tour;
+      if (cell >= nrt)
+      {
+        // first cell on the diagonal inside the accumulator
+        cell -= (nt + 1) * (y0 + tour + 1 - nr);
+        if (cell % nt >= x0) cell = cell0;
+      }
+      else
+      {
+        // process top cell HERE
+        if (mask[cell-nt] && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          tl = true;
+        }
+        cell -= nt + 1;
+        if (cell % nt >= x0) cell = cell0;
+      }
+      while (cell / nt > y0)
+      {
+        // process cell HERE
+        if ((mask[cell-nt] || mask[cell+1])
+            && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          tl = true;
+        }
+        cell -= nt + 1;
+        if (cell % nt >= x0) cell = cell0;
+      }
+    }
+
+    // left cell next
+    if (lb)
+    {
+      lb = false;
+      cell = cell0 - tour;
+      if (tour > x0)
+      {
+        // first cell on the diagonal inside the accumulator
+        cell -= (nt - 1) * (tour - x0);
+        if (cell < 0) cell = cell0;
+      }
+      else
+      {
+        // process left cell HERE
+        if (mask[cell+1] && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          lb = true;
+        }
+        cell -= nt - 1;
+        if (cell < 0) cell = cell0;
+      }
+      while (cell % nt < x0)
+      {
+        // process cell HERE
+        if ((mask[cell+1] || mask[cell+nt])
+            && acc[cell] > (acc[cellMax] * minsel) / 100)
+        {
+          mask[cell] = true;
+          lb = true;
+        }
+        cell -= nt - 1;
+        if (cell < 0) cell = cell0;
+      }
+    }
+    tour ++;
+  }
+}
diff --git a/Code/Seg/BlurredSegment/linespacefilter.h b/Code/Seg/BlurredSegment/linespacefilter.h
new file mode 100755
index 0000000000000000000000000000000000000000..3c6be37fd1fc7c5dd23a8ead91a7ca19e45a4879
--- /dev/null
+++ b/Code/Seg/BlurredSegment/linespacefilter.h
@@ -0,0 +1,293 @@
+#ifndef LINE_SPACE_FILTER_H
+#define LINE_SPACE_FILTER_H
+
+#include <vector>
+#include "pt2i.h"
+#include "blurredsegment.h"
+
+using namespace std;
+
+
+/** 
+ * @class Parameter space filter for detecting thick straight lines.
+ * \author {P. Even}
+ */
+class LineSpaceFilter
+{
+
+public:
+
+  /** Default number of line space filter angle cells. */
+  static const int DEFAULT_NB_ANG_CELLS;
+  /** Default number of line space filter distance cells. */
+  static const int DEFAULT_NB_DIST_CELLS;
+  
+
+  /**
+   * \brief Creates a empty line space.
+   */
+  LineSpaceFilter ();
+
+  /**
+   * \brief Deletes the line space.
+   */
+  ~LineSpaceFilter ();
+
+  /**
+   * \brief Clears the stored information.
+   */
+  void clear ();
+
+  /** \brief Filters and returns a blurred segment.
+    * @param bs The blurred segment to be processed.
+    */
+  BlurredSegment *filter (BlurredSegment *bs);
+
+  /**
+   * \brief Gets the filtering cells.
+   */
+  inline bool *getMask () const
+  {
+    return mask;
+  }
+
+  /**
+   * \brief Gets the accumulator values.
+   * @param map Accumulator vote cells
+   * @param solution Accumulator max cell coordinates
+   */
+  void getAccumulator (unsigned char *map, int *solution);
+
+  /** \brief Returns the number of columns of the accumulation filter.
+    */
+  inline int width () const { return nt; }
+
+  /** \brief Returns the number of lines of the accumulation filter.
+    */
+  inline int height () const { return nr; }
+
+  /** \brief Resizes the accumulation array.
+    * Returns true if the required modification is actually performed.
+    * @param larger Sets larger if true, smaller otherwise.
+    */
+  bool resize (bool larger);
+
+  /**
+   * \brief Returns the angular resolution in radians.
+   */
+  inline double angularResolution () const
+  {
+    return da;
+  }
+
+  /** \brief Returns the distance resolution in pixels.
+    */
+  inline double distanceResolution () const
+  {
+    return dr;
+  }
+
+  /** \brief Returns the distance zoom factor of the accumulator display.
+    */
+  inline int getZoom () const
+  {
+    return (dzoom);
+  }
+
+  /** \brief Zooms in or out the accumulator display.
+    * Returns true if the required modification is actually performed.
+    * @param in Zooms in if true, out otherwise.
+    */
+  bool zoom (bool in);
+
+  /** \brief Returns the sub-pixel resolution used for voting.
+    */
+  inline int getSubpix () const
+  {
+    return (nbSubpix);
+  }
+
+  /** \brief Modifies the subpixellic resolution for voting.
+    * Returns true if the required modification is actually performed.
+    * @param larger Sets larger if true, smaller otherwise.
+    */
+  bool subpixellise (bool larger);
+
+  /** \brief Returns the selection threshold (in percent).
+    */
+  inline int getSelectionThreshold () const
+  {
+    return (minsel);
+  }
+
+  /** \brief Modifies the filter selection threshold.
+    * Returns true if the required modification is actually performed.
+    * @param larger Sets larger if true, smaller otherwise.
+    */
+  bool setSelectivity (bool larger);
+
+  /**
+   * \brief Returns the accepted points by the line space filter.
+   */
+  vector<Pt2i> getAccepted ();
+
+  /**
+   * \brief Returns the rejected points by the line space filter.
+   */
+  inline vector<Pt2i> getRejected () const { return out; }
+
+  /**
+   * \brief Returns the blurred segment size before filtering.
+   */
+  inline int blurredSegmentInitialSize () const { return bsInitialSize; }
+
+  /**
+   * \brief Returns the blurred segment size after filtering.
+   */
+  inline int blurredSegmentFinalSize () const { return bsFinalSize; }
+
+  /**
+   * \brief Scans manhattan circles around the highest vote.
+   * Votes for one specific radius to test the scan correctness.
+   */
+  void checkManhattanScan ();
+
+
+private :
+
+  /** Min number of line space filter angle cells. */
+  static const int MIN_NB_ANG_CELLS;
+  /** Max number of line space filter angle cells. */
+  static const int MAX_NB_ANG_CELLS;
+  /** Min number of line space filter distance cells. */
+  static const int MIN_NB_DIST_CELLS;
+  /** Max number of line space filter distance cells. */
+  static const int MAX_NB_DIST_CELLS;
+  /** Default filter selection threshold (in percentage). */
+  static const int DEFAULT_SELECTION_THRESHOLD;
+  /** Minimal filter selection threshold (in percentage). */
+  static const int MIN_SELECTION_THRESHOLD;
+  /** Maximal filter selection threshold (in percentage). */
+  static const int MAX_SELECTION_THRESHOLD;
+  /** Increment value for the selection threshold setting. */
+  static const int INC_SELECTION_THRESHOLD;
+  /** Default sub-pixellic resolution for voting. */
+  static const int NO_SUBPIXEL;
+  /** Maximal sub-pixellic resolution for voting. */
+  static const int MAX_SUBPIXEL;
+  /** Angle zoom factor default value. */
+  static const int ANG_DEF_ZOOM;
+  /** Angle zoom factor min value. */
+  static const int ANG_MIN_ZOOM;
+  /** Angle zoom factor max value. */
+  static const int ANG_MAX_ZOOM;
+  /** Distance zoom factor default value. */
+  static const int DIST_DEF_ZOOM;
+  /** Distance zoom factor min value. */
+  static const int DIST_MIN_ZOOM;
+  /** Distance zoom factor max value. */
+  static const int DIST_MAX_ZOOM;
+
+  /** Accumulator. */
+  int *acc;
+  /** Angle zoom factor. */
+  int azoom; 
+  /** Distance zoom factor. */
+  int dzoom; 
+  /** Subpixel resolution for voting. */
+  int nbSubpix; 
+
+  /** Count of accumulator rows (angles). */
+  int nt;
+  /** Pre-computed array of deviated normal vectors. */
+  double *ncos, *nsin;
+  /** Angular resolution (in readians). */
+  double da;
+
+  /** Count of accumulator columns (distances). */
+  int nr;
+  /** Distance resolution (offset between consecutive accumulator columns). */
+  double dr;
+  /** Origin of the line space. */
+  int cx, cy;
+  /** Distance value of the accumulator bottom line. */
+  double r0;
+
+  /** Dominant cell (-1 if not yet determined) */
+  int cellMax;
+  /** Extraction mask used to prune outlier candidates. */
+  bool *mask;
+  /** Filter selection ratio (in %) */
+  int minsel;
+
+  /** Blurred segment size before filtering. */
+  int bsInitialSize;
+  /** Blurred segment size after filtering. */
+  int bsFinalSize;
+  /** Accepted left points after line space filtering. */
+  vector<Pt2i> leftIn;
+  /** Accepted right points after line space filtering. */
+  vector<Pt2i> rightIn;
+  /** Rejected points after line space filtering. */
+  vector<Pt2i> out;
+
+
+  /**
+   * \brief Clears the accumulator and centers it on a new blurred segment.
+   * @param x0 Segment center abscissae
+   * @param y0 Segment center ordinate
+   * @param a Segment normal vector abscissae
+   * @param b Segment normal vector ordinate
+   * @param length Segment length
+   * @param width Segment width
+   */
+  void init (double x0, double y0, int a, int b,
+             double length, double width);
+
+  /**
+   * \brief Direct vote into the accumulator for testing
+   */
+  void vote (int i, int j);
+
+  /**
+   * \brief Adds one point votes into the accumulator
+   * @param pix Voting point
+   */
+  void vote (Pt2i pix);
+
+  /**
+   * \brief Adds multiple points votes into the accumulator
+   * @param points Voting points
+   */
+  void vote (const vector<Pt2i>& points);
+
+  /**
+   * \brief Checks whether the point votes in the active part of the accumulator
+   * @param pix Voting point
+   */
+  bool voteInMask (Pt2i pix);
+
+  /**
+   * \brief Tests multiple points votes into the active part of the accumulator
+   * @param points Voting points
+   * Returns a vector of inlier points
+   */
+  vector<Pt2i> voteInMask (vector<Pt2i>& points);
+
+  /**
+   * \brief Determines the cell with the highest vote.
+   */
+  void findMax ();
+
+  /**
+   * \brief Determines the rho=0 cell with the highest vote.
+   */
+  void findMaxThroughOrigin ();
+
+  /**
+   * \brief Fits the extraction mask around the interest area.
+   */
+  void fitMask ();
+
+};
+#endif
diff --git a/Code/Seg/ConvexHull/antipodal.cpp b/Code/Seg/ConvexHull/antipodal.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..60b70fdceb44aefe4ac686839a42b3adca6ad4b0
--- /dev/null
+++ b/Code/Seg/ConvexHull/antipodal.cpp
@@ -0,0 +1,343 @@
+#include "antipodal.h"
+
+
+Antipodal::Antipodal ()
+{
+  ix = 0;
+  iy = 1;
+  vpt = NULL;
+  ept1 = NULL;
+  ept2 = NULL;
+}
+
+
+void Antipodal::init (CHVertex *v1, CHVertex *v2, CHVertex *v3)
+{
+  if (v1->get (iy) < v2->get (iy))
+  {
+    if (v2->get (iy) < v3->get (iy))
+    {
+      vpt = v2;
+      ept1 = v1;
+      ept2 = v3;
+    }
+    else
+    {
+      if (v1->get (iy) < v3->get (iy))
+      {
+        vpt = v3;
+        ept1 = v1;
+        ept2 = v2;
+      }
+      else
+      {
+        vpt = v1;
+        ept1 = v2;
+        ept2 = v3;
+      }
+    }
+  }
+  else
+  {
+    if (v1->get (iy) < v3->get (iy))
+    {
+      vpt = v1;
+      ept1 = v2;
+      ept2 = v3;
+    }
+    else
+    {
+      if (v2->get (iy) <= v3->get (iy))     // EQUIV : au lieu de "<" !!!
+      {
+        vpt = v3;
+        ept1 = v1;
+        ept2 = v2;
+      }
+      else
+      {
+        vpt = v2;
+        ept1 = v1;
+        ept2 = v3;
+      }
+    }
+  }
+}
+
+
+AbsRat Antipodal::rationalWidth () const
+{
+  int den = ept2->get (iy) - ept1->get (iy);
+  return (AbsRat (((vpt->get (ix) - ept1->get (ix)) * den
+                   - (vpt->get (iy) - ept1->get (iy))
+                     * (ept2->get (ix) - ept1->get (ix))), den));
+}
+
+
+void Antipodal::width (int &num, int &den) const
+{
+  den = ept2->get (iy) - ept1->get (iy);
+  if (den < 0) den = -den;
+  num = (vpt->get (ix) - ept1->get (ix)) * den
+        - (vpt->get (iy) - ept1->get (iy)) * (ept2->get (ix) - ept1->get (ix));
+  if (num < 0) num = -num;
+}
+
+
+int Antipodal::remainder (CHVertex *v) const
+{
+  int a = ept2->y () - ept1->y ();
+  int b = ept2->x () - ept1->x ();
+  if (a == 0) return ((b > 0 ? -b : b) * v->y ());
+  if (a < 0)
+  {
+    a = -a;
+    b = -b;
+  }
+  return (a * v->x () - b * v->y ());
+}
+
+
+bool Antipodal::edgeInFirstQuadrant () const
+{
+  if (iy) return true;
+  int a = ept2->y () - ept1->y ();
+  if (a == 0) return true;
+  return (a > 0 ? (ept1->x () < ept2->x ()) : (ept2->x () < ept1->x ()));
+}
+
+
+int Antipodal::getA () const
+{
+  int a = ept2->y () - ept1->y ();
+  return (a < 0 ? -a : a);
+}
+
+
+int Antipodal::getB () const
+{
+  int a = ept2->y () - ept1->y ();
+  int b = ept2->x () - ept1->x ();
+  if (a < 0) b = -b;
+  else if (a == 0 && b < 0) b = -b;
+  return (b);
+}
+
+
+ostream& operator<< (ostream &os, const Antipodal &ap)
+{
+  os << (ap.ix ? "AV [" : "AH [") << *(ap.vpt) << " + ("
+     << *(ap.ept1) << " - " << *(ap.ept2) << ")]";
+  if (ap.remainder (ap.vpt) == ap.remainder (ap.ept1)) os << "--HS--";
+  return os;
+}
+
+
+void Antipodal::update (CHVertex *pt)
+{
+  CHVertex *rpt = pt->right ();
+  CHVertex *lpt = pt->left ();
+
+  int rmp = remainder (pt);
+  int rmv = remainder (vpt);
+  int rme = remainder (ept1);
+  int zpt = pt->get (iy);     // vertical AP : Z -> X -- horizontal AP : Z -> Y
+  int zav = vpt->get (iy);    // coord of antipodal vertex
+  int zas = ept1->get (iy);   // coord of antipodal edge start
+  int zae = ept2->get (iy);   // coord of antipodal edge end
+
+  CHVertex *pvertex;
+  if (remainder (rpt) == rmv) pvertex = rpt;
+  else if (remainder (lpt) == rmv) pvertex = lpt;
+  else pvertex = vpt;
+
+  CHVertex *pedge;
+  if (remainder (rpt) == rme) pedge = rpt;
+  else if (remainder (lpt) == rme) pedge = lpt;
+  else pedge = ept1;
+
+
+  // P on the line supported by the Edge
+  if (rmp == rme)
+  {
+    // P between start end end of antipodal Edge : no change (IMPOSSIBLE)
+    if ((zpt == zas) || (zpt == zae) || ((zpt < zas) != (zpt < zae))) return;
+    // -> prolongation of antipodal Edge up to P
+    setEdge (pt, pedge);
+    return;
+  }
+
+  // P on the line (parallel to Edge) supported by the Vertex
+  if (rmp == rmv)
+  {
+    // P at the height of Edge -> P is the new Vertex
+    if ((zpt == zas) || (zpt == zae) || ((zpt < zas) != (zpt < zae)))
+      setVertex (pt);
+    else
+    {
+      // P beyond Edge Start : -> the Edge Start is the new Vertex
+      if ((zas == zae) || ((zas < zpt) != (zas < zae))) setVertex (ept1);
+      // P beyond Edge End : -> the Edge End is the new Vertex
+      if ((zae < zpt) != (zae < zas)) setVertex (ept2);
+      // -> the new Edge joins P to the former Vertex
+      setEdge (pt, pvertex);
+    }
+    return;
+  }
+ 
+  // P strictly between antipodal Edge and Vertex -> no change
+  if ((rmp < rmv) != (rmp < rme)) return;
+
+
+  // P at the height of the antipodal Vertex
+  if (zpt == zav)
+  {
+    // P beyond the antipodal Vertex
+    if ((rmv < rmp) != (rmv < rme))
+    {				
+      // -> P is the new Vertex
+      setVertex (pt);
+      return;
+    }
+
+    CHVertex *oldvpt = vpt;
+    if (zav != lpt->get (iy))
+    {
+      if (oldvpt->vprod (oldvpt->left (), lpt, pt) > 0)
+      {
+        setVertex (oldvpt);
+        setEdge (lpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (oldvpt, oldvpt->left ());
+      }
+    }
+    else
+    {
+      if (oldvpt->vprod (oldvpt->right (), rpt, pt) < 0)
+      {
+        setVertex (oldvpt);
+        setEdge (rpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (oldvpt, oldvpt->right ());
+      }
+    }
+    return;
+  }
+
+
+  // Main case
+  //==============================================================
+  CHVertex *cvx = NULL;   // candidate rotation vertex
+  CHVertex *lvx, *rvx;    // left and right vertices of candidate
+  int zvx;                // coord of candidate
+
+  bool firstQuad = true;
+  if (edgeInFirstQuadrant ())
+  {
+    if (((rmp > rme) && (rmp > rmv) && (zpt > zav))
+        || ((rmp < rme) && (rmp < rmv) && (zpt < zav))) firstQuad = false;
+  }
+  else
+    if (((rmp > rme) && (rmp > rmv) && (zpt < zav))
+        || ((rmp < rme) && (rmp < rmv) && (zpt > zav))) firstQuad = false;
+
+  if (firstQuad)
+  {
+    if ((rme < rmp) != (rme < rmv)) cvx = pvertex;
+    if ((rmv < rme) != (rmv < rmp))
+      cvx = (ept1->right () == ept2 ? ept1 : ept2);
+    zvx = cvx->get (iy);
+    lvx = cvx->left ();
+    rvx = cvx->right ();
+
+    while (cvx->vprod (rvx, rpt, pt) > 0)
+    {
+      cvx = rvx;
+      lvx = cvx->left ();
+      rvx = cvx->right ();
+      zvx = cvx->get (iy);
+      int zpn = lvx->get (iy);
+      if ((zpt == zvx) || (zpt == zpn) || ((zpt < zvx) != (zpt < zpn))) break;
+    }
+
+    if (zvx == zpt)
+    {
+      if (cvx->vprod (rvx, rpt, pt) <= 0)   // Au lieu de < chez Phuong
+      {
+        setVertex (cvx);
+        setEdge (rpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (cvx, rvx);
+      }
+    }
+    else
+    {
+      int zpn = rpt->get (iy);
+      if ((zvx == zpn) || ((zvx < zpt) != (zvx < zpn)))
+      {
+        setVertex (cvx);
+        setEdge (rpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (lvx, cvx);
+      }
+    }
+  }
+
+  else // second quadrant
+  {
+    if ((rme < rmp) != (rme < rmv)) cvx = pvertex;
+    if ((rmv < rme) != (rmv < rmp))
+      cvx = (ept1->left () == ept2 ? ept1 : ept2);
+    zvx = cvx->get (iy);
+    rvx = cvx->right ();
+    lvx = cvx->left ();
+
+    while (cvx->vprod (lvx, lpt, pt) < 0)
+    {
+      cvx = lvx;
+      rvx = cvx->right ();
+      lvx = cvx->left ();
+      zvx = cvx->get (iy);
+      int zvn = rvx->get (iy);
+      if ((zpt == zvx) || (zpt == zvn) || ((zpt < zvx) != (zpt < zvn))) break;
+    }
+    if (zvx == zpt)
+    {
+      if (cvx->vprod (lvx, lpt, pt) >= 0)
+      {
+        setVertex (cvx);
+        setEdge (lpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (cvx, lvx);
+      }
+    }
+    else
+    {
+      int zvn = lpt->get (iy);
+      if ((zvx == zvn) || ((zvx < zvn) != (zvx < zpt)))
+      {
+        setVertex (cvx);
+        setEdge (lpt, pt);
+      }
+      else
+      {
+        setVertex (pt);
+        setEdge (rvx, cvx);
+      }
+    }
+  }
+}
diff --git a/Code/Seg/ConvexHull/antipodal.h b/Code/Seg/ConvexHull/antipodal.h
new file mode 100755
index 0000000000000000000000000000000000000000..4983403c66f75db1b3b7bbdf6a927bca585a5b48
--- /dev/null
+++ b/Code/Seg/ConvexHull/antipodal.h
@@ -0,0 +1,82 @@
+#ifndef ANTIPODAL_H
+#define ANTIPODAL_H
+
+#include "chvertex.h"
+#include <ostream>
+
+using namespace std;
+
+
+class Antipodal
+{
+public:
+
+  /** Builds an empty (undetermined) horizontal antipodal pair. */
+  Antipodal ();
+
+  /** Sets the coordinates for a vertical antipodal pair. */
+  inline void setVertical () { ix = 1; iy = 0; }
+
+  /** Initializes the vertex/edge pair from three unordered vertices. */
+  void init (CHVertex *vpt, CHVertex *ept1, CHVertex *ept2);
+
+  /** Sets the vertex and the edge of the antipodal pair. */
+  inline void setVertexAndEdge (CHVertex *pt, CHVertex *es, CHVertex *ee) {
+                             vpt = pt; ept1 = es; ept2 = ee; }
+
+  /** Sets the vertex of the antipodal pair. */
+  inline void setVertex (CHVertex *pt) { vpt = pt; }
+
+  /** Sets the edge of the antipodal pair. */
+  inline void setEdge (CHVertex *pt1, CHVertex *pt2) { ept1 = pt1; ept2 = pt2; }
+
+  /** Returns the vertex of the antipodal pair. */
+  inline CHVertex *vertex () const { return vpt; }
+
+  /** Returns the leaning edge start of the antipodal pair. */
+  inline CHVertex *edgeStart () const { return ept1; }
+
+  /** Returns the leaning edge end of the antipodal pair. */
+  inline CHVertex *edgeEnd () const { return ept2; }
+
+  /** Returns the horizontal or vertical width of the antipodal pair. */
+  AbsRat rationalWidth () const;
+
+  /** Gets the rational main axis width of the antipodal pair. */
+  void width (int &num, int &den) const;
+
+  /** Returns the remainder of the edge line equation for given vertex. */
+  int remainder (CHVertex *v) const;
+
+  /** Checks if the edge lies in the first quadrant (x = y). */
+  bool edgeInFirstQuadrant () const;
+
+  /** Gets the edge vector Y coordinate. */
+  int getA () const;
+
+  /** Gets the edge vector X coordinate. */
+  int getB () const;
+
+  /** Updates the antipodal pair after the insertion of a new vertex. */
+  void update (CHVertex *pt);
+
+  /** Returns a string that represents the antipodal pair. */
+  friend ostream& operator<< (ostream &os, const Antipodal &ap);
+
+
+protected:
+
+  /** First coordinate (X for horizonal pair, Y for vertical pair). */
+  int ix;
+  /** Second coordinate (Y for horizonal pair, X for vertical pair). */
+  int iy;
+
+  /** Leaning vertex. */
+  CHVertex *vpt;
+  /** Start of the leaning edge. */
+  CHVertex *ept1;
+  /** End of the leaning edge. */
+  CHVertex *ept2;
+
+};
+#endif
diff --git a/Code/Seg/ConvexHull/chvertex.cpp b/Code/Seg/ConvexHull/chvertex.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..95f857d5e5a75a62fab6137cb552d54e24a111fb
--- /dev/null
+++ b/Code/Seg/ConvexHull/chvertex.cpp
@@ -0,0 +1,34 @@
+#include "chvertex.h"
+
+
+CHVertex::CHVertex () : Pt2i ()
+{
+  lv = NULL;
+  rv = NULL;
+}
+
+
+CHVertex::CHVertex (int x, int y) : Pt2i (x, y)
+{
+  lv = NULL;
+  rv = NULL;
+}
+
+
+CHVertex::CHVertex (const Pt2i &p) : Pt2i (p)
+{
+  lv = NULL;
+  rv = NULL;
+}
+
+
+CHVertex::~CHVertex ()
+{
+}
+
+
+ostream& operator<< (ostream &os, const CHVertex &v)
+{
+  os << "(" << v.xp << ", " << v.yp << ")";
+  return os;
+}
diff --git a/Code/Seg/ConvexHull/chvertex.h b/Code/Seg/ConvexHull/chvertex.h
new file mode 100755
index 0000000000000000000000000000000000000000..543e35d0d12e7c4cfaa172e623725f458b7654e8
--- /dev/null
+++ b/Code/Seg/ConvexHull/chvertex.h
@@ -0,0 +1,51 @@
+#ifndef CHVERTEX_H
+#define CHVERTEX_H
+
+#include "pt2i.h"
+#include <iostream>
+
+
+/** Chained point with two adjacent points. */
+class CHVertex : public Pt2i
+{
+ 
+public:
+
+  /** Builds a default vertex. */
+  CHVertex ();
+
+  /** Builds a vertex on given coordinates. */
+  CHVertex (int x, int y);
+
+  /** Builds a vertex at the position of the given point. */
+  CHVertex (const Pt2i &p);
+  ~CHVertex ();
+
+  inline CHVertex *left () const { return lv; }
+  inline CHVertex *right () const { return rv; }
+  inline void setLeft (CHVertex *v) { lv = v; }
+  inline void setRight (CHVertex *v) { rv = v; }
+
+  /** Returns the vector product of vector (this, pt) and vector (vx, vy)
+   */
+  inline int vprod (CHVertex *pt, int vx, int vy) const {
+                   return ((pt->xp - xp) * vy - vx * (pt->yp - yp)); }
+
+  /** Returns the vector product of vector (this, p2) and vector (p3, p4)
+   */
+  inline int vprod (CHVertex *p2, CHVertex *p3, CHVertex *p4) const {
+                   return ((p2->xp - xp) * (p4->yp - p3->yp)
+                           - (p4->xp - p3->xp) * (p2->yp - yp)); }
+
+  friend ostream& operator<< (ostream &os, const CHVertex &v);
+
+
+protected:
+
+  /** Adjacent vertex to the left. */
+  CHVertex *lv;
+  /** Adjacent vertex to the right. */
+  CHVertex *rv;
+};
+    
+#endif
diff --git a/Code/Seg/ConvexHull/convexhull.cpp b/Code/Seg/ConvexHull/convexhull.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..d93a2575fc4cf81575d923e4b1c5cae3ff6b93ba
--- /dev/null
+++ b/Code/Seg/ConvexHull/convexhull.cpp
@@ -0,0 +1,260 @@
+#include "convexhull.h"
+
+
+ConvexHull::ConvexHull (const Pt2i &lpt, const Pt2i &cpt, const Pt2i &rpt)
+{
+  CHVertex *cvert = new CHVertex (cpt);
+  leftVertex = new CHVertex (lpt);
+  rightVertex = new CHVertex (rpt);
+  lastToLeft = false;
+
+  if (lpt.toLeft (cpt, rpt))
+  {
+    leftVertex->setRight (cvert);
+    cvert->setLeft (leftVertex);
+    cvert->setRight (rightVertex);
+    rightVertex->setLeft (cvert);
+    rightVertex->setRight (leftVertex);
+    leftVertex->setLeft (rightVertex);
+  }
+  else
+  {
+    leftVertex->setRight (rightVertex);
+    rightVertex->setLeft (leftVertex);
+    rightVertex->setRight (cvert);
+    cvert->setLeft (rightVertex);
+    cvert->setRight (leftVertex);
+    leftVertex->setLeft (cvert);
+  }
+
+  aph.init (leftVertex, cvert, rightVertex);
+  apv.setVertical ();
+  apv.init (leftVertex, cvert, rightVertex);
+
+  gbg.push_back (leftVertex);
+  gbg.push_back (cvert);
+  gbg.push_back (rightVertex);
+
+  old_left = leftVertex;
+  old_right = rightVertex;
+  old_aph_vertex = aph.vertex ();
+  old_aph_edge_start = aph.edgeStart ();
+  old_aph_edge_end = aph.edgeEnd ();
+  old_apv_vertex = apv.vertex ();
+  old_apv_edge_start = apv.edgeStart ();
+  old_apv_edge_end = apv.edgeEnd ();
+}
+
+
+ConvexHull::~ConvexHull ()
+{
+  for (int i = 0; i < (int) (gbg.size ()); ++i) delete gbg [i];
+}
+
+
+void ConvexHull::preserve ()
+{
+  old_aph_vertex = aph.vertex ();
+  old_aph_edge_start = aph.edgeStart ();
+  old_aph_edge_end = aph.edgeEnd ();
+  old_apv_vertex = apv.vertex ();
+  old_apv_edge_start = apv.edgeStart ();
+  old_apv_edge_end = apv.edgeEnd ();
+  old_left = leftVertex;
+  old_right = rightVertex;
+}
+
+
+void ConvexHull::restore ()
+{
+  rconnect->setLeft (rdisconnect);
+  lconnect->setRight (ldisconnect);
+  leftVertex = old_left;
+  rightVertex = old_right;
+  aph.setVertexAndEdge (old_aph_vertex, old_aph_edge_start, old_aph_edge_end);
+  apv.setVertexAndEdge (old_apv_vertex, old_apv_edge_start, old_apv_edge_end);
+}
+
+
+bool ConvexHull::addPoint (const Pt2i &pix, bool toleft)
+{
+  if (inHull (pix, toleft)) return false;
+  CHVertex *pt = new CHVertex (pix);
+  lastToLeft = toleft;
+  gbg.push_back (pt);
+  preserve ();
+  insert (pt, toleft);
+  aph.update (pt);
+  apv.update (pt);
+  return true;
+}
+
+
+bool ConvexHull::addPointDS (const Pt2i &pix, bool toleft)
+{
+  CHVertex *pt = new CHVertex (pix);
+  lastToLeft = toleft;
+  gbg.push_back (pt);
+  preserve ();
+  insertDS (pt, toleft);
+  aph.update (pt);
+  apv.update (pt);
+  return true;
+}
+
+
+bool ConvexHull::moveLastPoint (const Pt2i &pix)
+{
+  restore ();
+  if (inHull (pix, lastToLeft)) return false;
+  gbg.pop_back ();
+  preserve ();
+  addPoint (pix, lastToLeft);
+  return true;
+}
+
+
+AbsRat ConvexHull::rationalThickness () const
+{
+  AbsRat aphw = aph.rationalWidth ();
+  AbsRat apvw = apv.rationalWidth ();
+  return (apvw.lessThan (aphw) ? apvw : aphw);
+}
+
+
+void ConvexHull::antipodalEdgeAndVertex (Pt2i &s, Pt2i &e, Pt2i &v) const
+{
+  int n1, d1, n2, d2;
+  aph.width (n1, d1);
+  apv.width (n2, d2);
+  const Antipodal *ap = ((n2 * d1 < n1 * d2) ? &apv : &aph);
+  s.set (*(ap->edgeStart ()));
+  e.set (*(ap->edgeEnd ()));
+  v.set (*(ap->vertex ()));
+}
+
+
+bool ConvexHull::inHull (const Pt2i &pix, bool toleft) const
+{
+  CHVertex *ext = (toleft ? leftVertex : rightVertex);
+  return (pix.toLeftOrOn (*ext, *(ext->right ()))
+          && pix.toLeftOrOn (*(ext->left ()), *ext));
+}
+
+
+void ConvexHull::insert (CHVertex *pt, bool toleft)
+{
+  bool opIn = false; // Opposite polyline top in the new convex hull
+  CHVertex *opVertex = NULL; // Opposite vertex
+
+  if (toleft)
+  {
+    lconnect = leftVertex;
+    rconnect = leftVertex;
+    leftVertex = pt;
+    opVertex = rightVertex;
+  }
+  else
+  {
+    lconnect = rightVertex;
+    rconnect = rightVertex;
+    rightVertex = pt;
+    opVertex = leftVertex;
+  }
+
+  ldisconnect = lconnect->right ();
+  while (pt->toLeftOrOn (*lconnect, *(lconnect->left ())))
+  {
+    if (lconnect == opVertex) opIn = true;
+    ldisconnect = lconnect;
+    lconnect = lconnect->left ();
+  }
+  if (opIn)
+  {
+    if (toleft) rightVertex = lconnect;
+    else leftVertex = lconnect;
+  }
+
+  opIn = false;
+  rdisconnect = rconnect->left ();
+  while (! pt->toLeft (*rconnect, *(rconnect->right ())))
+  {
+    if (rconnect == opVertex) opIn = true;
+    rdisconnect = rconnect;
+    rconnect = rconnect->right ();
+  }
+  if (opIn)
+  {
+    if (toleft) rightVertex = rconnect;
+    else leftVertex = rconnect;
+  }
+  
+  lconnect->setRight (pt);
+  pt->setLeft (lconnect);
+  rconnect->setLeft (pt);
+  pt->setRight (rconnect);
+}
+
+
+void ConvexHull::insertDS (CHVertex *pt, bool toleft)
+{
+  if (toleft)
+  {
+    lconnect = leftVertex;
+    rconnect = leftVertex;
+    leftVertex = pt;
+  }
+  else
+  {
+    lconnect = rightVertex;
+    rconnect = rightVertex;
+    rightVertex = pt;
+  }
+
+  ldisconnect = lconnect->right ();
+  while (pt->toLeftOrOn (*lconnect, *(lconnect->left ())))
+  {
+    ldisconnect = lconnect;
+    lconnect = lconnect->left ();
+  }
+
+  rdisconnect = rconnect->left ();
+  while (! pt->toLeft (*rconnect, *(rconnect->right ())))
+  {
+    rdisconnect = rconnect;
+    rconnect = rconnect->right ();
+  }
+  
+  lconnect->setRight (pt);
+  pt->setLeft (lconnect);
+  rconnect->setLeft (pt);
+  pt->setRight (rconnect);
+}
+
+
+ostream& operator<< (ostream &os, const ConvexHull &ch)
+{
+  os << "APH = " << ch.aph << endl;
+  os << "APV = " << ch.apv << endl;
+  os << "FIRST " << *(ch.leftVertex);
+  CHVertex *next = ch.leftVertex->right ();
+  int i = 0;
+  while (i++ < 20 && next != ch.leftVertex)
+  {
+    os << " - " << *next;
+    next = next->right ();
+  }
+  if (i >= 20) os << " ---";
+  os << endl;
+  os << "LAST " << *(ch.rightVertex);
+  next = ch.rightVertex->left ();
+  i = 0;
+  while (i++ < 20 && next != ch.rightVertex)
+  {
+    os << " - " << *next;
+    next = next->left ();
+  }
+  if (i >= 20) os << " ---";
+
+  return os;
+}
diff --git a/Code/Seg/ConvexHull/convexhull.h b/Code/Seg/ConvexHull/convexhull.h
new file mode 100755
index 0000000000000000000000000000000000000000..7d54e8688ff72433782c68aa5e7dbffdcd08cd6a
--- /dev/null
+++ b/Code/Seg/ConvexHull/convexhull.h
@@ -0,0 +1,169 @@
+#ifndef CONVEXHULL
+#define CONVEXHULL
+
+
+#include <vector> 
+#include "antipodal.h"
+
+using namespace std;
+
+
+class ConvexHull
+{
+
+public:
+
+  /**
+   * \brief Creates a convex hull from a triangle.
+   * Be very careful with the points ordering : lpt, cpt, then rpt.
+   * Ensure that the points are NOT COLINEAR (not tested here).
+   * @param lpt : left end of the polyline.
+   * @param cpt : center of the polyline.
+   * @param rpt : right end of the polyline.
+   */
+  ConvexHull (const Pt2i &lpt, const Pt2i &cpt, const Pt2i &rpt);
+
+  /**
+   * \brief Deletes the convex hull.
+   * Removes all the registred vertices.
+   */
+  ~ConvexHull ();
+
+  /**
+   * \brief Restores the convexhull features after a modification.
+   */
+  void restore ();
+
+  
+  /**
+   * \brief Appends a new point at one side of the convex hull.
+   */
+  bool addPoint (const Pt2i &pix, bool toleft);
+
+  /**
+   * \brief Appends a new point at one side of the convex hull.
+   * To be used with directional scans :
+   *   In that case, added point can not be inside the hull.
+   */
+  bool addPointDS (const Pt2i &pix, bool toleft);
+
+  /**
+   * \brief Moves the last entered point and returns the success.
+   */
+  bool moveLastPoint (const Pt2i &pix);
+
+  /**
+   * \brief Checks whether the line to the given point crosses the hull.
+   */
+  bool inHull (const Pt2i &pix, bool toleft) const;
+
+
+  /**
+   * Returns the antipodal vertex.
+   * @param s Antipodal edge start.
+   * @param e Antipodal edge end.
+   * @param v Antipodal vertex.
+   */
+  void antipodalEdgeAndVertex (Pt2i &s, Pt2i &e, Pt2i &v) const;
+
+  /**
+   * Returns the minimal vertical or horizontal thickness of the convex hull.
+   */
+  AbsRat rationalThickness () const;
+
+  /**
+   * Returns a string that represents the convex hull.
+   */
+  friend ostream& operator<< (ostream &os, const ConvexHull &ch);
+
+  /**
+   * Returns the first vertex of the convex hull.
+   */
+  inline CHVertex *getFirstVertex () const { return (leftVertex); }
+
+  /**
+   * Returns the last vertex of the convex hull.
+   */
+  inline CHVertex *getLastVertex () const { return (rightVertex); }
+
+  /**
+   * Returns the horizontal antipodal vertex.
+   */
+  inline CHVertex *getAphVertex () const { return (aph.vertex ()); }
+
+  /**
+   * Returns the horizontal antipodal edge start.
+   */
+  inline CHVertex *getAphEdgeStart () const { return (aph.edgeStart ()); }
+
+  /**
+   * Returns the horizontal antipodal edge end.
+   */
+  inline CHVertex *getAphEdgeEnd () const { return (aph.edgeEnd ()); }
+
+  /**
+   * Returns the vertical antipodal vertex.
+   */
+  inline CHVertex *getApvVertex () const { return (apv.vertex ()); }
+
+  /**
+   * Returns the vertical antipodal edge start.
+   */
+  inline CHVertex *getApvEdgeStart () const { return (apv.edgeStart ()); }
+
+  /**
+   * Returns the vertical antipodal edge end.
+   */
+  inline CHVertex *getApvEdgeEnd () const { return (apv.edgeEnd ()); }
+
+
+private:
+
+  /**
+   * Stores the convexhull features before a modification.
+   */
+  void preserve ();
+
+  /**
+   * Inserts a new point into the convex hull.
+   */
+  void insert (CHVertex *pt, bool toleft);
+
+  /**
+   * Inserts a new point into the convex hull.
+   * To be used with directional scans :
+   *   In that case, opposite ends of the polyline can never pass each other.
+   */
+  void insertDS (CHVertex *pt, bool toleft);
+
+
+protected:
+
+  /** Polyline left end point. */
+  CHVertex *leftVertex;
+  /** Polyline right end point. */
+  CHVertex *rightVertex;
+  /** Indicates if the last vertex was entered to the left. */
+  bool lastToLeft;
+
+  /** Antipodal pair in horizontal direction. */
+  Antipodal aph;
+  /** Antipodal pair in vertical direction. */
+  Antipodal apv;
+
+  /** Registration of previous horizontal antipodal pair. */
+  CHVertex *old_aph_vertex, *old_aph_edge_start, *old_aph_edge_end;;
+  /** Registration of previous vertical antipodal pair. */
+  CHVertex *old_apv_vertex, *old_apv_edge_start, *old_apv_edge_end;
+  /** Registration of previous polyline left end point. */
+  CHVertex *old_left;
+  /** Registration of previous polyline right end point. */
+  CHVertex *old_right;
+  /** Registration of previous connections. */
+  CHVertex *lconnect, *ldisconnect, *rconnect, *rdisconnect;
+
+  /** Collection of vertices for clearance. */
+  vector<CHVertex*> gbg;
+
+};
+#endif
diff --git a/Code/Seg/DirectionalScanner/directionalscanner.cpp b/Code/Seg/DirectionalScanner/directionalscanner.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2c94dbd2632a39b5bf07d469318d4163bec4057f
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscanner.cpp
@@ -0,0 +1,18 @@
+#include <cstdlib>
+#include "directionalscanner.h"
+
+
+
+void DirectionalScanner::bindTo (int a, int b, int c)
+{
+  (void) a;
+  (void) b;
+  (void) c;
+}
+
+
+DirectionalScanner::~DirectionalScanner ()
+{
+  if (steps != NULL) delete steps;
+  steps = NULL;
+}
diff --git a/Code/Seg/DirectionalScanner/directionalscanner.h b/Code/Seg/DirectionalScanner/directionalscanner.h
new file mode 100755
index 0000000000000000000000000000000000000000..d7a6870ff749ea2527c522a2336ee6543d7315fb
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscanner.h
@@ -0,0 +1,110 @@
+#ifndef DIRECTIONAL_SCANNER_H
+#define DIRECTIONAL_SCANNER_H
+
+#include <cstdlib>
+#include <vector>
+#include "pt2i.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DirectionalScanner directionalscanner.h
+ * \brief Incremental directional scanner.
+ * This scanner iterately provides parallel scan lines.
+ * \author {P. Even and B. Kerautret}
+ */
+class DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn ~DirectionalScan()
+   * \brief Deletes the scan strip.
+   */
+  virtual ~DirectionalScanner ();
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  virtual int first (vector<Pt2i> &scan) = 0;
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  virtual int nextOnLeft (vector<Pt2i> &scan) = 0;
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  virtual int nextOnRight (vector<Pt2i> &scan) = 0;
+
+  /**
+   * @fn bindTo(int a, int b, int c)
+   * \brief Binds the scan stripe to wrap the given digital line.
+   * Resets the bounding lines parameters to center on the given line.
+   * @param a New value for the 'a' parameter of the current scan stripe.
+   * @param b New value for the 'b' parameter of the current scan stripe.
+   * @param c New value for the medial axis of the current scan stripe.
+   */
+  virtual void bindTo (int a, int b, int c);
+
+
+protected:
+
+  /** Scanable area. */
+  int xmin, ymin, xmax, ymax;
+
+  /** Coefficients of the discrete upper support line. */
+  int dla, dlb, dlc2;
+
+  /** Size of the discrete line pattern. */
+  int nbs;
+
+  /** Discrete line pattern and its end. */
+  bool *steps, *fs;
+
+  /** Start position of a scan for both directions. */
+  int lcx, lcy, rcx, rcy;
+
+  /** Current step in scan direction. */
+  bool *lst2, *rst2;
+
+  DirectionalScanner () { }
+
+  /**
+   * @fn DirectionalScanner(int xmini, int ymini, int xmaxi, int ymaxi,
+   *                        int nb, bool* st, int sx, int sy)
+   * \brief Creates an incremental directional scanner.
+   * Creates a directional scanner from pattern and start.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point and a line pattern.
+   * @param xmini left border of the scan area
+   * @param ymini low border of the scan area
+   * @param xmaxi right border of the scan area
+   * @param ymaxi up border of the scan area
+   * @param nb size of the support line pattern
+   * @param st support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DirectionalScanner (int xmini, int ymini, int xmaxi, int ymaxi,
+                      int nb, bool* st, int sx, int sy)
+             : xmin (xmini), ymin (ymini), xmax (xmaxi), ymax (ymaxi),
+               nbs (nb), steps (st),
+               lcx (sx), lcy (sy), rcx (sx), rcy (sy) { }
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/directionalscannero1.cpp b/Code/Seg/DirectionalScanner/directionalscannero1.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..a31f3109df263334adc589e52781c357f701f578
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero1.cpp
@@ -0,0 +1,223 @@
+#include <cstdlib>
+#include <iostream>
+#include "directionalscannero1.h"
+
+
+
+DirectionalScannerO1::DirectionalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO1::DirectionalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else this->dlc2 = c2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx ++;
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO1::DirectionalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx ++;
+    lcy --;
+  }
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cx--;
+    cy++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+int DirectionalScannerO1::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO1::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (ltransition)
+  {
+    lcy --;
+    if (--lst2 < steps) lst2 = fs - 1;
+    ltransition = false;
+  }
+  else
+  {
+    if (--lst1 < steps) lst1 = fs - 1;
+    lcx --;
+    if (*lst1)
+    {
+      lcy --;
+      if (--lst2 < steps) lst2 = fs - 1;
+      if (*lst2)
+      {
+        if (++lst2 >= fs) lst2 = steps;
+        lcy ++;
+        ltransition = true;
+      }
+    }
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO1::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (rtransition)
+  {
+    rcx ++;
+    rtransition = false;
+  }
+  else
+  {
+    rcx ++;
+    if (*rst1)
+    {
+      if (*rst2)
+      {
+        rcx --;
+        rtransition = true;
+      }
+      rcy ++;
+      if (++rst2 >= fs) rst2 = steps;
+    }
+    if (++rst1 >= fs) rst1 = steps;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/directionalscannero1.h b/Code/Seg/DirectionalScanner/directionalscannero1.h
new file mode 100755
index 0000000000000000000000000000000000000000..ee48df78dc0af2356f7ee832503110ee89119597
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero1.h
@@ -0,0 +1,125 @@
+#ifndef DIRECTIONAL_SCANNER_O1_H
+#define DIRECTIONAL_SCANNER_O1_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DirectionalScannerO1 directionalscannero1.h
+ * \brief Incremental directional scanner for the 1st octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DirectionalScannerO1 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DirectionalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int mu2,
+   *                          int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DirectionalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DirectionalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int c1, int c2,
+   *                          int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */ 
+  DirectionalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DirectionalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b,
+   *                          int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DirectionalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b,
+                        int nbs, bool *steps,
+                        int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+private:
+
+  /** Current step in strip direction */
+  bool *lst1, *rst1;
+
+  /** State of the scan */
+  bool ltransition, rtransition;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/directionalscannero2.cpp b/Code/Seg/DirectionalScanner/directionalscannero2.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..5d6ff02db5149207e16fcee6fa46ded209aa663d
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero2.cpp
@@ -0,0 +1,222 @@
+#include <cstdlib>
+#include <iostream>
+#include "directionalscannero2.h"
+
+
+
+DirectionalScannerO2::DirectionalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO2::DirectionalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else this->dlc2 = c2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx ++;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO2::DirectionalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx ++;
+  }
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cy++;
+    cx--;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  ltransition = false; 
+  rtransition = false;
+}
+
+
+int DirectionalScannerO2::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO2::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (ltransition)
+  {
+    lcy --;
+    ltransition = false;
+  }
+  else
+  {
+    if (--lst1 < steps) lst1 = fs - 1;
+    lcy --;
+    if (*lst1)
+    {
+      lcx --;
+      if (*lst2)
+      {
+        lcy ++;
+        ltransition = true;
+      }
+      if (++lst2 >= fs) lst2 = steps;
+    }
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO2::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (rtransition)
+  {
+    rcx ++;
+    if (--rst2 < steps) rst2 = fs - 1;
+    rtransition = false;
+  }
+  else
+  {
+    rcy ++;
+    if (*rst1)
+    {
+      if (--rst2 < steps) rst2 = fs - 1;
+      if (*rst2)
+      {
+        if (++rst2 >= fs) rst2 = steps;
+        rtransition = true;
+      }
+      else rcx ++;
+    }
+    if (++rst1 >= fs) rst1 = steps;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/directionalscannero2.h b/Code/Seg/DirectionalScanner/directionalscannero2.h
new file mode 100755
index 0000000000000000000000000000000000000000..6e06b5dfc3715467a494b49e27291b71a56e64e8
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero2.h
@@ -0,0 +1,125 @@
+#ifndef DIRECTIONAL_SCANNER_O2_H
+#define DIRECTIONAL_SCANNER_O2_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DirectionalScannerO2 directionalscannero2.h
+ * \brief Incremental directional scanner for the 2nd octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DirectionalScannerO2 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DirectionalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int mu2,
+   *                          int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DirectionalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DirectionalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int c1, int c2,
+   *                          int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DirectionalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DirectionalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b,
+   *                          int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DirectionalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b,
+                        int nbs, bool *steps,
+                        int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+private:
+
+  /** Current step in strip direction */
+  bool *lst1, *rst1;
+
+  /** State of the scan */
+  bool ltransition, rtransition;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/directionalscannero7.cpp b/Code/Seg/DirectionalScanner/directionalscannero7.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..c62fb5313c81f0f4b80eac54c530c84d5a6e31e1
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero7.cpp
@@ -0,0 +1,223 @@
+#include <cstdlib>
+#include <iostream>
+#include "directionalscannero7.h"
+
+
+
+DirectionalScannerO7::DirectionalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO7::DirectionalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else this->dlc2 = c2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO7::DirectionalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx --;
+  }
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cy++;
+    cx++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+int DirectionalScannerO7::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO7::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (ltransition)
+  {
+    lcx --;
+    if (--lst2 < steps) lst2 = fs - 1;
+    ltransition = false;
+  }
+  else
+  {
+    if (--lst1 < steps) lst1 = fs - 1;
+    lcy ++;
+    if (*lst1)
+    {
+      if (--lst2 < steps) lst2 = fs - 1;
+      if (*lst2)
+      {
+        if (++lst2 >= fs) lst2 = steps;
+        ltransition = true;
+      }
+      else lcx --;
+    }
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO7::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (rtransition)
+  {
+    rcy --;
+    rtransition = false;
+  }
+  else
+  {
+    rcy --;
+    if (*rst1)
+    {
+      rcx ++;
+      if (*rst2)
+      {
+        rcy ++;
+        rtransition = true;
+      }
+      if (++rst2 >= fs) rst2 = steps;
+    }
+    if (++rst1 >= fs) rst1 = steps;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst == fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst == fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/directionalscannero7.h b/Code/Seg/DirectionalScanner/directionalscannero7.h
new file mode 100755
index 0000000000000000000000000000000000000000..404338da972dbf320783d38c1e352e5e4d08a63f
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero7.h
@@ -0,0 +1,125 @@
+#ifndef DIRECTIONAL_SCANNER_O7_H
+#define DIRECTIONAL_SCANNER_O7_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DirectionalScannerO7 directionalscannero7.h
+ * \brief Incremental directional scanner for the 7th octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DirectionalScannerO7 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DirectionalScannerO7(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int mu2,
+   *                          int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DirectionalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DirectionalScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int c1, int c2,
+   *                          int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DirectionalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DirectionalScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b,
+   *                          int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DirectionalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b,
+                        int nbs, bool *steps,
+                        int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+private:
+
+  /** Current step in strip direction */
+  bool *lst1, *rst1;
+
+  /** State of the scan */
+  bool ltransition, rtransition;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/directionalscannero8.cpp b/Code/Seg/DirectionalScanner/directionalscannero8.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..3b78148bc9b92003e0efbcf19bbfbf2d60340112
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero8.cpp
@@ -0,0 +1,223 @@
+#include <cstdlib>
+#include <iostream>
+#include "directionalscannero8.h"
+
+
+
+DirectionalScannerO8::DirectionalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO8::DirectionalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else this->dlc2 = c2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx --;
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+DirectionalScannerO8::DirectionalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx --;
+    lcy --;
+  }
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cx++;
+    cy++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst1 = steps;
+  rst1 = steps;
+  lst2 = steps;
+  rst2 = steps;
+  ltransition = false;
+  rtransition = false;
+}
+
+
+
+int DirectionalScannerO8::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO8::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (ltransition)
+  {
+    lcx --;
+    ltransition = false;
+  }
+  else
+  {
+    if (--lst1 < steps) lst1 = fs - 1;
+    lcx --;
+    if (*lst1)
+    {
+      lcy ++;
+      if (*lst2)
+      {
+        lcx ++;
+        ltransition = true;
+      }
+      if (++lst2 >= fs) lst2 = steps;
+    }
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DirectionalScannerO8::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  if (rtransition)
+  {
+    rcy --;
+    if (--rst2 < steps) rst2 = fs - 1;
+    rtransition = false;
+  }
+  else
+  {
+    rcx ++;
+    if (*rst1)
+    {
+      if (--rst2 < steps) rst2 = fs - 1;
+      if (*rst2)
+      {
+        if (++rst2 >= fs) rst2 = steps;
+        rtransition = true;
+      }
+      else rcy --;
+    }
+    if (++rst1 >= fs) rst1 = steps;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/directionalscannero8.h b/Code/Seg/DirectionalScanner/directionalscannero8.h
new file mode 100755
index 0000000000000000000000000000000000000000..0e8bea1c6cae99e0f1cfef3a25c8d0cfa443b7c2
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/directionalscannero8.h
@@ -0,0 +1,125 @@
+#ifndef DIRECTIONAL_SCANNER_O8_H
+#define DIRECTIONAL_SCANNER_O8_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DirectionalScannerO8 directionalscannero8.h
+ * \brief Incremental directional scanner for the 8th octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DirectionalScannerO8 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DirectionalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int mu2,
+   *                          int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DirectionalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DirectionalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b, int c1, int c2,
+   *                          int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DirectionalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DirectionalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                          int a, int b,
+   *                          int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DirectionalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b,
+                        int nbs, bool *steps,
+                        int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+private:
+
+  /** Current step in strip direction */
+  bool *lst1, *rst1;
+
+  /** State of the scan */
+  bool ltransition, rtransition;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..a3cad70c82ed2d953a3863d2394b720510a375f0
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp
@@ -0,0 +1,245 @@
+#include <cstdlib>
+#include <iostream>
+#include "dynamicalscannero1.h"
+
+
+
+DynamicalScannerO1::DynamicalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+  this->dlc1 = a * sx + b * sy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO1::DynamicalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx ++;
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO1::DynamicalScannerO1 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx ++;
+    lcy --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cx--;
+    cy++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+int DynamicalScannerO1::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO1::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcx --;
+  // Whenever the control line changed
+  while (lcy < ymax - 1 && lcx >= xmin && dla * lcx + dlb * lcy > dlc1)
+  {
+    if (*lst2) lcx --;
+    lcy ++;
+    if (++lst2 >= fs) lst2 = steps;
+  }
+  while (lcy > ymin && lcx < xmax && dla * lcx + dlb * lcy < dlc1)
+  {
+    if (--lst2 < steps) lst2 = steps + nbs - 1;
+    if (*lst2) lcx ++;
+    lcy --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x --;
+    y ++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x --;
+    y ++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO1::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcx ++;
+  while (rcy < ymax - 1 && rcx >= xmin && dla * rcx + dlb * rcy > dlc1)
+  {
+    if (*rst2) rcx --;
+    rcy ++;
+    if (++rst2 >= fs) rst2 = steps;
+  }
+  while (rcy > ymin && rcx < xmax && dla * rcx + dlb * rcy < dlc1)
+  {
+    if (--rst2 < steps) rst2 = steps + nbs - 1;
+    if (*rst2) rcx ++;
+    rcy --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((x >= xmax || y < ymin) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x--;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+void DynamicalScannerO1::bindTo (int a, int b, int c)
+{
+  if (a < 0)
+  {
+    dla = -a;
+    dlb = -b;
+    c = -c;
+  }
+  else
+  {
+    dla = a;
+    dlb = b;
+  }
+  int old_b = (templ_b < 0 ? -templ_b : templ_b);
+  int old_n1 = templ_a + old_b;
+  int old_ninf = (old_b > templ_a ? old_b : templ_a);
+  int new_a = (a < 0 ? -a : a);
+  int new_b = (b < 0 ? -b : b);
+  int new_n1 = new_a + new_b;
+  int new_ninf = (new_b > new_a ? new_b : new_a);
+  int nu;
+  if (new_n1 * old_ninf > old_n1 * new_ninf)
+    nu = (templ_nu * new_n1) / old_n1;
+  else
+    nu = (templ_nu * new_ninf) / old_ninf;
+  dlc1 = c + nu / 2;
+  dlc2 = c - nu / 2;
+}
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero1.h b/Code/Seg/DirectionalScanner/dynamicalscannero1.h
new file mode 100755
index 0000000000000000000000000000000000000000..4756ef31f2382fc76a8b4d67fc8e6bf48947c62c
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero1.h
@@ -0,0 +1,137 @@
+#ifndef DYNAMICAL_SCANNER_O1_H
+#define DYNAMICAL_SCANNER_O1_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DynamicalScannerO1 dynamicalscannero1.h
+ * \brief Dynamical directional scanner for the 1st octant.
+ * \author {P. Even}
+ */
+class DynamicalScannerO1 : public DirectionalScanner
+{
+
+public:
+
+  /**
+   * @fn DynamicalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int mu2,
+   *                        int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DynamicalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DynamicalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int c1, int c2,
+   *                        int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */ 
+  DynamicalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DynamicalScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b,
+   *                        int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length .
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DynamicalScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                      int a, int b,
+                      int nbs, bool *steps,
+                      int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+  /**
+   * @fn bindTo(int a, int b, int c)
+   * \brief Binds the scan stripe to wrap the given digital line.
+   * Resets the bounding lines parameters to center on the given line.
+   * @param a New value for the 'a' parameter of the current scan stripe.
+   * @param b New value for the 'b' parameter of the current scan stripe.
+   * @param c New value for the medial axis of the current scan stripe.
+   */
+  void bindTo (int a, int b, int c);
+
+protected :
+
+  DynamicalScannerO1 () { }
+  
+  /** Coefficients of the template discrete support lines */
+  int templ_a, templ_b, templ_nu;
+
+  /** Intercept coefficient of the discrete lower support line */
+  int dlc1;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero2.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero2.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..bfb7a6a6d6ad3a81e8cf95522298e3cad9c62294
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero2.cpp
@@ -0,0 +1,245 @@
+#include <cstdlib>
+#include <iostream>
+#include "dynamicalscannero2.h"
+
+
+
+DynamicalScannerO2::DynamicalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+  this->dlc1 = a * sx + b * sy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO2::DynamicalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx ++;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO2::DynamicalScannerO2 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx ++;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cy++;
+    cx--;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+int DynamicalScannerO2::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO2::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcy --;
+  // Whenever the control line changed
+  while (lcx > xmin && lcy < ymax && dla * lcx + dlb * lcy > dlc1)
+  {
+    if (*lst2) lcy ++;
+    lcx --;
+    if (++lst2 >= fs) lst2 = steps;
+  }
+  while (lcx < xmax - 1 && lcy >= ymin && dla * lcx + dlb * lcy < dlc1)
+  {
+    if (--lst2 < steps) lst2 = steps + nbs - 1;
+    if (*lst2) lcy --;
+    lcx ++;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO2::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcy ++;
+  while (rcx > xmin && rcy < ymax && dla * rcx + dlb * rcy > dlc1)
+  {
+    if (*rst2) rcy ++;
+    rcx --;
+    if (++rst2 >= fs) rst2 = steps;
+  }
+  while (rcx < xmax - 1 && rcy >= ymin && dla * rcx + dlb * rcy < dlc1)
+  {
+    if (--rst2 < steps) rst2 = steps + nbs - 1;
+    if (*rst2) rcy --;
+    rcx ++;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x--;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+void DynamicalScannerO2::bindTo (int a, int b, int c)
+{
+  if (a < 0)
+  {
+    dla = -a;
+    dlb = -b;
+    c = -c;
+  }
+  else
+  {
+    dla = a;
+    dlb = b;
+  }
+  int old_b = (templ_b < 0 ? -templ_b : templ_b);
+  int old_n1 = templ_a + old_b;
+  int old_ninf = (old_b > templ_a ? old_b : templ_a);
+  int new_a = (a < 0 ? -a : a);
+  int new_b = (b < 0 ? -b : b);
+  int new_n1 = new_a + new_b;
+  int new_ninf = (new_b > new_a ? new_b : new_a);
+  int nu;
+  if (new_n1 * old_ninf > old_n1 * new_ninf)
+    nu = (templ_nu * new_n1) / old_n1;
+  else
+    nu = (templ_nu * new_ninf) / old_ninf;
+  dlc1 = c + nu / 2;
+  dlc2 = c - nu / 2;
+}
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero2.h b/Code/Seg/DirectionalScanner/dynamicalscannero2.h
new file mode 100755
index 0000000000000000000000000000000000000000..e7500c3b89c0f5c07e8384347ae652704949c037
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero2.h
@@ -0,0 +1,137 @@
+#ifndef DYNAMICAL_SCANNER_O2_H
+#define DYNAMICAL_SCANNER_O2_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DynamicalScannerO2 dynamicalscannero2.h
+ * \brief Dynamical directional scanner for the 2nd octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DynamicalScannerO2 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DynamicalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int mu2,
+   *                        int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DynamicalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DynamicalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int c1, int c2,
+   *                        int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DynamicalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DynamicalScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b,
+   *                        int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DynamicalScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                      int a, int b,
+                      int nbs, bool *steps,
+                      int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+  /**
+   * @fn bindTo(int a, int b, int c)
+   * \brief Binds the scan stripe to wrap the given digital line.
+   * Resets the bounding lines parameters to center on the given line.
+   * @param a New value for the 'a' parameter of the current scan stripe.
+   * @param b New value for the 'b' parameter of the current scan stripe.
+   * @param c New value for the medial axis of the current scan stripe.
+   */
+  void bindTo (int a, int b, int c);
+
+protected :
+
+  DynamicalScannerO2 () { }
+
+  /** Coefficients of the template discrete support lines */
+  int templ_a, templ_b, templ_nu;
+
+  /** Intercept coefficient of the discrete lower support line */
+  int dlc1;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero7.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero7.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..5e05a2bbc932242886d074890d020a4cc1636504
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero7.cpp
@@ -0,0 +1,246 @@
+#include <cstdlib>
+#include <iostream>
+#include "dynamicalscannero7.h"
+
+
+
+DynamicalScannerO7::DynamicalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+  this->dlc1 = a * sx + b * sy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO7::DynamicalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO7::DynamicalScannerO7 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcy --;
+    lcx --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cy++;
+    cx++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+
+int DynamicalScannerO7::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO7::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcy ++;
+  while (lcx < xmax - 1 && lcy < ymax && dla * lcx + dlb * lcy < dlc1)
+  {
+    if (*lst2) lcy ++;
+    lcx ++;
+    if (++lst2 >= fs) lst2 = steps;
+  }
+  while (lcx > xmin && lcy >= ymin && dla * lcx + dlb * lcy > dlc1)
+  {
+    if (--lst2 < steps) lst2 = steps + nbs - 1;
+    if (*lst2) lcy --;
+    lcx --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO7::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcy --;
+  // Whenever the control corridor changed
+  while (rcx < xmax - 1 && rcy < ymax && dla * rcx + dlb * rcy < dlc1)
+  {
+    if (*rst2) rcy ++;
+    rcx ++;
+    if (++rst2 >= fs) rst2 = steps;
+  }
+  while (rcx > xmin && rcy >= ymin && dla * rcx + dlb * rcy > dlc1)
+  {
+    if (--rst2 < steps) rst2 = steps + nbs - 1;
+    if (*rst2) rcy --;
+    rcx --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((y < ymin || x < xmin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) y++;
+    x++;
+    if (++nst == fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) y++;
+    x++;
+    if (++nst == fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+void DynamicalScannerO7::bindTo (int a, int b, int c)
+{
+  if (a < 0)
+  {
+    dla = -a;
+    dlb = -b;
+    c = -c;
+  }
+  else
+  {
+    dla = a;
+    dlb = b;
+  }
+  int old_b = (templ_b < 0 ? -templ_b : templ_b);
+  int old_n1 = templ_a + old_b;
+  int old_ninf = (old_b > templ_a ? old_b : templ_a);
+  int new_a = (a < 0 ? -a : a);
+  int new_b = (b < 0 ? -b : b);
+  int new_n1 = new_a + new_b;
+  int new_ninf = (new_b > new_a ? new_b : new_a);
+  int nu;
+  if (new_n1 * old_ninf > old_n1 * new_ninf)
+    nu = (templ_nu * new_n1) / old_n1;
+  else
+    nu = (templ_nu * new_ninf) / old_ninf;
+  dlc1 = c - nu / 2;
+  dlc2 = c + nu / 2;
+}
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero7.h b/Code/Seg/DirectionalScanner/dynamicalscannero7.h
new file mode 100755
index 0000000000000000000000000000000000000000..34174fcaa737f971efb73bdfbea123d821b69b50
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero7.h
@@ -0,0 +1,137 @@
+#ifndef DYNAMICAL_SCANNER_O7_H
+#define DYNAMICAL_SCANNER_O7_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DynamicalScannerO7 controlablescannero7.h
+ * \brief Dynamical directional scanner for the 7th octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DynamicalScannerO7 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DynamicalScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int mu2,
+   *                        int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DynamicalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DynamicalScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int c1, int c2,
+   *                        int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DynamicalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DynamicalScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b,
+   *                        int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DynamicalScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                      int a, int b,
+                      int nbs, bool *steps,
+                      int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+  /**
+   * @fn bindTo(int a, int b, int c)
+   * \brief Binds the scan stripe to wrap the given digital line.
+   * Resets the bounding lines parameters to center on the given line.
+   * @param a New value for the 'a' parameter of the current scan stripe.
+   * @param b New value for the 'b' parameter of the current scan stripe.
+   * @param c New value for the medial axis of the current scan stripe.
+   */
+  void bindTo (int a, int b, int c);
+
+protected :
+
+  DynamicalScannerO7 () { }
+
+  /** Coefficients of the template discrete support lines */
+  int templ_a, templ_b, templ_nu;
+
+  /** Intercept coefficient of the discrete lower support line */
+  int dlc1;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..ae42796b1c7427341166944879e130001fcc5a50
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp
@@ -0,0 +1,246 @@
+#include <cstdlib>
+#include <iostream>
+#include "dynamicalscannero8.h"
+
+
+
+DynamicalScannerO8::DynamicalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, sx, sy)
+{
+  this->dla = a;
+  this->dlb = b;
+  this->dlc2 = c;
+  this->dlc1 = a * sx + b * sy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO8::DynamicalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  do
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx --;
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+DynamicalScannerO8::DynamicalScannerO8 (
+                          int xmin, int ymin, int xmax, int ymax,
+                          int a, int b,
+                          int nbs, bool *steps, int cx, int cy, int length)
+                    : DirectionalScanner (xmin, ymin, xmax, ymax,
+                                          nbs, steps, cx, cy)
+{
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  bool *st = steps + nbs;
+  for (int i = 0; i < w_2; i++)
+  {
+    if (--st < steps) st = steps + nbs - 1;
+    if (*st) lcx --;
+    lcy --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  st = steps;
+  while (w_2-- > 0)
+  {
+    if (*st) cx++;
+    cy++;
+    if (++st >= fs) st = steps;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+
+int DynamicalScannerO8::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+  bool *nst = steps;         // Current step in scan direction (jpts)
+
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO8::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcx --;
+  while (lcy < ymax - 1 && lcx < xmax && dla * lcx + dlb * lcy < dlc1)
+  {
+    if (*lst2) lcx ++;
+    lcy ++;
+    if (++lst2 >= fs) lst2 = steps;
+  }
+  while (lcy > ymin && lcx >= xmin && dla * lcx + dlb * lcy > dlc1)
+  {
+    if (--lst2 < steps) lst2 = steps + nbs - 1;
+    if (*lst2) lcx --;
+    lcy --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  bool *nst = lst2;
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int DynamicalScannerO8::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcx ++;
+  // Whenever the control corridor changed
+  while (rcy < ymax - 1 && rcx < xmax && dla * rcx + dlb * rcy < dlc1)
+  {
+    if (*rst2) rcx ++;
+    rcy ++;
+    if (++rst2 >= fs) rst2 = steps;
+  }
+  while (rcy > ymin && rcx >= xmin && dla * rcx + dlb * rcy > dlc1)
+  {
+    if (--rst2 < steps) rst2 = steps + nbs - 1;
+    if (*rst2) rcx --;
+    rcy --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  bool *nst = rst2;
+  while ((x < xmin || y < ymin) && dla * x + dlb * y <= dlc2)
+  {
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    if (*nst) x++;
+    y++;
+    if (++nst >= fs) nst = steps;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+void DynamicalScannerO8::bindTo (int a, int b, int c)
+{
+  if (a < 0)
+  {
+    dla = -a;
+    dlb = -b;
+    c = -c;
+  }
+  else
+  {
+    dla = a;
+    dlb = b;
+  }
+  int old_b = (templ_b < 0 ? -templ_b : templ_b);
+  int old_n1 = templ_a + old_b;
+  int old_ninf = (old_b > templ_a ? old_b : templ_a);
+  int new_a = (a < 0 ? -a : a);
+  int new_b = (b < 0 ? -b : b);
+  int new_n1 = new_a + new_b;
+  int new_ninf = (new_b > new_a ? new_b : new_a);
+  int nu;
+  if (new_n1 * old_ninf > old_n1 * new_ninf)
+    nu = (templ_nu * new_n1) / old_n1;
+  else
+    nu = (templ_nu * new_ninf) / old_ninf;
+  dlc1 = c - nu / 2;
+  dlc2 = c + nu / 2;
+}
diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero8.h b/Code/Seg/DirectionalScanner/dynamicalscannero8.h
new file mode 100755
index 0000000000000000000000000000000000000000..5944231351d80134eb2e7cef35e1274465c0a43b
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/dynamicalscannero8.h
@@ -0,0 +1,137 @@
+#ifndef DYNAMICAL_SCANNER_O8_H
+#define DYNAMICAL_SCANNER_O8_H
+
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class DynamicalScannerO8 dynamicalscannero8.h
+ * \brief Dynamical directional scanner for the 8th octant.
+ * \author {P. Even and B. Kerautret}
+ */
+class DynamicalScannerO8 : public DirectionalScanner
+{
+
+public:
+  
+  /**
+   * @fn DynamicalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int mu2,
+   *                        int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a directional scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  DynamicalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c,
+                        int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn DynamicalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b, int c1, int c2,
+   *                        int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a directional scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  DynamicalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                        int a, int b, int c1, int c2,
+                        int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn DynamicalScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                        int a, int b,
+   *                        int nbs, bool *steps, int cx, int cy, int length)
+   * \brief Creates a directional scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  DynamicalScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                      int a, int b,
+                      int nbs, bool *steps,
+                      int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+  /**
+   * @fn bindTo(int a, int b, int c)
+   * \brief Binds the scan stripe to wrap the given digital line.
+   * Resets the bounding lines parameters to center on the given line.
+   * @param a New value for the 'a' parameter of the current scan stripe.
+   * @param b New value for the 'b' parameter of the current scan stripe.
+   * @param c New value for the medial axis of the current scan stripe.
+   */
+  void bindTo (int a, int b, int c);
+
+protected :
+
+  DynamicalScannerO8 () { }
+
+  /** Coefficients of the template discrete support lines */
+  int templ_a, templ_b, templ_nu;
+
+  /** Intercept coefficient of the discrete lower support line */
+  int dlc1;
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/scannerprovider.cpp b/Code/Seg/DirectionalScanner/scannerprovider.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..6cc5bedf73e0ca954c373d0c7fa91967570431a7
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/scannerprovider.cpp
@@ -0,0 +1,264 @@
+#include <cstdlib>
+#include <iostream>
+#include "scannerprovider.h"
+#include "directionalscannero2.h"
+#include "directionalscannero7.h"
+#include "directionalscannero1.h"
+#include "directionalscannero8.h"
+#include "vhscannero2.h"
+#include "vhscannero7.h"
+#include "vhscannero1.h"
+#include "vhscannero8.h"
+
+
+
+DirectionalScanner *ScannerProvider::getScanner (
+                Pt2i p1, Pt2i p2,
+                int xmin, int ymin, int xmax, int ymax)
+{
+  // Enforces P1 to be lower than P2
+  // or to left of P2 in cas of equality
+  if ((p1.y () > p2.y ())
+      || ((p1.y () == p2.y ()) && (p1.x () > p2.x ())))
+  {
+    Pt2i tmp = p1;
+    p1 = p2;
+    p2 = tmp;
+  }
+
+  // Computes the steps position array
+  int nbs = 0;
+  bool *steps = p1.stepsTo (p2, &nbs);
+
+  // Equation of the strip support lines : ax + by = c
+  int a = p2.x () - p1.x ();
+  int b = p2.y () - p1.y ();
+  if (a < 0 || (a == 0 && b < 0)) // Enforces a >= 0, then b > 0
+  {
+    a = -a;
+    b = -b;
+  }
+  int c2 = a * p2.x () + b * p2.y ();
+
+  // Builds and returns the appropriate scanner
+  if (b < 0)
+    if (-b > a)
+    {
+      if (isOrtho)
+      {
+        int repx = (p1.x () + p2.x ()) / 2;    // central scan start
+        int repy = p1.y () - (int) ((p1.x () - repx) * (p1.x () - p2.x ())
+                                    / (p2.y () - p1.y ()));
+        return (new VHScannerO1 (xmin, ymin, xmax, ymax,
+                                 a, b, c2, nbs, steps, repx, repy));
+      }
+      else return (new DirectionalScannerO1 (xmin, ymin, xmax, ymax,
+                          a, b, c2, nbs, steps, p1.x (), p1.y ()));
+    }
+    else
+    {
+      if (isOrtho)
+      {
+        int repy = (p1.y () + p2.y ()) / 2;    // central scan start
+        int repx = p1.x () + (int) ((repy - p1.y ()) * (p2.y () - p1.y ())
+                                    / (p1.x () - p2.x ()));
+        return (new VHScannerO2 (xmin, ymin, xmax, ymax,
+                                 a, b, c2, nbs, steps, repx, repy));
+      }
+      else return (new DirectionalScannerO2 (xmin, ymin, xmax, ymax,
+                          a, b, c2, nbs, steps, p1.x (), p1.y ()));
+    }
+  else
+    if (b > a)
+    {
+      if (isOrtho)
+      {
+        int repx = (p1.x () + p2.x ()) / 2;    // central scan start
+        int repy = p1.y () - (int) ((repx - p1.x ()) * (p2.x () - p1.x ())
+                                    / (p2.y () - p1.y ()));
+        return (new VHScannerO8 (xmin, ymin, xmax, ymax,
+                                 a, b, c2, nbs, steps, repx, repy));
+      }
+      else return (new DirectionalScannerO8 (xmin, ymin, xmax, ymax,
+                          a, b, c2, nbs, steps, p1.x (), p1.y ()));
+    }
+    else
+    {
+      if (isOrtho)
+      {
+        int repy = (p1.y () + p2.y ()) / 2;    // central scan start
+        int repx = p1.x () - (int) ((repy - p1.y ()) * (p2.y () - p1.y ())
+                                    / (p2.x () - p1.x ()));
+        return (new VHScannerO7 (xmin, ymin, xmax, ymax,
+                                 a, b, c2, nbs, steps, repx, repy));
+      }
+      else return (new DirectionalScannerO7 (xmin, ymin, xmax, ymax,
+                          a, b, c2, nbs, steps, p1.x (), p1.y ()));
+    }
+}
+
+
+
+DirectionalScanner *ScannerProvider::getScanner (
+                Pt2i p1, Pt2i p2, Pt2i v1, Pt2i v2,
+                int xmin, int ymin, int xmax, int ymax)
+{
+  // Get the scan strip center
+  int cx = (p1.x () + p2.x ()) / 2;
+  int cy = (p1.y () + p2.y ()) / 2;
+    
+  // Gets the steps position array
+  int nbs = 0;
+  bool *steps = v1.stepsTo (v2, &nbs);
+
+  // Equation of the straight line passing through the center : ax - by = mu
+  int a = v2.y () - v1.y ();
+  int b = v1.x () - v2.x ();
+  if (a < 0 || (a == 0 && b < 0))
+  {
+    a = -a;
+    b = -b;
+  }
+
+  // Equation of the support lines of the scan strip
+  int c1 = a * p1.x () + b * p1.y ();
+  int c2 = a * p2.x () + b * p2.y ();
+
+  // Builds and returns the appropriate scanner
+  if (b < 0)
+    if (-b > a)
+      return (new DirectionalScannerO1 (xmin, ymin, xmax, ymax,
+                                        a, b, c1, c2, nbs, steps, cx, cy));
+    else
+      return (new DirectionalScannerO2 (xmin, ymin, xmax, ymax,
+                                        a, b, c1, c2, nbs, steps, cx, cy));
+  else
+    if (b > a)
+      return (new DirectionalScannerO8 (xmin, ymin, xmax, ymax,
+                                        a, b, c1, c2, nbs, steps, cx, cy));
+    else
+      return (new DirectionalScannerO7 (xmin, ymin, xmax, ymax,
+                                       a, b, c1, c2, nbs, steps, cx, cy));
+}
+
+
+DirectionalScanner *ScannerProvider::getScanner (
+                Pt2i centre, Vr2i normal, int length,
+                int xmin, int ymin, int xmax, int ymax)
+{
+  // Gets the steps position array
+  int nbs = 0;
+  bool *steps = normal.steps (&nbs);
+
+  // Orients the direction rightwards
+  int a = normal.x ();
+  int b = normal.y ();  // as equation is (ax - by)
+  if (a < 0 || (a == 0 && b < 0))
+  {
+    a = -a;
+    b = -b;
+  }
+
+  // Builds and returns the appropriate scanner
+  if (b < 0)
+    if (-b > a)
+      return (new DirectionalScannerO1 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+    else
+      return (new DirectionalScannerO2 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+  else
+    if (b > a)
+      return (new DirectionalScannerO8 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+    else
+      return (new DirectionalScannerO7 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+}
+
+
+DirectionalScanner *ScannerProvider::getScanner (
+                Pt2i centre, Vr2i normal, int length, bool controlable,
+                int xmin, int ymin, int xmax, int ymax)
+{
+  // Gets the steps position array
+  int nbs = 0;
+  bool *steps = normal.steps (&nbs);
+
+  // Orients the direction rightwards
+  int a = normal.x ();
+  int b = normal.y ();  // as equation is (ax - by)
+  if (a < 0 || (a == 0 && b < 0))
+  {
+    a = -a;
+    b = -b;
+  }
+
+  
+  if (b < 0)
+    if (-b > a)
+      return (controlable ?
+              (isOrtho ?
+               (DirectionalScanner *)
+               new VHScannerO1 (xmin, ymin, xmax, ymax,
+                                a, b, nbs, steps,
+                                centre.x (), centre.y (), length) :
+               (DirectionalScanner *)
+               new DynamicalScannerO1 (xmin, ymin, xmax, ymax,
+                                       a, b, nbs, steps,
+                                       centre.x (), centre.y (), length)) :
+              (DirectionalScanner *)
+              new DirectionalScannerO1 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+    else
+      return (controlable ?
+              (isOrtho ?
+               (DirectionalScanner *)
+               new VHScannerO2 (xmin, ymin, xmax, ymax,
+                                a, b, nbs, steps,
+                                centre.x (), centre.y (), length) :
+               (DirectionalScanner *)
+               new DynamicalScannerO2 (xmin, ymin, xmax, ymax,
+                                       a, b, nbs, steps,
+                                       centre.x (), centre.y (), length)) :
+              (DirectionalScanner *)
+              new DirectionalScannerO2 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+  else
+    if (b > a)
+      return (controlable ?
+              (isOrtho ?
+               (DirectionalScanner *)
+               new VHScannerO8 (xmin, ymin, xmax, ymax,
+                                a, b, nbs, steps,
+                                centre.x (), centre.y (), length) :
+               (DirectionalScanner *)
+               new DynamicalScannerO8 (xmin, ymin, xmax, ymax,
+                                       a, b, nbs, steps,
+                                       centre.x (), centre.y (), length)) :
+              (DirectionalScanner *)
+              new DirectionalScannerO8 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+    else
+      return (controlable ?
+              (isOrtho ?
+               (DirectionalScanner *)
+               new VHScannerO7 (xmin, ymin, xmax, ymax,
+                                a, b, nbs, steps,
+                                centre.x (), centre.y (), length) :
+               (DirectionalScanner *)
+               new DynamicalScannerO7 (xmin, ymin, xmax, ymax,
+                                       a, b, nbs, steps,
+                                       centre.x (), centre.y (), length)) :
+              (DirectionalScanner *)
+              new DirectionalScannerO7 (xmin, ymin, xmax, ymax,
+                                        a, b, nbs, steps,
+                                        centre.x (), centre.y (), length));
+}
diff --git a/Code/Seg/DirectionalScanner/scannerprovider.h b/Code/Seg/DirectionalScanner/scannerprovider.h
new file mode 100755
index 0000000000000000000000000000000000000000..3dd5be35b6603c3cabfa8feaddec612009b5407e
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/scannerprovider.h
@@ -0,0 +1,118 @@
+#ifndef SCANNER_PROVIDER_H
+#define SCANNER_PROVIDER_H
+
+#include <cstdlib>
+#include "directionalscanner.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class ScannerProvider scannerprovider.h
+ * \brief Directional scanner provider.
+ * Provides ad-hoc directional scanners in the relevant octant
+ *   and according to static or dynamical needs.
+ * \author {P. Even}
+ */
+class ScannerProvider
+{
+
+public:
+
+  /**
+   * @fn ScannerProvider()
+   * \brief Builds a directional scanner provider.
+   */
+  ScannerProvider () : isOrtho (false) { }
+  
+  /**
+   * @fn getScanner(Pt2i p1, Pt2i p2,
+   *                int xmin, int xmax, int ymin, int ymax)
+   * \brief Returns an incremental directional scanner.
+   * Returns a directional scanner from two control points.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by control points p1 and p2.
+   * @param p1 Start control point.
+   * @param p2 End control point.
+   * @param xmin Left border of the scan area.
+   * @param xmax Right border of the scan area.
+   * @param ymin Low border of the scan area.
+   * @param ymax Up border of the scan area.
+   */
+  DirectionalScanner *getScanner (Pt2i p1, Pt2i p2,
+                                  int xmin, int xmax, int ymin, int ymax);
+  
+  /**
+   * @fn getScanner(Pt2i p1, Pt2i p2, Pt2i v1, Pt2i v2,
+   *                int xmin, int ymin, nt xmax, int ymax)
+   * \brief Returns an incremental directional scanner.
+   * Returns a directional scanner from two points and direction v1 -> v2.
+   * The scan strip is composed of parallel scan lines, centered on the middle
+   *   of (p1,p2) and aligned on (v1,v2).
+   * @param p1 start control point
+   * @param p2 end control point
+   * @param v1 direction start point
+   * @param v2 direction end point
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   */
+  DirectionalScanner *getScanner (Pt2i p1, Pt2i p2,
+                                  Pt2i v1, Pt2i v2,
+                                  int xmin, int ymin, int xmax, int ymax);
+
+  /**
+   * @fn getScanner(Pt2i centre, Vr2i normal, int length,
+   *                int xmin, int ymin, nt xmax, int ymax)
+   * \brief Returns an incremental directional scanner.
+   * Returns a directional scanner from two points and direction v1 -> v2.
+   * The scan strip is composed of parallel scan lines, centered on the middle
+   *   of (p1,p2) and aligned on (v1,v2).
+   * @param centre central point
+   * @param normal scan strip normal vector
+   * @param length length of a scan line
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   */
+  DirectionalScanner *getScanner (Pt2i centre, Vr2i normal, int length,
+                                  int xmin, int ymin, int xmax, int ymax);
+
+  /**
+   * @fn getScanner(Pt2i centre, Vr2i normal, int length, bool controlable,
+   *                int xmin, int ymin, nt xmax, int ymax)
+   * \brief Returns an incremental directional scanner.
+   * Returns a directional scanner from two points and direction v1 -> v2.
+   * The scan strip is composed of parallel scan lines, centered on the middle
+   *   of (p1,p2) and aligned on (v1,v2).
+   * @param centre central point
+   * @param normal scan strip normal vector
+   * @param length half length of a scan line
+   * @param controlable controlability request (true for a dynamical scanner)
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   */
+  DirectionalScanner *getScanner (Pt2i centre, Vr2i normal,
+                                  int length, bool controlable,
+                                  int xmin, int ymin, int xmax, int ymax);
+
+  /**
+   * @fn setOrtho(bool status)
+   * \brief Sets the orthogonal scanner modality.
+   * @param status new status for the orthogonal scanner modality.
+   */
+  inline void setOrtho (bool status) { isOrtho = status; }
+
+
+private:
+
+  /** Orthogonal scanner modality. */
+  bool isOrtho;
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/vhscannero1.cpp b/Code/Seg/DirectionalScanner/vhscannero1.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..0de21e9aa06c5d43e49ea8c2bdd292514ed4afed
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero1.cpp
@@ -0,0 +1,188 @@
+#include <cstdlib>
+#include <iostream>
+#include "vhscannero1.h"
+
+
+
+VHScannerO1::VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DynamicalScannerO1 (xmin, ymin, xmax, ymax,
+                                          a, b, c, nbs, steps, sx, sy)
+{
+}
+
+
+
+VHScannerO1::VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  // Looking for the central scan start position
+  do
+  {
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+VHScannerO1::VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int nbs, bool *steps,
+                          int cx, int cy, int length)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  for (int i = 0; i < w_2; i++)
+  {
+    lcy --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  while (w_2-- > 0)
+  {
+    cy++;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+int VHScannerO1::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+
+  while (y < ymin && dla * x + dlb * y >= dlc2)
+  {
+    y++;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO1::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcx --;
+  if (lcx < xmin) return 0;
+
+  // Whenever the control line changed
+  while (lcy < ymax - 1 && dla * lcx + dlb * lcy > dlc1)
+  {
+    lcy ++;
+  }
+  while (lcy > ymin && dla * lcx + dlb * lcy < dlc1)
+  {
+    lcy --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  while (y < ymin && dla * x + dlb * y >= dlc2)
+  {
+    y ++;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y ++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO1::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcx ++;
+  if (rcx >= xmax) return 0;
+
+  while (rcy < ymax - 1 && dla * rcx + dlb * rcy > dlc1)
+  {
+    rcy ++;
+  }
+  while (rcy > ymin && dla * rcx + dlb * rcy < dlc1)
+  {
+    rcy --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  while (y < ymin && dla * x + dlb * y >= dlc2)
+  {
+    y++;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y++;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/vhscannero1.h b/Code/Seg/DirectionalScanner/vhscannero1.h
new file mode 100755
index 0000000000000000000000000000000000000000..9644a24fbc71ccd0d4a2650f9655d3d605c27ef2
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero1.h
@@ -0,0 +1,116 @@
+#ifndef VH_SCANNER_O1_H
+#define VH_SCANNER_O1_H
+
+#include "dynamicalscannero1.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class VHScannerO1 vhscannero1.h
+ * \brief Vertical/horizontal directional scanner for the 1st octant.
+ * \author {P. Even}
+ */
+class VHScannerO1 : public DynamicalScannerO1
+{
+
+public:
+  
+  /**
+   * @fn VHScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c,
+   *                 int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a vh scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c,
+               int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn VHScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c1, int c2,
+   *                 int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a vh scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */ 
+  VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c1, int c2,
+               int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn VHScanner01(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, *int nbs, bool *steps,
+   *                 int cx, int cy, int length)
+   * \brief Creates a vh scanner from pattern, center and length .
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymin low border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  VHScannerO1 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int nbs, bool *steps,
+               int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/vhscannero2.cpp b/Code/Seg/DirectionalScanner/vhscannero2.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..59eccb10625d031bddf2cec0d44df82e019d56cf
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero2.cpp
@@ -0,0 +1,188 @@
+#include <cstdlib>
+#include <iostream>
+#include "vhscannero2.h"
+
+
+
+VHScannerO2::VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DynamicalScannerO2 (xmin, ymin, xmax, ymax,
+                                          a, b, c, nbs, steps, sx, sy)
+{
+}
+
+
+
+VHScannerO2::VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  if (c2 > c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  // Looking for the central scan start position
+  do
+  {
+    lcx ++;
+  }
+  while (dla * lcx + dlb * lcy < c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+VHScannerO2::VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int nbs, bool *steps,
+                          int cx, int cy, int length)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  for (int i = 0; i < w_2; i++)
+  {
+    lcx ++;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  while (w_2-- > 0)
+  {
+    cx--;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc1 - this->dlc2;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+int VHScannerO2::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+
+  while (x >= xmax && dla * x + dlb * y >= dlc2)
+  {
+    x--;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    x--;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO2::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcy --;
+  if (lcy < ymin) return 0;
+
+  // Whenever the control line changed
+  while (lcx > xmin && dla * lcx + dlb * lcy > dlc1)
+  {
+    lcx --;
+  }
+  while (lcx < xmax - 1 && dla * lcx + dlb * lcy < dlc1)
+  {
+    lcx ++;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  while (x >= xmax && dla * x + dlb * y >= dlc2)
+  {
+    x--;
+  }
+  while (dla * x + dlb * y >= dlc2 && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    x--;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO2::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcy ++;
+  if (rcy >= ymax) return 0;
+
+  while (rcx > xmin && dla * rcx + dlb * rcy > dlc1)
+  {
+    rcx --;
+  }
+  while (rcx < xmax - 1 && dla * rcx + dlb * rcy < dlc1)
+  {
+    rcx ++;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  while ((y < ymin || x >= xmax) && dla * x + dlb * y >= dlc2)
+  {
+    x--;
+  }
+  while (dla * x + dlb * y >= dlc2 && y < ymax && x >= xmin)
+  {
+    scan.push_back (Pt2i (x, y));
+    x--;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/vhscannero2.h b/Code/Seg/DirectionalScanner/vhscannero2.h
new file mode 100755
index 0000000000000000000000000000000000000000..b0a8e8ae5c76d197ca52572295c57944961c18ba
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero2.h
@@ -0,0 +1,116 @@
+#ifndef VH_SCANNER_O2_H
+#define VH_SCANNER_O2_H
+
+#include "dynamicalscannero2.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class VHScannerO2 dynamicalscannero2.h
+ * \brief Vertical / horizontal directional scanner for the 2nd octant.
+ * \author {P. Even}
+ */
+class VHScannerO2 : public DynamicalScannerO2
+{
+
+public:
+  
+  /**
+   * @fn VHScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c,
+   *                 int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a vh scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c,
+               int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn VHScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c1, int c2,
+   *                 int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a vh scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c1, int c2,
+               int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn VHScanner02(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int nbs, bool *steps,
+   *                 int cx, int cy, int length)
+   * \brief Creates a vh scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  VHScannerO2 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int nbs, bool *steps,
+               int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/vhscannero7.cpp b/Code/Seg/DirectionalScanner/vhscannero7.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..f46b883dbee1983b9bc07b306324e23bbe5862f9
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero7.cpp
@@ -0,0 +1,189 @@
+#include <cstdlib>
+#include <iostream>
+#include "vhscannero7.h"
+
+
+
+VHScannerO7::VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DynamicalScannerO7 (xmin, ymin, xmax, ymax,
+                                          a, b, c, nbs, steps, sx, sy)
+{
+}
+
+
+
+VHScannerO7::VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  // Looking for the central scan start position
+  do
+  {
+    lcx --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+VHScannerO7::VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int nbs, bool *steps,
+                          int cx, int cy, int length)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  for (int i = 0; i < w_2; i++)
+  {
+    lcx --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  while (w_2-- > 0)
+  {
+    cx++;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+
+int VHScannerO7::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+
+  while (x < xmin && dla * x + dlb * y <= dlc2)
+  {
+    x++;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    x++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO7::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcy ++;
+  if (lcy >= ymax) return 0;
+
+  while (lcx < xmax - 1 && dla * lcx + dlb * lcy < dlc1)
+  {
+    lcx ++;
+  }
+  while (lcx > xmin && dla * lcx + dlb * lcy > dlc1)
+  {
+    lcx --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  while (x < xmin && dla * x + dlb * y <= dlc2)
+  {
+    x++;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    x++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO7::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcy --;
+  if (rcy < ymin) return 0;
+
+  // Whenever the control corridor changed
+  while (rcx < xmax - 1 && dla * rcx + dlb * rcy < dlc1)
+  {
+    rcx ++;
+  }
+  while (rcx > xmin && dla * rcx + dlb * rcy > dlc1)
+  {
+    rcx --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  while (x < xmin && dla * x + dlb * y <= dlc2)
+  {
+    x++;
+  }
+  while (dla * x + dlb * y <= dlc2 && x < xmax)
+  {
+    scan.push_back (Pt2i (x, y));
+    x++;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/vhscannero7.h b/Code/Seg/DirectionalScanner/vhscannero7.h
new file mode 100755
index 0000000000000000000000000000000000000000..5ad1e12b4fae43fcecacdeb757bc0606857ff382
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero7.h
@@ -0,0 +1,116 @@
+#ifndef VH_SCANNER_O7_H
+#define VH_SCANNER_O7_H
+
+#include "dynamicalscannero7.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class VHScannerO7 vhscannero7.h
+ * \brief Vertical / horizontal directional scanner for the 7th octant.
+ * \author {P. Even}
+ */
+class VHScannerO7 : public DynamicalScannerO7
+{
+
+public:
+  
+  /**
+   * @fn VHScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c,
+   *                 int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a vh scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c,
+               int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn VHScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c1, int c2,
+   *                 int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a vh scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c1, int c2,
+               int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn VHScanner07(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int nbs, bool *steps,
+                     int cx, int cy, int length)
+   * \brief Creates a vh scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  VHScannerO7 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int nbs, bool *steps,
+               int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+};
+
+#endif
diff --git a/Code/Seg/DirectionalScanner/vhscannero8.cpp b/Code/Seg/DirectionalScanner/vhscannero8.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..f6b8c612e83ac2456bbb015d9a75dbbe9e406c51
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero8.cpp
@@ -0,0 +1,189 @@
+#include <cstdlib>
+#include <iostream>
+#include "vhscannero8.h"
+
+
+
+VHScannerO8::VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c,
+                          int nbs, bool *steps, int sx, int sy)
+                    : DynamicalScannerO8 (xmin, ymin, xmax, ymax,
+                                          a, b, c, nbs, steps, sx, sy)
+{
+}
+
+
+
+VHScannerO8::VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int c1, int c2,
+                          int nbs, bool *steps, int cx, int cy)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  if (c2 < c1)
+  {
+    this->dlc1 = c2;
+    this->dlc2 = c1;
+    c1 = c2;
+  }
+  else
+  {
+    this->dlc1 = c1;
+    this->dlc2 = c2;
+  }
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  // Looking for the central scan start position
+  do
+  {
+    lcy --;
+  }
+  while (dla * lcx + dlb * lcy > c1);
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+  fs = steps + nbs;
+}
+
+
+
+VHScannerO8::VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+                          int a, int b, int nbs, bool *steps,
+                          int cx, int cy, int length)
+{
+  this->xmin = xmin;
+  this->xmax = xmax;
+  this->ymin = ymin;
+  this->ymax = ymax;
+  this->nbs = nbs;
+  this->steps = steps;
+  lcx = cx;
+  lcy = cy;
+  rcx = cx;
+  rcy = cy;
+  this->dla = a;
+  this->dlb = b;
+  fs = steps + nbs;
+  int w_2 = (length + 1) / 2;
+
+  // Looking for the central scan start position
+  for (int i = 0; i < w_2; i++)
+  {
+    lcy --;
+  }
+  dlc1 = dla * lcx + dlb * lcy;
+
+  // Looking for the upper leaning line
+  while (w_2-- > 0)
+  {
+    cy++;
+  }
+  dlc2 = dla * cx + dlb * cy;
+
+  this->templ_a = a;
+  this->templ_b = b;
+  this->templ_nu = this->dlc2 - this->dlc1;
+
+  rcx = lcx;
+  rcy = lcy;
+  lst2 = steps;
+  rst2 = steps;
+}
+
+
+
+int VHScannerO8::first (vector<Pt2i> &scan)
+{
+  int x = lcx, y = lcy;      // Current position coordinates
+
+  while (y < ymin && dla * x + dlb * y <= dlc2)
+  {
+    y++;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO8::nextOnLeft (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  lcx --;
+  if (lcx < xmin) return 0;
+
+  while (lcy < ymax - 1 && dla * lcx + dlb * lcy < dlc1)
+  {
+    lcy ++;
+  }
+  while (lcy > ymin && dla * lcx + dlb * lcy > dlc1)
+  {
+    lcy --;
+  }
+
+  // Computes the next scan
+  int x = lcx;
+  int y = lcy;
+  while (y < ymin && dla * x + dlb * y <= dlc2)
+  {
+    y++;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y++;
+  }
+  return ((int) (scan.size ()));
+}
+
+
+int VHScannerO8::nextOnRight (vector<Pt2i> &scan)
+{
+  // Prepares the next scan
+  scan.clear ();
+  rcx ++;
+  if (rcx >= xmax) return 0;
+
+  // Whenever the control corridor changed
+  while (rcy < ymax - 1 && dla * rcx + dlb * rcy < dlc1)
+  {
+    rcy ++;
+  }
+  while (rcy > ymin && dla * rcx + dlb * rcy > dlc1)
+  {
+    rcy --;
+  }
+
+  // Computes the next scan
+  int x = rcx;
+  int y = rcy;
+  while (y < ymin && dla * x + dlb * y <= dlc2)
+  {
+    y++;
+  }
+  while (dla * x + dlb * y <= dlc2 && y < ymax)
+  {
+    scan.push_back (Pt2i (x, y));
+    y++;
+  }
+  return ((int) (scan.size ()));
+}
diff --git a/Code/Seg/DirectionalScanner/vhscannero8.h b/Code/Seg/DirectionalScanner/vhscannero8.h
new file mode 100755
index 0000000000000000000000000000000000000000..e05ba493570648a83c1895c300a9bb432ec0593c
--- /dev/null
+++ b/Code/Seg/DirectionalScanner/vhscannero8.h
@@ -0,0 +1,116 @@
+#ifndef VH_SCANNER_O8_H
+#define VH_SCANNER_O8_H
+
+#include "dynamicalscannero8.h"
+
+using namespace std;
+
+
+
+/** 
+ * @class VHScannerO8 vhscannero8.h
+ * \brief Vertical / horizontal directional scanner for the 8th octant.
+ * \author {P. Even}
+ */
+class VHScannerO8 : public DynamicalScannerO8
+{
+
+public:
+  
+  /**
+   * @fn VHScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c,
+   *                 int nbs, bool *steps, int sx, int sy)
+   * \brief Creates a vh scanner from pattern, start and upper bound.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a start point, a line pattern, and an upper bound.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c y intercept parameter of the upper bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param sx abscissae of the central scan start point
+   * @param sy ordinate of the central scan start point
+   */
+  VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c,
+               int nbs, bool *steps, int sx, int sy);
+
+  /**
+   * @fn VHScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int c1, int c2,
+   *                 int nbs, bool *steps, int cx, int cy)
+   * \brief Creates a vh scanner from pattern, center and bounds.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, upper and lower bounds.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param c1 y intercept parameter of one of the bounds
+   * @param c2 y intercept parameter of the other bound
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   */
+  VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int c1, int c2,
+               int nbs, bool *steps, int cx, int cy);
+
+  /**
+   * @fn VHScanner08(int xmin, int ymin, int xmax, int ymax,
+   *                 int a, int b, int nbs, bool *steps,
+   *                 int cx, int cy, int length)
+   * \brief Creates a vh scanner from pattern, center and length.
+   * The scan strip is composed of parallel scan lines, the first one being
+   *   defined by a center, a line pattern, and a length value.
+   * @param xmin left border of the scan area
+   * @param ymin low border of the scan area
+   * @param xmax right border of the scan area
+   * @param ymax up border of the scan area
+   * @param a x coefficient of the discrete support line
+   * @param b y coefficient of the discrete support line
+   * @param nbs size of the support line pattern
+   * @param steps support line pattern
+   * @param cx abscissae of the central scan center
+   * @param cy ordinate of the central scan center
+   * @param length length of a scan strip
+   */
+  VHScannerO8 (int xmin, int ymin, int xmax, int ymax,
+               int a, int b, int nbs, bool *steps,
+               int cx, int cy, int length);
+
+  /**
+   * @fn first(vector<Pt2i> &scan)
+   * \brief Returns the central scan.
+   * Fills in the vector with the central scan and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int first (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnLeft(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the left.
+   * Fills in the vector with the next scan on left and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnLeft (vector<Pt2i> &scan);
+
+  /**
+   * @fn nextOnRight(vector<Pt2i> &scan)
+   * \brief Returns the next scan on the right.
+   * Fills in the vector with the next scan on right and returns its size.
+   * @param scan vectors of points to be filled in.
+   */
+  int nextOnRight (vector<Pt2i> &scan);
+
+};
+
+#endif
diff --git a/Code/Seg/ImageTools/absrat.cpp b/Code/Seg/ImageTools/absrat.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..e5a7a8cd6b49977f23799e52e051315ec046d061
--- /dev/null
+++ b/Code/Seg/ImageTools/absrat.cpp
@@ -0,0 +1,44 @@
+#include "absrat.h"
+
+
+AbsRat::AbsRat ()
+{
+  num = 1;
+  den = 0;
+}
+
+
+AbsRat::AbsRat (int numerator, int denominator)
+{
+  num = (numerator < 0 ? - numerator : numerator);
+  den = (denominator < 0 ? - denominator : denominator);
+}
+
+
+AbsRat::AbsRat (const AbsRat &rat)
+{
+  num = rat.num;
+  den = rat.den;
+}
+
+
+void AbsRat::attractsTo (const AbsRat &val, const AbsRat &ratio)
+{
+  if (val.den != 0)
+    num = (ratio.den * num * val.den
+           - (num * val.den - den * val.num) * ratio.num)
+          / (ratio.den * val.den);
+}
+
+
+void AbsRat::sticksTo (const AbsRat &val)
+{
+  if (val.den != 0) num = (den * val.num) / val.den;
+}
+
+
+void AbsRat::mult (const AbsRat &val)
+{
+  num *= val.num;
+  den *= val.den;
+}
diff --git a/Code/Seg/ImageTools/absrat.h b/Code/Seg/ImageTools/absrat.h
new file mode 100755
index 0000000000000000000000000000000000000000..a52e710687322f77120e679931e9e7c86c93767f
--- /dev/null
+++ b/Code/Seg/ImageTools/absrat.h
@@ -0,0 +1,162 @@
+#ifndef ABSOLUTE_RATIONAL_H
+#define ABSOLUTE_RATIONAL_H
+
+
+using namespace std;
+
+
+
+/** 
+ * @class AbsRat absrat.h
+ * \brief Absolute rational number.
+ * 
+ * This absolute number may have a null denominator.
+ * It should not be evaluated.
+ * It is mostly intended to comparison operations.
+ * \author {P. Even}
+ */
+class AbsRat
+{
+
+public:
+
+  /**
+   * @fn AbsRat ()
+   * \brief Creates a null absolute rational number.
+   */
+  AbsRat ();
+
+  /**
+   * @fn AbsRat (int numerator, int denominator)
+   * \brief Creates a absolute rational number from numerator and denominator.
+   * @param numerator Numerator.
+   * @param denominator Denominator.
+   */
+  AbsRat (int numerator, int denominator);
+
+  /**
+   * @fn AbsRat (const AbsRat &rat)
+   * \brief Creates a absolute rational number from another one.
+   * @param rat The rational number to copy.
+   */
+  AbsRat (const AbsRat &rat);
+
+  /**
+   * @fn ~AbsRatRational ()
+   * \brief Deletes the absolute rational number.
+   */
+  ~AbsRat () { }
+
+  /**
+   * @fn int numerator ()
+   * \brief Returns the numerator of the absolute rational number.
+   */
+  inline int numerator () const { return num; }
+
+  /**
+   * @fn int denominator ()
+   * \brief Returns the denominator of the absolute rational number.
+   */
+  inline int denominator () const { return den; }
+
+  /**
+   * @fn void set (const AbsRat &val)
+   * \brief Sets the value of the rational number.
+   * @value val New value of the rational number.
+   */
+  inline void set (const AbsRat &val) { num = val.num; den = val.den; }
+
+  /**
+   * @fn void set (int val)
+   * \brief Sets the value of the rational number.
+   * @value val New value of the rational number.
+   */
+  inline void set (int val) { num = val; den = 1; }
+
+  /**
+   * @fn void set (int numerator, int denominator)
+   * \brief Sets the value of the rational number.
+   * @value numerator New numerator of the rational number.
+   * @value denominator New denominator of the rational number.
+   */
+  inline void set (int numerator, int denominator) {
+    num = numerator; den = denominator; }
+
+  /**
+   * @fn bool equals (const AbsRat &r)
+   * \brief Checks equivalence to the given rational number.
+   * @param r the given rational number.
+   */
+  inline bool equals (const AbsRat &r) const {
+    return (num * r.den == den * r.num); }
+
+  /**
+   * @fn bool lessThan (const AbsRat &r)
+   * \brief Checks if the rational number is strictly less than given one.
+   * @param r the given rational number.
+   */
+  inline bool lessThan (const AbsRat &r) const {
+    return (num * r.den < den * r.num); }
+
+  /**
+   * @fn bool lessEqThan (const AbsRat &r)
+   * \brief Checks if the rational number is less or equal to given one.
+   * @param r the given rational number.
+   */
+  inline bool lessEqThan (const AbsRat &r) const {
+    return (num * r.den <= den * r.num); }
+
+  /**
+   * @fn bool greaterThan (const AbsRat &r)
+   * \brief Checks if the rational number is strictly greater than given one.
+   * @param r the given rational number.
+   */
+  inline bool greaterThan (const AbsRat &r) const {
+    return (num * r.den > den * r.num); }
+
+  /**
+   * @fn bool greaterEqThan (const AbsRat &r)
+   * \brief Checks if the rational number is greater or equal to given one.
+   * @param r the given rational number.
+   */
+  inline bool greaterEqThan (const AbsRat &r) const {
+    return (num * r.den >= den * r.num); }
+
+  /**
+   * @fn void attractsTo (const AbsRat &val, const AbsRat &ratio)
+   * \brief Attracts the rational number to the given one with given ratio.
+   * Withdraws to the rational number
+   *   the difference between the rational number and an attractor number
+   *   multiplied by the ratio.
+   * The denominator is left unchanged.
+   * @param val Goal rational value.
+   * @param ratio Attraction ratio.
+   */
+  void attractsTo (const AbsRat &val, const AbsRat &ratio);
+
+  /**
+   * @fn void sticksTo (const AbsRat &val)
+   * \brief Sets the rational number to the given one value.
+   * The denominator is left unchanged.
+   * @param val Given rational number.
+   */
+  void sticksTo (const AbsRat &val);
+
+  /**
+   * @fn void mult (const AbsRat &val)
+   * \brief Multiplies the rational number by the given one.
+   * @param val Given rational number.
+   */
+  void mult (const AbsRat &val);
+
+
+protected:
+
+  /** Positive numerator of the rational number. */
+  int num;
+  /** Positive denominator of the rational number (might be null). */
+  int den;
+
+};
+
+#endif
diff --git a/Code/Seg/ImageTools/digitalstraightline.cpp b/Code/Seg/ImageTools/digitalstraightline.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..db1f446e568853184d0ac5ae9d2c185d62fca915
--- /dev/null
+++ b/Code/Seg/ImageTools/digitalstraightline.cpp
@@ -0,0 +1,452 @@
+#include <cstdlib>
+#include <iostream>
+#include "digitalstraightline.h"
+
+
+const int DigitalStraightLine::DSL_THIN = 1;
+const int DigitalStraightLine::DSL_NAIVE = 2;
+const int DigitalStraightLine::DSL_STANDARD = 3;
+
+
+DigitalStraightLine::DigitalStraightLine (int a, int b, int c, int nu)
+{
+  this->a = a;
+  this->b = b;
+  if (nu < 0)
+  {
+    this->c = c + 1 + nu;
+    this->nu = - nu;
+  }
+  else
+  {
+    this->c = c;
+    this->nu = nu;
+  }
+  if (a < 0)
+  {
+    this->a = - this->a;
+    this->b = - this->b;
+    this->c = 1 - c - nu;
+  }
+  else if (a == 0 && b < 0)
+  {
+    this->b = - this->b;
+    this->c = 1 - c - nu;
+  }
+  int pg = pgcd (a, (b < 0 ?  - b : b));
+  if (pg != 1)
+  {
+    a /= pg;
+    b /= pg;
+    c /= pg;
+    nu /= pg;
+  }
+}
+
+
+DigitalStraightLine::DigitalStraightLine (Pt2i p1, Pt2i p2, int type)
+{
+  if (p1.y () < p2.y ())
+  {
+    a = p2.y () - p1.y ();
+    b = p1.x () - p2.x ();
+  }
+  else
+  {
+    a = p1.y () - p2.y ();
+    b = p2.x () - p1.x ();
+    if (a == 0 && b < 0) b = -b;
+  }
+  int pg = pgcd (a, b < 0 ? -b : b);
+  a /= pg;
+  b /= pg;
+  c = a * p1.x () + b * p1.y ();
+
+  if (type == DSL_NAIVE)
+  {
+    nu = b;
+    if (nu < 0) nu = -nu;
+    if (nu < a) nu = a;
+    // To match the Pt2i::stepsTo method ...
+    if ((b > 0 && a > b) || (b < 0 && a < -b))
+      c -= (nu - 1) / 2;
+    else
+      c -= nu / 2;
+  }
+
+  else if (type == DSL_STANDARD)
+  {
+    nu = a + (b < 0 ? -b : b);
+    if ((b > 0 && a > b) || (b < 0 && a < -b))
+      c -= (nu - 1) / 2;
+    else
+      c -= nu / 2;
+  }
+
+  else // type == DSL_THIN
+    nu = 1;
+}
+
+
+DigitalStraightLine::DigitalStraightLine (Pt2i p1, Pt2i p2, Pt2i p3)
+{
+  if (p1.y () < p2.y ())
+  {
+    a = p2.y () - p1.y ();
+    b = p1.x () - p2.x ();
+  }
+  else
+  {
+    a = p1.y () - p2.y ();
+    b = p2.x () - p1.x ();
+    if (a == 0 && b < 0) b = -b;
+  }
+  int pg = pgcd (a, b < 0 ? -b : b);
+  a /= pg;
+  b /= pg;
+  c = a * p1.x () + b * p1.y ();
+  int d = a * p3.x () + b * p3.y ();
+  if (d < c)
+  {
+    nu = c - d + 1;
+    c = d;
+  }
+  else nu = d - c + 1;
+}
+
+
+DigitalStraightLine::DigitalStraightLine (Pt2i p1, Pt2i p2,
+                                          int type, int atRight)
+{
+  if (p1.y () < p2.y ())
+  {
+    a = p2.y () - p1.y ();
+    b = p1.x () - p2.x ();
+  }
+  else
+  {
+    a = p1.y () - p2.y ();
+    b = p2.x () - p1.x ();
+    if (a == 0 && b < 0) b = -b;
+  }
+  int pg = pgcd (a, b < 0 ? -b : b);
+  a /= pg;
+  b /= pg;
+  c = a * p1.x () + b * p1.y ();
+
+  int bb = (b < 0 ? -b : b);
+  c += atRight * (a < bb ? bb : a);
+
+  if (type == DSL_NAIVE)
+  {
+    nu = b;
+    if (nu < 0) nu = -nu;
+    if (nu < a) nu = a;
+    // To match the Pt2i::stepsTo method ...
+    if ((b > 0 && a > b) || (b < 0 && a < -b))
+      c -= (nu - 1) / 2;
+    else
+      c -= nu / 2;
+  }
+
+  else if (type == DSL_STANDARD)
+  {
+    nu = a + (b < 0 ? -b : b);
+    if ((b > 0 && a > b) || (b < 0 && a < -b))
+      c -= (nu - 1) / 2;
+    else
+      c -= nu / 2;
+  }
+
+  else // type == DSL_THIN
+    nu = 1;
+}
+
+
+DigitalStraightLine::DigitalStraightLine (const DigitalStraightLine &l)
+{
+  a = l.a;
+  b = l.b;
+  c = l.c;
+  nu = l.nu;
+}
+
+
+int DigitalStraightLine::manhattan (Pt2i pix) const
+{
+  int absb = b < 0 ? -b : b;
+  int per = (a < absb ? absb : a);
+  int pos = a * pix.x () + b * pix.y () - c;
+  if (pos < 0) return ((pos + 1 - per) / per);
+  else if (pos >= nu) return ((pos + per - nu) / per);
+  else return 0;
+}
+
+
+Pt2i DigitalStraightLine::getABoundingPoint (bool upper) const
+{
+  int sa = a, sb = b, u1 = 1, v1 = 0, u2 = 0, v2 = 1;
+  while (sb != 0)
+  {
+    int r = sa % sb;
+    int q = sa / sb;
+    int u3 = u1 - q * u2;
+    int v3 = v1 - q * v2;
+    u1 = u2;
+    v1 = v2;
+    u2 = u3;
+    v2 = v3;
+    sa = sb;
+    sb = r;
+  }
+  if (sa < 0)  // should be 1 or -1 if a and b are primal
+  {
+    u1 = - u1;
+    v1 = - v1;
+  }
+  return (upper ? Pt2i (u1 * (c + nu - 1), v1 * (c + nu - 1))
+                : Pt2i (u1 * c, v1 * c));
+}
+
+
+void DigitalStraightLine::adjustWorkArea (int &xmin, int &ymin,
+                                          int &width, int &height) const
+{
+  (void) xmin;
+  (void) ymin;
+  (void) width;
+  (void) height;
+}
+
+
+void DigitalStraightLine::getBounds (vector<Pt2i> &bound,
+                             int xmin, int ymin, int width, int height) const
+{
+  getBoundPoints (bound, false, xmin, ymin, width, height);
+  if (nu > period ()) getBoundPoints (bound, true, xmin, ymin, width, height);
+}
+
+
+void DigitalStraightLine::getBoundPoints (vector<Pt2i> &points, bool opposite,
+                       int xmin, int ymin, int width, int height) const
+{
+  if (opposite && nu < period ()) return;
+
+  int x, y, dec, r;
+  Pt2i pb = getABoundingPoint (opposite);
+  adjustWorkArea (xmin, ymin, width, height);
+
+  if (b > 0)   // downwards
+    if (b >= a) // rather horizontal (8th octant)
+    {
+      x = pb.x ();
+      y = pb.y ();
+      dec = x <= xmin ? (xmin - x) / b : (xmin - x) / b - 1;
+      x += dec * b;
+      y -= dec * a;
+      r = (opposite ? b - 1 : 0);
+
+      while (x < xmin)
+      {
+        x++;
+        r += a; if (r >= b)
+        {
+          y --;
+          r -= b;
+        }
+      }
+      if ((opposite || r < nu ) && y >= ymin && y < ymin + height)
+        points.push_back (Pt2i (x, y));
+      while (++x < xmin + width)
+      {
+        r += a;
+        if (r >= b)
+        {
+          y --;
+          r -= b;
+        }
+        if ((opposite || r < nu) && y >= ymin && y < ymin + height)
+          points.push_back (Pt2i (x, y));
+      }
+    }
+    else // rather vertical (7th octant)
+    {
+      x = pb.x ();
+      y = pb.y ();
+      dec = y >= ymin + height ? (y - ymin - height) / a
+                                 : (y - ymin - height) / a - 1;
+      x += dec * b;
+      y -= dec * a;
+      r = (opposite ? 0 : a - 1);
+
+      while (y >= ymin + height)
+      {
+        y--;
+        r += b;
+        if (r >= a)
+        {
+          x ++;
+          r -= a;
+        }
+      }
+
+      if ((opposite || r >= a - nu) && x >= xmin && x < xmin + width)
+        points.push_back (Pt2i (x, y));
+      while (y-- > ymin)
+      {
+        r += b;
+        if (r >= a)
+        {
+          x ++;
+          r -= a;
+        }
+        if ((opposite || r >= a - nu) && x >= xmin && x < xmin + width)
+          points.push_back (Pt2i (x, y));
+      }
+    }
+  else   // upwards
+    if (-b >= a) // rather horizontal (1st octant)
+    {
+      x = pb.x ();
+      y = pb.y ();
+      dec = x <= xmin ? (x - xmin) / b : (x - xmin) / b - 1;
+      x -= dec * b;
+      y += dec * a;
+      r = (opposite ? b + 1 : 0);
+
+      while (x < xmin)
+      {
+        x++;
+        r -= a;
+        if (r <= b)
+        {
+          y ++;
+          r -= b;
+        }
+      }
+
+      if ((opposite || r > -nu) && y >= ymin && y < ymin + height)
+        points.push_back (Pt2i (x, y));
+      while (++x < xmin + width)
+      {
+        r -= a;
+        if (r <= b)
+        {
+          y ++;
+          r -= b;
+        }
+        if ((opposite || r > -nu) && y >= ymin && y < ymin + height)
+          points.push_back (Pt2i (x, y));
+      }
+    }
+    else // rather vertical (2nd octant)
+    {
+      x = pb.x ();
+      y = pb.y ();
+      dec = y > ymin ? (ymin - y) / a - 1 : (ymin - y) / a;
+      x -= dec * b;
+      y += dec * a;
+      r = (opposite ? 0 : a - 1);
+
+      while (y < ymin)
+      {
+        y++;
+        r -= b;
+        if (r >= a)
+        {
+          x ++;
+          r -= a;
+        }
+      }
+
+      if ((opposite || r >= a - nu) && x >= xmin && x < xmin + width)
+        points.push_back (Pt2i (x, y));
+      while (++y < ymin + height)
+      {
+        r -= b;
+        if (r >= a)
+        {
+          x ++;
+          r -= a;
+        }
+        if ((opposite || r >= a - nu) && x >= xmin && x < xmin + width)
+          points.push_back (Pt2i (x, y));
+      }
+    }
+}
+
+
+const Pt2i DigitalStraightLine::centerOfIntersection (
+                                     DigitalStraightLine *l) const
+{
+  int den = a * l->b - b * l->a;
+  if (den == 0) return (Pt2i (0, 0));
+  return (Pt2i (
+    ((c + nu / 2) * l->b - b * (l->c + l->nu / 2) + den / 2) / den,
+    (a * (l->c + l->nu / 2) - (c + nu / 2) * l->a + den / 2) / den));
+}
+
+
+const Pt2i DigitalStraightLine::centerOfIntersection (
+                                     Pt2i p1, Pt2i p2) const
+{
+  int sa = p2.y () - p1.y ();
+  int sb = p1.x () - p2.x ();
+  if (sa == 0)
+  {
+    if (sb == 0) return (Pt2i (0, 0));
+    if (sb < 0) sb = -sb;
+  }
+  if (sa < 0)
+  {
+    sa = -sa;
+    sb = -sb;
+  }
+  int pg = pgcd (sa, sb < 0 ? -sb : sb);
+  sa /= pg;
+  sb /= pg;
+
+  int den = a * sb - b * sa;
+  if (den == 0) return (Pt2i (0, 0));
+  int sc = sa * p1.x () + sb * p1.y ();
+  return (Pt2i (((c + nu / 2) * sb - b * sc + den / 2) / den,
+                 (a * sc - (c + nu / 2) * sa + den / 2) / den));
+}
+
+
+bool DigitalStraightLine::owns (const Pt2i &p) const
+{
+  int val = a * p.x () + b * p.y () - c;
+  return (val >= 0 && val < nu);
+}
+
+
+bool DigitalStraightLine::owns (const Pt2i &p1, const Pt2i &p2) const
+{
+  int val1 = a * p1.x () + b * p1.y () - c;
+  int val2 = a * p2.x () + b * p2.y () - c;
+  return (val1 < val2 ? val1 <= 0 && val2 < nu
+                      : val2 <= 0 && val1 < nu);
+}
+
+
+bool DigitalStraightLine::crosses (const Pt2i &p1, const Pt2i &p2) const
+{
+  int val1 = a * p1.x () + b * p1.y () - c;
+  int val2 = a * p2.x () + b * p2.y () - c;
+  return (val1 < val2 ? val2 >= 0 && val1 < nu
+                      : val1 >= 0 && val2 < nu);
+}
+
+
+int DigitalStraightLine::pgcd (int a, int b)
+{
+  int r;
+  while (b != 0)
+  {
+    r = a % b;
+    a = b;
+    b = r;
+  }
+  return (a);
+}
diff --git a/Code/Seg/ImageTools/digitalstraightline.h b/Code/Seg/ImageTools/digitalstraightline.h
new file mode 100755
index 0000000000000000000000000000000000000000..8a5c518406663e73b26bec0e68dc221692c99985
--- /dev/null
+++ b/Code/Seg/ImageTools/digitalstraightline.h
@@ -0,0 +1,239 @@
+#ifndef DIGITAL_STRAIGHT_LINE_H
+#define DIGITAL_STRAIGHT_LINE_H
+
+
+#include <vector>
+#include "pt2i.h"
+
+using namespace std;
+
+
+/** 
+ * @class DigitalStraightLine digitalstraightline.h
+ * \brief Digital straight line.
+ * The digital straightline is defined by equation : c <= ax + by < c + nu
+ *   where a >= 0, b > 0 if a = 0, and nu > 0.
+ * \author {P. Even}
+ */
+class DigitalStraightLine
+{
+
+public:
+
+  /** Digital line type : Thin line (width = 1). */
+  static const int DSL_THIN;
+  /** Digital line type : Naive line (width = max (|a|,|b|)). */
+  static const int DSL_NAIVE;
+  /** Digital line type : Standard line (width = |a|+|b|). */
+  static const int DSL_STANDARD;
+
+  /**
+   * Creates a digital straightline from its equation parameters.
+   * @param a X value slope parameter of equation : c <= ax + by < c + nu
+   * @param b Y value slope parameter of equation : c <= ax + by < c + nu
+   * @param c Intercept parameter of equation : c <= ax + by < c + nu
+   * @param nu Width parameter of equation : c <= ax + by < c + nu
+   */
+  DigitalStraightLine (int a, int b, int c, int nu);
+
+  /**
+   * Creates a digital straight line bounded by the line joining two points.
+   * @param p1 First point on the bounding line.
+   * @param p2 Second point on the bounding line.
+   * @param type Digital line type : DSL_THIN, DSL_NAIVE or DSL_STANDARD.
+   */
+  DigitalStraightLine (Pt2i p1, Pt2i p2, int type);
+
+  /**
+   * Creates a digital straight line from an antipodal pair.
+   * @param p1 First segment end of the antipodal pair.
+   * @param p1 Second segment end of the antipodal pair.
+   * @param p3 Opposite point of the antipodal pair.
+   */
+  DigitalStraightLine (Pt2i p1, Pt2i p2, Pt2i p3);
+
+  /**
+   * Creates a digital straight line parallel to the line joining two points.
+   * Unknown use, care the side correctness in case of.
+   * @param p1 First point.
+   * @param p2 Second point.
+   * @param type Digital line type : DSL_THIN, DSL_NAIVE or DSL_STANDARD
+   * @param atRight Rightwards parallel offset to p1p2 line.
+   */
+  DigitalStraightLine (Pt2i p1, Pt2i p2, int type, int atRight);
+
+  /**
+   * Creates a similar digital straight line to an other one.
+   * @param l The original line.
+   */
+  DigitalStraightLine (const DigitalStraightLine &l);
+
+  /**
+   * Deletes the digital straight line.
+   */
+  virtual ~DigitalStraightLine () { }
+
+  /**
+   * \brief Fills in the given array with the three medial axis parameters.
+   * @param a X slope parameter to provide.
+   * @param b Y slope parameter to provide.
+   * @param c0 intercept parameter of the median axis.
+   */
+  inline void getMedialAxis (int &a, int &b, int &c0) const
+  {
+    a = this->a;
+    b = this->b;
+    c0 = c + nu / 2;
+  }
+
+  /**
+   * \brief Returns the period of the digital straight line : max (|a|,|b|).
+   */
+  inline int period () const
+  {
+    int absb = b < 0 ? -b : b;
+    return (a < absb ? absb : a);
+  }
+
+  /**
+   * \brief Returns the lower of the digital straight line : min (|a|,|b|).
+   */
+  inline int antiperiod () const
+  {
+    int absb = b < 0 ? -b : b;
+    return (a < absb ? a : absb);
+  }
+
+  /**
+   * \brief Returns the manhattan width of the digital straight line.
+   */
+  inline int width () const
+  {
+    return (nu);
+  }
+
+  /**
+   * \brief Returns a support vector of the digital straight line.
+   */
+  inline Vr2i supportVector () const
+  {
+    return (Vr2i (-b, a));
+  }
+
+  /**
+   * \brief Returns the signed manhattan distance to the given point.
+   * Right values are provided for points on the right side (yp > line (yp))
+   */
+  int manhattan (Pt2i pix) const;
+
+  /**
+   * \brief Returns a bounding point of the digital straight line.
+   * @param upper true for a upper bounding point, false for a lower one.
+   */
+  virtual Pt2i getABoundingPoint (bool upper) const;
+
+  /**
+   * \brief Fills in the vector with the requested bounding line points.
+   *   The bounding line is naive if (nu < period).
+   *   Restricts the points in the specified area.
+   * @param bound The vector of points to fill in.
+   * @param opposite true to get the opposite bounding line (ax+by=c+nu-1).
+   * @param xmin X coordinate of the viewport.
+   * @param ymin Y coordinate of the viewport.
+   * @param width Width of the viewport.
+   * @param height Height of the viewport.
+   */
+  void getBoundPoints (vector<Pt2i> &bound, bool opposite,
+                       int xmin, int ymin, int width, int height) const;
+
+  /**
+   * \brief Fills in the provided vector with the digital line bounding points.
+   * @param bound The vector of points to fill in.
+   * @param xmin X coordinate of the viewport.
+   * @param ymin Y coordinate of the viewport.
+   * @param width Width of the viewport.
+   * @param height Height of the viewport.
+   */
+  void getBounds (vector<Pt2i> &bound,
+                  int xmin, int ymin, int width, int height) const;
+
+  /**
+   * \brief Checks if given point belongs to the digital line.
+   * @param p Given point.
+   */
+  bool owns (const Pt2i &p) const;
+
+  /**
+   * \brief Checks if given segment entirely belongs to the digital line.
+   * @param p1 Given segment start point.
+   * @param p2 Given segment end point.
+   */
+  bool owns (const Pt2i &p1, const Pt2i &p2) const;
+
+  /**
+   * \brief Checks if given segment belongs even partially to the digital line.
+   * @param p1 Given segment start point.
+   * @param p2 Given segment end point.
+   */
+  bool crosses (const Pt2i &p1, const Pt2i &p2) const;
+
+  /**
+   * \brief Returns the center of the intersection with an other digital line.
+   * @param l The other digital line.
+   */
+  const Pt2i centerOfIntersection (DigitalStraightLine *l) const;
+
+  /**
+   * \brief Returns the center of the intersection with line P1-P2.
+   *   Care : returns (0,0) if p1 == p2 or if P1P2 is parallel to the line.
+   * @param p1 = start point of the crossed line.
+   * @param p2 = end point of the crossed line.
+   */
+  const Pt2i centerOfIntersection (Pt2i p1, Pt2i p2) const;
+
+
+protected:
+
+  /**
+   * \brief X value of the slope parameter in equation : c <= ax + by < c + nu.
+   *  a is greater or equal to 0.
+   */
+  int a;
+
+  /**
+   * \brief Y value of the slope parameter in equation : c <= ax + by < c + nu.
+   * b is a positive value when the line is horizontal (a = 0).
+   */
+  int b;
+
+  /**
+   * \brief Intercept parameter in equation : c <= ax + by < c + nu.
+   */
+  int c;
+
+  /**
+   * \brief Width parameter in equation : c <= ax + by < c + nu.
+   * nu is a positive value.
+   */
+  int nu;
+
+
+  /**
+   * \brief Adjusts the provided area on the straight line limits.
+   * @param xmin Left coordinate of the area.
+   * @param ymin Bottom coordinate of the area.
+   * @param width Width of the area.
+   * @param height Height of the area.
+   */
+  virtual void adjustWorkArea (int &xmin, int &ymin,
+                               int &width, int &height) const;
+
+  /**
+   * \brief Returns the greater common divisor between two integer values.
+   * @param a First integer.
+   * @param b Second integer.
+   */
+  static int pgcd (int a, int b);
+
+};
+#endif
diff --git a/Code/Seg/ImageTools/digitalstraightsegment.cpp b/Code/Seg/ImageTools/digitalstraightsegment.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..212aadc363bfba23462aa0f745a8abe1bd40f766
--- /dev/null
+++ b/Code/Seg/ImageTools/digitalstraightsegment.cpp
@@ -0,0 +1,103 @@
+#include <iostream>
+#include "digitalstraightsegment.h"
+
+
+
+DigitalStraightSegment::DigitalStraightSegment (Pt2i p1, Pt2i p2, int type,
+                                 int xmin, int ymin, int xmax, int ymax)
+                      : DigitalStraightLine (p1, p2, type)
+{
+  if (a < (b < 0 ? -b : b))
+  {
+    min = xmin;
+    max = xmax;
+  }
+  else
+  {
+    min = ymin;
+    max = ymax;
+  }
+}
+
+
+DigitalStraightSegment::DigitalStraightSegment (Pt2i p1, Pt2i p2, Pt2i p3,
+                                 int xmin, int ymin, int xmax, int ymax)
+                      : DigitalStraightLine (p1, p2, p3)
+{
+  if (a < (b < 0 ? -b : b))
+  {
+    min = xmin;
+    max = xmax;
+  }
+  else
+  {
+    min = ymin;
+    max = ymax;
+  }
+}
+
+
+Pt2i DigitalStraightSegment::getABoundingPoint (bool upper) const
+{
+  int sa = a, sb = b, u1 = 1, v1 = 0, u2 = 0, v2 = 1;
+  while (sb != 0)
+  {
+    int r = sa % sb;
+    int q = sa / sb;
+    int u3 = u1 - q * u2;
+    int v3 = v1 - q * v2;
+    u1 = u2;
+    v1 = v2;
+    u2 = u3;
+    v2 = v3;
+    sa = sb;
+    sb = r;
+  }
+  if (sa < 0)  // should be 1 or -1 if a and b are primal
+  {
+    u1 = - u1;   // necessary if sa = -1
+    v1 = - v1;
+  }
+  Pt2i extr (upper ? Pt2i (u1 * (c + nu - 1), v1 * (c + nu - 1))
+                   : Pt2i (u1 * c, v1 * c));
+  
+  int dec = 0;
+  int bb = (b < 0 ? -b : b);
+  if (a < bb)
+  {
+    if (extr.x () > max)
+      dec = 1 + (extr.x () - max) / bb;
+    else if (extr.x () < min)
+      dec = -1 - (min - extr.x ()) / bb;
+    if (b < 0) dec = -dec;
+  }
+  else
+  {
+    if (extr.y () > max)
+      dec = -1 - (extr.y () - max) / a;
+    else if (extr.y () < min)
+      dec = 1 + (min - extr.y ()) / a;
+  }
+  extr.set (extr.x () - dec * b, extr.y () + dec * a);
+  return extr;
+}
+
+
+void DigitalStraightSegment::adjustWorkArea (int &xmin, int &ymin,
+                                             int &width, int &height) const
+{
+  if (b > a || -b > a)
+  {
+    if (xmin < min) xmin = min;
+    // Caution, segment max limit is excluded
+    int x2 = (xmin + width < max + 1 ? xmin + width : max + 1);
+    width = (xmin >= x2 ? 0 : x2 - xmin);
+  }
+  else
+  {
+    if (ymin < min) ymin = min;
+    // Cochon, segment max limit is excluded
+    int y2 = (ymin + height < max + 1 ? ymin + height : max + 1);
+    height = (ymin >= y2 ? 0 : y2 - ymin);
+  }
+}
diff --git a/Code/Seg/ImageTools/digitalstraightsegment.h b/Code/Seg/ImageTools/digitalstraightsegment.h
new file mode 100755
index 0000000000000000000000000000000000000000..21c2074532e9208b244abfd58680de8cf3af3894
--- /dev/null
+++ b/Code/Seg/ImageTools/digitalstraightsegment.h
@@ -0,0 +1,85 @@
+#ifndef DIGITAL_STRAIGHT_SEGMENT_H
+#define DIGITAL_STRAIGHT_SEGMENT_H
+
+
+#include "digitalstraightline.h"
+
+using namespace std;
+
+
+/** 
+ * @class DigitalStraightSegment digitalstraightsegment.h
+ * \brief Digital straight segment is a bounded digital straight line.
+ * The digital straightline is defined by equation : c <= ax + by < c + nu
+ *   where a >= 0 and nu > 0. Seemingly b is unconstrained when a = 0.
+ * The bounds are horizontal lines (min <= y <= max) if the segment is vertical,
+ *   vertical lines (min <= x <= max) if the segment is horizontal.
+ * The bound points belong to the digital straight segment.
+ * \author {P. Even}
+ */
+class DigitalStraightSegment : public DigitalStraightLine
+{
+public:
+
+  /**
+   * Creates a null-thick segment joining two points.
+   * @param p1 First point on the line.
+   * @param p2 Second point on the line.
+   * @param type Digital line type : DSL_THIN, DSL_NAIVE or DSL_STANDARD.
+   * @param xmin Segment min X coordinate.
+   * @param ymin Segment min Y coordinate.
+   * @param xmax Segment max X coordinate.
+   * @param ymax Segment max Y coordinate.
+   */
+  DigitalStraightSegment (Pt2i p1, Pt2i p2, int type,
+                          int xmin, int ymin, int xmax, int ymax);
+
+  /**
+   * Creates a digital straight segment from an antipodal pair.
+   * @param p1 First segment end of the antipodal pair.
+   * @param p1 Second segment end of the antipodal pair.
+   * @param p3 Opposite point of the antipodal pair.
+   * @param xmin Segment min X coordinate.
+   * @param ymin Segment min Y coordinate.
+   * @param xmax Segment max X coordinate.
+   * @param ymax Segment max Y coordinate.
+   */
+  DigitalStraightSegment (Pt2i p1, Pt2i p2, Pt2i p3,
+                          int xmin, int ymin, int xmax, int ymax);
+
+  /**
+   * \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;
+
+
+protected:
+
+  /**
+   * \brief Bounding line lower coordinate.
+   * If the segment is stictly horizontal, it enforces x >= xmin.
+   * If the segment is vertical or diagonal, it enforces y >= ymin.
+   * The bound belongs to the segment.
+   */
+  int min;
+  /**
+   * \brief Bounding line upper coordinate.
+   * If the segment is stictly horizontal, it enforces x <= xmax.
+   * If the segment is vertical or diagonal, it enforces y <= ymax.
+   * The bound belongs to the segment.
+   */
+  int max;
+
+
+  /**
+   * \brief Adjusts the provided area on the segment limits.
+   * @param xmin Left coordinate of the area.
+   * @param ymin Bottom coordinate of the area.
+   * @param width Width of the area.
+   * @param height Height of the area.
+   */
+  void adjustWorkArea (int &xmin, int &ymin, int &width, int &height) const;
+
+};
+#endif
diff --git a/Code/Seg/ImageTools/pt2i.cpp b/Code/Seg/ImageTools/pt2i.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2da369428315247f8df2f5708566e80c3524a155
--- /dev/null
+++ b/Code/Seg/ImageTools/pt2i.cpp
@@ -0,0 +1,794 @@
+#include "pt2i.h"
+#include <cmath>
+
+
+Pt2i::Pt2i ()
+{
+  xp = 0;
+  yp = 0;
+}
+
+
+Pt2i::Pt2i (int x, int y)
+{
+  xp = x;
+  yp = y;
+}
+
+
+Pt2i::Pt2i (const Pt2i &p)
+{
+  xp = p.xp;
+  yp = p.yp;
+}
+
+
+Vr2i Pt2i::vectorTo (Pt2i p) const
+{
+  return (Vr2i (p.xp - xp, p.yp - yp));
+}
+
+
+AbsRat Pt2i::triangleRationalHeight (const Pt2i &p1, const Pt2i &p2) const
+{
+  AbsRat xh = triangleXRationalHeight (p1, p2);
+  AbsRat yh = triangleYRationalHeight (p1, p2);
+  return (xh.lessThan (yh) ? xh : yh);
+}
+
+
+AbsRat Pt2i::triangleXRationalHeight (const Pt2i &p1, const Pt2i &p2) const
+{
+  int ax, ay, bx, by, cx, cy;
+  if (xp < p1.xp)
+    if (xp < p2.xp)
+    {
+      ax = xp;
+      ay = yp;
+      if (p1.xp < p2.xp)
+      {
+        bx = p1.xp;
+        by = p1.yp;
+        cx = p2.xp;
+        cy = p2.yp;
+      }
+      else
+      {
+        bx = p2.xp;
+        by = p2.yp;
+        cx = p1.xp;
+        cy = p1.yp;
+      }
+    }
+    else
+    {
+      ax = p2.xp;
+      ay = p2.yp;
+      bx = xp;
+      by = yp;
+      cx = p1.xp;
+      cy = p1.yp;
+    }
+  else
+    if (xp < p2.xp)
+    {
+      ax = p1.xp;
+      ay = p1.yp;
+      bx = xp;
+      by = yp;
+      cx = p2.xp;
+      cy = p2.yp;
+    }
+    else {
+      cx = xp;
+      cy = yp;
+      if (p1.xp < p2.xp)
+      {
+        ax = p1.xp;
+        ay = p1.yp;
+        bx = p2.xp;
+        by = p2.yp;
+      }
+      else
+      {
+        ax = p2.xp;
+        ay = p2.yp;
+        bx = p1.xp;
+        by = p1.yp;
+      }
+    }
+  return (AbsRat ((bx - ax) * (cy - ay) - (by - ay) * (cx - ax), cx - ax));
+}
+
+
+AbsRat Pt2i::triangleYRationalHeight (const Pt2i &p1, const Pt2i &p2) const
+{
+  int ax, ay, bx, by, cx, cy;
+  if (yp < p1.yp)
+    if (yp < p2.yp)
+    {
+      ax = xp;
+      ay = yp;
+      if (p1.yp < p2.yp)
+      {
+        bx = p1.xp;
+        by = p1.yp;
+        cx = p2.xp;
+        cy = p2.yp;
+      }
+      else
+      {
+        bx = p2.xp;
+        by = p2.yp;
+        cx = p1.xp;
+        cy = p1.yp;
+      }
+    }
+    else
+    {
+      ax = p2.xp;
+      ay = p2.yp;
+      bx = xp;
+      by = yp;
+      cx = p1.xp;
+      cy = p1.yp;
+    }
+  else
+    if (yp < p2.yp)
+    {
+      ax = p1.xp;
+      ay = p1.yp;
+      bx = xp;
+      by = yp;
+      cx = p2.xp;
+      cy = p2.yp;
+    }
+    else {
+      cx = xp;
+      cy = yp;
+      if (p1.yp < p2.yp)
+      {
+        ax = p1.xp;
+        ay = p1.yp;
+        bx = p2.xp;
+        by = p2.yp;
+      }
+      else
+      {
+        ax = p2.xp;
+        ay = p2.yp;
+        bx = p1.xp;
+        by = p1.yp;
+      }
+    }
+  return (AbsRat ((bx - ax) * (cy - ay) - (by - ay) * (cx - ax), cy - ay));
+}
+
+
+Pt2i *Pt2i::drawing (const Pt2i p, int *n) const
+{
+  int x1, y1, x2, y2;
+  if (xp > p.xp)
+  {
+    x1 = p.xp;
+    x2 = xp;
+    y1 = p.yp;
+    y2 = yp;
+  }
+  else
+  {
+    x1 = xp;
+    x2 = p.xp;
+    y1 = yp;
+    y2 = p.yp;
+  }
+  int dx = x2 - x1;
+  int dy = y2 - y1;
+  int e, i = 0;
+  Pt2i *pts;
+
+  if (dy > 0)
+  {
+    // Octant 1
+    if (dx >= dy)
+    {
+      *n = dx + 1;
+      pts = new Pt2i[dx + 1];
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        pts[i++] = Pt2i (x1, y1);
+        x1 ++;
+        e -= dy;
+        if (e < 0)
+        {
+          y1 ++;
+          e += dx;
+        }
+      }
+      pts[i] = Pt2i (x1, y1);
+    }
+
+    // Octant 2
+    else
+    {
+      *n = dy + 1;
+      pts = new Pt2i[dy + 1];
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 < y2)
+      {
+        pts[i++] = Pt2i (x1, y1);
+        y1 ++;
+        e -= dx;
+        if (e < 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      pts[i] = Pt2i (x1, y1);
+    }
+  }
+
+  else
+  {
+    // Octant 8
+    if (dx >= -dy)
+    {
+      *n = 1 + dx;
+      pts = new Pt2i[dx + 1];
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        pts[i++] = Pt2i (x1, y1);
+        x1 ++;
+        e += dy;
+        if (e < 0)
+        {
+          y1 --;
+          e += dx;
+        }
+      }
+      pts[i] = Pt2i (x1, y1);
+    }
+
+    // Octant 7
+    else
+    {
+      *n = 1 - dy;
+      pts = new Pt2i[1 - dy];
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 > y2)
+      {
+        pts[i++] = Pt2i (x1, y1);
+        y1 --;
+        e += dx;
+        if (e > 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      pts[i] = Pt2i (x1, y1);
+    }
+  }
+  return (pts);
+}
+
+
+void Pt2i::draw (vector<Pt2i> &line, Pt2i p) const
+{
+  int x1, y1, x2, y2;
+  if (xp > p.xp)
+  {
+    x1 = p.xp;
+    x2 = xp;
+    y1 = p.yp;
+    y2 = yp;
+  }
+  else
+  {
+    x1 = xp;
+    x2 = p.xp;
+    y1 = yp;
+    y2 = p.yp;
+  }
+  int dx = x2 - x1;
+  int dy = y2 - y1;
+  int e;
+
+  if (dy > 0)
+  {
+    // Octant 1
+    if (dx >= dy)
+    {
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        line.push_back (Pt2i (x1, y1));
+        x1 ++;
+        e -= dy;
+        if (e < 0)
+        {
+          y1 ++;
+          e += dx;
+        }
+      }
+      line.push_back (Pt2i (x1, y1));
+    }
+
+    // Octant 2
+    else
+    {
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 < y2)
+      {
+        line.push_back (Pt2i (x1, y1));
+        y1 ++;
+        e -= dx;
+        if (e < 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      line.push_back (Pt2i (x1, y1));
+    }
+  }
+
+  else
+  {
+    // Octant 8
+    if (dx >= -dy)
+    {
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        line.push_back (Pt2i (x1, y1));
+        x1 ++;
+        e += dy;
+        if (e < 0)
+        {
+          y1 --;
+          e += dx;
+        }
+      }
+      line.push_back (Pt2i (x1, y1));
+    }
+
+    // Octant 7
+    else
+    {
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 > y2)
+      {
+        line.push_back (Pt2i (x1, y1));
+        y1 --;
+        e += dx;
+        if (e > 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      line.push_back (Pt2i (x1, y1));
+    }
+  }
+}
+
+
+Pt2i *Pt2i::pathTo (Pt2i p, int *n) const
+{
+  int x1, y1, x2, y2, delta;
+  if (xp > p.xp)
+  {
+    x1 = p.xp;
+    x2 = xp;
+    y1 = p.yp;
+    y2 = yp;
+    delta = -1;
+  }
+  else
+  {
+    x1 = xp;
+    x2 = p.xp;
+    y1 = yp;
+    y2 = p.yp;
+    delta = 1;
+  }
+  int dx = x2 - x1;
+  int dy = y2 - y1;
+  int e, i = 0;
+  Pt2i *pts;
+
+  if (dy > 0)
+  {
+    // Octant 1
+    if (dx >= dy)
+    {
+      *n = dx;
+      pts = new Pt2i[dx];
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        x1 ++;
+        e -= dy;
+        if (e < 0)
+        {
+          y1 ++;
+          e += dx;
+          pts[i++] = Pt2i (delta, delta);
+        }
+        else pts[i++] = Pt2i (delta, 0);
+      }
+    }
+
+    // Octant 2
+    else
+    {
+      *n = dy;
+      pts = new Pt2i[dy];
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 < y2)
+      {
+        y1 ++;
+        e -= dx;
+        if (e < 0)
+        {
+          x1 ++;
+          e += dy;
+          pts[i++] = Pt2i (delta, delta);
+        }
+        else pts[i++] = Pt2i (0, delta);
+      }
+    }
+  }
+
+  else
+  {
+    // Octant 8
+    if (dx >= -dy)
+    {
+      *n = dx;
+      pts = new Pt2i[dx];
+      e = dx;
+      dx *= 2;
+      dy *= 2;
+      while (x1 < x2)
+      {
+        x1 ++;
+        e += dy;
+        if (e < 0)
+        {
+          y1 --;
+          e += dx;
+          pts[i++] = Pt2i (delta, -delta);
+        }
+        else pts[i++] = Pt2i (delta, 0);
+      }
+    }
+    // Octant 7
+    else
+    {
+      *n = dy;
+      pts = new Pt2i[-dy];
+      e = dy;
+      dx *= 2;
+      dy *= 2;
+      while (y1 > y2)
+      {
+        y1 --;
+        e += dx;
+        if (e > 0)
+        {
+          x1 ++;
+          e += dy;
+          pts[i++] = Pt2i (delta, -delta);
+        }
+        else pts[i++] = Pt2i (0, -delta);
+      }
+    }
+  }
+  return (pts);
+}
+
+
+bool *Pt2i::stepsTo (Pt2i p, int *n) const
+{
+  int x2 = (xp > p.xp) ? xp - p.xp : p.xp - xp;
+  int y2 = (yp > p.yp) ? yp - p.yp : p.yp - yp;
+  int dx = x2, dy = y2;
+  if (y2 > x2)
+  {
+    dx = y2;
+    dy = x2;
+    x2 = y2;
+  }
+  int e, x = 0, i = 0;
+  *n = x2;
+  bool *paliers = new bool[x2];
+
+  e = dx;
+  dx *= 2;
+  dy *= 2;
+
+  while (x < x2)
+  {
+    x ++;
+    e -= dy;
+    if (e < 0)
+    {
+      e += dx;
+      paliers[i++] = true;
+    }
+    else paliers[i++] = false;
+  }
+  return (paliers); 
+}
+
+
+vector<Pt2i> Pt2i::drawOrtho (const Pt2i p2, int offset) const
+{
+  vector<Pt2i> pts;
+
+  int x1 = xp;
+  int y1 = yp;
+  int x2 = p2.x ();
+  int y2 = p2.y ();
+  int dx = x2 - x1;
+  int dy = y2 - y1;
+  int e;
+
+  int num = dx * dy;
+  if (num < 0) num = - num;
+  int den = dx * dx + dy * dy;
+  int nabs = (offset < 0 ? -offset : offset);
+  int steps = (offset * num) / den;
+  if ((nabs * num) % den >= den / 2) steps += (offset < 0 ? -1 : 1);
+  int floors;
+
+  if (dx > 0 && dy > 0)   // Quadrant 1
+  {
+    if (dx >= dy) // Octant 1
+    {
+      e = dx;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (steps * dy - e) / dx;
+      else floors = (e - 1 + steps * dy) / dx;
+      e += floors * dx - steps * dy;
+      x1 += steps;
+      y1 -= offset - floors;
+      x2 += steps;
+      // y2 -= offset - floors;   // inutile
+      while (x1 < x2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        x1 ++;
+        e = e - dy;
+        if (e < 0)
+        {
+          y1 ++;
+          e = e + dx;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+    else if (dx < dy) // Octant 2
+    {
+      e = dy;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (1 - e + steps * dx) / dy;
+      else floors = (e + steps * dx) / dy;
+      e -= floors * dy - steps * dx;
+      x1 += offset - floors;
+      y1 -= steps;
+      // x2 += offset - floors;  // inutile
+      y2 -= steps;  // inutile
+      while (y1 < y2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        y1 ++;
+        e -= dx;
+        if (e < 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+  }
+
+  else if (dx > 0 && dy < 0) // Quadrant 4
+  {
+    if (dx >= -dy) // Octant 8
+    {
+      e = dx;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (e - 1 + steps * dy) / dx;
+      else floors = (steps * dy - e) / dx;   // < 0
+      e += floors * dx - steps * dy;
+      x1 -= steps;
+      y1 -= offset + floors;
+      x2 -= steps;
+      // y2 -= offset + floors;  // inutile
+      while (x1 < x2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        x1 ++;
+        e += dy;
+        if (e < 0)
+        {
+          y1 --;
+          e += dx;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+    else // Octant 7
+    {
+      e = dy;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = - (e + steps * dx) / dy;
+      else floors = (e + 1 - steps * dx) / dy;
+      e += floors * dy + steps * dx;
+      x1 -= offset - floors;
+      y1 -= steps;
+      // x2 -= offset - floors;  // inutile
+      y2 -= steps;
+      while (y1 > y2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        y1 --;
+        e += dx;
+        if (e > 0)
+        {
+          x1 ++;
+          e += dy;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+  }
+  else if (dy == 0 && dx > 0)
+    while (x1 <= x2) pts.push_back (Pt2i (x1++, y1 - offset));
+
+  if (dx < 0 && dy > 0)    // Quadrant 2
+  {
+    if (-dx >= dy) // Octant 4
+    {
+      e = dx;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = - (steps * dy + e) / dx;
+      else floors = (e + 1 - steps * dy) / dx;  // > 0
+      e -= steps * dy + floors * dx;
+      x1 += steps;
+      y1 += offset - floors;
+      x2 += steps;
+      // y2 += offset - floors;   // inutile
+      while (x1 > x2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        x1 --;
+        e += dy;
+        if (e >= 0)
+        {
+          y1 ++;
+          e += dx;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+    else if (-dx < dy) // Octant 3
+    {
+      e = dy;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (1 - e - steps * dx) / dy;
+      else floors = (e - steps * dx) / dy;
+      e += floors * dy + steps * dx;
+      x1 += offset - floors;
+      y1 += steps;
+      // x2 += offset - floors;   // inutile
+      y2 += steps;
+      while (y1 < y2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        y1 ++;
+        e += dx;
+        if (e <= 0)
+        {
+          x1 --;
+          e += dy;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+  }
+
+  else if (dx < 0 && dy < 0)    // Quadrant 3
+  {
+    if (dx <= dy) // Octant 5
+    {
+      e = dx;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (steps * dy - e - 1) / dx;
+      else floors = (steps * dy + e) / dx;
+      e += floors * dx - steps * dy;
+      x1 -= steps;
+      y1 += offset - floors;
+      x2 -= steps;
+      // y2 += offset - floors;  // inutile
+      while (x1 > x2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        x1 --;
+        e -= dy;
+        if (e >= 0)
+        {
+          y1 --;
+          e += dx;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+    else // Octant 6
+    {
+      e = dy;
+      dx = dx * 2;
+      dy = dy * 2;
+      if (offset < 0) floors = (e - steps * dx) / dy;  // > 0
+      else floors = - (steps * dx + e + 1) / dy;
+      e += floors * dy + steps * dx;
+      x1 -= offset + floors;
+      y1 += steps;
+      y2 += steps;
+     // x2 -= offset - floors;  // calcul inutile
+      while (y1 > y2)
+      {
+        pts.push_back (Pt2i (x1, y1));
+        y1 --;
+        e -= dx;
+        if (e >= 0)
+        {
+          x1 --;
+          e += dy;
+        }
+      }
+      pts.push_back (Pt2i (x1, y1));
+    }
+  }
+  else if (dy == 0 && dx < 0)
+    while (x1 >= x2) pts.push_back (Pt2i (x1--, y1 + offset));
+  else if (dx == 0 && dy > 0)
+    while (y1 <= y2) pts.push_back (Pt2i (x1 + offset, y1++));
+  else if (dx == 0 && dy < 0)
+    while(y1 >= y2) pts.push_back (Pt2i (x1 - offset, y1--));
+  return pts;
+}
diff --git a/Code/Seg/ImageTools/pt2i.h b/Code/Seg/ImageTools/pt2i.h
new file mode 100755
index 0000000000000000000000000000000000000000..a48b5b1d3bef9b3cbcab390b85c67e635eb514af
--- /dev/null
+++ b/Code/Seg/ImageTools/pt2i.h
@@ -0,0 +1,247 @@
+#ifndef PT2I_H
+#define PT2I_H
+
+#include "vr2i.h"
+#include "absrat.h"
+#include <vector>
+
+using namespace std;
+
+
+
+/** 
+ * @class Pt2i pt2i.h
+ * \brief Point in the digital plane.
+ * \author {P. Even}
+ */
+class Pt2i
+{
+
+public:
+
+  /**
+   * @fn Pt2i ()
+   * \brief Creates a point at origin.
+   */
+  Pt2i ();
+
+  /**
+   * @fn Pt2i (int x, int y)
+   * \brief Creates a point using coordinates.
+   * @param x X coordinate.
+   * @param y Y coordinate.
+   */
+  Pt2i (int x, int y);
+
+  /**
+   * @fn Pt2i (Pt2i p)
+   * \brief Creates a copy of a given point.
+   * @param p Original.
+   */
+  Pt2i (const Pt2i &p);
+
+  /**
+   * @fn ~Pt2i ()
+   * \brief Deletes the point.
+   */
+  ~Pt2i () { }
+
+  /**
+   * @fn int x ()
+   * \brief Returns the point abscissae.
+   */
+  inline int x () const
+  {
+    return xp;
+  }
+
+  /**
+   * @fn int y ()
+   * \brief Returns the point ordinate.
+   */
+  inline int y () const
+  {
+    return yp;
+  }
+
+  /**
+   * @fn int get (int n)
+   * \brief Returns the nth coordinate.
+   * @param n Coordinate index.
+   */
+  inline int get (int n) const
+  {
+    return (n ? yp : xp);
+  }
+
+  /**
+   * @fn void set (int x, int y)
+   * \brief Sets the point coordinates.
+   * @param x New abscissae.
+   * @param y New ordinate.
+   */
+  inline void set (int x, int y)
+  {
+    xp = x;
+    yp = y;
+  }
+
+  /**
+   * @fn void set (int x, int y)
+   * \brief Sets the point coordinates.
+   * @param point to recopy.
+   */
+  inline void set (const Pt2i &p)
+  {
+    xp = p.xp;
+    yp = p.yp;
+  }
+
+  /**
+   * @fn bool equals (Pt2i p)
+   * \brief Checks equivalence to the given point.
+   * @param p the given point.
+   */
+  inline bool equals (Pt2i p) const
+  {
+    return (p.xp == xp && p.yp == yp);
+  }
+
+  /**
+   * @fn int manhattan (Pt2i p)
+   * \brief Returns the manhattan distance to the given point.
+   * @param p the given point.
+   */
+  inline int manhattan (Pt2i p) const
+  {
+    return (((p.xp > xp) ? p.xp - xp : xp - p.xp)
+            + ((p.yp > yp) ? p.yp - yp : yp - p.yp));
+  }
+
+  /**
+   * @fn int isConnectedTo (Pt2i p)
+   * \brief Checks whether the point is connected (chessboard) to the given one.
+   * @param p the given point.
+   */
+  inline bool isConnectedTo (Pt2i p) const
+  {
+    return ((p.xp - xp <= 1) && (xp - p.xp <= 1)
+            && (p.yp - yp <= 1) && (yp - p.yp <= 1));
+  }
+
+  /**
+   * @fn bool colinearTo (const Point2D &p1, const Point2D &p2)
+   * Checks whether the point is colinear to tho other point.
+   * @param p1 First distinct point.
+   * @param p2 Second distinct point.
+   */
+  inline bool colinearTo (const Pt2i &p1, const Pt2i &p2) const
+  {
+    return ((p1.xp - xp) * (p2.yp - yp) == (p2.xp - xp) * (p1.yp - yp));
+  }
+
+  /**
+   * @fn bool toLeft (const Point2D &p1, const Point2D &p2)
+   * Checks whether the point is to the left of the segment (p1p2).
+   * @param p1 Segment start point.
+   * @param p2 Segment end point.
+   */
+  inline bool toLeft (const Pt2i &p1, const Pt2i &p2) const
+  {
+    return ((p1.xp - xp) * (p2.yp - yp) > (p2.xp - xp) * (p1.yp - yp));
+  }
+
+  /**
+   * @fn bool toLeftOrOn (const Point2D &p1, const Point2D &p2)
+   * Checks whether the point is to the left or on the segment (p1p2).
+   * @param p1 Segment start point.
+   * @param p2 Segment end point.
+   */
+  inline bool toLeftOrOn (const Pt2i &p1, const Pt2i &p2) const
+  {
+    return ((p1.xp - xp) * (p2.yp - yp) >= (p2.xp - xp) * (p1.yp - yp));
+  }
+
+  /**
+   * @fn AbsRat triangleRationalHeight (const Pt2i &p1, const Pt2i &p2)
+   * \brief Returns the X/Y height of the triangle with two other points.
+   * @param p1 First distinct point.
+   * @param p2 Second distinct point.
+   */
+  AbsRat triangleRationalHeight (const Pt2i &p1, const Pt2i &p2) const;
+
+  /**
+   * @fn AbsRat triangleXRationalHeight (const Pt2i &p1, const Pt2i &p2)
+   * \brief Returns the vertical height of the triangle with two other points.
+   * @param p1 First distinct point.
+   * @param p2 Second distinct point.
+   */
+  AbsRat triangleXRationalHeight (const Pt2i &p1, const Pt2i &p2) const;
+
+  /**
+   * @fn AbsRat triangleYRationalHeight (const Pt2i &p1, const Pt2i &p2)
+   * \brief Returns the horizontal height of the triangle with two other points.
+   * @param p1 First distinct point.
+   * @param p2 Second distinct point.
+   */
+  AbsRat triangleYRationalHeight (const Pt2i &p1, const Pt2i &p2) const;
+
+  /**
+   * @fn Vr2i vectorTo (Pt2i p)
+   * \brief Returns the discrete vector to the given point.
+   * @param p the given point.
+   */
+  Vr2i vectorTo (Pt2i p) const;
+
+  /**
+   * @fn Pt2i *drawing (Pt2i p, int *n)
+   * \brief Returns the segment to the given point.
+   * @param p the given point.
+   * @param n size of the returned array.
+   */
+  Pt2i *drawing (const Pt2i p, int *n) const;
+
+  /**
+   * @fn Pt2i *drawing (Pt2i p, int *n)
+   * \brief Fills the provided vector with the segment to the given point.
+   * @param line Vector of points to fill in.
+   * @param p Distant point.
+   */
+  void draw (vector<Pt2i> &line, Pt2i p) const;
+
+  /**
+   * @fn Pt2i *pathTo (Pt2i p, int *n)
+   * \brief Returns the succession of local moves to reach the given point.
+   * A local move is the vector from a point to one of his neighbours.
+   * @param p the given point.
+   * @param n size of the returned array.
+   */
+  Pt2i *pathTo (Pt2i p, int *n) const;
+
+  /**
+   * @fn bool *stepsTo (Pt2i p, int *n)
+   * \brief Returns the location of the steps to reach the given point.
+   * @param p the given point.
+   * @param n size of the returned array.
+   */
+  bool *stepsTo (Pt2i p, int *n) const;
+
+  /**
+   * @fn vector<Pt2i> drawOrtho (const Pt2i p2, int offset) const
+   * \brief Returns the segment orthogonal to the segment to p2.
+   * @param p2 The distant point.
+   * @param offset The orthogonal offset.
+   */
+  vector<Pt2i> drawOrtho (const Pt2i p2, int offset) const;
+
+
+protected:
+
+  /** Point abscissae. */
+  int xp;
+  /** Point ordinate. */
+  int yp;
+
+};
+
+#endif
diff --git a/Code/Seg/ImageTools/strucel.cpp b/Code/Seg/ImageTools/strucel.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..caade0b8f74bedd28f482e6ffffd913e17b41fb1
--- /dev/null
+++ b/Code/Seg/ImageTools/strucel.cpp
@@ -0,0 +1,158 @@
+#include <iostream>
+#include "strucel.h"
+
+using namespace std;
+
+
+const int Strucel::TYPE_PLUS_3X3 = 0;
+
+
+Strucel::Strucel (int type)
+{
+  if (type == TYPE_PLUS_3X3)
+  {
+    width = 3;
+    height = 3;
+    size = 5;
+    pattern = new Vr2i[5];
+    pattern[0] = Vr2i (0, 0);
+    pattern[1] = Vr2i (0, 1);
+    pattern[2] = Vr2i (-1, 0);
+    pattern[3] = Vr2i (1, 0);
+    pattern[4] = Vr2i (0, -1);
+  }
+  else
+  {
+    width = 1;
+    height = 1;
+    size = 1;
+    pattern = new Vr2i[1];
+    pattern[0] = Vr2i (1, 1);
+  }
+}
+
+
+Strucel::~Strucel ()
+{
+  delete pattern;
+}
+
+
+void Strucel::tophatGradient (int *out, int **in, int width, int height)
+{
+cout << "TH IN" << endl;
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int min = -1;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+          if (min == -1 || in[y][x] < min) min = in[y][x];
+      }
+      out[j * width + i] = in[j][i] - min;
+    }
+cout << "TH OUT" << endl;
+}
+
+
+void Strucel::tophatGradient (int *out, int *in, int width, int height)
+{
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int min = -1;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+          if (min == -1 || in[y * width + x] < min) min = in[y * width + x];
+      }
+      out[j * width + i] = in[j * width + i] - min;
+    }
+}
+
+
+void Strucel::blackhatGradient (int *out, int **in, int width, int height)
+{
+cout << "BH IN" << endl;
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int max = 0;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+          if (in[y][x] > max) max = in[y][x];
+      }
+      out[j * width + i] = max - in[j][i];
+    }
+cout << "BH OUT" << endl;
+}
+
+
+void Strucel::blackhatGradient (int *out, int *in, int width, int height)
+{
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int max = 0;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+          if (in[y * width + x] > max) max = in[y * width + x];
+      }
+      out[j * width + i] = max - in[j * width + i];
+    }
+}
+
+
+void Strucel::morphoGradient (int *out, int **in, int width, int height)
+{
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int max = 0;
+      int min = -1;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+        {
+          if (min == -1 || in[y][x] < min) min = in[y][x];
+          if (in[y][x] > max) max = in[y][x];
+        }
+      }
+      out[j * width + i] = max - min;
+    }
+}
+
+
+void Strucel::morphoGradient (int *out, int *in, int width, int height)
+{
+  for (int j = 0; j < height; j++)
+    for (int i = 0; i < width; i++)
+    {
+      int max = 0;
+      int min = -1;
+      for (int k = 0; k < size; k++)
+      {
+        int x = i - pattern[k].x ();
+        int y = j - pattern[k].y ();
+        if (x >= 0 && x < width && y >= 0 && y < height)
+        {
+          if (min == -1 || in[y * width + x] < min) min = in[y * width + x];
+          if (in[y * width + x] > max) max = in[y * width + x];
+        }
+      }
+      out[j * width + i] = max - min;
+    }
+}
diff --git a/Code/Seg/ImageTools/strucel.h b/Code/Seg/ImageTools/strucel.h
new file mode 100755
index 0000000000000000000000000000000000000000..9503cd28d8e1242eb70ad9fb7c28b59a79374025
--- /dev/null
+++ b/Code/Seg/ImageTools/strucel.h
@@ -0,0 +1,118 @@
+#ifndef STRUCEL_H
+#define STRUCEL_H
+
+#include "vr2i.h"
+
+using namespace std;
+
+
+/** 
+ * @class Strucel strucel.h
+ * \brief Structuring element for morphological operations.
+ */
+class Strucel
+{
+
+public:
+
+  /** 3x3 cross structuring element type. */
+  static const int TYPE_PLUS_3X3;
+
+
+  /** 
+   * \brief Creates a structural element.
+   * @param type Pattern type.
+   */
+  Strucel (int type);
+
+  /** 
+   * \brief Deletes the structuring element.
+   */
+  ~Strucel ();
+
+  /** 
+   * \brief Returns the pattern width.
+   */
+  inline int getWidth () const
+  {
+    return width;
+  }
+
+  /** 
+   * \brief Returns the pattern height.
+
+   */
+  inline int getHeight () const
+  {
+    return height;
+  }
+
+  /** 
+   * \brief Calculates the top hat gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image bi-dimensional array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void tophatGradient (int *out, int **in, int width, int height);
+
+  /** 
+   * \brief Calculates the top hat gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void tophatGradient (int *out, int *in, int width, int height);
+
+  /** 
+   * \brief Calculates the black hat gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image bi-dimensional array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void blackhatGradient (int *out, int **in, int width, int height);
+
+  /** 
+   * \brief Calculates the black hat gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void blackhatGradient (int *out, int *in, int width, int height);
+
+  /** 
+   * \brief Calculates the morphological gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image bi-dimensional array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void morphoGradient (int *out, int **in, int width, int height);
+
+  /** 
+   * \brief Calculates the morphological gradient of an image.
+   * @param out Output gradient array (the memory should be allocated before).
+   * @param in Image array.
+   * @param width Image width.
+   * @param height Image height.
+   */
+  void morphoGradient (int *out, int *in, int width, int height);
+
+
+private:
+
+  /** Width of the structuring element. */
+  int width;
+  /** Height of the structuring element. */
+  int height;
+  /** Size of the pattern. */
+  int size;
+  /** Pattern of the structuring element as the list of occupied pixels. */
+  Vr2i *pattern;
+
+};
+
+#endif
diff --git a/Code/Seg/ImageTools/vmap.cpp b/Code/Seg/ImageTools/vmap.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..3cd61824e5cf80663da62d8c3211fc2efc3e3a64
--- /dev/null
+++ b/Code/Seg/ImageTools/vmap.cpp
@@ -0,0 +1,486 @@
+// #include <iostream>
+#include "vmap.h"
+#include "math.h"
+
+using namespace std;
+
+
+const int VMap::TYPE_SOBEL_3X3 = 0;
+const int VMap::TYPE_SOBEL_5X5 = 1;
+const int VMap::TYPE_TOP_HAT = 2;
+const int VMap::TYPE_BLACK_HAT = 3;
+const int VMap::TYPE_MORPHO = 4;
+
+const int VMap::NEAR_SQ_ANGLE = 80;  // 80% (roughly 25 degrees)
+const int VMap::LARGE_SQ_ANGLE = 25;  // 25% (60 degrees)
+const int VMap::DEFAULT_GRADIENT_THRESHOLD = 30;
+
+
+VMap::VMap (int width, int height, int *data, int type)
+{
+  this->width = width;
+  this->height = height;
+  if (type == TYPE_SOBEL_5X5) buildSobel5x5Map (data);
+  else buildGradientMap (data);
+  imap = new int[width * height];
+  if (type == TYPE_TOP_HAT)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.tophatGradient (imap, data, width, height);
+  }
+  else if (type == TYPE_BLACK_HAT)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.blackhatGradient (imap, data, width, height);
+  }
+  else if (type == TYPE_MORPHO)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.morphoGradient (imap, data, width, height);
+  }
+  else
+    for (int i = 0; i < width * height; i++)
+      imap[i] = (int) sqrt (map[i].norm2 ());
+  mask = new bool[width * height];
+  for (int i = 0; i < width * height; i++) mask[i] = false;
+  masking = false;
+  angleThreshold = NEAR_SQ_ANGLE;
+  orientedGradient = false;
+  formerOrientedGradient = false;
+}
+
+
+VMap::VMap (int width, int height, int **data, int type)
+{
+  this->width = width;
+  this->height = height;
+  if (type == TYPE_SOBEL_5X5) buildSobel5x5Map (data);
+  else buildGradientMap (data);
+  imap = new int[width * height];
+  if (type == TYPE_TOP_HAT)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.tophatGradient (imap, data, width, height);
+  }
+  else if (type == TYPE_BLACK_HAT)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.blackhatGradient (imap, data, width, height);
+  }
+  else if (type == TYPE_MORPHO)
+  {
+    Strucel se (Strucel::TYPE_PLUS_3X3);
+    se.morphoGradient (imap, data, width, height);
+  }
+  else
+    for (int i = 0; i < width * height; i++)
+      imap[i] = sqrt (map[i].norm2 ());
+  mask = new bool[width * height];
+  for (int i = 0; i < width * height; i++) mask[i] = false;
+  masking = false;
+  angleThreshold = NEAR_SQ_ANGLE;
+  orientedGradient = false;
+  formerOrientedGradient = false;
+}
+
+
+VMap::~VMap ()
+{
+  delete map;
+  delete imap;
+  delete mask;
+}
+
+
+void VMap::buildGradientMap (int *data)
+{
+  map = new Vr2i[width * height];
+  Vr2i *gm = map;
+
+  for (int j = 0; j < width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int i = 1; i < height - 1; i++)
+  {
+    gm->set (0, 0);
+    gm++;
+    for (int j = 1; j < width - 1; j++)
+    {
+      gm->set (data[(i - 1) * height + j + 1]
+               + 2 * data[i * height + j + 1]
+               + data[(i + 1) * height + j + 1]
+               - data[(i - 1) * height + j - 1]
+               - 2 * data[i * height + j - 1]
+               - data[(i + 1) * height + j - 1],
+               data[(i + 1) * height + j - 1]
+               + 2 * data[(i + 1) * height + j]
+               + data[(i + 1) * height + j + 1]
+               - data[(i - 1) * height + j - 1]
+               - 2 * data[(i - 1) * height + j]
+               - data[(i - 1) * height + j + 1]);
+      gm++;
+    }
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int j = 0; j < width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+}
+
+
+void VMap::buildGradientMap (int **data)
+{
+  map = new Vr2i[width * height];
+  Vr2i *gm = map;
+
+  for (int j = 0; j < width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int i = 1; i < height - 1; i++)
+  {
+    gm->set (0, 0);
+    gm++;
+    for (int j = 1; j < width - 1; j++)
+    {
+      gm->set (data[i-1][j+1] + 2 * data[i][j+1] + data[i+1][j+1]
+               - data[i-1][j-1] - 2 * data[i][j-1] - data[i+1][j-1],
+               data[i+1][j-1] + 2 * data[i+1][j] + data[i+1][j+1]
+               - data[i-1][j-1] - 2 * data[i-1][j] - data[i-1][j+1]);
+      gm++;
+    }
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int j = 0; j < width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+}
+
+
+void VMap::buildSobel5x5Map (int *data)
+{
+  map = new Vr2i[width * height];
+  Vr2i *gm = map;
+
+  for (int j = 0; j < 2 * width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int i = 2; i < height - 2; i++)
+  {
+    gm->set (0, 0);
+    gm++;
+    gm->set (0, 0);
+    gm++;
+    for (int j = 2; j < width - 2; j++)
+    {
+      gm->set (5 * data[(i - 2) * height + j + 2]
+                 + 8 * data[(i - 1) * height + j + 2]
+                 + 10 * data[i * height + j + 2]
+                 + 8 * data[(i + 1) * height + j + 2]
+                 + 5 * data[(i + 2) * height + j + 2]
+               + 4 * data[(i - 2) * height + j + 1]
+                 + 10 * data[(i - 1) * height + j + 1]
+                 + 20 * data[i * height + j + 1]
+                 + 10 * data[(i + 1) * height + j + 1]
+                 + 4 * data[(i + 2) * height + j + 1]
+               - 4 * data[(i - 2) * height + j - 1]
+                 - 10 * data[(i - 1) * height + j - 1]
+                 - 20 * data[i * height + j - 1]
+                 - 10 * data[(i + 1) * height + j - 1]
+                 - 4 * data[(i + 2) * height + j - 1] 
+               - 5 * data[(i - 2) * height + j - 2]
+                 - 8 * data[(i - 1) * height + j - 2]
+                 - 10 * data[i * height + j - 2]
+                 - 8 * data[(i + 1) * height + j - 2]
+                 - 5 * data[(i + 2) * height + j - 2],
+               5 * data[(i + 2) * height + j - 2]
+                 + 8 * data[(i + 2) * height + j - 1]
+                 + 10 * data[(i + 2) * height + j]
+                 + 8 * data[(i + 2) * height + j + 1]
+                 + 5 * data[(i + 2) * height + j + 2]
+               + 4 * data[(i + 1) * height + j - 2]
+                 + 10 * data[(i + 1) * height + j - 1]
+                 + 20 * data[(i + 1) * height + j]
+                 + 10 * data[(i + 1) * height + j + 1]
+                 + 4 * data[(i + 1) * height + j + 2]
+               - 4 * data[(i - 1) * height + j - 2]
+                 - 10 * data[(i - 1) * height + j - 1]
+                 - 20 * data[(i - 1) * height + j]
+                 - 10 * data[(i - 1) * height + j + 1]
+                 - 4 * data[(i - 1) * height + j + 2]
+               - 5 * data[(i - 2) * height + j - 2]
+                 - 8 * data[(i - 2) * height + j - 1]
+                 - 10 * data[(i - 2) * height + j]
+                 - 8 * data[(i - 2) * height + j + 1]
+                 - 5 * data[(i - 2) * height + j + 2]);
+      gm++;
+    }
+    gm->set (0, 0);
+    gm++;
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int j = 0; j < 2 * width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+}
+
+
+void VMap::buildSobel5x5Map (int **data)
+{
+  map = new Vr2i[width * height];
+  Vr2i *gm = map;
+
+  for (int j = 0; j < 2 * width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int i = 2; i < height - 2; i++)
+  {
+    gm->set (0, 0);
+    gm++;
+    gm->set (0, 0);
+    gm++;
+    for (int j = 2; j < width - 2; j++)
+    {
+      gm->set (
+        5 * data[i-2][j+2] + 8 * data[i-1][j+2] + 10 * data[i][j+2]
+                           + 8 * data[i+1][j+2] + 5 * data[i+2][j+2]
+        + 4 * data[i-2][j+1] + 10 * data[i-1][j+1] + 20 * data[i][j+1]
+                           + 10 * data[i+1][j+1] + 4 * data[i+2][j+1]
+        - 4 * data[i-2][j-1] - 10 * data[i-1][j-1] - 20 * data[i][j-1]
+                           - 10 * data[i+1][j-1] - 4 * data[i+2][j-1]
+        - 5 * data[i-2][j-2] - 8 * data[i-1][j-2] - 10 * data[i][j-2]
+                           - 8 * data[i+1][j-2] - 5 * data[i+2][j-2],
+        5 * data[i+2][j-2] + 8 * data[i+2][j-1] + 10 * data[i+2][j]
+                           + 8 * data[i+2][j+1] + 5 * data[i+2][j+2]
+        + 4 * data[i+1][j-2] + 10 * data[i+1][j-1] + 20 * data[i+1][j]
+                           + 10 * data[i+1][j+1] + 4 * data[i+1][j+2]
+        - 4 * data[i-1][j-2] - 10 * data[i-1][j-1] - 20 * data[i-1][j]
+                           - 10 * data[i-1][j+1] - 4 * data[i-1][j+2]
+        - 5 * data[i-2][j-2] - 8 * data[i-2][j-1] - 10 * data[i-2][j]
+                           - 8 * data[i-2][j+1] - 5 * data[i-2][j+2]);
+      gm++;
+    }
+    gm->set (0, 0);
+    gm++;
+    gm->set (0, 0);
+    gm++;
+  }
+  for (int j = 0; j < 2 * width; j++)
+  {
+    gm->set (0, 0);
+    gm++;
+  }
+}
+
+
+int VMap::sqNorm (int i, int j) const
+{
+  return (map[j * width + i].norm2 ());
+}
+
+
+int VMap::sqNorm (Pt2i p) const
+{
+  return (map[p.y () * width + p.x ()].norm2 ());
+}
+
+
+int VMap::largestIn (const vector<Pt2i> &pix) const
+{
+  if (pix.empty ()) return (-1);
+
+  int imax = -1;
+  vector<Pt2i>::const_iterator pt = pix.begin ();
+  int gmax = imap[pt->y() * width + pt->x()];
+  if (gmax < DEFAULT_GRADIENT_THRESHOLD) gmax = DEFAULT_GRADIENT_THRESHOLD;
+
+  int i = 0;
+  while (pt != pix.end ())
+  {
+    int g = imap[pt->y() * width + pt->x()];
+    if (g > gmax)
+    {
+      gmax = g;
+      imax = i;
+    }
+    pt ++;
+    i ++;
+  }
+  return (imax == i - 1 ? -1 : imax);
+}
+
+
+int VMap::keepFreeElementsIn (const vector<Pt2i> &pix, int n, int *ind) const
+{
+  int i = 0;
+  while (i < n)
+  {
+    if (mask[pix[ind[i]].y () * width + pix[ind[i]].x ()]) ind[i] = ind[--n];
+    else i++;
+  }
+  return (n);
+}
+
+
+int VMap::keepOrientedElementsIn (const vector<Pt2i> &pix,
+                                       const Vr2i &ref, int n, int *ind) const
+{
+  int vx = ref.x ();
+  int vy = ref.y ();
+  int i = 0;
+  while (i < n)
+  {
+    Vr2i gr = map[pix[ind[i]].y () * width + pix[ind[i]].x ()];
+    if (vx * gr.x () + vy * gr.y () <= 0) ind[i] = ind[--n];
+    else i++;
+  }
+  return (n);
+}
+
+
+int VMap::keepDirectedElementsIn (const vector<Pt2i> &pix,
+                                  const Vr2i &ref, int n, int *ind) const
+{
+  int vx = ref.x ();
+  int vy = ref.y ();
+  long vn2 = vx * vx + vy * vy;
+
+  int i = 0;
+  while (i < n)
+  {
+    Pt2i p = pix.at (ind[i]);
+    Vr2i gr = map[p.y () * width + p.x ()];
+    long gx = gr.x ();
+    long gy = gr.y ();
+    if ((vx * vx * gx * gx + vy * vy * gy * gy + 2 * vx * vy * gx * gy) * 100
+        < vn2 * (gx * gx + gy * gy) * angleThreshold)
+      ind[i] = ind[--n];
+    else i++;
+  }
+  return (n);
+}
+
+
+int VMap::localMax (int *lmax, const vector<Pt2i> &pix, const Vr2i &gref) const
+{
+  // Builds the gradient norm signal
+  int n = (int) pix.size ();
+  int *gn = new int[n];
+  int i = 0;
+  vector<Pt2i>::const_iterator it = pix.begin ();
+  while (it != pix.end ()) gn[i++] = cmpNorm (*it++);
+
+  // 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 = keepOrientedElementsIn (pix, gref, count, lmax);
+
+  // Prunes the candidates wrongly oriented
+  count = keepDirectedElementsIn (pix, gref, count, lmax);
+
+  // Sorts candidates by gradient magnitude
+  sortMax (lmax, count, gn);
+
+  delete gn;
+  return count;
+}
+
+
+int VMap::searchLocalMax (int *lmax, int n, int *in) const
+{
+  int offset = 0;
+  int count = 0;
+  bool up = true;
+
+  // Gets the first distinct value from start
+  while (offset < n - 1 && in[offset] == in[0])
+  {
+    if (in[offset] - in[offset + 1] < 0)
+    {
+      up = true;
+      break;
+    }
+    if (in[offset] - in[offset + 1] > 0)
+    {
+      up = false;
+      break;
+    }
+    offset++;
+  }
+
+  for(int i = offset; i < n - 1; i++)
+  {
+    if (up)
+    {
+      if ((in[i + 1] - in[i]) < 0)
+      {
+        up = false;
+        int k = i;
+        while (in[k - 1] == in[i]) k--;
+        lmax[count++] = k + (i - k) / 2;
+      }
+    }
+    else
+      if (in[i + 1] - in[i] > 0) up = true;
+  }
+  return count;
+}
+
+
+void VMap::sortMax (int *lmax, int n, int *val) const
+{
+  for (int i = 1; i < n; i ++)
+  {
+    int j = i, tmp = lmax[i];
+    bool on = true;
+    while (on && j > 0)
+    {
+      if (val[tmp] > val[lmax[j-1]])
+      {
+        lmax[j] = lmax[j-1];
+        j --;
+      }
+      else on = false;
+    }
+    lmax[j] = tmp;
+  }
+}
+
+
+void VMap::clearMask ()
+{
+  for (int i = 0; i < width * height; i++) mask[i] = false;
+}
+
+
+void VMap::setMask (const vector<Pt2i> &pts)
+{
+  vector<Pt2i>::const_iterator it = pts.begin ();
+  while (it != pts.end ())
+  {
+    Pt2i pt = *it++;
+    mask[pt.y () * width + pt.x ()] = true;
+  }
+}
diff --git a/Code/Seg/ImageTools/vmap.h b/Code/Seg/ImageTools/vmap.h
new file mode 100755
index 0000000000000000000000000000000000000000..c846596367e068dedca685425f4f079f94017b69
--- /dev/null
+++ b/Code/Seg/ImageTools/vmap.h
@@ -0,0 +1,303 @@
+#ifndef VMAP_H
+#define VMAP_H
+
+#include "pt2i.h"
+#include "strucel.h"
+
+using namespace std;
+
+
+/** 
+ * @class VMap vmap.h
+ * \brief Vector map.
+ * \author {P. Even}
+ */
+class VMap
+{
+
+public:
+
+  /** Gradient extraction method : Sobel with 3x3 kernel. */
+  static const int TYPE_SOBEL_3X3;
+  /** Gradient extraction method : Sobel with 5x5 kernel. */
+  static const int TYPE_SOBEL_5X5;
+  /** Gradient extraction method : Morphological top hat (I - E(I)). */
+  static const int TYPE_TOP_HAT;
+  /** Gradient extraction method : Morphological black hat (D(I) - I). */
+  static const int TYPE_BLACK_HAT;
+  /** Gradient extraction method : Morphological gradient (D(I) - E(I)). */
+  static const int TYPE_MORPHO;
+
+
+  /** 
+   * \brief Creates a gradient map from scalar data.
+   * @param width Map width.
+   * @param height Map height.
+   * @param data Scalar data array.
+   * @param type Gradient extraction method (default is Soble with 3x3 kernel).
+   */
+  VMap (int width, int height, int *data, int type = 0);
+
+  /** 
+   * \brief Creates a gradient map from scalar data.
+   * @param width Map width.
+   * @param height Map height.
+   * @param data Scalar data bi-dimensional array.
+   */
+  VMap (int width, int height, int **data, int type = 0);
+
+  /** 
+   * \brief Deletes the vector map.
+   */
+  ~VMap ();
+
+  /** 
+   * \brief Returns the map width.
+   */
+  inline int getWidth () const
+  {
+    return width;
+  }
+
+  /** 
+   * \brief Returns the map height.
+   */
+  inline int getHeight () const
+  {
+    return height;
+  }
+
+  /** 
+   * \brief Returns the maximal value between map width or height.
+   */
+  inline int getHeightWidthMax () const
+  {
+    return (height > width ? height : width);
+  }
+
+  /**
+   * \brief Checks whether the given point lies within the map bounds.
+   * @param i Column number.
+   * @param j Line number.
+   */
+  inline bool contains (int i, int j)
+  {
+    return (i >= 0 && i < width && j >= 0 && j < height);
+  }
+
+  /**
+   * \brief Returns the vector at point (i,j).
+   * @param i Column number.
+   * @param j Line number.
+   */
+  Vr2i getValue (int i, int j) const
+  {
+    return (map[j * width + i]);
+  }
+
+  /**
+   * \brief Returns the vector at given point.
+   * @param p Point position.
+   */
+  Vr2i getValue (Pt2i p) const
+  {
+    return (map[p.y () * width + p.x ()]);
+  }
+
+  /**
+   * \brief Returns the squared norm of the vector magnitude at point (i,j).
+   * @param i Column number.
+   * @param j Line number.
+   */
+  int sqNorm (int i, int j) const;
+
+  /**
+   * \brief Returns the squared norm of the vector magnitude at given point.
+   * @param p Point position.
+   */
+  int sqNorm (Pt2i p) const;
+
+  /**
+   * \brief Returns the comparable norm of the vector magnitude at point (i,j).
+   * @param i Column number.
+   * @param j Line number.
+   */
+  inline int cmpNorm (int i, int j) const { return (imap[j * width + i]); }
+
+  /**
+   * \brief Returns the comparable norm of the vector magnitude at given point.
+   * @param p Point position.
+   */
+  inline int cmpNorm (Pt2i p) const { return (imap[p.y () * width + p.x ()]); }
+
+  /** 
+   * \brief Returns the index of the largest vector at given positions.
+   *   First and last points of the list are not accepted.
+   *   A gradient minimal threshold is set for the test.
+   * Returns -1 if no max is found.
+   * @param pix List of points.
+   */
+  int largestIn (const vector<Pt2i> &pix) const;
+
+  /**
+   * Keeps elements that are not already selected (in the mask array).
+   * Returns the number of remaining elements in the selection.
+   * @param pix Input array of scanned points.
+   * @param n Initial size of the selection of points.
+   * @param ind Selection of points.
+   */
+  int keepFreeElementsIn (const vector<Pt2i> &pix, int n, int *ind) const;
+
+  /**
+   * Keeps elements that are oriented along a reference vector
+   *   in a selection of points.
+   * Returns the number of remaining elements in the selection.
+   * @param pix Input array of scanned points.
+   * @param ref The reference vector.
+   * @param n Initial size of the selection of points.
+   * @param ind Selection of points.
+   */
+  int keepOrientedElementsIn (const vector<Pt2i> &pix,
+                              const Vr2i &ref, int n, int *ind) const;
+
+  /**
+   * Keeps elements with gradient value near a reference vector
+   *   in a selection of points.
+   * Returns the number of remaining elements in the selection.
+   * @param pix Input array of scanned points.
+   * @param ref The reference vector.
+   * @param n Initial size of the selection of points.
+   * @param ind Selection of points.
+   */
+  int keepDirectedElementsIn (const vector<Pt2i> &pix,
+                              const Vr2i &ref, int n, int *ind) const;
+
+  /**
+   * \brief Gets filtered and sorted local gradient maxima.
+   * Local maxima are filtered according to the gradient direction and sorted.
+   * Returns the count of found gradient maxima.
+   * @param lmax Local max index array.
+   * @param pix Provided points.
+   * @param gref Gradient vector reference.
+   */
+  int localMax (int *lmax, const vector<Pt2i> &pix, const Vr2i &gref) const;
+
+  /**
+   * \brief Switches the direction constraint for local maxima selection.
+   */
+  inline void switchOrientationConstraint () {
+    orientedGradient = ! orientedGradient; }
+
+  /**
+   * \brief Temporarily releases the direction constraint for large angle tests.
+   */
+  inline void releaseOrientationConstraint () {
+    formerOrientedGradient = orientedGradient;
+    orientedGradient = false;
+    angleThreshold = LARGE_SQ_ANGLE;
+  }
+
+  /**
+   * \brief Restores the direction constraint status for fine angle tests.
+   */
+  inline void restoreOrientationConstraint () {
+    orientedGradient = formerOrientedGradient;
+    angleThreshold = NEAR_SQ_ANGLE;
+  }
+
+  /**
+   * \brief Clears the occupancy mask.
+   */
+  void clearMask ();
+
+  /**
+   * \brief Adds positions to the occupancy mask.
+   * @param pts Vector of points.
+   */
+  void setMask (const vector<Pt2i> &pts);
+
+  /**
+   * \brief Sets mask activation on or off
+   * @param status Required activation status.
+   */
+  inline void setMasking (bool status) { masking = status; }
+
+
+private:
+
+  /** Default value for near angular deviation tests. */
+  static const int NEAR_SQ_ANGLE;
+  /** Default value for large angular deviation tests. */
+  static const int LARGE_SQ_ANGLE;
+  /** Effective value for the angular deviation test. */
+  int angleThreshold;
+  /** Default threshold value for the gradient selection. */
+  static const int DEFAULT_GRADIENT_THRESHOLD;
+
+  /** Image width. */
+  int width;
+  /** Image height. */
+  int height;
+  /** Vector map. */
+  Vr2i *map;
+  /** Intensity map (squarred norm or morphologicalgradient). */
+  int *imap;
+
+  /** Occupancy mask. */
+  bool *mask;
+  /** Flag indicating whether the occupancy mask is in use. */
+  bool masking;
+  /** Direction constraint for local gradient maxima. */
+  bool orientedGradient;
+  /** Registred direction constraint for local gradient maxima. */
+  bool formerOrientedGradient;
+
+
+  /** 
+   * \brief Builds the vector map as a gradient map from provided data.
+   * Uses a Sobel 3x3 kernel.
+   * @param data Initial scalar data.
+   */
+  void buildGradientMap (int *data);
+
+  /** 
+   * \brief Builds the vector map as a gradient map from provided data.
+   * Uses a Sobel 3x3 kernel.
+   * @param data Initial bi-dimensional scalar data.
+   */
+  void buildGradientMap (int **data);
+
+  /** 
+   * \brief Builds the vector map as a gradient map from provided data.
+   * Uses a Sobel 5x5 kernel.
+   * @param data Initial scalar data.
+   */
+  void buildSobel5x5Map (int *data);
+
+  /** 
+   * \brief Builds the vector map as a gradient map from provided data.
+   * Uses a Sobel 5x5 kernel.
+   * @param data Initial bi-dimensional scalar data.
+   */
+  void buildSobel5x5Map (int **data);
+
+  /**
+   * \brief Searches local gradient maxima values.
+   * Returns the count of local maxima found.
+   * @param lmax Local max index array.
+   * @param n Count of input values.
+   * @param in Array of input values.
+   */
+  int searchLocalMax (int *lmax, int n, int *in) const;
+
+  /**
+   * \brief Sorts the candidates array by highest magnitude.
+   * @param lmax Local max index array.
+   * @param n Size of index array.
+   * @param val Input values.
+   */
+  void sortMax (int *lmax, int n, int *val) const;
+
+};
+
+#endif
diff --git a/Code/Seg/ImageTools/vr2i.cpp b/Code/Seg/ImageTools/vr2i.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..5f0ab4d8eb15a7bf94a377bba71a1b4a7dca688a
--- /dev/null
+++ b/Code/Seg/ImageTools/vr2i.cpp
@@ -0,0 +1,62 @@
+#include "vr2i.h"
+
+
+Vr2i::Vr2i ()
+{
+  xv = 1;
+  yv = 0;
+}
+
+
+Vr2i::Vr2i (int x, int y)
+{
+  xv = x;
+  yv = y;
+}
+
+
+Vr2i::Vr2i (const Vr2i &v)
+{
+  xv = v.xv;
+  yv = v.yv;
+}
+
+
+Vr2i Vr2i::orthog () const
+{
+  return (Vr2i (-yv, xv));
+}
+
+
+bool *Vr2i::steps (int *n) const
+{
+  int x2 = (xv > 0 ? xv : - xv);
+  int y2 = (yv > 0 ? yv : - yv);
+  int dx = x2, dy = y2;
+  if (y2 > x2)
+  {
+    dx = y2;
+    dy = x2;
+    x2 = y2;
+  }
+  int e, x = 0, i = 0;
+  *n = x2;
+  bool *paliers = new bool[x2];
+
+  e = dx;
+  dx *= 2;
+  dy *= 2;
+
+  while (x < x2)
+  {
+    x ++;
+    e -= dy;
+    if (e < 0)
+    {
+      e += dx;
+      paliers[i++] = true;
+    }
+    else paliers[i++] = false;
+  }
+  return (paliers); 
+}
diff --git a/Code/Seg/ImageTools/vr2i.h b/Code/Seg/ImageTools/vr2i.h
new file mode 100755
index 0000000000000000000000000000000000000000..95b34edbd00c6ff18b439c758f5ec32341e96bf6
--- /dev/null
+++ b/Code/Seg/ImageTools/vr2i.h
@@ -0,0 +1,160 @@
+#ifndef VR2I_H
+#define VR2I_H
+
+using namespace std;
+
+
+/** 
+ * @class Vr2i vr2i.h
+ * \brief Vector in the discrete plane.
+ * \author {P. Even}
+ */
+class Vr2i
+{
+
+public:
+
+  /**
+   * @fn Vr2i ()
+   * \brief Creates a unit vector on X axis.
+   */
+  Vr2i ();
+
+  /**
+   * @fn Vr2i (int x, int y)
+   * \brief Creates a vector using coordinates.
+   * @param x abscissae.
+   * @param y ordinate.
+   */
+  Vr2i (int x, int y);
+
+  /**
+   * @fn Vr2i (Vr2i p)
+   * \brief Creates a copy of a given vector.
+   * @param v original.
+   */
+  Vr2i (const Vr2i &v);
+
+  /**
+   * @fn int x ()
+   * \brief Returns the vector abscissae.
+   */
+  inline int x () const
+  {
+    return xv;
+  }
+
+  /**
+   * @fn int y ()
+   * \brief Returns the vector ordinate.
+   */
+  inline int y () const
+  {
+    return yv;
+  }
+
+  /**
+   * @fn void set (int x, int y)
+   * \brief Sets the vector coordinates.
+   * @param x new abscissae.
+   * @param y new ordinate.
+   */
+  inline void set (int x, int y)
+  {
+    xv = x;
+    yv = y;
+  }
+
+  /**
+   * @fn int norm2 ()
+   * \brief Returns the squared norm of the vector.
+   * If intensity value holds on a byte, gradient holds on a short
+   *   and gradient squared norm holds on a int.
+   */
+  inline int norm2 () const
+  {
+    return (xv * xv + yv * yv);
+  }
+
+  /**
+   * @fn int scalarProduct (Vr2i vec)
+   * \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.
+   */
+  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.
+   */
+  inline int squaredScalarProduct (Vr2i vec) const
+  {
+    return ((xv * vec.xv + yv * vec.yv)
+            * (xv * vec.xv + yv * vec.yv));
+  }
+
+  /**
+   * @fn bool equals (Vr2i p)
+   * \brief Checks equivalence to the given vector.
+   * @param v the given vector.
+   */
+  inline bool equals (Vr2i v) const
+  {
+    return (v.xv == xv && v.yv == yv);
+  }
+
+  /**
+   * @fn int manhattan ()
+   * \brief Returns the manhattan length of the vector.
+   */
+  inline int manhattan () const
+  {
+    return ((xv > 0 ? xv : - xv) + (yv > 0 ? yv : - yv));
+  }
+
+  /**
+   * @fn Vr2i orthog ()
+   * \brief Returns a CCW orthogonal vector.
+   */
+  Vr2i orthog () const;
+
+  /**
+   * @fn bool orientedAs (Vr2i v)
+   * \brief Returns true if v has the same orientation as the vector.
+   */
+  inline bool orientedAs (Vr2i v) const
+  {
+    return (xv * v.xv + yv * v.yv >= 0);
+  }
+
+  /**
+   * @fn void invert ()
+   * \brief Inverts the vector.
+   */
+  inline void invert ()
+  {
+    xv = -xv;
+    yv = -yv;
+  }
+
+  /**
+   * @fn bool *steps (int *n)
+   * \brief Returns the location of the steps between the vector ends.
+   * @param n size of the returned array.
+   */
+  bool *steps (int *n) const;
+
+
+private:
+
+  /** Vector abscissae. */
+  int xv;
+  /** Vector ordinate. */
+  int yv;
+};
+
+#endif
diff --git a/Code/Seg/Seg.pro b/Code/Seg/Seg.pro
new file mode 100644
index 0000000000000000000000000000000000000000..c73224c9692062cac526aec58dd48e245e884b4b
--- /dev/null
+++ b/Code/Seg/Seg.pro
@@ -0,0 +1,93 @@
+######################################################################
+# Automatically generated by qmake (3.0) mer. nov. 7 21:11:32 2018
+######################################################################
+
+QT+=widgets
+TEMPLATE = app
+TARGET = Seg
+INCLUDEPATH += . \
+           BSTools \
+           BlurredSegment \
+           DirectionalScanner \
+           ConvexHull \
+           ImageTools
+OBJECTS_DIR = obj
+
+# Input
+HEADERS += BlurredSegment/biptlist.h \
+           BlurredSegment/blurredsegment.h \
+           BlurredSegment/blurredsegmentproto.h \
+           BlurredSegment/bsdetector.h \
+           BlurredSegment/bstracker.h \
+           BlurredSegment/linespacefilter.h \
+           BSTools/bsaccumulatoritem.h \
+           BSTools/bsaccumulatorview.h \
+           BSTools/bsdetectionwidget.h \
+           BSTools/bsprofileitem.h \
+           BSTools/bsprofileview.h \
+           BSTools/bsstructureitem.h \
+           BSTools/bsstructureview.h \
+           BSTools/bswindow.h \
+           ConvexHull/antipodal.h \
+           ConvexHull/chvertex.h \
+           ConvexHull/convexhull.h \
+           DirectionalScanner/directionalscanner.h \
+           DirectionalScanner/directionalscannero1.h \
+           DirectionalScanner/directionalscannero2.h \
+           DirectionalScanner/directionalscannero7.h \
+           DirectionalScanner/directionalscannero8.h \
+           DirectionalScanner/dynamicalscannero1.h \
+           DirectionalScanner/dynamicalscannero2.h \
+           DirectionalScanner/dynamicalscannero7.h \
+           DirectionalScanner/dynamicalscannero8.h \
+           DirectionalScanner/scannerprovider.h \
+           DirectionalScanner/vhscannero1.h \
+           DirectionalScanner/vhscannero2.h \
+           DirectionalScanner/vhscannero7.h \
+           DirectionalScanner/vhscannero8.h \
+           ImageTools/absrat.h \
+           ImageTools/digitalstraightline.h \
+           ImageTools/digitalstraightsegment.h \
+           ImageTools/pt2i.h \
+           ImageTools/strucel.h \
+           ImageTools/vmap.h \
+           ImageTools/vr2i.h
+SOURCES += main.cpp \
+           BlurredSegment/biptlist.cpp \
+           BlurredSegment/blurredsegment.cpp \
+           BlurredSegment/blurredsegmentproto.cpp \
+           BlurredSegment/bsdetector.cpp \
+           BlurredSegment/bstracker.cpp \
+           BlurredSegment/linespacefilter.cpp \
+           BSTools/bsaccumulatoritem.cpp \
+           BSTools/bsaccumulatorview.cpp \
+           BSTools/bsdetectionwidget.cpp \
+           BSTools/bsprofileitem.cpp \
+           BSTools/bsprofileview.cpp \
+           BSTools/bsstructureitem.cpp \
+           BSTools/bsstructureview.cpp \
+           BSTools/bswindow.cpp \
+           ConvexHull/antipodal.cpp \
+           ConvexHull/chvertex.cpp \
+           ConvexHull/convexhull.cpp \
+           DirectionalScanner/directionalscanner.cpp \
+           DirectionalScanner/directionalscannero1.cpp \
+           DirectionalScanner/directionalscannero2.cpp \
+           DirectionalScanner/directionalscannero7.cpp \
+           DirectionalScanner/directionalscannero8.cpp \
+           DirectionalScanner/dynamicalscannero1.cpp \
+           DirectionalScanner/dynamicalscannero2.cpp \
+           DirectionalScanner/dynamicalscannero7.cpp \
+           DirectionalScanner/dynamicalscannero8.cpp \
+           DirectionalScanner/scannerprovider.cpp \
+           DirectionalScanner/vhscannero1.cpp \
+           DirectionalScanner/vhscannero2.cpp \
+           DirectionalScanner/vhscannero7.cpp \
+           DirectionalScanner/vhscannero8.cpp \
+           ImageTools/absrat.cpp \
+           ImageTools/digitalstraightline.cpp \
+           ImageTools/digitalstraightsegment.cpp \
+           ImageTools/pt2i.cpp \
+           ImageTools/strucel.cpp \
+           ImageTools/vmap.cpp \
+           ImageTools/vr2i.cpp
diff --git a/Code/Seg/main.cpp b/Code/Seg/main.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..ada2ffd8113b16bf7c14cf79b22587f5efcd1f1d
--- /dev/null
+++ b/Code/Seg/main.cpp
@@ -0,0 +1,68 @@
+#include <QApplication>
+#include <string>
+#include "bswindow.h"
+// #include "scanwindow.h"
+
+
+int main (int argc, char *argv[])
+{
+  int val = 0;
+  int imageName = 0;
+  bool testing = false;
+  QApplication app (argc, argv);
+
+/*
+  if (argc == 2 && string (argv[1]) == string ("scans"))
+  {
+    ScanWindow sw (&val);
+    sw.setWindowTitle ("Scans");
+    sw.show ();
+    return app.exec ();
+  }
+*/
+
+  BSWindow window (&val);   // val : necessary argument !
+  for (int i = 1; i < argc; i++)
+  {
+    if (string(argv[i]).at(0) == '-')
+    {
+      if (string(argv[i]) == string ("-profile")) window.toggleProfWindow ();
+      else if (string(argv[i]) == string ("-accu")) window.toggleAccuWindow ();
+      else if (string(argv[i]) == string ("-seg")) window.toggleSegWindow ();
+      // Test command : time ./Seg -test ../Images/couloir.jpg
+      else if (string(argv[i]) == string ("-test")) testing = true;
+      else if (string(argv[i]) == string ("-sobel3x3"))
+        window.useGradient (VMap::TYPE_SOBEL_3X3);
+      else if (string(argv[i]) == string ("-sobel5x5"))
+        window.useGradient (VMap::TYPE_SOBEL_5X5);
+      else if (string(argv[i]) == string ("-tophat"))
+        window.useGradient (VMap::TYPE_TOP_HAT);
+      else if (string(argv[i]) == string ("-blackhat"))
+        window.useGradient (VMap::TYPE_BLACK_HAT);
+      else if (string(argv[i]) == string ("-morpho"))
+        window.useGradient (VMap::TYPE_MORPHO);
+      else
+      {
+        int l = string (argv[i]).length ();
+        for (int j = 1; j < l; j++)
+        {
+          char carac = string(argv[i]).at(j);
+          if (carac == 'p') window.toggleProfWindow ();
+          else if (carac == 'a') window.toggleAccuWindow ();
+          else if (carac == 's') window.toggleSegWindow ();
+        }
+      }
+    }
+    else imageName = i;
+  }
+  if (imageName != 0) window.setFile (QString (argv[imageName]));
+  else window.setFile (QString ("../couloir.gif"));
+  if (testing)
+  {
+    window.runTest ();
+    return (EXIT_SUCCESS);
+  }
+  window.runOptions (); 
+  window.show ();
+  return app.exec ();
+}