#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: /** Identifier for the final detection step. */ static const int STEP_FINAL; /** Identifier for the initial detection step. */ static const int STEP_INITIAL; /** Identifier for the preliminary detection step. */ static const int STEP_PRELIM; /** 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_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; /** 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 : initial detection of a closely oriented segment. */ static const int RESULT_INITIAL_CLOSE_ORIENTATION; /** 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. * Parses X direction first, the Y direction. */ void detectAll (); /** * \brief Detects all blurred segments in the picture. * Parses simultaneously the X and Y directions. */ void detectAllWithBalancedXY (); /** * \brief Detects blurred segments between two input points. * @param p1 First input point. * @param p2 Second input point. */ void detectSelection (const Pt2i &p1, const Pt2i &p2); /** * \brief Runs the last detection again. */ void redetect (); /** * \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 centralp Set to true if the central point is provided. * @param pc Initial central point. */ void detect (const Pt2i &p1, const Pt2i &p2, bool centralp = false, const Pt2i &pc = Pt2i ()); /** * \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: 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. * The directional scan is oriented on the segment of step 1. * Step 3: id. step 2. * The directional scan is oriented on the segment of step 2. * Note : Multi-detection along a stroke requires an initial start point. * @param p1 First input point. * @param p2 Second input point. * @param centralp Set to true if the central point is provided. * @param pc Initial central point. */ void olddetect (const Pt2i &p1, const Pt2i &p2, bool centralp = false, const Pt2i &pc = Pt2i ()); /** * \brief Returns the detected blurred segment at given step. * @param step Detection step. */ BlurredSegment *getBlurredSegment (int step = STEP_FINAL) const; /** * \brief Returns the list of detected blurred segments at final step. */ inline const vector<BlurredSegment *> getBlurredSegments () const { return (mbsf); } /** * \brief Avoids the deletion of the last extracted blurred segment. */ inline void preserveFormerBlurredSegment () { bsf = NULL; } /** * \brief Avoids the deletion of the last extracted blurred segments. */ inline void preserveFormerBlurredSegments () { mbsf.clear (); } /** * \brief Returns the assigned maximal width for the fast tracks. */ inline int fastTracksMaxWidth () const { return bst1->fastTracksMaxWidth (); } /** * \brief Sets the assigned width for the fast tracks. */ inline void setFastTracksMaxWidth (int value) { bst1->setFastTracksMaxWidth (value); } /** * \brief Returns the assigned maximal width for the fine tracks. */ inline int fineTracksMaxWidth () const { return bst1->fineTracksMaxWidth (); } /** * \brief Sets the assigned maximal width for the fine tracks. */ inline void setFineTracksMaxWidth (int value) { bst1->setFineTracksMaxWidth (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 threshold used for maximal gradient detection. */ inline int getGradientThreshold () const { return (gMap->getGradientThreshold ()); } /** * \brief Increments the threshold used for maximal gradient detection. * @param inc Increment value. */ inline void incGradientThreshold (int inc) { return (gMap->incGradientThreshold (inc)); } /** * \brief Returns the gradient threshold used for local max filtering. */ inline int getGradientResolution () const { return (gMap->getGradientResolution ()); } /** * \brief Increments the gradient threshold used for local maximal filtering. * @param inc Increment value. */ inline void incGradientResolution (int inc) { return (gMap->incGradientResolution (inc)); } /** * \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 preliminary detection modality status. */ inline bool isPreliminary () { return (prelimDetectionOn); } /** * \brief Switches preliminary detection modality. */ void switchPreliminary (); /** * \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 fine scan is recentred on the detected segment. */ inline bool isScanRecentering () { return recenteringOn; } /** * \brief Switches on or off the scan recentering modality. */ inline void switchScanRecentering () { recenteringOn = ! recenteringOn; } /** * \brief Returns true if the fine scan is fitted to the detected segment. */ inline bool isScanFitting () { return fittingOn; } /** * \brief Switches on or off the scan fitting modality. */ inline void switchScanFitting () { fittingOn = ! fittingOn; } /** * \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 scan lines at final step. */ const vector <vector <Pt2i> > getFinalScans () const; /** * \brief Returns whether the final scan record modality is set. */ bool finalScansRecordOn () const; /** * \brief Sets the scan record modality at final step. * @param status Sets on if true, off otherwise. */ void setFinalScansRecord (bool 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 the vicinity threshold used for fast tracking. */ inline int getVicinityThreshold () { return (bst1->getVicinityThreshold ()); } /** * \brief Increments the vicinity threshold used for fast tracking. * @param inc Increment value. */ inline void incVicinityThreshold (int inc) { bst1->incVicinityThreshold (inc); } /** * \brief Returns the vicinity test status. */ inline bool vicinityConstraintOn () { return (bst1->vicinityConstraintOn ()); } /** * \brief Switches the vicinity test used for fast tracking. */ inline void switchVicinityConstraint () { bst1->switchVicinityConstraint (); } /** * \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 thickenning control is activated. */ inline bool isThickenningOn () const { return bst2->isThickenningOn (); } /** * \brief Toggles the thickenning control. */ inline void toggleThickenning () { bst2->toggleThickenning (); } /** * \brief Returns the thickenning limit. */ inline int getThickenningLimit () const { return bst2->getThickenningLimit (); } /** * \brief Increments the thickenning limit. */ inline void incThickenningLimit (int val) { bst2->incThickenningLimit (val); } /** * \brief Returns if the thinning is activated. */ inline bool isThinningActivated () const { 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 == STEP_FINAL ? 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 == STEP_FINAL ? (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 { if (step == STEP_FINAL) return (filteringOn); else if (step == STEP_INITIAL) return (prefilteringOn); else return false; } /** * \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 getConnectedComponentMinSize () { return ccMinSize; } /** * \brief Increments the minimal size of the connected components. * @param increase Positive increment if true, negative otherwise. */ bool incConnectedComponentMinSize (bool increase); /* * \brief Returns the count of trials in a multi-detection. */ inline int countOfTrials () const { return (nbtrials); } /** * \brief Sets the maximum number of trials in a multi-detection. * @param nb Number of trials (0 if illimited). */ inline void setMaxTrials (int nb) { nbmaxtrials = nb; } /** * \brief Returns the maximum number of trials for a multi-detection. */ inline int getMaxTrials () const { return nbmaxtrials; } /** * \brief Retuns whether the last trial was successful. */ inline bool isLastTrialOk () { return lastTrialOk; } /** * \brief Gets the last detection inputs. * @param step Detection step. * @param p1 Input stroke first point to fill in. * @param p2 Input stroke end point to fill in. * @param width Input stroke width to fill in. * @param pc Input central point to fill in. */ void getScanInput (int step, Pt2i &p1, Pt2i &p2, int &width, Pt2i &pc) const; /** * \brief Retuns whether the old detector (IWCIA '09) is used. */ inline bool oldDetectorOn () { return oldp; } /** * \brief Toggles the detector used (between IWCIA '09 and present). */ inline void switchDetector () { oldp = ! oldp; } 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; /** Default value for the preliminary stroke half length. */ static const int PRELIM_MIN_HALF_WIDTH; /** Gradient map. */ VMap *gMap; /** 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 size of the detected blurred segment. */ int bsMinSize; /** Connectivity constraint status. */ bool ccOn; /** Minimal size of the connected components to validate a blurred segment. */ int ccMinSize; /** Automatic scan recentering (based on previous detection). */ bool recenteringOn; /** Automatic scan width selection (based on previous detection). */ bool fittingOn; /** Density test modality after initial detection. */ bool densityTestOn; /** Segment multi-selection modality status. */ bool multiSelection; /** Flag indicating if the last trial was successful. */ bool lastTrialOk; /** Count of trials in a multi-detection. */ int nbtrials; /** Maximum number of trials in a multi-detection. */ int nbmaxtrials; /** Automatic detection modality. */ bool autodet; /** Grid resolution for the automatic extraction. */ int autoResol; /** Result of the blurred segment extraction. */ int resultValue; /** Old detector (IWCIA'09) modality. */ bool oldp; /** Last input start point. */ Pt2i prep1; /** Last input end point. */ Pt2i prep2; /** Last input central point. */ Pt2i prepc; /** Last input central point modality. */ bool precentralp; /** Preliminary stage modality. */ bool prelimDetectionOn; /** Preliminary rough tracker. */ BSTracker *bst0; /** Preliminary detected blurred segment. */ BlurredSegment *bspre; /** Initial rough tracker. */ BSTracker *bst1; /** Last input start point for initial step. */ Pt2i inip1; /** Last input end point for initial step. */ Pt2i inip2; /** Last input central point for initial step. */ Pt2i inipc; /** Last input central point modality for initial step. */ bool inicentralp; /** Initially detected blurred segment (initial step result). */ BlurredSegment *bsini; /** Fine tracker. */ BSTracker *bst2; /** Old detector (IWCIA'09) fine tracker. */ BSTracker *bstold; /** Detected blurred segment (final result). */ BlurredSegment *bsf; /** Detected blurred segments in case of multi-detection (final results). */ 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; /** * \brief Detects all blurred segments between two input points. * Returns the continuation modality. * @param p1 First input point. * @param p2 Second input point. */ bool runMultiDetection (const Pt2i &p1, const Pt2i &p2); /** * \brief Resets the multi-selection list. */ void freeMultiSelection (); }; #endif