diff --git a/Article/Fig_hard/hardNew.png b/Article/Fig_hard/hardNew.png new file mode 100644 index 0000000000000000000000000000000000000000..e8336570e65f61df6d220a094a4adf6a4ee2c4b3 Binary files /dev/null and b/Article/Fig_hard/hardNew.png differ diff --git a/Article/Fig_hard/hardOld.png b/Article/Fig_hard/hardOld.png new file mode 100644 index 0000000000000000000000000000000000000000..bf99614b7b36f914ffaa3d6f880ccef22f38c639 Binary files /dev/null and b/Article/Fig_hard/hardOld.png differ diff --git a/Article/Fig_method/algoAuto.tex b/Article/Fig_method/algoAuto.tex index 8c25e21d3db37a694261074c90182bb4d766e1fc..1931812a0f2ff6e6356e89c5d74bd49377e5cdbd 100644 --- a/Article/Fig_method/algoAuto.tex +++ b/Article/Fig_method/algoAuto.tex @@ -19,7 +19,7 @@ \SetKwData{Begin}{Start} \SetKwData{End}{End} - \Input{Image \image, width \iwidth, height \iheight, resolution \resol} + \Input{Image \image, width \iwidth, height \iheight, sweeping step \resol} \Output{\textit{\bslist} $\rightarrow$ list of detected blurred segments} \BlankLine \bslist $\leftarrow$ \nullset\; @@ -41,5 +41,5 @@ $y \leftarrow y~+$ \resol\; } - \caption{AutoDetect: finds all blurred segments in the image.} + \caption{AutoDetect: finds all the blurred segments in the image.} \end{algorithm} diff --git a/Article/Fig_method/algoMulti.tex b/Article/Fig_method/algoMulti.tex index 84f36d47a8ce307fe247c8de745a7fefb8a9c7b0..7f37ef95b3def955cd882577718b85a540f47682 100644 --- a/Article/Fig_method/algoMulti.tex +++ b/Article/Fig_method/algoMulti.tex @@ -17,14 +17,14 @@ \SetKwFunction{locmax}{ComputeAndSortGradientLocalMax} \SetKwFunction{sortgradmax}{SortByGradientMagnitude} + \SetKwFunction{updatemask}{UpdateOccupancyMask} \SetKwFunction{taille}{Size} \SetKwFunction{cardinal}{Card} \SetKwData{Begin}{Start} \SetKwData{End}{End} - \Input{Stroke points \pta, \ptb} - \Input{Occupancy mask \mask} + \Input{Stroke points \pta, \ptb, occupancy mask \mask} \Output{\textit{\bslist} $\rightarrow$ list of detected blurred segments} \BlankLine \bslist $\leftarrow$ \nullset\; @@ -32,11 +32,9 @@ \BlankLine \For{$i \leftarrow 0$ \KwTo \taille(\lm)}{ \bseg $\leftarrow$ detect (\lm[i], \ortho, \eps, \mask)\; - \For{$j \leftarrow 0$ \KwTo \cardinal (\bseg)}{ - \mask $\leftarrow$ \bseg[j]\; - } + \updatemask (\mask, \bseg)\; \bslist $\leftarrow$ \bseg\; } - \caption{MultiDetect: finds all blurred segments from input selection.} + \caption{MultiDetect: finds all the selected blurred segments.} \end{algorithm} diff --git a/Article/Fig_synth/stats.txt b/Article/Fig_synth/stats.txt new file mode 100644 index 0000000000000000000000000000000000000000..e4b72402bd803ccba9566408bddfbfe23e45b755 --- /dev/null +++ b/Article/Fig_synth/stats.txt @@ -0,0 +1,26 @@ + RESULTS FOR THE OLD DETECTOR +56.515 (pm 16.826) segments searches (local min) / image +21.223 (pm 5.31578) provided segments / image +10.898 (pm 1.88339) provided long segments / image +1.15 (pm 1.79798) undetected segments per image +96.8287 (pm 0.608812) % of points found +0.0154251 (pm 0.0252677) % of points found more than once (redetections) +6.92689 (pm 1.0261) % false points produced +Width difference : 2.08036 (0.266341) per matched segment +Absolute width difference : 2.10178 (0.264193) per matched segment +Angle difference : -0.00233791 (0.675674) degrees per matched segment +Absolute angle difference : 0.872721 (0.780913) per matched segment +Absolute long edge angle difference : 0.400459 (0.627538) per matched segment + RESULTS FOR THE NEW DETECTOR +61.405 (pm 15.4125) segments searches (local min) / image +27.334 (pm 6.37535) provided segments / image +9.03 (pm 2.15261) provided long segments / image +0.281 (pm 0.562455) undetected segments per image +96.8063 (pm 0.615733) % of points found +0.011969 (pm 0.0195106) % of points found more than once (redetections) +6.5253 (pm 0.94361) % false points produced +Width difference : 1.90539 (0.236267) per matched segment +Absolute width difference : 1.94935 (0.230798) per matched segment +Angle difference : 0.00697535 (0.724535) degrees per matched segment +Absolute angle difference : 0.916683 (0.754317) per matched segment +Long edge absolute angle difference : 0.336041 (0.595828) per matched segment diff --git a/Article/Fig_synth/statsExample.png b/Article/Fig_synth/statsExample.png new file mode 100644 index 0000000000000000000000000000000000000000..7695e11e6bd8b5bb0a6cfb74f1b9ef21519d553d Binary files /dev/null and b/Article/Fig_synth/statsExample.png differ diff --git a/Article/Fig_synth/statsTable.tex b/Article/Fig_synth/statsTable.tex new file mode 100644 index 0000000000000000000000000000000000000000..497b19cc03e451a4545ec11d14ac0b80d30406be --- /dev/null +++ b/Article/Fig_synth/statsTable.tex @@ -0,0 +1,20 @@ +\begin{tabular}{|l||rcl|rcl|} +\hline +Number of input segments per image +& 21.22 & $\pm$ & 5.32 & 27.33 & $\pm$ & 6.38 \\ +Number of long input segments per image +& 10.90 & $\pm$ & 1.88 & 9.03 & $\pm$ & 2.15 \\ +Number of undetected segments per image +& 1.15 & $\pm$ & 1.80 & 0.28 & $\pm$ & 0.56 \\ +Percentage of true segment area found +& 96.83 & $\pm$ & 0.61 & 96.81 & $\pm$ & 0.62 \\ +Percentage of false segment area found +& 6.9 & $\pm$ & 1.0 & 6.52 & $\pm$ & 0.94 \\ +Width difference (in pixels) to input segment +& 2.08 & $\pm$ & 0.27 & 1.91 & $\pm$ & 0.24 \\ +Angle difference (in degrees) to input segment +& 0.87 & $\pm$ & 0.78 & 0.92 & $\pm$ & 0.75 \\ +Long segment angle difference (in degrees) +& 0.40 & $\pm$ & 0.63 & 0.34 & $\pm$ & 0.60 \\ +\hline +\end{tabular} diff --git a/Article/Fig_synth/statsnewBounds.png b/Article/Fig_synth/statsnewBounds.png new file mode 100644 index 0000000000000000000000000000000000000000..d8afbc5714b69fd6b874b5df4bcc7da6d0a08c59 Binary files /dev/null and b/Article/Fig_synth/statsnewBounds.png differ diff --git a/Article/Fig_synth/statsnewPoints.png b/Article/Fig_synth/statsnewPoints.png new file mode 100644 index 0000000000000000000000000000000000000000..20f59fc72ec8e5107fbc8a0866075748b16e9ad0 Binary files /dev/null and b/Article/Fig_synth/statsnewPoints.png differ diff --git a/Article/Fig_synth/statsoldBounds.png b/Article/Fig_synth/statsoldBounds.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3264c50c98a47760467023c5baf5e9af22418e Binary files /dev/null and b/Article/Fig_synth/statsoldBounds.png differ diff --git a/Article/Fig_synth/statsoldPoints.png b/Article/Fig_synth/statsoldPoints.png new file mode 100644 index 0000000000000000000000000000000000000000..8ceb0081266380e6751c61ee4bf3464eff56e734 Binary files /dev/null and b/Article/Fig_synth/statsoldPoints.png differ diff --git a/Article/biblio.bib b/Article/biblio.bib index 62f91c07a0754c8d496f51f6f1b7d04288d68cb5..5df469aa1210f967deb6cc8e49bfba81cc421324 100755 --- a/Article/biblio.bib +++ b/Article/biblio.bib @@ -56,7 +56,7 @@ number = "6", pages = "1675--1684", year = "2007", - doi = "10.1016/j.patcog.2006.10.005" + optdoi = "10.1016/j.patcog.2006.10.005" } @@ -81,7 +81,7 @@ year = {2017}, number = {2}, pages = {35-54}, - doi = {10.1016/j.patcog.2006.10.005} + optdoi = {10.1016/j.patcog.2006.10.005} } @@ -124,7 +124,7 @@ optmonth = apr, year = {2010}, pages = {722--732}, - doi = {10.1109/TPAMI.2008.300} + optdoi = {10.1109/TPAMI.2008.300} } @@ -147,7 +147,7 @@ publisher = {IEEE}, year = {2015}, pages = {507--511}, - doi = {10.1109/ICIP.2015.7350850} + optdoi = {10.1109/ICIP.2015.7350850} } @@ -161,5 +161,5 @@ number = {01}, year = {2012}, pages = {1255002}, - doi = {10.1142/S0218001412550026} + optdoi = {10.1142/S0218001412550026} } diff --git a/Article/expe.tex b/Article/expe.tex index 03c226d75f8316109ed925312d10477a7315afaf..c6e3634e9668941ba2426951896da5643a1dd4d9 100755 --- a/Article/expe.tex +++ b/Article/expe.tex @@ -9,6 +9,10 @@ detection followed by two refinement steps) is integrated as an option into the code of the new detector, so that both methods rely on the same optimized basic routines. +\input{expeSynthese} + +\input{expeHard} + The first test compares the computation times of both detectors on a selection of input strokes (\RefFig{fig:buro}). Results are displayed in \RefTab{tab:cmpOldNew}. diff --git a/Article/expeHard.tex b/Article/expeHard.tex new file mode 100755 index 0000000000000000000000000000000000000000..953064d4e6fe6042f43549fe595356c010b568f3 --- /dev/null +++ b/Article/expeHard.tex @@ -0,0 +1,29 @@ + +The second test (\RefFig{fig:hard}) compares the performance of both +detectors on a quite difficult image with a lot of gradient noise. +The new detector provides less outliers and misaligned segments, and +globally more relevant informations to infere the structure of the brick wall. +\begin{figure}[h] +%\center + \begin{tabular}{ + c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}} + \includegraphics[width=0.32\textwidth]{Fig_method/parpaings.png} & + \includegraphics[width=0.32\textwidth]{Fig_hard/hardOld.png} & + \includegraphics[width=0.32\textwidth]{Fig_hard/hardNew.png} + \begin{picture}(1,1) + {\color{dwhite}{ + \put(-286,4.5){\circle*{8}} + \put(-171,4.5){\circle*{8}} + \put(-58,4.5){\circle*{8}} + }} + \put(-288.5,2){a} + \put(-173.5,2){b} + \put(-60.5,2){c} + \end{picture} + \end{tabular} + \caption{Evaluation on a quite textured image: + 1) imput image, + 2) results of the old detector, + 3) results of the new detector.} + \label{fig:hard} +\end{figure} diff --git a/Article/expeSynthese.tex b/Article/expeSynthese.tex new file mode 100755 index 0000000000000000000000000000000000000000..358904731a68bf481744151fbc490dbaafa5466d --- /dev/null +++ b/Article/expeSynthese.tex @@ -0,0 +1,41 @@ + +The first test (\RefFig{fig:synth}) compares the performance of both +detectors on a set of 1000 synthesized images containing 10 randomly +placed straight segments with random width between 1 and 4 pixels. +Altough this perfect world context with low gradient noise tends to soften +the old detector weaknesses, the results of \RefTab{tab:synth} show slightly +better measurements of width and angle on long segments for the new detector. +The new detector generates more small segments that degrade the angle +estimations, but it produces a smaller amount of false detections and +succeeds in finding most of the segments. +\begin{figure}[h] +%\center + \begin{tabular}{ + c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c} + \includegraphics[width=0.19\textwidth]{Fig_synth/statsExample.png} & + \includegraphics[width=0.19\textwidth]{Fig_synth/statsoldPoints.png} & + \includegraphics[width=0.19\textwidth]{Fig_synth/statsoldBounds.png} & + \includegraphics[width=0.19\textwidth]{Fig_synth/statsnewPoints.png} & + \includegraphics[width=0.19\textwidth]{Fig_synth/statsnewBounds.png} + \begin{picture}(1,1) + \put(-310,0){1)} + \put(-240,0){2)} + \put(-170,0){3)} + \put(-100,0){4)} + \put(-30,0){5)} + \end{picture} + \end{tabular} + \caption{Evaluation on synthesized images: + 1) one of the test images, + 2) output segments points from the old detector and + 3) their minimal digital straight segments, + 4) output segments points from the new detector and + 5) their minimal digital straight segments.} + \label{fig:synth} +\end{figure} +\begin{table} +\centering +\input{Fig_synth/statsTable} +\caption{Measured performance of both detectors on a set of synthesized images.} +\label{tab:synth} +\end{table} diff --git a/Article/method.tex b/Article/method.tex index b07121d78e5b0ceb7e287fb6bff654efd0e3473d..2371979aec470d17f682c4b8d15ac4393f64294c 100755 --- a/Article/method.tex +++ b/Article/method.tex @@ -257,6 +257,8 @@ In order to avoid multiple detections of the same edge, an occupancy mask, initially empty, collects the dilated points of all the blurred segments, so that these points can not be added to another segment. +\input{Fig_method/algoMulti} + First the positions $M_j$ of the prominent local maxima of the gradient 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: @@ -265,14 +267,13 @@ For each of them the main detection process is run with three modifications: $\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; -\item the occupancy mask is filled in with the points of the detected blurred -segments $\mathcal{B}_j''$ at the end of each successful detection; +\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 21 pixels bowl is used to get the segment dilation); \item points marked as occupied are rejected when selecting candidates for the blurred segment extension in the fine tracking step. \end{enumerate} -\input{Fig_method/algoMulti} - In edge selection mode (\RefFig{fig:edgeDir} b), the multi-detection algorithm is executed twice, first in main edge selection mode, then in opposite edge selection mode. @@ -334,41 +335,41 @@ is described in Algorithm 2. A stroke that crosses the whole image, is swept in both direction, 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. +In the present work, the stroke sweeping step $\delta$ is set to 10 pixels. \input{Fig_method/algoAuto} -\RefFig{fig:evalAuto}b gives an idea of the automatic detection performance. -In the example of \RefFig{fig:noisy}, hardly perceptible edges are detected -despite of a quite textured context. -Unsurpringly the length of the detected edges is linked to the initial -value of the assigned width, but a large value also augments the rate -of interfering outliers insertion. - -\begin{figure}[h] -\center - \begin{tabular}{c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c} - \includegraphics[width=0.32\textwidth]{Fig_method/parpaings.png} & - \includegraphics[width=0.32\textwidth]{Fig_method/parpaings2.png} & - \includegraphics[width=0.32\textwidth]{Fig_method/parpaings3.png} - \end{tabular} - \begin{picture}(1,1)(0,0) - {\color{dwhite}{ - \put(-286,-25.5){\circle*{8}} - \put(-171,-25.5){\circle*{8}} - \put(-58,-25.5){\circle*{8}} - }} - \put(-288.5,-28){a} - \put(-173.5,-28){b} - \put(-60.5,-28){c} - \end{picture} - \caption{Automatic detection of blurred segments on a textured image. - a) the input image, - b) automatic detection result with initial assigned width set - to 3 pixels, - c) automatic detection result with initial assigned width set - to 8 pixels.} - \label{fig:noisy} -\end{figure} +%\RefFig{fig:evalAuto}b gives an idea of the automatic detection performance. +%In the example of \RefFig{fig:noisy}, hardly perceptible edges are detected +%despite of a quite textured context. +%Unsurpringly the length of the detected edges is linked to the initial +%value of the assigned width, but a large value also augments the rate +%of interfering outliers insertion. +% +%\begin{figure}[h] +%\center \begin{tabular}{c@{\hspace{0.1cm}}c@{\hspace{0.1cm}}c} +% \includegraphics[width=0.32\textwidth]{Fig_method/parpaings.png} & +% \includegraphics[width=0.32\textwidth]{Fig_method/parpaings2.png} & +% \includegraphics[width=0.32\textwidth]{Fig_method/parpaings3.png} +% \end{tabular} +% \begin{picture}(1,1)(0,0) +% {\color{dwhite}{ +% \put(-286,-25.5){\circle*{8}} +% \put(-171,-25.5){\circle*{8}} +% \put(-58,-25.5){\circle*{8}} +% }} +% \put(-288.5,-28){a} +% \put(-173.5,-28){b} +% \put(-60.5,-28){c} +% \end{picture} +% \caption{Automatic detection of blurred segments on a textured image. +% a) the input image, +% b) automatic detection result with initial assigned width set +% to 3 pixels, +% c) automatic detection result with initial assigned width set +% to 8 pixels.} +% \label{fig:noisy} +%\end{figure} The automatic detection of blurred segments in a whole image is left available for testing in an online demonstration at the following address: \\ diff --git a/Code/Seg/BSTools/bsdetectionwidget.cpp b/Code/Seg/BSTools/bsdetectionwidget.cpp index 04ae746f654dd57f01e9b2b0d91aabc9cada9222..d8c432d08ab9c2ed416655fe4b1412ec865e6c1e 100755 --- a/Code/Seg/BSTools/bsdetectionwidget.cpp +++ b/Code/Seg/BSTools/bsdetectionwidget.cpp @@ -39,6 +39,7 @@ BSDetectionWidget::BSDetectionWidget (QWidget *parent) // Sets initial user outputs parameters alternate = 0; verbose = false; + stats = false; background = BACK_IMAGE; bsBoundsVisible = false; blevel = 0; @@ -335,10 +336,6 @@ void BSDetectionWidget::mouseReleaseEvent (QMouseEvent *event) cerr << "p2 defined: " << p2.x () << " " << p2.y () << endl; detector.resetMaxDetections (); extract (); - if (detector.isMultiSelection ()) - cout << detector.getBlurredSegments().size () - << " blurred segments detected on " - << detector.countOfTrials () << " essais " << endl; } } @@ -543,9 +540,6 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event) udef = false; detector.resetMaxDetections (); extract (); - cout << detector.getBlurredSegments().size () - << " blurred segments detected on " - << detector.countOfTrials () << " essais " << endl; } break; @@ -783,6 +777,11 @@ void BSDetectionWidget::keyPressEvent (QKeyEvent *event) displayDetectionResult (); break; + case Qt::Key_Asterisk : + switchStats (); + displayDetectionResult (); + break; + case Qt::Key_1 : switchPixelAnalyzer (); break; @@ -1030,6 +1029,7 @@ void BSDetectionWidget::displayDetectionResult () strucview->repaint (); } if (verbose) writeDetectionStatus (); + if (stats) writeStats (); } } @@ -1097,6 +1097,60 @@ void BSDetectionWidget::clearSavedSegments () } +void BSDetectionWidget::writeStats () +{ + vector<BlurredSegment *> bss = detector.getBlurredSegments (); + if (bss.empty ()) + { + BlurredSegment *bs = detector.getBlurredSegment (); + if (bs != NULL) + { + Pt2i ptb = bs->getLastRight (); + Pt2i ptf = bs->getLastLeft (); + double length = sqrt ((ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ())); + cout << "Length : " << length << endl; + DigitalStraightSegment *dss = bs->getSegment (); + if (dss != NULL) + { + double width = dss->width () / (double) (dss->period ()); + cout << "Width : " << width << endl; + } + else cout << "DSS null" << endl; + } + } + else + { + int nbdssnull = 0; + double ltotal = 0.; + double wtotal = 0.; + vector<BlurredSegment *>::iterator it = bss.begin (); + while (it != bss.end ()) + { + Pt2i ptb = (*it)->getLastRight (); + Pt2i ptf = (*it)->getLastLeft (); + double length = sqrt ((ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ())); + ltotal += length; + DigitalStraightSegment *dss = (*it)->getSegment (); + if (dss != NULL) + { + double width = dss->width () / (double) (dss->period ()); + wtotal += width * length; + } + else nbdssnull ++; + it ++; + } + + cout << bss.size () << " blurred segments detected on " + << detector.countOfTrials () << " trials " << endl; + cout << "Mean length : " << ltotal / bss.size () << endl; + cout << "Mean width (per unit length) : " << wtotal / ltotal << endl; + cout << nbdssnull << " DSS null" << endl; + } +} + + void BSDetectionWidget::writeDetectionStatus () { int res = detector.result (); @@ -1262,6 +1316,7 @@ QSize BSDetectionWidget::setRandomImage (int type) { width = 256; height = 256; + int longEdgeThreshold = 1600; loadedImage = QImage (width, height, QImage::Format_RGB32); srand (time (NULL)); udef = false; @@ -1282,6 +1337,10 @@ QSize BSDetectionWidget::setRandomImage (int type) int newTrials[nbruns]; int oldDetections[nbruns]; int newDetections[nbruns]; + int oldLongDetections[nbruns]; + int newLongDetections[nbruns]; + int oldNbNomatch[nbruns]; + int newNbNomatch[nbruns]; int oldUndet[nbruns]; int newUndet[nbruns]; int oldRedet[nbruns]; @@ -1292,10 +1351,14 @@ QSize BSDetectionWidget::setRandomImage (int type) double newNbMatched[nbruns]; double oldWidthDiff[nbruns]; double newWidthDiff[nbruns]; - double oldAbsDiff[nbruns]; - double newAbsDiff[nbruns]; + double oldAbsWDiff[nbruns]; + double newAbsWDiff[nbruns]; double oldAngDiff[nbruns]; double newAngDiff[nbruns]; + double oldAbsADiff[nbruns]; + double newAbsADiff[nbruns]; + double oldLongADiff[nbruns]; + double newLongADiff[nbruns]; for (int run = 0; run < nbruns; run ++) { @@ -1353,11 +1416,9 @@ QSize BSDetectionWidget::setRandomImage (int type) if (dispEach) cout << "Analyzing the old blurred segments" << endl; for (int i = 0; i < nbsegs; i++) rbs[i].clear (); - int nbnomatch = 0; - int nbokortho = 0; - int nbokcolin = 0; - int nbokmid = 0; + oldNbNomatch[run] = 0; int nbdssnul = 0; + oldLongDetections[run] = 0; double nomatchlength = 0.; vector<BlurredSegment *> bss = detector.getBlurredSegments (); vector<BlurredSegment *>::iterator bsit = bss.begin (); @@ -1388,34 +1449,30 @@ QSize BSDetectionWidget::setRandomImage (int type) Pt2i bsc ((ptb.x () + ptf.x ()) / 2, (ptb.y () + ptf.y ()) / 2); double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ()); - bool searching = true; - for (int si = 0; searching && si < nbsegs; si++) + if (bsl2 > longEdgeThreshold) oldLongDetections[run] ++; + double score[nbsegs]; + double minscore = 0.; + int bestfit = -1; + for (int si = 0; si < nbsegs; si++) { - if (rdir[si].squaredVectorProduct (dssdir) - < 0.1 * rdir[si].norm2 () * dssdir.norm2 ()) + double denom = rdir[si].norm2 () * dssdir.norm2 (); + score[si] = rdir[si].squaredScalarProduct (dssdir) / denom; + Vr2i bsac = rp1[si].vectorTo (bsc); + denom = rdir[si].norm2 () * bsac.norm2 (); + score[si] *= rdir[si].squaredScalarProduct (bsac) / denom; + if (rdir[si].scalarProduct (bsac) < 0) score[si] = 0.; + Vr2i bscb = bsc.vectorTo (rp2[si]); + if (rdir[si].scalarProduct (bscb) < 0) score[si] = 0.; + if (minscore < score[si]) { - nbokortho ++; - Vr2i bsac = rp1[si].vectorTo (bsc); - if (rdir[si].squaredVectorProduct (bsac) - < 0.1 * rdir[si].norm2 () * bsac.norm2 ()) - { - nbokcolin ++; - if (rdir[si].scalarProduct (bsac) > 0) - { - Vr2i bscb = bsc.vectorTo (rp2[si]); - if (rdir[si].scalarProduct (bscb) > 0) - { - nbokmid ++; - rbs[si].push_back (*bsit); - searching = false; - } - } - } + minscore = score[si]; + bestfit = si; } } - if (searching) + if (minscore > 0.7) rbs[bestfit].push_back (*bsit); + else { - nbnomatch ++; + oldNbNomatch[run] ++; nomatchlength += sqrt (bsl2); } } @@ -1427,8 +1484,12 @@ QSize BSDetectionWidget::setRandomImage (int type) oldTrials[run] = detector.countOfTrials (); oldDetections[run] = (int) (detector.getBlurredSegments().size ()); if (dispEach) + { cout << oldDetections[run] << " blurred segments detected on " << oldTrials[run] << " trials " << endl; + cout << oldLongDetections[run] << " long blurred segments detected on " + << oldTrials[run] << " trials " << endl; + } oldUndet[run] = 0; for (int i = 0; i < width * height; i++) if (virgin[i]) oldUndet[run] ++; if (dispEach) @@ -1451,17 +1512,17 @@ QSize BSDetectionWidget::setRandomImage (int type) cout << oldFalse[run] << " false points detected on " << nbIniPts[run] << " (" << oldFalse[run] * 100 / (double) nbIniPts[run] << " %)" << endl; - cout << nbnomatch << " unmatched blurred segment (mean length : " - << (nbnomatch != 0 ? nomatchlength / nbnomatch : 0) << ")" << endl; - cout << nbokortho << " test ortho OK" << endl; - cout << nbokcolin << " test colin OK" << endl; - cout << nbokmid << " test mid OK" << endl; + cout << oldNbNomatch[run] << " unmatched blurred segment (mean length : " + << (oldNbNomatch[run] != 0 ? nomatchlength / oldNbNomatch[run] : 0) + << ")" << endl; cout << nbdssnul << " DSS nuls" << endl; } oldWidthDiff[run] = 0.; - oldAbsDiff[run] = 0.; + oldAbsWDiff[run] = 0.; oldAngDiff[run] = 0.; + oldAbsADiff[run] = 0.; + oldLongADiff[run] = 0.; oldNbMatched[run] = 0; for (int si = 0; si < nbsegs; si ++) { @@ -1474,19 +1535,27 @@ QSize BSDetectionWidget::setRandomImage (int type) double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ()); DigitalStraightSegment *mydss = (*sit)->getSegment (); - double wd = (mydss->width () / (double) (mydss->period ())) - * sqrt (bsl2) / sqrt (rdir[si].norm2 ()) - rw[si]; + double wd = (mydss->width () / (double) (mydss->period ()) - rw[si]) + * sqrt (bsl2) / sqrt (rdir[si].norm2 ()); oldWidthDiff[run] += wd; if (wd < 0) wd = -wd; - oldAbsDiff[run] += wd; + oldAbsWDiff[run] += wd; Vr2i mydir = mydss->supportVector (); double ang = rdir[si].scalarProduct (mydir); - if (ang < 0.) ang = - ang; + bool onleft = rdir[si].leftside (mydir); + if (ang < 0.) + { + ang = - ang; + onleft = - onleft; + } double den = sqrt (rdir[si].norm2 ()) * sqrt (mydir.norm2 ()); if (den > ang) { ang = acos (ang / den) * 180 / M_PI; - oldAngDiff[run] += ang * sqrt (bsl2) / sqrt (rdir[si].norm2 ()); + ang *= sqrt (bsl2) / sqrt (rdir[si].norm2 ()); + oldAbsADiff[run] += ang; + oldAngDiff[run] += (onleft ? ang : -ang); + if (bsl2 > longEdgeThreshold) oldLongADiff[run] += ang; } sit ++; } @@ -1498,10 +1567,16 @@ QSize BSDetectionWidget::setRandomImage (int type) oldWidthDiff[run] / oldNbMatched[run] : 0) << endl; cout << "Absolute width difference = " << (oldNbMatched[run] != 0 ? - oldAbsDiff[run] / oldNbMatched[run] : 0) << endl; + oldAbsWDiff[run] / oldNbMatched[run] : 0) << endl; cout << "Angle difference = " << (oldNbMatched[run] != 0 ? oldAngDiff[run] / oldNbMatched[run] : 0) << endl; + cout << "Absolute angle difference = " + << (oldNbMatched[run] != 0 ? + oldAbsADiff[run] / oldNbMatched[run] : 0) << endl; + cout << "Long edge angle difference = " + << (oldNbMatched[run] != 0 ? + oldLongADiff[run] / oldNbMatched[run] : 0) << endl; } if (dispEach) cout << "Resetting the result maps" << endl; @@ -1517,12 +1592,9 @@ QSize BSDetectionWidget::setRandomImage (int type) if (dispEach) cout << "Analyzing the new blurred segments" << endl; for (int i = 0; i < nbsegs; i++) rbs[i].clear (); - nbnomatch = 0; - nomatchlength = 0.; - nbokortho = 0; - nbokcolin = 0; - nbokmid = 0; + newNbNomatch[run] = 0; nbdssnul = 0; + newLongDetections[run] = 0; nomatchlength = 0.; bss = detector.getBlurredSegments (); bsit = bss.begin (); @@ -1553,34 +1625,30 @@ QSize BSDetectionWidget::setRandomImage (int type) Pt2i bsc ((ptb.x () + ptf.x ()) / 2, (ptb.y () + ptf.y ()) / 2); double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ()); - bool searching = true; - for (int si = 0; searching && si < nbsegs; si++) + if (bsl2 > longEdgeThreshold) newLongDetections[run] ++; + double score[nbsegs]; + double minscore = 0.; + int bestfit = -1; + for (int si = 0; si < nbsegs; si++) { - if (rdir[si].squaredVectorProduct (dssdir) - < 0.1 * rdir[si].norm2 () * dssdir.norm2 ()) - { - nbokortho ++; - Vr2i bsac = rp1[si].vectorTo (bsc); - if (rdir[si].squaredVectorProduct (bsac) - < 0.1 * rdir[si].norm2 () * bsac.norm2 ()) - { - nbokcolin ++; - if (rdir[si].scalarProduct (bsac) > 0) - { - Vr2i bscb = bsc.vectorTo (rp2[si]); - if (rdir[si].scalarProduct (bscb) > 0) - { - nbokmid ++; - rbs[si].push_back (*bsit); - searching = false; - } - } - } + double denom = rdir[si].norm2 () * dssdir.norm2 (); + score[si] = rdir[si].squaredScalarProduct (dssdir) / denom; + Vr2i bsac = rp1[si].vectorTo (bsc); + denom = rdir[si].norm2 () * bsac.norm2 (); + score[si] *= rdir[si].squaredScalarProduct (bsac) / denom; + if (rdir[si].scalarProduct (bsac) < 0) score[si] = 0.; + Vr2i bscb = bsc.vectorTo (rp2[si]); + if (rdir[si].scalarProduct (bscb) < 0) score[si] = 0.; + if (minscore < score[si]) + { + minscore = score[si]; + bestfit = si; } } - if (searching) + if (minscore > 0.7) rbs[bestfit].push_back (*bsit); + else { - nbnomatch ++; + newNbNomatch[run] ++; nomatchlength += sqrt (bsl2); } } @@ -1592,8 +1660,12 @@ QSize BSDetectionWidget::setRandomImage (int type) newTrials[run] = detector.countOfTrials (); newDetections[run] = (int) (detector.getBlurredSegments().size ()); if (dispEach) + { cout << newDetections[run] << " blurred segments detected on " << newTrials[run] << " trials " << endl; + cout << newLongDetections[run] << " long blurred segments detected on " + << newTrials[run] << " trials " << endl; + } newUndet[run] = 0; for (int i = 0; i < width * height; i++) if (virgin[i]) newUndet[run] ++; if (dispEach) @@ -1616,17 +1688,17 @@ QSize BSDetectionWidget::setRandomImage (int type) cout << newFalse[run] << " false points detected on " << nbIniPts[run] << " (" << newFalse[run] * 100 / (double) nbIniPts[run] << " %)" << endl; - cout << nbnomatch << " unmatched blurred segment (mean length : " - << (nbnomatch != 0 ? nomatchlength / nbnomatch : 0) << ")" << endl; - cout << nbokortho << " test ortho OK" << endl; - cout << nbokcolin << " test colin OK" << endl; - cout << nbokmid << " test mid OK" << endl; + cout << newNbNomatch[run] << " unmatched blurred segment (mean length : " + << (newNbNomatch[run] != 0 ? nomatchlength / newNbNomatch[run] : 0) + << ")" << endl; cout << nbdssnul << " DSS nuls" << endl; } newWidthDiff[run] = 0.; - newAbsDiff[run] = 0.; + newAbsWDiff[run] = 0.; newAngDiff[run] = 0.; + newAbsADiff[run] = 0.; + newLongADiff[run] = 0.; newNbMatched[run] = 0; for (int si = 0; si < nbsegs; si ++) { @@ -1639,19 +1711,27 @@ QSize BSDetectionWidget::setRandomImage (int type) double bsl2 = (ptb.x () - ptf.x ()) * (ptb.x () - ptf.x ()) + (ptb.y () - ptf.y ()) * (ptb.y () - ptf.y ()); DigitalStraightSegment *mydss = (*sit)->getSegment (); - double wd = (mydss->width () / (double) (mydss->period ())) - * sqrt (bsl2) / sqrt (rdir[si].norm2 ()) - rw[si]; + double wd = (mydss->width () / (double) (mydss->period ()) - rw[si]) + * sqrt (bsl2) / sqrt (rdir[si].norm2 ()); newWidthDiff[run] += wd; if (wd < 0) wd = -wd; - newAbsDiff[run] += wd; + newAbsWDiff[run] += wd; Vr2i mydir = mydss->supportVector (); double ang = rdir[si].scalarProduct (mydir); - if (ang < 0.) ang = - ang; + bool onleft = rdir[si].leftside (mydir); + if (ang < 0.) + { + ang = - ang; + onleft = - onleft; + } double den = sqrt (rdir[si].norm2 ()) * sqrt (mydir.norm2 ()); if (den > ang) { ang = acos (ang / den) * 180 / M_PI; - newAngDiff[run] += ang * sqrt (bsl2) / sqrt (rdir[si].norm2 ()); + ang *= sqrt (bsl2) / sqrt (rdir[si].norm2 ()); + newAbsADiff[run] += ang; + newAngDiff[run] += (onleft ? ang : -ang); + if (bsl2 > longEdgeThreshold) newLongADiff[run] += ang; } sit ++; } @@ -1663,81 +1743,262 @@ QSize BSDetectionWidget::setRandomImage (int type) newWidthDiff[run] / newNbMatched[run] : 0) << endl; cout << "Absolute width difference = " << (newNbMatched[run] != 0 ? - newAbsDiff[run] / newNbMatched[run] : 0) << endl; + newAbsWDiff[run] / newNbMatched[run] : 0) << endl; cout << "Angle difference = " << (newNbMatched[run] != 0 ? newAngDiff[run] / newNbMatched[run] : 0) << endl; + cout << "Absolute angle difference = " + << (newNbMatched[run] != 0 ? + newAbsADiff[run] / newNbMatched[run] : 0) << endl; + cout << "Long edge angle difference = " + << (newNbMatched[run] != 0 ? + newLongADiff[run] / newNbMatched[run] : 0) << endl; } } + double mean, sdev, total; double total_nbIniPts = 0; for (int i = 0; i < nbruns; i++) total_nbIniPts += nbIniPts[i]; - cout << " BILAN OLD" << endl; - double total_oldTrials = 0.; - for (int i = 0; i < nbruns; i++) total_oldTrials += oldTrials[i]; - cout << total_oldTrials / nbruns << " trials" << endl; - double total_oldDetections = 0.; - for (int i = 0; i < nbruns; i++) total_oldDetections += oldDetections[i]; - cout << total_oldDetections / nbruns << " detections" << endl; - double total_oldOkdet = 0; + cout << " RESULTS FOR THE OLD DETECTOR" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldTrials[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (oldTrials[i] - mean) * (oldTrials[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") segments searches (local min) / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldDetections[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (oldDetections[i] - mean) * (oldDetections[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") provided segments / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldLongDetections[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (oldLongDetections[i] - mean) * (oldLongDetections[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") provided long segments / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldNbNomatch[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (oldNbNomatch[i] - mean) * (oldNbNomatch[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") undetected segments per image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += nbIniPts[i] - oldUndet[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += ((nbIniPts[i] - oldUndet[i]) / (double) nbIniPts[i] - mean) + * ((nbIniPts[i] - oldUndet[i]) / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % of points found" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldRedet[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += (oldRedet[i] / (double) nbIniPts[i] - mean) + * (oldRedet[i] / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % of points found more than once (redetections)" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldFalse[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += (oldFalse[i] / (double) nbIniPts[i] - mean) + * (oldFalse[i] / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % false points produced" << endl; + total = 0; + for (int i = 0; i < nbruns; i++) total += oldNbMatched[i]; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldWidthDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (oldWidthDiff[i] / (double) oldNbMatched[i] - mean) + * (oldWidthDiff[i] / (double) oldNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Width difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldAbsWDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (oldAbsWDiff[i] / (double) oldNbMatched[i] - mean) + * (oldAbsWDiff[i] / (double) oldNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Absolute width difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldAngDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (oldAngDiff[i] / (double) oldNbMatched[i] - mean) + * (oldAngDiff[i] / (double) oldNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Angle difference : " << mean << " (" << sdev + << ") degrees per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldAbsADiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (oldAbsADiff[i] / (double) oldNbMatched[i] - mean) + * (oldAbsADiff[i] / (double) oldNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Absolute angle difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += oldLongADiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (oldLongADiff[i] / (double) oldNbMatched[i] - mean) + * (oldLongADiff[i] / (double) oldNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Absolute long edge angle difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + + cout << " RESULTS FOR THE NEW DETECTOR" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newTrials[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (newTrials[i] - mean) * (newTrials[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") segments searches (local min) / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newDetections[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (newDetections[i] - mean) * (newDetections[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") provided segments / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newLongDetections[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (newLongDetections[i] - mean) * (newLongDetections[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") provided long segments / image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newNbNomatch[i]; + mean /= nbruns; + for (int i = 0; i < nbruns; i++) + sdev += (newNbNomatch[i] - mean) * (newNbNomatch[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << mean << " (pm " << sdev + << ") undetected segments per image" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += nbIniPts[i] - newUndet[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += ((nbIniPts[i] - newUndet[i]) / (double) nbIniPts[i] - mean) + * ((nbIniPts[i] - newUndet[i]) / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % of points found" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newRedet[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += (newRedet[i] / (double) nbIniPts[i]- mean) + * (newRedet[i] / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % of points found more than once (redetections)" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newFalse[i]; + mean /= total_nbIniPts; + for (int i = 0; i < nbruns; i++) + sdev += (newFalse[i] / (double) nbIniPts[i] - mean) + * (newFalse[i] / (double) nbIniPts[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << 100 * mean << " (pm " << 100 * sdev + << ") % false points produced" << endl; + total = 0; + for (int i = 0; i < nbruns; i++) total += newNbMatched[i]; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newWidthDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (newWidthDiff[i] / (double) newNbMatched[i] - mean) + * (newWidthDiff[i] / (double) newNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Width difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newAbsWDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (newAbsWDiff[i] / (double) newNbMatched[i] - mean) + * (newAbsWDiff[i] / (double) newNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Absolute width difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newAngDiff[i]; + mean /= total; + for (int i = 0; i < nbruns; i++) + sdev += (newAngDiff[i] / (double) newNbMatched[i] - mean) + * (newAngDiff[i] / (double) newNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Angle difference : " << mean << " (" << sdev + << ") degrees per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newAbsADiff[i]; + mean /= total; for (int i = 0; i < nbruns; i++) - total_oldOkdet += nbIniPts[i] - oldUndet[i]; - cout << 100 * total_oldOkdet / total_nbIniPts << " % success" << endl; - double total_oldRedet = 0; - for (int i = 0; i < nbruns; i++) total_oldRedet += oldRedet[i]; - cout << 100 * total_oldRedet / total_nbIniPts << " % coverture" << endl; - double total_oldFalse = 0; - for (int i = 0; i < nbruns; i++) total_oldFalse += oldFalse[i]; - cout << 100 * total_oldFalse / total_nbIniPts - << " % false detections" << endl; - int total_nbmatched = 0; - for (int i = 0; i < nbruns; i++) total_nbmatched += oldNbMatched[i]; - double total_widthdiff = 0; - for (int i = 0; i < nbruns; i++) total_widthdiff += oldWidthDiff[i]; - cout << "Width difference : " << total_widthdiff / total_nbmatched - << " per matched segment" << endl; - double total_absdiff = 0; - for (int i = 0; i < nbruns; i++) total_absdiff += oldAbsDiff[i]; - cout << "Absolute width difference : " << total_absdiff / total_nbmatched - << " per matched segment" << endl; - double total_angdiff = 0; - for (int i = 0; i < nbruns; i++) total_angdiff += oldAngDiff[i]; - cout << "Angle difference : " << total_angdiff / total_nbmatched - << " degrees per matched segment" << endl; - - cout << " BILAN NEW" << endl; - double total_newTrials = 0.; - for (int i = 0; i < nbruns; i++) total_newTrials += newTrials[i]; - cout << total_newTrials / nbruns << " trials" << endl; - double total_newDetections = 0; - for (int i = 0; i < nbruns; i++) total_newDetections += newDetections[i]; - cout << total_newDetections / nbruns << " detections" << endl; - double total_newOkdet = 0; + sdev += (newAbsADiff[i] / (double) newNbMatched[i] - mean) + * (newAbsADiff[i] / (double) newNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Absolute angle difference : " << mean << " (" << sdev + << ") per matched segment" << endl; + mean = 0.; + sdev = 0.; + for (int i = 0; i < nbruns; i++) mean += newLongADiff[i]; + mean /= total; for (int i = 0; i < nbruns; i++) - total_newOkdet += nbIniPts[i] - newUndet[i]; - cout << 100 * total_newOkdet / total_nbIniPts << " % success" << endl; - double total_newRedet = 0; - for (int i = 0; i < nbruns; i++) total_newRedet += newRedet[i]; - cout << 100 * total_newRedet / total_nbIniPts << " % coverture" << endl; - double total_newFalse = 0; - for (int i = 0; i < nbruns; i++) total_newFalse += newFalse[i]; - cout << 100 * total_newFalse / total_nbIniPts - << " % false detections" << endl; - total_nbmatched = 0; - for (int i = 0; i < nbruns; i++) total_nbmatched += newNbMatched[i]; - total_widthdiff = 0; - for (int i = 0; i < nbruns; i++) total_widthdiff += newWidthDiff[i]; - cout << "Width difference : " << total_widthdiff / total_nbmatched - << " per matched segment" << endl; - total_absdiff = 0; - for (int i = 0; i < nbruns; i++) total_absdiff += newAbsDiff[i]; - cout << "Absolute width difference : " << total_absdiff / total_nbmatched - << " per matched segment" << endl; - total_angdiff = 0; - for (int i = 0; i < nbruns; i++) total_angdiff += newAngDiff[i]; - cout << "Angle difference : " << total_angdiff / total_nbmatched - << " degrees per matched segment" << endl; + sdev += (newLongADiff[i] / (double) newNbMatched[i] - mean) + * (newLongADiff[i] / (double) newNbMatched[i] - mean); + sdev = sqrt (sdev / (nbruns - 1)); + cout << "Long edge absolute angle difference : " << mean << " (" << sdev + << ") per matched segment" << endl; cout << "Updating the displays" << endl; augmentedImage = loadedImage; diff --git a/Code/Seg/BSTools/bsdetectionwidget.h b/Code/Seg/BSTools/bsdetectionwidget.h index 5deb3759cb1475a4c03f6fea6013feafabae43e4..5aced00deb713a2c3e7e6273532a0d20acf89f84 100755 --- a/Code/Seg/BSTools/bsdetectionwidget.h +++ b/Code/Seg/BSTools/bsdetectionwidget.h @@ -128,6 +128,11 @@ public: */ void switchHighlightColors (); + /** + * \brief Switches the extraction stats display on or off. + */ + inline void switchStats () { stats = ! stats; } + /** * \brief Switches the extraction result display on or off. */ @@ -241,6 +246,8 @@ private: int background; /** Black level used to lighten background images. */ int blevel; + /** Flag indicating whether detection stats should be output. */ + bool stats; /** Flag indicating whether detection result should be output. */ bool verbose; @@ -348,6 +355,11 @@ private: */ void displayBackground (); + /** + * \brief Writes the stats of the last detection in a file. + */ + void writeStats (); + /** * \brief Writes the result of the last detection in a file. */ diff --git a/Code/Seg/BlurredSegment/blurredsegmentproto.cpp b/Code/Seg/BlurredSegment/blurredsegmentproto.cpp index 8f48d13a39d92aec6fc7e38783d0ff708c32f1c8..957e06c60d4ab86bd4082c159826a2f4309d6496 100755 --- a/Code/Seg/BlurredSegment/blurredsegmentproto.cpp +++ b/Code/Seg/BlurredSegment/blurredsegmentproto.cpp @@ -271,6 +271,7 @@ BlurredSegment *BlurredSegmentProto::endOfBirth () DigitalStraightLine::DSL_THIN, xmin, ymin, xmax, ymax); } + else return (NULL); Pt2i aps (-1, -1), ape (-1, -1), apv (-1, -1); if (convexhull != NULL) convexhull->antipodalEdgeAndVertex (aps, ape, apv); diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp index a3cad70c82ed2d953a3863d2394b720510a375f0..7bb550e9b7b05568f0036c2aa912194b3dd0c703 100755 --- a/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp +++ b/Code/Seg/DirectionalScanner/dynamicalscannero1.cpp @@ -240,6 +240,12 @@ void DynamicalScannerO1::bindTo (int a, int b, int c) nu = (templ_nu * new_n1) / old_n1; else nu = (templ_nu * new_ninf) / old_ninf; + if (dlb < 0) // dlb should stay positive to avoid the direction change + { // of the support line inequations. + dla = -dla; + dlb = -dlb; + c = -c; + } dlc1 = c + nu / 2; dlc2 = c - nu / 2; } diff --git a/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp b/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp index ae42796b1c7427341166944879e130001fcc5a50..b33e4a55b1e0c2061740802ba22f9b7ac893c72f 100755 --- a/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp +++ b/Code/Seg/DirectionalScanner/dynamicalscannero8.cpp @@ -241,6 +241,12 @@ void DynamicalScannerO8::bindTo (int a, int b, int c) nu = (templ_nu * new_n1) / old_n1; else nu = (templ_nu * new_ninf) / old_ninf; + if (dlb < 0) // dlb should stay positive to avoid the direction change + { // of the support line inequations. + dla = -dla; + dlb = -dlb; + c = -c; + } dlc1 = c - nu / 2; dlc2 = c + nu / 2; } diff --git a/Code/Seg/ImageTools/vr2i.h b/Code/Seg/ImageTools/vr2i.h index 5fc99ef15dda3db918812269775ab66e0b2bc33c..a34800934a00f1bfbaac84b63ed10582c0860798 100755 --- a/Code/Seg/ImageTools/vr2i.h +++ b/Code/Seg/ImageTools/vr2i.h @@ -87,6 +87,14 @@ public: return ((xv * vec.xv + yv * vec.yv) * (xv * vec.xv + yv * vec.yv)); } + /** + * @fn bool leftside (Vr2i vec) + * \brief Returns if the given vector is on the left side of the vector. + * @param vec The given vector. + */ + inline bool leftside (Vr2i vec) const { + return (xv * vec.yv > yv * vec.xv); } + /** * @fn int squaredVectorProduct (Vr2i vec) * \brief Returns the squared norm of the vector product with given vector.