diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp index c1af1a64d497a5265eb076fccc673f4674ca37b6..290d72a33b62da207a6eefc8d5f00b330e1f4a64 100755 --- a/Code/Seg/BSTools/bsdetectionwidget.cpp +++ b/Code/Seg/BSTools/bsdetectionwidget.cpp @@ -439,6 +439,13 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event) extract (true); break; + case Qt::Key_J : + detector.switchPreliminary (); + cout << "Preliminary detection " + << (detector.isPreliminary () ? "on" : "off") << endl; + extract (true); + break; + case Qt::Key_1 : switchPixelAnalyzer (); break; @@ -711,6 +718,10 @@ void BSDetectionWidget::displayExtractionResult () cout << "Extraction : undetermined." << endl; else if (res == BSDetector::RESULT_OK) cout << "Extraction : OK." << endl; + else if (res == BSDetector::RESULT_PRELIM_NO_DETECTION) + cout << "Extraction : no preliminary detection (bs0 == NULL)." << endl; + else if (res == BSDetector::RESULT_PRELIM_TOO_FEW) + cout << "Extraction : two few points at preliminary detection." << 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) @@ -759,26 +770,29 @@ void BSDetectionWidget::alternateTest () void BSDetectionWidget::performanceTest () { -/* - if (p1.equals (p2)) + if (detector.isMultiSelection ()) { - cout << "Stroke undefined" << endl; - return; + cout << "Automatic extraction test" << endl; + clock_t start = clock (); + for (int i = 0; i < 100; i++) detector.detectAll (); + double diff = (clock () - start) / (double) CLOCKS_PER_SEC; + cout << "Test run : " << diff << endl; + extract (true); + } + else + { + 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 << "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); } @@ -791,8 +805,8 @@ void BSDetectionWidget::localTest () p2 = Pt2i (232, 152); */ - p1 = Pt2i (298, 199); - p2 = Pt2i (279, 173); + p1 = Pt2i (157, 125); + p2 = Pt2i (165, 88); extract (true); cout << "Test run" << endl; diff --git a/Code/Seg/BlurredSegment/bsdetector.cpp b/Code/Seg/BlurredSegment/bsdetector.cpp index efa1ae6f700667e92f449329dc471706310af7da..0b742192073aa1a5b1cfd462e46c2c13bdf09cb4 100755 --- a/Code/Seg/BlurredSegment/bsdetector.cpp +++ b/Code/Seg/BlurredSegment/bsdetector.cpp @@ -4,6 +4,8 @@ const int BSDetector::RESULT_UNDETERMINED = -1; const int BSDetector::RESULT_OK = 0; +const int BSDetector::RESULT_PRELIM_NO_DETECTION = 1; +const int BSDetector::RESULT_PRELIM_TOO_FEW = 2; const int BSDetector::RESULT_INITIAL_NO_DETECTION = 11; const int BSDetector::RESULT_INITIAL_TOO_FEW = 12; const int BSDetector::RESULT_INITIAL_TOO_SPARSE = 13; @@ -17,6 +19,7 @@ const int BSDetector::DEFAULT_BS_MIN_SIZE = 5; const int BSDetector::ABSOLUTE_BS_MIN_SIZE = 3; const int BSDetector::DEFAULT_CONNECT_MIN_SIZE = 5; const int BSDetector::DEFAULT_AUTO_RESOLUTION = 10; +const int BSDetector::PRELIM_SIZE = 10; BSDetector::BSDetector () @@ -41,6 +44,7 @@ BSDetector::BSDetector () densityTestOn = true; multiSelection = false; autoResol = DEFAULT_AUTO_RESOLUTION; + prelim = false; bsini = NULL; bsf = NULL; @@ -161,13 +165,45 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0) if (prefilteringOn) lsf1->clear (); if (filteringOn) lsf2->clear (); if (bsini != NULL) delete bsini; + bsini = NULL; if (bsf != NULL) delete bsf; bsf = NULL; if (p1.equals (p2)) return; + Pt2i pt1 (p1); + Pt2i pt2 (p2); + + // Preliminary based on highest gradient without orientation constraint + //--------------------------------------------------------------------- + if (prelim) + { + BlurredSegment *bs0 = bst1->fastTrack (p1, p2, p0); + if (bs0 == NULL || bs0->size () < bsMinSize) + { + resultValue = (bs0 == NULL ? RESULT_PRELIM_NO_DETECTION + : RESULT_PRELIM_TOO_FEW); + if (bs0 != NULL) delete bs0; + return; + } + + Vr2i v0 = bs0->getSupportVector (); + Pt2i pc = bs0->getSegment()->centerOfIntersection (p1, p2); + v0.setOrthog (); + int l = v0.chessboard (); + int dx = (int) ((v0.x () * PRELIM_SIZE) / l); + int dy = (int) ((v0.y () * PRELIM_SIZE) / l); + if (dx * dy != 0) + { + pt1 = Pt2i (pc.x () + dx, pc.y () + dy); + pt2 = Pt2i (pc.x () - dx, pc.y () - dy); + p0 = NULL; + } + bst1->clear (); + delete bs0; + } // Initial detection based on highest gradient without orientation constraint //--------------------------------------------------------------------------- - bsini = bst1->fastTrack (p1, p2, p0); + bsini = bst1->fastTrack (pt1, pt2, p0); if (bsini == NULL || bsini->size () < bsMinSize) { resultValue = (bsini == NULL ? RESULT_INITIAL_NO_DETECTION @@ -179,7 +215,7 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0) //------------- if (densityTestOn) { - DigitalStraightLine mydsl (p1, p2, DigitalStraightLine::DSL_NAIVE); + DigitalStraightLine mydsl (pt1, pt2, DigitalStraightLine::DSL_NAIVE); int mydrlf = mydsl.manhattan (bsini->getLastRight ()) - mydsl.manhattan (bsini->getLastLeft ()); if (mydrlf < 0) mydrlf = -mydrlf; // Case of horizontal P1P2 @@ -225,7 +261,7 @@ void BSDetector::detect (const Pt2i &p1, const Pt2i &p2, Pt2i *p0) if (bswidth < minScanLength) bswidth = minScanLength; } scanwidth2 = bswidth; - pCenter = bsini->getSegment()->centerOfIntersection (p1, p2); + pCenter = bsini->getSegment()->centerOfIntersection (pt1, pt2); } bsf = bst2->fineTrack (pCenter, bsini->getSupportVector(), scanwidth2, bswidth, gRef); diff --git a/Code/Seg/BlurredSegment/bsdetector.h b/Code/Seg/BlurredSegment/bsdetector.h index 468d5d17aca80228e7676c067d33846f09eec8d2..38a6569f34570c6d77a41cd87306620985755053 100755 --- a/Code/Seg/BlurredSegment/bsdetector.h +++ b/Code/Seg/BlurredSegment/bsdetector.h @@ -22,6 +22,10 @@ public: /** Extraction result : successful extraction. */ static const int RESULT_OK; /** Extraction result : no initial detection (bsini == NULL). */ + static const int RESULT_PRELIM_NO_DETECTION; + /** Extraction result : too few points at initial detection. */ + static const int RESULT_PRELIM_TOO_FEW; + /** 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; @@ -166,6 +170,16 @@ public: */ inline void switchAutoRestart () { bst2->switchAutoRestart (); } + /** + * \brief Returns the preliminary detection modality status. + */ + inline bool isPreliminary () { return (prelim); } + + /** + * \brief Switches preliminary detection modality. + */ + inline void switchPreliminary () { prelim = ! prelim; } + /** * \brief Returns the edge direction constraint status. * +1 : Edge direction constrained to the initial direction. @@ -390,6 +404,8 @@ private : static const int DEFAULT_CONNECT_MIN_SIZE; /** Default value for the automatic detection grid resolution. */ static const int DEFAULT_AUTO_RESOLUTION; + /** Default value for half the preliminary stroke size. */ + static const int PRELIM_SIZE; /** Direction constraint of the detected edge : @@ -414,6 +430,8 @@ private : bool multiSelection; /** Grid resolution for the automatic extraction. */ int autoResol; + /** Preliminary stage modality. */ + bool prelim; /** Gradient map. */ diff --git a/Code/Seg/ImageTools/vr2i.h b/Code/Seg/ImageTools/vr2i.h index 95b34edbd00c6ff18b439c758f5ec32341e96bf6..35cca7ab2135e9cf3a3b6c4df8c9febb380c2d83 100755 --- a/Code/Seg/ImageTools/vr2i.h +++ b/Code/Seg/ImageTools/vr2i.h @@ -39,19 +39,15 @@ public: * @fn int x () * \brief Returns the vector abscissae. */ - inline int x () const - { - return xv; - } + inline int x () const { + return xv; } /** * @fn int y () * \brief Returns the vector ordinate. */ - inline int y () const - { - return yv; - } + inline int y () const { + return yv; } /** * @fn void set (int x, int y) @@ -59,11 +55,9 @@ public: * @param x new abscissae. * @param y new ordinate. */ - inline void set (int x, int y) - { + inline void set (int x, int y) { xv = x; - yv = y; - } + yv = y; } /** * @fn int norm2 () @@ -71,10 +65,8 @@ public: * 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); - } + inline int norm2 () const { + return (xv * xv + yv * yv); } /** * @fn int scalarProduct (Vr2i vec) @@ -82,39 +74,39 @@ public: * 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); - } + 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 - { + inline int squaredScalarProduct (Vr2i vec) const { return ((xv * vec.xv + yv * vec.yv) - * (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); - } + 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)); - } + inline int manhattan () const { + return ((xv > 0 ? xv : - xv) + (yv > 0 ? yv : - yv)); } + + /** + * @fn int chessboard () + * \brief Returns the chessboard length of the vector. + */ + inline int chessboard () const { + int x = (xv < 0 ? -xv : xv), y = (yv < 0 ? -yv : yv); + return (x > y ? x : y); } /** * @fn Vr2i orthog () @@ -122,24 +114,26 @@ public: */ Vr2i orthog () const; + /** + * @fn void setOrthog () + * \brief Returns a CCW orthogonal vector. + */ + inline void setOrthog () { int tmp = xv; xv = - yv; yv = tmp; } + /** * @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); - } + inline bool orientedAs (Vr2i v) const { + return (xv * v.xv + yv * v.yv >= 0); } /** * @fn void invert () * \brief Inverts the vector. */ - inline void invert () - { + inline void invert () { xv = -xv; - yv = -yv; - } + yv = -yv; } /** * @fn bool *steps (int *n)