From 389fa6fbad30a39ae08bb4701dc60dcfa7a8e34a Mon Sep 17 00:00:00 2001 From: even <philippe.even@loria.fr> Date: Mon, 29 Apr 2019 17:47:10 +0200 Subject: [PATCH] Thickness defined --- Article/Expe_auto/compTable.tex | 16 +- Article/Fig_method/algoMulti.tex | 7 +- Article/Fig_notions/bswidth.tex | 24 ++- Article/Fig_synth/statsTable.tex | 2 +- Article/abstract.tex | 8 +- Article/conclusion.tex | 13 +- Article/expeV2.tex | 15 +- Article/introV2.tex | 17 +- Article/main.tex | 2 +- Article/methodV2.tex | 85 +++++---- Article/notionsV2.tex | 178 ++++++++++++++++++ Code/FBSD/BSTools/bsdetectionwidget.cpp | 5 +- Code/FBSD/BSTools/bsyorkitem.cpp | 107 +++++------ Code/FBSD/BSTools/bsyorkitem.h | 49 +++-- Code/FBSD/BSTools/bsyorkview.cpp | 14 +- Code/FBSD/BSTools/extlines.cpp | 155 +++------------ Code/FBSD/BSTools/extlines.h | 23 +-- .../BlurredSegment/blurredsegmentproto.cpp | 20 +- .../FBSD/BlurredSegment/blurredsegmentproto.h | 11 +- Code/FBSD/BlurredSegment/bsdetector.cpp | 6 +- Code/FBSD/BlurredSegment/bsdetector.h | 10 + Code/FBSD/BlurredSegment/bstracker.cpp | 11 +- Code/FBSD/BlurredSegment/bstracker.h | 11 ++ Code/FBSD/ConvexHull/antipodal.cpp | 2 +- Code/FBSD/ConvexHull/antipodal.h | 6 +- Code/FBSD/ConvexHull/convexhull.cpp | 6 +- Code/FBSD/ConvexHull/convexhull.h | 7 +- Code/FBSD/main.cpp | 11 +- Methode/methode.tex | 86 ++++----- 29 files changed, 503 insertions(+), 404 deletions(-) create mode 100755 Article/notionsV2.tex diff --git a/Article/Expe_auto/compTable.tex b/Article/Expe_auto/compTable.tex index 2dd1069..10ccfd0 100644 --- a/Article/Expe_auto/compTable.tex +++ b/Article/Expe_auto/compTable.tex @@ -5,16 +5,16 @@ Measure $M$ & \multicolumn{2}{c|}{$T$ (ms)} & \multicolumn{2}{c|}{$C$ (\%)} & \multicolumn{2}{c|}{$L$ (pixels)} & \multicolumn{2}{c|}{$L/N$} \\ \hline LSD -& 63.5 & 13.1 & 61.3 & 11.2 -& 536 & 194 & 17745 & 5364 & 34.6 & 8.0 \\ +& 63.2 & 14.0 & 60.9 & 11.2 +& 561 & 202 & 17956 & 5387 & 33.5 & 7.7 \\ ED-Lines -& 32.3 & 6.4 & 64.6 & 11.1 -& 568 & 210 & 19331 & 5694 & 35.9 & 8.9 \\ +& 55.5 & 10.0 & 64.0 & 11.2 +& 617 & 228 & 19775 & 5790 & 33.8 & 8.3 \\ CannyLines -& 75.5 & 11.7 & 60.6 & 10.6 -& 467 & 139 & 17678 & 4419 & 39.5 & 10.2 \\ +& 69.8 & 10.5 & 60.5 & 10.6 +& 478 & 142 & 17779 & 4407 & 38.8 & 10.1 \\ Our detector -& 66.6 & 14.8 & \textbf{65.8} & \textbf{9.3} -& 524 & 119 & 19210 & 3797 & 37.4 & 5.9 \\ +& 68.7 & 15.8 & \textbf{67.9} & \textbf{9.6} +& 449 & 104 & 19175 & 3912 & \textbf{43.7} & 7.7 \\ \hline \end{tabular} diff --git a/Article/Fig_method/algoMulti.tex b/Article/Fig_method/algoMulti.tex index 7f37ef9..2804c89 100644 --- a/Article/Fig_method/algoMulti.tex +++ b/Article/Fig_method/algoMulti.tex @@ -6,7 +6,7 @@ \SetKwData{lm}{LocMax} \SetKwData{nullset}{$\emptyset$} \SetKwData{ortho}{$\vec{AB}_\perp$} - \SetKwData{eps}{$2~\varepsilon_{ini}$} + \SetKwData{eps}{$2~\varepsilon_{0}$} \SetKwData{pta}{$A$} \SetKwData{ptb}{$B$} \SetKwData{Result}{Result} @@ -24,7 +24,7 @@ \SetKwData{Begin}{Start} \SetKwData{End}{End} - \Input{Stroke points \pta, \ptb, occupancy mask \mask} + \Input{Stroke points \pta, \ptb, occupancy mask \mask, initial thickness $\varepsilon_0$} \Output{\textit{\bslist} $\rightarrow$ list of detected blurred segments} \BlankLine \bslist $\leftarrow$ \nullset\; @@ -35,6 +35,5 @@ \updatemask (\mask, \bseg)\; \bslist $\leftarrow$ \bseg\; } - - \caption{MultiDetect: finds all the selected blurred segments.} + \caption{MultiDetect: finds all segments crossing the selection stroke.} \end{algorithm} diff --git a/Article/Fig_notions/bswidth.tex b/Article/Fig_notions/bswidth.tex index 3211f8c..e37cc96 100644 --- a/Article/Fig_notions/bswidth.tex +++ b/Article/Fig_notions/bswidth.tex @@ -1,7 +1,10 @@ \begin{picture}(220,60) - \multiput(0,6)(2,-6){2}{\line(3,1){150}} - \multiput(0,8)(30,6){8}{\color{blue}{\line(5,1){10}}} - \multiput(0,18)(30,6){8}{\color{blue}{\line(5,1){10}}} +% \multiput(0,6)(2,-6){2}{\line(3,1){150}} + \multiput(0,7)(2,-8){2}{\line(3,1){150}} +% \multiput(0,8)(30,6){8}{\color{blue}{\line(5,1){10}}} + \multiput(0,7)(30,6){8}{\color{blue}{\line(5,1){10}}} +% \multiput(0,18)(30,6){8}{\color{blue}{\line(5,1){10}}} + \multiput(0,19)(30,6){8}{\color{blue}{\line(5,1){10}}} \put(45,21){\circle*{3}} \put(55,21){\circle*{3}} \put(65,21){\circle*{3}} @@ -12,11 +15,16 @@ \put(66,37){$\mathcal{B}_{i-1}$} \put(110,30){\circle{3}} \put(112,21){$P_i$} - \put(140,36){\vector(0,1){10}} - \put(140,62.66){\vector(0,-1){10}} +% \put(140,36){\vector(0,1){10}} + \put(140,35){\vector(0,1){10}} +% \put(140,62.66){\vector(0,-1){10}} + \put(140,63.66){\vector(0,-1){10}} \put(120,58){$\mu_{i-1}$} - \put(160,30){\color{blue}{\vector(0,1){10}}} - \put(160,60){\color{blue}{\vector(0,-1){10}}} - \put(164,36){\color{blue}{$\mu_i$}} +% \put(160,30){\color{blue}{\vector(0,1){10}}} + \put(160,29){\color{blue}{\vector(0,1){10}}} +% \put(160,60){\color{blue}{\vector(0,-1){10}}} + \put(160,61){\color{blue}{\vector(0,-1){10}}} +% \put(164,36){\color{blue}{$\mu_i$}} + \put(164,30){\color{blue}{$\mu_i$}} \put(180,60){\color{blue}{$\mathcal{B}_{i}$}} \end{picture} diff --git a/Article/Fig_synth/statsTable.tex b/Article/Fig_synth/statsTable.tex index 62c08f1..d93b912 100644 --- a/Article/Fig_synth/statsTable.tex +++ b/Article/Fig_synth/statsTable.tex @@ -14,7 +14,7 @@ Recall (ratio of true detection, \%): $R = \#(D\cap S)/\#S$ & 89.20 & $\pm$ & 3.94 & \textbf{90.08} & $\pm$ & \textbf{2.77} \\ F-measure (harmonic mean,\%): $F = 2\times P\times R/(P+R)$ & 79.85 & $\pm$ & 6.78 & \textbf{84.17} & $\pm$ & \textbf{4.17} \\ -Width difference (in pixels) to matched input segment +Thickness difference (in pixels) to matched input segment & 0.92 & $\pm$ & 0.31 & \textbf{0.76} & $\pm$ & \textbf{0.23} \\ Angle difference (in degrees) to matched input segment & 1.48 & $\pm$ & 1.42 & \textbf{1.05} & $\pm$ & \textbf{0.80} \\ diff --git a/Article/abstract.tex b/Article/abstract.tex index 63b48cf..74c13ef 100755 --- a/Article/abstract.tex +++ b/Article/abstract.tex @@ -3,8 +3,8 @@ detector in gray-level images, where line segments are enriched with a thickness parameter intended to provide a quality criterion on the extracted feature. This study firstly enhances previous works on interactive -line detection with a better estimation of the segment width and +line detection with a better estimation of the segment thickness and orientation through two main improvements: adaptive directional scans and -the control of the assigned width to the detection algorithm. -Then, a new contribution to the automatic detection of all the segments in a single -image is also proposed and left available in an online demonstration. +the control of assigned thickness to the detection algorithm. +Then, a new contribution to the automatic detection of all the segments in +a single image is also proposed and left available in an online demonstration. diff --git a/Article/conclusion.tex b/Article/conclusion.tex index fe06c83..9190f67 100755 --- a/Article/conclusion.tex +++ b/Article/conclusion.tex @@ -4,7 +4,7 @@ This paper introduced a new straight edge detector based on a local analysis of the image gradient and on the use of blurred segments to embed an -estimation of the detected edge width. +estimation of the detected edge thickness. It relies on directional scans of the input image around maximal values of the gradient magnitude, and on %that have previously been presented in \cite{KerautretEven09}. @@ -18,12 +18,15 @@ gradient magnitude, and on the integration of two new concepts: adaptive directional scans that continuously adjust the scan strip to the detected edge direction, and -control of the assigned width based on the observation of the +control of assigned thickness based on the observation of the blurred segment growth. Experiments on synthetic images show the better performance -and especially the more accurate estimation of the line width brought by -these concepts. Such an result can not be compared to other approach since they do not provide any width estimation. -Moreover the performance of the unsupervised mode give better coverage of the detected edges and produce quite comparable execution time. +and especially the more accurate estimation of the line thickness brought by +these concepts. +Such a result can not be compared to other approaches since they do not +provide any thickness estimation. +Moreover the performance of the unsupervised mode gives better coverage of +the detected edges and produces quite comparable execution time. A residual weakness of the approach is the sensitivity to the initial conditions. diff --git a/Article/expeV2.tex b/Article/expeV2.tex index b3f8f3f..942de10 100755 --- a/Article/expeV2.tex +++ b/Article/expeV2.tex @@ -26,7 +26,7 @@ At first, the benefits of introduced concepts are evaluated through a comparison of the performance of both versions of the detector on a set of 1000 synthesized images containing 10 randomly -placed input segments with random width between 2 and 5 pixels. +placed input segments with random thickness between 2 and 5 pixels. As these values are controlled, these images can be considered as a ground truth. The absolute value of the difference of each found segment to its @@ -36,7 +36,7 @@ matched input segment is measured. %images containing only one input segment (no possible interaction) %and the found value (1.4 pixel) was taken into account in the test. \RefTab{tab:synth} shows -slightly better width and angle measurements for the new detector. +slightly better thickness and angle measurements for the new detector. The new detector shows more precise, with a smaller amount of false detections and succeeds in finding most of the input segments. Other experiments, also available at the {\it GitHub} repository, show @@ -143,17 +143,8 @@ on the York Urban Database \cite{DenisAl08}.} \label{tab:comp} \end{table} -\begin{table} -\centering -\input{Expe_auto/compTable} - -\caption{Measured performance of recent line detectors and of our detector -on the York Urban Database \cite{DenisAl08}.} -\label{tab:comp} -\end{table} - On these images, CannyLines provides longer lines and ED-Lines is much faster. Globally, the performance of the new detector is pretty similar and competitive to the other ones, and additionnaly, our detector provides an indication -on the detected lines quality through the additional width parameter. +on the detected lines quality through the additional thickness parameter. diff --git a/Article/introV2.tex b/Article/introV2.tex index aba20e5..52688b0 100755 --- a/Article/introV2.tex +++ b/Article/introV2.tex @@ -32,9 +32,7 @@ geometric objects, such as lines or circles, have been developed to better fit to the discrete nature of most of today's data to process. In particular, the notion of blurred segment \cite{Buzer07,DebledAl05} was introduced to cope with the image noise or other sources of imperfections -from the real world using a width\footnote{We use equivalently the terms -width and thickness in this work.} -parameter. +from the real world using a thickness parameter. Efficient algorithms have already been designed to recognize these digital objects in binary images \cite{DebledAl06}. Blurred segments seem well suited to reflect the required line quality @@ -46,20 +44,21 @@ information. %on discrete epipolar geometry \cite{NatsumiAl08}. The present work aims at designing a flexible tool to detect blurred segments -with optimal width and orientation in gray-level images for as well +with optimal thickness and orientation in gray-level images for as well supervised as unsupervised contexts. User-friendly solutions are sought, with ideally no parameter to set, or at least quite few values with intuitive meaning. A first attempt was already made in a previous work \cite{KerautretEven09} -but the segment width was initially fixed by the user and not estimated, +but the segment thickness was initially fixed by the user and not estimated, leading to erroneous orientations of the detected lines. In the present work, the limitations of this first detector were solved by the introduction of two new concepts: (i) adaptive directional scan designed to get some compliance to the unpredictable orientation problem; -(ii) control of the assigned width to the blurred segment -recognition algorithm, intended to derive more reliable information on the -line orientation and quality. +(ii) control of assigned thickness to the blurred segment +recognition algorithm. +% intended to derive more reliable information on the +%line orientation and quality. As a side effect, these two major evolutions also led to a noticeable improvement of the time performance of the detector. They are also put forward within a global line extraction algorithm @@ -70,7 +69,7 @@ which can be evaluated through an online demonstration at : In the next section, the main theoretical notions used in this work are introduced. The new detector workflow, the adaptive directional scan, the control -of the assigned width and their integration into both supervised and +of assigned thickness and their integration into both supervised and unsupervised contexts are then presented in \RefSec{sec:method}. Experiments led to assess the achieved performance of this new detector are decribed in \RefSec{sec:expe}. diff --git a/Article/main.tex b/Article/main.tex index b95e82b..6db042e 100755 --- a/Article/main.tex +++ b/Article/main.tex @@ -54,7 +54,7 @@ \input{introV2} - \input{notions} + \input{notionsV2} \input{methodV2} diff --git a/Article/methodV2.tex b/Article/methodV2.tex index 204d4c8..23bac4e 100755 --- a/Article/methodV2.tex +++ b/Article/methodV2.tex @@ -17,7 +17,8 @@ Therefore we use a Sobel operator with a 5x5 pixels mask \subsection{Previous work} In a former paper \cite{KerautretEven09}, an efficient tool to detect -blurred segments of fixed width in gray-level images was already introduced. +blurred segments of fixed thickness in gray-level images was already +introduced. It was based on a first rough detection in a local image area defined by the user. At that stage, the goal was to disclose the presence of a straight edge. Therefore as simple a test as the gradient maximal value @@ -28,8 +29,8 @@ In order to prevent local disturbances such as the presence of a sharper edge nearby, all the local gradient maxima were successively tested untill a correct candidate with an acceptable gradient orientation was found. -Despite of good performances achieved, several drawbacks remained. -First, the blurred segment width was not measured but initially set by the +Despite of a good behavior reported, several drawbacks remained. +First, the blurred segment thickness was not measured but initially set by the user according to the application requirements. The produced information on the edge quality was rather poor, and especially when the edge is thin, the risk to incorporate outlier points was quite high, thus producing a @@ -61,8 +62,11 @@ $\mathcal{B}$ based on points with highest norm gradient found in each scan of a static directional scan defined by an input segment $AB$. Validity tests are then applied to decide of the detection pursuit. -They aim at rejecting too short or too sparse blurred segments, or +They aim at rejecting too small or too sparse blurred segments, or those with a close orientation to $AB$. +Size threshold is set to 3 pixels, angle closeness to $\pi/6$, +and the segment length (distance between end points) must be at least twice +the number of points. In case of positive response, the position $C$ and direction $\vec{D}$ of this initial blurred segment are extracted. @@ -70,16 +74,19 @@ In the fine tracking step, another blurred segment $\mathcal{B}'$ is built and extended with points that correspond to local maxima of the image gradient, ranked by magnitude order, and with gradient direction close to start point gradient direction. -At this refinement step, a {\it control of the assigned width} is applied -and an {\it adaptive directional scan} based on the found position $C$ and +At this refinement step, a {\it control of the assigned thickness} is applied +and an {\it adaptive directional scan} based on found position $C$ and direction $\vec{D}$ is used in order to extends the segment in the -appropriate direction. These two improvements are described in the -following sections (\ref{subsec:ads} and \ref{subsec:caw}). +appropriate direction. These two improvements are described in +following sections \ref{subsec:ads} and \ref{subsec:caw}. -The output segment $\mathcal{B}'$ is finally tested according to the -application needs. Too short, too sparse or too fragmented segments -can be rejected. Length, sparsity or fragmentation thresholds are -intuitive parameters left at the end user disposal. +The output segment $\mathcal{B}'$ is finally accepted according to the +application needs. +For the present work, only a size test is performed so that blurred +segments with less than 12 pixels are rejected. +%Too short, too sparse or too fragmented segments +%can be rejected. Length, sparsity or fragmentation thresholds are +%intuitive parameters left at the end user disposal. %None of these tests are activated for the experimental stage in order %to put forward achievable performance. @@ -129,10 +136,10 @@ the higher the probability gets to fail again on an escape from the scan strip. \label{fig:escape} \end{figure} -To overcome this issue, in the former work, an additional refinement step is +To overcome this issue, in the former work, an additional refinement step was run in the direction estimated from this longer segment. -It is enough to completely detect most of the tested edges, but certainly -not all, especially if big size images with much longer edges are processed. +It was enough to completely detect most of the tested edges, but certainly +not all, especially if big size images with much longer edges were processed. As a solution, this operation could be iterated as long as the blurred segment escapes from the directional scan using as any fine detection steps as necessary. @@ -144,41 +151,42 @@ the blurred segment all along the expansion stage. At each iteration $i$ of the expansion, the scan strip is aligned on the direction of the blurred segment $\mathcal{B}_{i-1}$ computed at previous iteration $i-1$. -More generally, an adaptive directional scan $ADS$ is defined by: +More formally, an adaptive directional scan $ADS$ is defined by: \begin{equation} ADS = \left\{ S_i = \mathcal{D}_i \cap \mathcal{N}_i \cap \mathcal{I} \left| \begin{array}{l} \vec{V}(\mathcal{N}_i) \cdot \vec{V}(\mathcal{D}_0) = 0 \\ \wedge~ h(\mathcal{N}_i) = h(\mathcal{N}_{i-1}) + p(\mathcal{D}_0) \\ -\wedge~ \mathcal{D}_{i} = \mathcal{D} (C_{i-1}, \vec{D}_{i-1}, w_{i-1}), +%\wedge~ \mathcal{D}_{i} = \mathcal{D} (C_{i-1}, \vec{D}_{i-1}, w_{i-1}), +\wedge~ \mathcal{D}_{i} = \mathcal{D}^{C_{i-1}, \vec{D}_{i-1}, \mu_{i-1}}, i > \lambda \end{array} \right. \right\} \end{equation} where $C_{i}$, $\vec{D}_{i}$ and $w_{i}$ are respectively a position, -a director vector and a width observed at iteration $i$. -In the scope of the present detector, $C_{i-1}$ is the intersection of -the input selection and the central line of $\mathcal{B}_{i-1}$, -$\vec{D}_{i-1}$ the support vector of the enclosing digital segment -$\mathcal{B}_{i-1}$, and $w_{i-1}$ a value slightly greater than the -minimal width of $\mathcal{B}_{i-1}$. -So the last clause expresses the update of the scan bounds at iteration $i$. +a director vector and a thickness observed at iteration $i$. +%In the scope of the present detector, +The last clause expresses the update of the scan bounds at iteration $i$ : +$C_{i-1}$, $\vec{D}_{i-1}$ and $\mu_{i-1}$ are respectively the intersection +of the input selection and the central line of $\mathcal{B}_{i-1}$, +the director vector of the optimal line of $\mathcal{B}_{i-1}$, +and the thickness of $\mathcal{B}_{i-1}$. +$\lambda$ is a delay set to 20 iterations to avoid direction unstabilities +when too few points are inserted. Compared to static directional scans where the scan strip remains fixed to the initial line $\mathcal{D}_0$, here the scan strip moves while scan lines remain fixed. This behavior ensures a complete detection of the blurred segment even when -the orientation of $\mathcal{D}_0$ is badly estimated (\RefFig{fig:escape} c). -In practice, it is started after $\lambda = 20$ iterations when the observed -direction becomes more stable. +the orientation of $\mathcal{D}_0$ is wrongly estimated (\RefFig{fig:escape} c). -\subsection{Control of the assigned width} +\subsection{Control of assigned thickness} \label{subsec:caw} -The assigned width $\varepsilon$ to the blurred segment recognition algorithm -is initially set to a large value $\varepsilon_0$ in order to allow the -detection of large blurred segments. -Then, when no more augmentation of the minimal width is observed after -$\tau$ iterations ($\mu_{i+\tau} = \mu_i$), it is set to a much +The assigned thickess $\varepsilon$ to the blurred segment recognition +algorithm is initially set to a large value $\varepsilon_0$ in order to +allow the detection of large blurred segments. +Then, when no more augmentation of the blurred segment thickness is observed +after $\tau$ iterations ($\mu_{i+\tau} = \mu_i$), it is set to a much stricter value able to circumscribe the possible interpretations of the segment, that take into account the digitization margins: \begin{equation} @@ -263,9 +271,9 @@ magnitude found under the stroke are sorted from the highest to the lowest. For each of them the main detection process is run with three modifications: \begin{enumerate} \item the initial detection takes $M_j$ and the orthogonal direction -$\vec{AB}_\perp$ to the stroke as input to build a static scan of fixed width -$2~\varepsilon_{ini}$, and $M_j$ is used as start point of the blurred -segment; +$\vec{AB}_\perp$ to the stroke as input to build a static scan of fixed +thickness $2~\varepsilon_0$, and $M_j$ is used as start point of the +blurred segment; \item the occupancy mask is filled in with the points of the dilated blurred segments $\mathcal{B}_j'$ at the end of each successful detection (a $5 \times 5$ octogonal neighborhood region of 21 pixels is used); @@ -280,7 +288,7 @@ blurred segment extension in the fine tracking step. \subsection{Automatic blurred segment detection} An unsupervised mode is also proposed to automatically detect all the -straight edges in the image. A stroke that crosses the whole image, is +straight lines in the image. A stroke that crosses the whole image, is swept in both directions, vertical then horizontal, from the center to the borders. At each position, the multi-detection algorithm is run to collect all the segments found under the stroke. @@ -289,8 +297,7 @@ of misaligned segments when the sweeping stroke crosses an image edge near one of its ends. In such situation, any nearby disturbing gradient is likely to deviate the blurred segment direction, and its expansion is quickly stopped. -In the present work, the stroke sweeping step is set to 15 pixels -and the length threshold to 10 pixels. +In the present work, the stroke sweeping step is set to 15 pixels. The automatic detection of blurred segments in a whole image is available for testing from the online demonstration diff --git a/Article/notionsV2.tex b/Article/notionsV2.tex new file mode 100755 index 0000000..8933340 --- /dev/null +++ b/Article/notionsV2.tex @@ -0,0 +1,178 @@ +\section{Theoretical background} + +\label{sec:notions} + +\subsection{Blurred segment} + +This work relies on the notion of digital straight line as classically +defined in the digital geometry literature \cite{KletteRosenfeld04}. +Only the 2D case is considered here. + +\begin{definition} +A \textbf{digital straight line} $\mathcal{L}(a,b,c,\nu)$, +with $(a,b,c,\nu) \in \mathbb{Z}^4$, +is the set of points $P(x,y)$ of $\mathbb{Z}^2$ that satisfy : +$0 \leq ax + by - c < \nu$. +\end{definition} + +In the following, we note $\vec{V}(\mathcal{L}) = (a,b)$ the director vector +of digital line $\mathcal{L}$, $w(\mathcal{L}) = \nu$ its arithmetical width, +$h(\mathcal{L}) = c$ its shift to origin, and $p(\mathcal{L}) = max(|a|,|b|)$ +its period (i.e. the length of its periodic pattern). +When $\nu = p(\mathcal{L})$, then $\mathcal{L}$ is the narrowest 8-connected +line and is called a {\it naive line}. + +The {\it thickness} $\mu = \frac{\nu}{max(|a|,|b|)}$ of the digital straight +line $\mathcal{L}(a,b,c,\nu)$ is the minimum of the vertical and horizontal +distances between lines $ax + by = c$ and $ax + by = c + \nu$. + +\begin{definition} +A \textbf{blurred segment} $\mathcal{B}$ of assigned thickness $\varepsilon$ +is a set of points in $\mathbb{Z}^2$ that all belong to a digital straight +line $\mathcal{L}$ of thickness $\mu = \varepsilon$. +The \textbf{optimal line} of the blurred segment is the digital straight +line with minimal thickness. +The \textbf{thickness} of the blurred segment is the thickness of its +optimal line. +\end{definition} + +A linear-time algorithm to recognize a blurred segment of assigned thickness +$\varepsilon$ \cite{DebledAl05} is used in this work. +It is based on an incremental growth of the convex hull of the blurred +segment when adding each point $P_i$ successively. +%The minimal width $\mu$ of the blurred segment $\mathcal{B}$ is the +%arithmetical width of the narrowest digital straight line that contains +%$\mathcal{B}$. +%It is also the minimal width of the convex hull of $\mathcal{B}$, +%that can be computed by Melkman's algorithm \cite{Melkman87}. +%The enclosing digital segment $E(\mathcal{B})$ is the section of this +%optimal digital straight line bounded by the end points of $\mathcal{B}$. +As depicted on \RefFig{fig:bs}, +the extension of the blurred segment $\mathcal{B}_{i-1}$ of assigned thickness +$\varepsilon$ and thickness $\mu_{i-1}$ at step $i-1$ with a new input +point $P_i$ is thus controlled by the recognition test $\mu_i < \varepsilon$. + +\begin{figure}[h] +\center + \input{Fig_notions/bswidth} + \caption{A growing blurred segment $\mathcal{B}_i$ : +when adding the new point $P_i$, the blurred segment minimal thickness +augments from $\mu_{i-1}$ to $\mu_i$; if the new thickness $\mu_i$ exceeds +the assigned thickness $\varepsilon$, then the new input point is rejected +and $\mathcal{B}_i = \mathcal{B}_{i-1}$.} + \label{fig:bs} +\end{figure} + +Associated to this primitive, the following definition of a directional scan +is an important point of the proposed method. + +\subsection{Directional scan} + +\begin{definition} +A directional scan $DS$ is an ordered partition restricted to the image +domain $\mathcal{I}$ of a digital straight line $\mathcal{D}$, called the +\textbf{scan strip}, into scans $S_i$, each of them being a segment of a +naive line $\mathcal{N}_i$, called a \textbf{scan line}, orthogonal to +$\mathcal{D}$. +\end{definition} + +\begin{equation} +DS = \left\{ S_i = \mathcal{D} \cap \mathcal{N}_i \cap \mathcal{I} +\left| \begin{array}{l} +\vec{V}(\mathcal{N}_i) \cdot \vec{V}(\mathcal{D}) = 0 \\ +\wedge~ h(\mathcal{N}_i) = h(\mathcal{N}_{i-1}) + p(\mathcal{D}) +\end{array} \right. \right\} +%S_i = \mathcal{D} \cap \mathcal{N}_i, \mathcal{N}_i \perp \mathcal{D} +\end{equation} +In this definition, the clause +$\vec{V}(\mathcal{N}_i) \cdot \vec{V}(\mathcal{D}) = 0$ +expresses the orthogonality constraint between the scan lines $\mathcal{N}_i$ +and the scan strip $\mathcal{D}$. +Then the shift of the period $p(\mathcal{D})$ between successive scans +guarantees that all points of the scan strip are travelled one and only one +time. + +The scans $S_i$ are developed on each side of a start scan $S_0$, +and ordered by their distance to the start line $\mathcal{N}_0$ with +a positive (resp. negative) sign if they are on the left (resp. right) +side of $\mathcal{N}_0$ (\RefFig{fig:ds}). +The directional scan is iteratively parsed from the start scan to both ends. +At each iteration $i$, the scans $S_i$ and $S_{-i}$ are successively processed. + +\begin{figure}[h] +\center +% \input{Fig_notions/fig} + \includegraphics[width=0.8\textwidth]{Fig_notions/scanstrip.eps} + \begin{picture}(1,1)(0,0) + \thicklines + \put(-176,112){\vector(2,-1){30}} + \put(-90,19){\vector(-2,1){30}} + {\color{dwhite}{ + \put(-181,114.5){\circle*{10}} + \put(-84,16.5){\circle*{10}} + \put(-16,102.5){\circle*{10}} + \put(-132,66.5){\circle*{12}} + \put(-72,96.5){\circle*{12}} + \put(-175.5,65.5){\circle*{20}} + \put(-117,10.5){\circle*{14}} + \put(-54,32.5){\circle*{14}} + \put(-161,10.5){\circle*{20}} + }} + \put(-88,13.5){$A$} + \put(-185,111.5){$B$} + \put(-20,98){$\mathcal{D}$} + \put(-137,64){\color{blue}{$S_0$}} + \put(-77,94){\color{red}{$S_8$}} + \put(-183,64){\color{dgreen}{$S_{-5}$}} + \put(-123,8){\color{blue}{$\mathcal{N}_0$}} + \put(-60,30){\color{red}{$\mathcal{N}_8$}} + \put(-169,8){\color{dgreen}{$\mathcal{N}_{-5}$}} + \end{picture} + \caption{A directional scan. + The start scan $S_0$ is drawn in blue, odd scans in green, + even scans in red, the bounds of scan lines $\mathcal{N}_i$ + with plain lines and the bounds of scan strip $\mathcal{D}$ + with dotted lines.} + \label{fig:ds} +\end{figure} + +A directional scan can be defined by its start scan $S_0$. +If $A(x_A,y_A)$ and $B(x_B,y_B)$ are the end points of $S_0$, +and if we note $\delta_x = x_B - x_A$, $\delta_y = y_B - y_A$, +$c_1 = \delta_x\cdot x_A + \delta_y\cdot y_A$, +$c_2 = \delta_x\cdot x_B + \delta_y\cdot y_B$ and +$p_{AB} = max (|\delta_x|, |\delta_y|)$, it is then defined by +the following scan strip $\mathcal{D}^{A,B}$ and scan lines +$\mathcal{N}_i^{A,B}$: +\begin{equation} +\left\{ \begin{array}{l} +\mathcal{D}^{A,B} = +\mathcal{L}(\delta_x,~ \delta_y,~ min (c1,c2),~ 1 + |c_1-c_2|) \\ +\mathcal{N}_i^{A,B} = \mathcal{L}(\delta_y,~ -\delta_x,~ +\delta_y\cdot x_A - \delta_x\cdot y_A + i\cdot p_{AB},~ p_{AB}) +\end{array} \right. +\end{equation} + +%The scan lines length is $d_\infty(AB)$ or $d_\infty(AB)-1$, where $d_\infty$ +%is the chessboard distance ($d_\infty = max (|d_x|,|d_y|)$). +%In practice, this difference of length between scan lines is not a drawback, +%as the image bounds should also be processed anyway. + +A directional scan can also be defined by a central point $C(x_C,y_C)$, +a direction $\vec{D}(X_D,Y_D)$ and a minimal thickness $w$. +If we note +$p_{\vec{D}} = max (|X_D|,|Y_D|)$, +$\nu_{\vec{D}} = \lceil w\cdot p_{\vec{D}} \rceil$, +$c_3 = x_C\cdot Y_D - y_C\cdot X_D - \frac{\nu_{\vec{D}}}{2}$, +$c_4 = X_D\cdot x_C + Y_D\cdot y_C - \frac{p_{\vec{D}}}{2}$, +it is then defined by +the following scan strip $\mathcal{D}^{C,\vec{D},w}$ and scan lines +$\mathcal{N}_i^{C,\vec{D},w}$: +\begin{equation} +\left\{ \begin{array}{l} +\mathcal{D}^{C,\vec{D},w} += \mathcal{L}(Y_D,~ -X_D,~ c_3,~ \nu_{\vec{D}}) \\ +\mathcal{N}_i^{C,\vec{D},w} = \mathcal{L}(X_D,~ Y_D,~ + c_4 + i\cdot p_{\vec{D}},~ p_{\vec{D}}) +\end{array} \right. +\end{equation} diff --git a/Code/FBSD/BSTools/bsdetectionwidget.cpp b/Code/FBSD/BSTools/bsdetectionwidget.cpp index cf65f36..cd6969d 100755 --- a/Code/FBSD/BSTools/bsdetectionwidget.cpp +++ b/Code/FBSD/BSTools/bsdetectionwidget.cpp @@ -365,7 +365,10 @@ void BSDetectionWidget::mousePressEvent (QMouseEvent *event) DigitalStraightSegment *dss = (*it)->getSegment (); if (dss != NULL) { - if (dss->contains (Pt2i (ex, ey), SELECT_TOL)) searching = false; + if (dss->contains (Pt2i (ex, ey), SELECT_TOL)) + { + searching = false; + } else nb ++; } else nb ++; diff --git a/Code/FBSD/BSTools/bsyorkitem.cpp b/Code/FBSD/BSTools/bsyorkitem.cpp index ed5ae18..e95a64a 100755 --- a/Code/FBSD/BSTools/bsyorkitem.cpp +++ b/Code/FBSD/BSTools/bsyorkitem.cpp @@ -7,22 +7,22 @@ using namespace std; -const int BSYorkItem::YORK_ALONE = 0; +const int BSYorkItem::GT_ALONE = 0; const int BSYorkItem::LSD_ALONE = 1; const int BSYorkItem::DILATED_LSD_ALONE = 2; -const int BSYorkItem::YORK_OVER_LSD = 3; +const int BSYorkItem::GT_OVER_LSD = 3; const int BSYorkItem::ED_ALONE = 4; const int BSYorkItem::DILATED_ED_ALONE = 5; -const int BSYorkItem::YORK_OVER_ED = 6; +const int BSYorkItem::GT_OVER_ED = 6; const int BSYorkItem::CANNY_ALONE = 7; const int BSYorkItem::DILATED_CANNY_ALONE = 8; -const int BSYorkItem::YORK_OVER_CANNY = 9; +const int BSYorkItem::GT_OVER_CANNY = 9; const int BSYorkItem::FBSD_LINES = 10; const int BSYorkItem::FBSD_ALONE = 11; -const int BSYorkItem::YORK_OVER_BS = 12; -const int BSYorkItem::YORK_OVER_DSS = 13; -const int BSYorkItem::YORK_WITH_CANNY = 14; -const int BSYorkItem::YORK_WITH_DSS = 15; +const int BSYorkItem::GT_OVER_BS = 12; +const int BSYorkItem::GT_OVER_DSS = 13; +const int BSYorkItem::GT_WITH_CANNY = 14; +const int BSYorkItem::GT_WITH_DSS = 15; const int BSYorkItem::NO_INFO = 16; const QColor BSYorkItem::ALONE_COLOR = Qt::black; const QColor BSYorkItem::OVER_COLOR = Qt::lightGray; @@ -41,9 +41,9 @@ BSYorkItem::BSYorkItem (int width, int height, const QImage *im, bsmap = new bool[size]; clmap = new bool[size]; det = detector; - type = YORK_ALONE; + type = GT_ALONE; dilationType = 0; - yorks = new ExtLines ("Data/yorklines.txt", w, h); + gts = new ExtLines ("Data/yorklines.txt", w, h); cannys = new ExtLines ("Data/cannylines.txt", w, h, 5); lsds = new ExtLines ("Data/lsdlines.txt", w, h, 7); eds = new ExtLines ("Data/edlines.txt", w, h, 4); @@ -71,51 +71,51 @@ void BSYorkItem::paint (QPainter *painter, Q_UNUSED (widget); for (int i = 0; i < w * h; i++) bsmap[i] = false; - if (type == YORK_ALONE) drawYorkLines (painter, true); + if (type == GT_ALONE) drawGroundTruth (painter, true); else if (type == ED_ALONE) drawEdLines (painter, true); else if (type == DILATED_ED_ALONE) drawDilatedEdLines (painter); - else if (type == YORK_OVER_ED) + else if (type == GT_OVER_ED) { drawEdLines (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } else if (type == LSD_ALONE) drawLsdLines (painter, true); else if (type == DILATED_LSD_ALONE) drawDilatedLsdLines (painter); - else if (type == YORK_OVER_LSD) + else if (type == GT_OVER_LSD) { drawLsdLines (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } else if (type == CANNY_ALONE) drawCannyLines (painter, true); else if (type == DILATED_CANNY_ALONE) drawDilatedCannyLines (painter); - else if (type == YORK_OVER_CANNY) + else if (type == GT_OVER_CANNY) { drawCannyLines (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } else if (type == FBSD_LINES) drawFbsdLines (painter, true); else if (type == FBSD_ALONE) drawDSS (painter, true); - else if (type == YORK_OVER_BS) + else if (type == GT_OVER_BS) { drawBS (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } - else if (type == YORK_OVER_DSS) + else if (type == GT_OVER_DSS) { drawDSS (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } - else if (type == YORK_WITH_CANNY) + else if (type == GT_WITH_CANNY) { drawCannyLines (painter, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } - else if (type == YORK_WITH_DSS) + else if (type == GT_WITH_DSS) { drawDSS (painter, false, false); - drawYorkLines (painter, false); + drawGroundTruth (painter, false); } - else drawYorkLines (painter, true); + else drawGroundTruth (painter, true); int nboth = 0, ncl = 0, nbs = 0; for (int i = 0; i < w * h; i++) if (clmap[i]) @@ -186,30 +186,33 @@ void BSYorkItem::drawPoints (QPainter *painter, vector<Pt2i> pts, bool disp) } -void BSYorkItem::drawYorkLines (QPainter *painter, bool alone) +void BSYorkItem::drawGroundTruth (QPainter *painter, bool alone) { - int n = 0; - Pt2i *pts = NULL; - int nb = yorks->countOfLines (); - for (int i = 0; i < nb; i++) + if (gts->areLinesLoaded ()) { - pts = Pt2i (yorks->xStart (i), yorks->yStart (i)).drawing ( - Pt2i (yorks->xEnd (i), yorks->yEnd (i)), &n); - for (int i = 0; i < n; i++) + int n = 0; + Pt2i *pts = NULL; + int nb = gts->countOfLines (); + for (int i = 0; i < nb; i++) { - if (pts[i].x () >= 0 && pts[i].x () < w - && pts[i].y () >= 0 && pts[i].y () < h) + pts = Pt2i (gts->xStart (i), gts->yStart (i)).drawing ( + Pt2i (gts->xEnd (i), gts->yEnd (i)), &n); + for (int i = 0; i < n; i++) { - painter->setPen (QPen (alone || bsmap[pts[i].y()*w+pts[i].x()] ? - BOTH_COLOR : OVER_COLOR, - DEFAULT_PEN_WIDTH, Qt::SolidLine, - Qt::RoundCap, Qt::RoundJoin)); - painter->drawPoint (QPoint (pts[i].x (), - h - 1 - pts[i].y ())); // dec 1 - clmap[pts[i].y()*w+pts[i].x()] = true; + if (pts[i].x () >= 0 && pts[i].x () < w + && pts[i].y () >= 0 && pts[i].y () < h) + { + painter->setPen (QPen (alone || bsmap[pts[i].y()*w+pts[i].x()] ? + BOTH_COLOR : OVER_COLOR, + DEFAULT_PEN_WIDTH, Qt::SolidLine, + Qt::RoundCap, Qt::RoundJoin)); + painter->drawPoint (QPoint (pts[i].x (), + h - 1 - pts[i].y ())); // dec 1 + clmap[pts[i].y()*w+pts[i].x()] = true; + } } + delete [] pts; } - delete [] pts; } } @@ -421,7 +424,6 @@ void BSYorkItem::drawDilatedCannyLines (QPainter *painter, bool disp) if (dilationType == 1) dil = dss->period (); else if (dilationType == 2) dil = dss->standard (); else if (dilationType == 3) dil = 2 * dss->period (); -cout << "Dilation of " << dil << endl; dss->dilate (dil); } dss->getPoints (points); @@ -476,21 +478,6 @@ void BSYorkItem::drawFbsdLines (QPainter *painter, bool alone, bool disp) } -void BSYorkItem::computeBScovering () -{ - det->detectAll (); - double fbsdCov = yorks->covering (det->getBlurredSegments ()); - cout << "FBSD covering : " << fbsdCov << endl; - int nb; - double lg; - double cannyCov = yorks->covering ( - "/home/even/tmp/FBSD/Data/cannylines.txt", 5, - nb, lg, det->finalSpreadMinLength ()); - cout << "Canny lines covering : " << cannyCov << endl; - -} - - bool BSYorkItem::toggleDilationType () { if (++dilationType == 4) dilationType = 0; diff --git a/Code/FBSD/BSTools/bsyorkitem.h b/Code/FBSD/BSTools/bsyorkitem.h index 0185132..a051a82 100755 --- a/Code/FBSD/BSTools/bsyorkitem.h +++ b/Code/FBSD/BSTools/bsyorkitem.h @@ -1,5 +1,5 @@ -#ifndef BS_YORK_ITEM_H -#define BS_YORK_ITEM_H +#ifndef BS_GT_ITEM_H +#define BS_GT_ITEM_H #include <QGraphicsItem> #include "bsdetector.h" @@ -51,11 +51,6 @@ public: */ bool toggleDilationType (); - /** - * \brief Computes and displays blurred segment covering. - */ - void computeBScovering (); - /** * \brief Returns the external lines view width. */ @@ -70,37 +65,37 @@ public: * \brief Returns the displayed information title. */ inline QString itemTitle () const { - if (type == YORK_ALONE) + if (type == GT_ALONE) return ("York Urban DB ground truth"); else if (type == DILATED_LSD_ALONE) return ("Dilated_LSD lines"); else if (type == LSD_ALONE) return ("LSD lines"); - else if (type == YORK_OVER_LSD) + else if (type == GT_OVER_LSD) return ("York over LSD lines"); else if (type == DILATED_ED_ALONE) return ("Dilated_ED lines"); else if (type == ED_ALONE) return ("ED lines"); - else if (type == YORK_OVER_ED) + else if (type == GT_OVER_ED) return ("York over ED lines"); else if (type == DILATED_CANNY_ALONE) return ("Dilated_Canny lines"); else if (type == CANNY_ALONE) return ("Canny lines"); - else if (type == YORK_OVER_CANNY) + else if (type == GT_OVER_CANNY) return ("York over Canny lines"); else if (type == FBSD_LINES) return ("FBSD output lines"); else if (type == FBSD_ALONE) return ("FBSD detection"); - else if (type == YORK_OVER_BS) + else if (type == GT_OVER_BS) return ("York over blurred segments points"); - else if (type == YORK_OVER_DSS) + else if (type == GT_OVER_DSS) return ("York over digital straight segments"); - else if (type == YORK_WITH_CANNY) + else if (type == GT_WITH_CANNY) return ("York blend with Canny lines"); - else if (type == YORK_WITH_DSS) + else if (type == GT_WITH_DSS) return ("York blend with digital straight lines"); else return ("No info"); } @@ -110,37 +105,37 @@ public: private: /** York lines alone display modality. */ - static const int YORK_ALONE; + static const int GT_ALONE; /** Lsd lines alone display modality. */ static const int LSD_ALONE; /** Dilated Lsd lines alone display modality. */ static const int DILATED_LSD_ALONE; /** York over Lsd display modality. */ - static const int YORK_OVER_LSD; + static const int GT_OVER_LSD; /** ED lines alone display modality. */ static const int ED_ALONE; /** Dilated ED lines alone display modality. */ static const int DILATED_ED_ALONE; /** York over ED display modality. */ - static const int YORK_OVER_ED; + static const int GT_OVER_ED; /** Canny lines alone display modality. */ static const int CANNY_ALONE; /** Dilated Canny lines alone display modality. */ static const int DILATED_CANNY_ALONE; /** York over Canny display modality. */ - static const int YORK_OVER_CANNY; + static const int GT_OVER_CANNY; /** FBSD output lines alone display modality. */ static const int FBSD_LINES; /** FBSD detected lines alone display modality. */ static const int FBSD_ALONE; /** York over BS display modality. */ - static const int YORK_OVER_BS; + static const int GT_OVER_BS; /** York over DSS display modality. */ - static const int YORK_OVER_DSS; + static const int GT_OVER_DSS; /** York with Canny display modality. */ - static const int YORK_WITH_CANNY; + static const int GT_WITH_CANNY; /** York with DSS display modality. */ - static const int YORK_WITH_DSS; + static const int GT_WITH_DSS; /** No info display modality. */ static const int NO_INFO; /** Default color for alone lines. */ @@ -154,8 +149,8 @@ private: /** Default value for pen width. */ static const int DEFAULT_PEN_WIDTH; - /** Set of York lines. */ - ExtLines *yorks; + /** Set of Ground truths lines. */ + ExtLines *gts; /** Set of Lsd lines. */ ExtLines *lsds; /** Set of ED lines. */ @@ -191,8 +186,8 @@ private: /** Displays a set of points */ void drawPoints (QPainter *painter, vector<Pt2i> pts, bool disp = true); - /** Displays York lines */ - void drawYorkLines (QPainter *painter, bool alone); + /** Displays ground truth */ + void drawGroundTruth (QPainter *painter, bool alone); /** Displays Lsd lines */ void drawLsdLines (QPainter *painter, bool alone, bool disp = true); diff --git a/Code/FBSD/BSTools/bsyorkview.cpp b/Code/FBSD/BSTools/bsyorkview.cpp index 0869ba9..15addd0 100755 --- a/Code/FBSD/BSTools/bsyorkview.cpp +++ b/Code/FBSD/BSTools/bsyorkview.cpp @@ -56,16 +56,12 @@ bool BSYorkView::processKeyEvent (QKeyEvent *event) } break; - case Qt::Key_J : // Still used ? - york->computeBScovering (); - break; - case Qt::Key_P : // Capture -// viewport()->grab ( -// QRect (QPoint (0, 0), -// QSize (york->getWidth(), york->getHeight())) -// ).toImage().save ("external.png"); -// cout << "External detectors view shot in external.png" << endl; + viewport()->grab ( + QRect (QPoint (0, 0), + QSize (york->getWidth(), york->getHeight())) + ).toImage().save ("external.png"); + cout << "External detectors view shot in external.png" << endl; break; } return processed; diff --git a/Code/FBSD/BSTools/extlines.cpp b/Code/FBSD/BSTools/extlines.cpp index 1b6382c..3c37dd2 100755 --- a/Code/FBSD/BSTools/extlines.cpp +++ b/Code/FBSD/BSTools/extlines.cpp @@ -7,10 +7,7 @@ using namespace std; -const int ExtLines::COV_DILATION = 4; const double ExtLines::MIN_LENGTH = 10.; -const double ExtLines::MIN_DTHETA = 4.; -const double ExtLines::MIN_SHIFT = 2.; ExtLines::ExtLines (bool groundTruth) @@ -19,16 +16,16 @@ ExtLines::ExtLines (bool groundTruth) im.load ("Data/york.jpg"); width = im.width (); height = im.height (); - gt = groundTruth; + loaded = false; if (groundTruth) { double val[4]; int i = 0, nb = 0; ifstream input ("Data/yorklines.txt", ios::in); - bool reading = true; - if (input) + if (input.is_open ()) { + bool reading = true; while (reading) { input >> val[i]; @@ -40,11 +37,17 @@ ExtLines::ExtLines (bool groundTruth) cl.sy = height - 1 - val[1]; cl.ex = val[2]; cl.ey = height - 1 - val[3]; - exts.push_back (cl); + if (cl.sx == cl.ex && cl.sy == cl.ey) + cout << "LIGNE NULLE !!!" << endl; + else + { + exts.push_back (cl); + nb++; + } i = 0; - nb++; } } + loaded = true; } } stats (im); @@ -63,9 +66,9 @@ ExtLines::ExtLines (const char *name, int width, int height, int nbinfo) double val[nbinfo]; int i = 0, nb = 0; ifstream input (name, ios::in); - bool reading = true; - if (input) + if (input.is_open ()) { + bool reading = true; while (reading) { input >> val[i]; @@ -77,13 +80,19 @@ ExtLines::ExtLines (const char *name, int width, int height, int nbinfo) cl.sy = height - 1 - val[1]; cl.ex = val[2]; cl.ey = height - 1 - val[3]; - exts.push_back (cl); + if (cl.sx == cl.ex && cl.sy == cl.ey) + cout << "LIGNE NULLE !!!" << endl; + else + { + exts.push_back (cl); + nb++; + } i = 0; - nb++; } } + loaded = true; } - gt = true; + else loaded = false; } @@ -151,9 +160,9 @@ double ExtLines::covering (const char *name, int nbinfo, nb = 0; lg = 0.; ifstream input (name, ios::in); - bool reading = true; if (input) { + bool reading = true; while (reading) { input >> val[i]; @@ -233,115 +242,6 @@ double ExtLines::covering (const char *name, int nbinfo, } -double ExtLines::diffangle (const char *name, int nbinfo, double minl) const -{ - // 1. Reading external lines file - vector<ExtLine> cannys; - double val[nbinfo]; - double clLength = 0.; - int i = 0; - ifstream input (name, ios::in); - bool reading = true; - if (input) - { - while (reading) - { - input >> val[i]; - if (input.eof ()) reading = false; - if (++i == nbinfo) - { - ExtLine cl; - cl.sx = val[0]; - cl.sy = height - 1 - val[1]; - cl.ex = val[2]; - cl.ey = height - 1 - val[3]; - clLength = sqrt ((cl.sx - cl.ex) * (cl.sx - cl.ex) - + (cl.sy - cl.ey) * (cl.sy - cl.ey)); - if (clLength > minl) cannys.push_back (cl); - i = 0; - } - } - } - - // 2. Matching - bool opposite = false; - double totl = 0., totdtheta = 0.; - double cosang = 0., dtheta = 0., shift = 0., cx = 0., cy = 0.; - double px = 0., py = 0., qx = 0., qy = 0., lgth = 0.; - vector<ExtLine>::const_iterator it = exts.begin (); - while (it != exts.end ()) - { - Vr2i vref (it->ex - it->sx, it->ey - it->sy); - double aref = it->ey - it->sy; - double bref = it->sx - it->ex; - double cref = aref * it->sx + bref * it->sy; - double dref = sqrt (aref * aref + bref * bref); - - vector<ExtLine>::iterator rit = cannys.begin (); - while (rit != cannys.end ()) - { - opposite = false; - Vr2i vtest (rit->ex - rit->sx, rit->ey - rit->sy); - cosang = vtest.scalarProduct (vref) - / (sqrt (vtest.norm2 ()) * sqrt (vref.norm2 ())); - if (cosang < 0.) - { - opposite = true; - cosang = - cosang; - } - dtheta = (180. / M_PI) * acos (cosang); - if (dtheta < MIN_DTHETA) - { - cx = (rit->sx + rit->ex) / 2; - cy = (rit->sy + rit->ey) / 2; - shift = (cref - aref * cx - bref * cy) / dref; - if (shift < 0) shift = - shift; - if (shift < MIN_SHIFT) - { - Vr2i vecac (cx - it->sx, cy - it->sy); - Vr2i vecbc (cx - it->ex, cy - it->ey); - if (vref.scalarProduct (vecac) >= 0. - && vref.scalarProduct (vecbc) <= 0.) - { - if (opposite) - { - px = rit->ex; - py = rit->ey; - qx = rit->sx; - qy = rit->sy; - } - else - { - px = rit->sx; - py = rit->sy; - qx = rit->ex; - qy = rit->ey; - } - Vr2i vecap (px - it->sx, py - it->sy); - if (vref.scalarProduct (vecap) < 0.) - { - px = it->sx; - py = it->sy; - } - Vr2i vecqb (it->ex - qx, it->sy - qy); - if (vref.scalarProduct (vecqb) < 0.) - { - qx = it->ex; - qy = it->ey; - } - lgth = sqrt ((qx - px) * (qx - px) + (qy - py) * (qy - py)); - totl += lgth; - totdtheta += dtheta * lgth; - } - } - } - rit ++; - } - } - return (totl != 0. ? totdtheta / totl : 0.); -} - - int ExtLines::count (const char *name, int nbinfo, double &lg, double minl) const { @@ -406,7 +306,7 @@ void ExtLines::stats (const QImage &im) if (detector.isFinalSpreadTestOn ()) detector.switchFinalSpreadTest (); detector.detectAll (); vector<BlurredSegment *> bss = detector.getBlurredSegments (); - if (gt) + if (loaded) { double covFBSD = covering (bss); ofstream outf ("Data/fbsdcov.txt", ios::out); @@ -441,17 +341,14 @@ void ExtLines::stats (const char *lname, int nbinfo, { int nel = 0; double lel = 0.; - if (gt) + if (loaded) { double covel = covering (lname, nbinfo, nel, lel, MIN_LENGTH); - double dang = diffangle (lname, nbinfo, MIN_LENGTH); - ofstream outf (covname, ios::out); - outf << covel << " " << dang << endl; + outf << covel << endl; outf.close (); } else nel = count (lname, nbinfo, lel, MIN_LENGTH); - ofstream outl (lgname, ios::out); outl << nel << " " << lel << " " << (lel / nel) << " " << endl; outl.close (); diff --git a/Code/FBSD/BSTools/extlines.h b/Code/FBSD/BSTools/extlines.h index 34127aa..2088bf6 100755 --- a/Code/FBSD/BSTools/extlines.h +++ b/Code/FBSD/BSTools/extlines.h @@ -61,6 +61,11 @@ public: inline int yEnd (int index) const { return ((int) (exts[index].ey + 0.5)); } + /** + * \brief Indicates if lines are available. + */ + inline bool areLinesLoaded () const { return (loaded); } + /** * \brief Returns the covering ratio of given blurred segments. */ @@ -77,14 +82,6 @@ public: double covering (const char *name, int nbinfo, int &nb, double &lg, double minl) const; - /** - * \brief Returns the angular difference. - * @param name External lines file name. - * @param nbinfo count of data per line. - * @param minl Minimal length of extarcted lines. - */ - double diffangle (const char *name, int nbinfo, double minl) const; - /** * \brief Returns the count and cumulated length of external lines. * @param name External lines file name. @@ -97,14 +94,8 @@ public: private: - /** Dilation distance for lines covering estimation. */ - static const int COV_DILATION; /** Minimal length of considered lines. */ static const double MIN_LENGTH; - /** Minimal angular deviation for line matching with ground truth. */ - static const double MIN_DTHETA; - /** Minimal distance shift for line matching with ground truth. */ - static const double MIN_SHIFT; /** Aggregation of segment extraction results with initial conditions. */ struct ExtLine @@ -119,8 +110,8 @@ private: double ey; }; - /** Indicatres if a ground truth is available. */ - bool gt; + /** Indicates if a lines are available. */ + bool loaded; /** Set of recorded external lines. */ vector<ExtLine> exts; diff --git a/Code/FBSD/BlurredSegment/blurredsegmentproto.cpp b/Code/FBSD/BlurredSegment/blurredsegmentproto.cpp index 99786a5..925ae8a 100755 --- a/Code/FBSD/BlurredSegment/blurredsegmentproto.cpp +++ b/Code/FBSD/BlurredSegment/blurredsegmentproto.cpp @@ -56,10 +56,22 @@ BlurredSegmentProto::~BlurredSegmentProto () } -AbsRat BlurredSegmentProto::minimalWidth () const +AbsRat BlurredSegmentProto::strictThickness () const { - return (convexhull != NULL ? convexhull->rationalThickness () - : AbsRat (0, 1)); + return (convexhull != NULL ? convexhull->strictThickness () : AbsRat (0, 1)); +} + + +AbsRat BlurredSegmentProto::digitalThickness () const +{ + if (bsOK) + { + Pt2i s, e, v; + convexhull->antipodalEdgeAndVertex (s, e, v); + DigitalStraightLine l (s, e, v); + return (AbsRat (l.width (), l.period ())); + } + return (AbsRat (1, 1)); } @@ -200,7 +212,7 @@ bool BlurredSegmentProto::addRight (Pt2i pix) bool BlurredSegmentProto::addPoint (Pt2i p, bool onleft) { bool inserted = convexhull->addPointDS (p, onleft); - if ((minimalWidth ()).greaterThan (maxWidth)) + if ((strictThickness ()).greaterThan (maxWidth)) { if (inserted) convexhull->restore (); return false; diff --git a/Code/FBSD/BlurredSegment/blurredsegmentproto.h b/Code/FBSD/BlurredSegment/blurredsegmentproto.h index b0aa66c..bad3be9 100755 --- a/Code/FBSD/BlurredSegment/blurredsegmentproto.h +++ b/Code/FBSD/BlurredSegment/blurredsegmentproto.h @@ -41,9 +41,16 @@ public: ~BlurredSegmentProto (); /** - * \brief Returns the minimal vertical or horizontal width. + * \brief Returns the built-in blurred segment strict thickness. + * The strict thickness is the distance between bounding lines, ie (nu-1)/p. */ - AbsRat minimalWidth () const; + AbsRat strictThickness () const; + + /** + * \brief Returns the built-in blurred segment digital thickness. + * The digital thickness is the width of the digital straight line, ie nu/p. + */ + AbsRat digitalThickness () const; /** * \brief Returns the requested max width of the segment. diff --git a/Code/FBSD/BlurredSegment/bsdetector.cpp b/Code/FBSD/BlurredSegment/bsdetector.cpp index 8144851..0ebae63 100755 --- a/Code/FBSD/BlurredSegment/bsdetector.cpp +++ b/Code/FBSD/BlurredSegment/bsdetector.cpp @@ -69,7 +69,7 @@ BSDetector::BSDetector () finalDensityTestOn = false; finalLengthTestOn = false; finalSpreadTestOn = true; - finalSpreadMin = 10; + finalSpreadMin = 12; // nbSmallBS = 0; multiSelection = false; autodet = false; @@ -485,9 +485,9 @@ int BSDetector::detect (const Pt2i &p1, const Pt2i &p2, delete bsini; bsini = fbs; } + if (bsini->size () < bsMinSize) + return RESULT_INITIAL_TOO_MANY_OUTLIERS; } - if (bsini->size () < bsMinSize) - return RESULT_INITIAL_TOO_MANY_OUTLIERS; // Orientation test for automatic extractions //------------------------------------------- diff --git a/Code/FBSD/BlurredSegment/bsdetector.h b/Code/FBSD/BlurredSegment/bsdetector.h index 1c513fb..bc8d97b 100755 --- a/Code/FBSD/BlurredSegment/bsdetector.h +++ b/Code/FBSD/BlurredSegment/bsdetector.h @@ -411,6 +411,16 @@ public: */ void switchOrthoScans (); + /** + * \brief Switches the strict thickenning option. + */ + inline void switchStrict () { bst2->switchStrict (); } + + /** + * \brief Returns if the strict thickenning option is activated. + */ + inline bool isStrictOn () const { return bst2->isStrictOn (); } + /** * \brief Returns if the thickenning control is activated. */ diff --git a/Code/FBSD/BlurredSegment/bstracker.cpp b/Code/FBSD/BlurredSegment/bstracker.cpp index 798b49a..a5ca5c4 100755 --- a/Code/FBSD/BlurredSegment/bstracker.cpp +++ b/Code/FBSD/BlurredSegment/bstracker.cpp @@ -25,6 +25,7 @@ const int BSTracker::FAILURE_LOST_ORIENTATION = 32; BSTracker::BSTracker () { + strictOn = false; proxTestOff = true; proxThreshold = DEFAULT_PROX_THRESHOLD; acceptedLacks = DEFAULT_ACCEPTED_LACKS; @@ -273,12 +274,14 @@ BlurredSegment *BSTracker::fineTrack (int bsMaxWidth, while (scanningRight || scanningLeft) { count ++; - AbsRat sw = bs.minimalWidth (); + AbsRat sw = bs.strictThickness (); // Handles thickenning if (thickenOn && stableWidthCount >= thickenningLimit) { - AbsRat finalWidth (sw.sumHalf ()); + AbsRat dth (sw); + if (strictOn) dth = bs.digitalThickness (); + AbsRat finalWidth (dth.sumHalf ()); if (finalWidth.lessThan (bs.getMaxWidth ())) bs.setMaxWidth (finalWidth); thickenOn = false; } @@ -357,7 +360,7 @@ BlurredSegment *BSTracker::fineTrack (int bsMaxWidth, stableWidthCount ++; if (added) { - if (sw.lessThan (bs.minimalWidth ())) stableWidthCount = 0; + if (sw.lessThan (bs.strictThickness ())) stableWidthCount = 0; rscan = count; if (rstop == 0) rstart = 0; else @@ -405,7 +408,7 @@ BlurredSegment *BSTracker::fineTrack (int bsMaxWidth, stableWidthCount ++; if (added) { - if (sw.lessThan (bs.minimalWidth ())) stableWidthCount = 0; + if (sw.lessThan (bs.strictThickness ())) stableWidthCount = 0; lscan = count; if (lstop == 0) lstart = 0; else diff --git a/Code/FBSD/BlurredSegment/bstracker.h b/Code/FBSD/BlurredSegment/bstracker.h index bb2613b..94a6b84 100755 --- a/Code/FBSD/BlurredSegment/bstracker.h +++ b/Code/FBSD/BlurredSegment/bstracker.h @@ -199,6 +199,16 @@ public: inline void incThickenningLimit (int val) { thickenningLimit += val; if (thickenningLimit < 1) thickenningLimit = 1; } + /** + * \brief Switches the strict thickenning option. + */ + inline void switchStrict () { strictOn = ! strictOn; } + + /** + * \brief Returns if the strict thickenning option is activated. + */ + inline bool isStrictOn () const { return strictOn; } + /** * \brief Returns if the thinning is activated. */ @@ -287,6 +297,7 @@ private : /** Crosswise segment detection modality. */ bool trackCrosswise; +bool strictOn; /** Segment thinning strategy. */ bool thinningOn; /** Width thinning delay. */ diff --git a/Code/FBSD/ConvexHull/antipodal.cpp b/Code/FBSD/ConvexHull/antipodal.cpp index 9e6b4e7..c9ef9c7 100755 --- a/Code/FBSD/ConvexHull/antipodal.cpp +++ b/Code/FBSD/ConvexHull/antipodal.cpp @@ -64,7 +64,7 @@ void Antipodal::init (CHVertex *v1, CHVertex *v2, CHVertex *v3) } -AbsRat Antipodal::rationalWidth () const +AbsRat Antipodal::strictThickness () const { int den = ept2->get (iy) - ept1->get (iy); return (AbsRat (((vpt->get (ix) - ept1->get (ix)) * den diff --git a/Code/FBSD/ConvexHull/antipodal.h b/Code/FBSD/ConvexHull/antipodal.h index 39ce1dd..36cd073 100755 --- a/Code/FBSD/ConvexHull/antipodal.h +++ b/Code/FBSD/ConvexHull/antipodal.h @@ -44,8 +44,10 @@ public: /** 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; + /** Returns the antipodal pair strict thickness. + * Strict thickness is the vertex horizontal distance to the edge. + */ + AbsRat strictThickness () const; /** Gets the rational main axis width of the antipodal pair. */ void width (int &num, int &den) const; diff --git a/Code/FBSD/ConvexHull/convexhull.cpp b/Code/FBSD/ConvexHull/convexhull.cpp index 9be4b4f..b20d532 100755 --- a/Code/FBSD/ConvexHull/convexhull.cpp +++ b/Code/FBSD/ConvexHull/convexhull.cpp @@ -114,10 +114,10 @@ bool ConvexHull::moveLastPoint (const Pt2i &pix) } -AbsRat ConvexHull::rationalThickness () const +AbsRat ConvexHull::strictThickness () const { - AbsRat aphw = aph.rationalWidth (); - AbsRat apvw = apv.rationalWidth (); + AbsRat aphw = aph.strictThickness (); + AbsRat apvw = apv.strictThickness (); return (apvw.lessThan (aphw) ? apvw : aphw); } diff --git a/Code/FBSD/ConvexHull/convexhull.h b/Code/FBSD/ConvexHull/convexhull.h index c3fdff6..731bfff 100755 --- a/Code/FBSD/ConvexHull/convexhull.h +++ b/Code/FBSD/ConvexHull/convexhull.h @@ -70,10 +70,11 @@ public: */ void antipodalEdgeAndVertex (Pt2i &s, Pt2i &e, Pt2i &v) const; - /** - * Returns the minimal vertical or horizontal thickness of the convex hull. + /** Returns the convex hull strict thickness. + * Strict thickness is defined as the minimal value of both antipodal pairs. + * It is also the minimal vertical or horizontal width of the convex hull. */ - AbsRat rationalThickness () const; + AbsRat strictThickness () const; /** * Returns a string that represents the convex hull. diff --git a/Code/FBSD/main.cpp b/Code/FBSD/main.cpp index 94bad17..cb7c041 100755 --- a/Code/FBSD/main.cpp +++ b/Code/FBSD/main.cpp @@ -141,7 +141,7 @@ int main (int argc, char *argv[]) << (x2.numerator () / (double) x2.denominator ()) << " " << (height - 1 - y2.numerator () / (double) y2.denominator ()) << " " - << (th.numerator () / (double) th.denominator ()) << endl; + << sqrt (th.numerator () / (double) th.denominator ()) << endl; } } it ++; @@ -151,8 +151,11 @@ int main (int argc, char *argv[]) } else if (yt) { + int repetitions = 100; QImage im; - im.load ("Data/york.jpg"); + im.load ("test.jpg"); + cout << "Time measure for " << repetitions + << " FBSD lines extractions" << endl; int width = im.width (); int height = im.height (); int **tabImage = new int*[height]; @@ -168,7 +171,7 @@ int main (int argc, char *argv[]) BSDetector detector; clock_t start = clock (); VMap *gMap = NULL; - for (int i = 0; i < 100; i++) + for (int i = 0; i < repetitions; i++) { if (gMap != NULL) delete gMap; gMap = new VMap (width, height, tabImage, VMap::TYPE_SOBEL_5X5); @@ -177,7 +180,7 @@ int main (int argc, char *argv[]) detector.detectAll (); } double diff = (clock () - start) / (double) CLOCKS_PER_SEC; - ofstream outf ("Data/fbsdperf.txt", ios::out); + ofstream outf ("fbsdperf.txt", ios::out); outf << diff << endl; outf.close (); return (EXIT_SUCCESS); diff --git a/Methode/methode.tex b/Methode/methode.tex index ae1b299..41c43c3 100755 --- a/Methode/methode.tex +++ b/Methode/methode.tex @@ -47,6 +47,7 @@ \subsection*{Suivi pr\'eliminaire} \begin{itemize} +\item Param\'etrage par d\'efaut : {\bf d\'esactiv\'e} \item Entr\'ees : \begin{itemize} @@ -91,18 +92,20 @@ dernier pixel ins\'er\'e (initialement 4 pixels, actuellement remont\'e \begin{itemize} \item Balayage directionnel statique pour cr\'eer et \'etendre un segment flou \`a partir du gradient maximal trouv\'e dans la barre. -\item Consigne d'\'epaisseur : si la modalit\'e {\tt scanFitting} est +\item Consigne d'\'epaisseur : si la modalit\'e {\tt fittingOn} est active, elle est cal\'ee sur l'\'epaisseur du segment d\'etect\'e \`a l'\'etape pr\'ec\'edente. Sinon, par d\'efaut 8 pixels, ajustable. -\item Centrage : si la modalit\'e {\tt scanRecentering} est active, le +Cette modalit\'e est {\bf d\'esactiv\'ee} par d\'efaut. +\item Centrage : si la modalit\'e {\tt recenteringOn} est active, le balayage est centr\'e sur le segment d\'etect\'e \`a l'\'etape pr\'ec\'edente. Sinon, il est centr\'e sur la barre utilisateur ($P_1P_2$). -\item La phase d'extension comporte un test de voisinage par rapport au -dernier pixel ins\'er\'e (initialement 4 pixels, actuellement remont\'e -\`a 10 pixels). Ce test est par d\'efaut d\'esactiv\'e. +Cette modalit\'e est {\bf activ\'ee} par d\'efaut. +\item La phase d'extension comporte un test de voisinage ({\tt proxTestOff}) +par rapport au dernier pixel ins\'er\'e (initialement 4 pixels, actuellement +remont\'e \`a 10 pixels). Par d\'efaut, ce test est {\bf d\'esactiv\'e}. \item Aucun test angulaire. -\item Tol\'erance aux interruptions : 5 pixels. -\item Seuil de gradient : 30. +\item Tol\'erance aux interruptions : {\bf 5 pixels}. +\item Seuil de gradient : {\bf 20}. \end{itemize} \end{itemize} @@ -114,20 +117,20 @@ dernier pixel ins\'er\'e (initialement 4 pixels, actuellement remont\'e \item Toujours activ\'e \item V\'erifie que le nombre de points du SF est sup\'erieur \`a {\tt bsMinSize} -\item Valeur par d\'efaut : 3 (modifiable) +\item Valeur par d\'efaut : {\bf 5 points} (modifiable) \end{itemize} \item Test de densit\'e : +\begin{itemize} +\item Par d\'efaut {\bf activ\'e} (d\'esactivable) \item V\'erifie que le nombre de points du SF est au moins 2 fois l'\'etendue du segments ($\#BS > (1 + d (P_{left}P_{right})) / 2$) -\begin{itemize} -\item Activ\'e par d\'efaut (d\'esactivable) \end{itemize} \end{enumerate} \subsection*{Pr\'e-filtrage} \begin{itemize} -\item Etat par d\'efaut : activ\'e. +\item Etat par d\'efaut : {\bf d\'esactiv\'e}. \item Fonctionnement : \begin{itemize} \item Utilisation d'une transform\'ee de Hough pour \'eliminer les points @@ -140,10 +143,11 @@ isol\'es \`a l'\'ecart du segment. \begin{enumerate} \item Test de longueur : \begin{itemize} -\item Toujours activ\'e +\item Si le pr\'e-filtrage est activ\'e, toujours activ\'e. +Sinon d\'esactiv\'e car redondant. \item V\'erifie que le nombre de points du SF est sup\'erieur \`a {\tt bsMinSize} -\item Valeur par d\'efaut : 3 (modifiable) +\item Valeur par d\'efaut : 5 points (modifiable) \end{itemize} \item Test d'orientation V\'erifie que l'orientation du segment n'est pas trop proche de @@ -170,8 +174,8 @@ celle de la barre de balayage $P_1P_2$ ($angle (BS,P_1P_2) > 30^o$). \end{itemize} \item Modalit\'es par d\'efaut : \begin{itemize} -\item alignement activ\'e (d\'esactivable). -\item asservissement de l'\'epaisseur d\'esactiv\'e (activable). +\item alignement {\bf activ\'e} (d\'esactivable). +\item asservissement de l'\'epaisseur {\bf d\'esactiv\'e} (activable). \end{itemize} \item Fonctionnement : \begin{itemize} @@ -229,65 +233,57 @@ un segment flou \`a partir des sommets de gradients, correctement orient\'es (tol\'erence d'environ 60$^o$), et class\'es par valeurs de gradient d\'ecroissantes, trouv\'es dans la barre. \item Aucun test de voisinage. -\item Tol\'erance aux interruptions : 5 pixels. -\item Seuil de gradient : 30. -\item Amincissement progressif (d\'esactiv\'e par d\'efaut) : +\item Tol\'erance aux interruptions : {\bf 5 pixels}. +\item Seuil de gradient : {\bf 20}. +\item Amincissement progressif ({\bf d\'esactiv\'e} par d\'efaut) : \`a partir de 20 balayages, la consigne d'\'epaisseur est r\'eduite de 2\% \`a chaque balayage jusqu'\`a atteindre une valeur minimale de 150\% de l'\'epaisseur du segment flou construit. -\item Contr\^ole de la consigne d'\'epaisseur (activ\'e par d\'efaut) : -au bout de $N$ ($N=20$ par d\'efaut) ajouts de points sans influence sur la -largeur minimale du segment flou, la consigne d'\'epaisseur est fix\'ee -\`a la largeur minimale, de sorte que le segment ne peut plus s'\'epaissir. +\item Contr\^ole de la consigne d'\'epaisseur ({\bf activ\'e} par d\'efaut) : +au bout de N ajouts de points sans influence sur la largeur minimale du +segment flou, la consigne d'\'epaisseur est fix\'ee \`a la largeur minimale, +de sorte que le segment ne peut plus s'\'epaissir. +Par d\'efaut, N est fix\'e \`a {\bf 20 points}. \end{itemize} \end{itemize} \subsection*{Tests de sortie} \begin{enumerate} -\item Test de longueur : +\item Test de longueur ({\tt finalSpreadTestOn}) : \begin{itemize} -\item Toujours activ\'e +\item Par d\'efaut {\bf activ\'e} (d\'esactivable) \item V\'erifie que le nombre de points du SF est sup\'erieur \`a {\tt bsMinSize} -\item Valeur par d\'efaut : 3 (modifiable) +\item Valeur par d\'efaut : {\bf 12 points} (modifiable) \end{itemize} -\item Test de densit\'e : +\item Test d'\'elongation ({\tt finalLengthTestOn}) : +\begin{itemize} \item V\'erifie que le nombre de points est sup\'erieur \`a 3 fois l'\'epaisseur arithm\'etique du segment. -\begin{itemize} -\item D\'esactiv\'e par d\'efaut (activable) +\item Par d\'efaut {\bf d\'esactiv\'e} (activable) \end{itemize} -\item Test de nettet\'e des petits segments : +\item Test de densit\'e ({\tt finalDensityTestOn}) : +\begin{itemize} \item V\'erifie que l'\'etendue du segment ($1 + d (P_{left}P_{right})$) est sup\'erieure \`a 20 pixels ou bien que le nombre de points du segment est sup\'erieur \`a 4/5 fois l'\'etendue (on accepte les petits segments s'ils sont bien remplis). -\begin{itemize} -\item D\'esactiv\'e par d\'efaut (activable) +\item Par d\'efaut {\bf d\'esactiv\'e} (activable) \end{itemize} -\item Test de remplissage : +\item Test de remplissage ({\tt ccOn}) : +\begin{itemize} \item V\'erifie qu'au moins la moiti\'e des points appartiennent \`a une courbe connexe d'au moins {\tt ccMinSize} pixels. -\begin{itemize} -\item D\'esactiv\'e par d\'efaut (activable) -\item Valeur par d\'efaut de {\tt ccMinSize} : 5 (modifiable) +\item Par d\'efaut {\bf d\'esactiv\'e} (activable) +\item Valeur par d\'efaut de {\tt ccMinSize} : 5 pixels (modifiable) \end{itemize} \end{enumerate} -\begin{itemize} -\item Etat par d\'efaut : activ\'e. -\item Fonctionnement : -\begin{itemize} -\item V\'erifie qu'au moins la moiti\'e des pixels du segment flou forment -des composantes 8-connexes de taille sup\'erieure \`a 5 pixels. -\end{itemize} -\end{itemize} - \subsection*{Filtrage} \begin{itemize} -\item Etat par d\'efaut : d\'esactiv\'e. +\item Etat par d\'efaut : {\bf d\'esactiv\'e}. \item Fonctionnement : \begin{itemize} \item Utilisation d'une transform\'ee de Hough pour \'eliminer les points -- GitLab