-
even authored7af2bb78
bsdetector.h 14.79 KiB
#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_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 : 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 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 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 at given step.
* @param step Initial step addressed if set to 0, final step otherwise.
*/
inline vector<BlurredSegment *> getBlurredSegments (int step) {
return (step == 0 ? mbsini : 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 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 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.
* -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;
/** Default value for half the preliminary stroke size. */
static const int PRELIM_SIZE;
/** 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;
/** Preliminary stage modality. */
bool prelim;
/** Gradient map. */
VMap *gMap;
/** Initial rough tracker */
BSTracker *bst1;
/** Initially detected blurred segment (initial step result). */
BlurredSegment *bsini;
/** Detected blurred segments in case of multi-detection (initial step). */
vector<BlurredSegment *> mbsini;
/** Fine tracker */
BSTracker *bst2;
/** 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;
/** 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);
/**
* \brief Resets the multi-selection list.
*/
void freeMultiSelection ();
};
#endif