Visual Servoing Platform version 3.5.0
testLineFitting.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Test line fitting.
33 *
34 *****************************************************************************/
35
41#include <visp3/core/vpConfig.h>
42
43#ifdef VISP_HAVE_CATCH2
44
45#include <visp3/core/vpMath.h>
46#include <visp3/core/vpGaussRand.h>
47
48#define CATCH_CONFIG_RUNNER
49#include <catch.hpp>
50
51namespace {
52void convertLineEquation(double A, double B, double C, double& a, double& b)
53{
54 a = -A/B;
55 b = C/B;
56}
57}
58
59TEST_CASE("Line fitting - Horizontal", "[line_fitting]") {
60 std::cout << "\nLine fitting - Horizontal" << std::endl;
61 double a = 0, b = 10;
62 std::vector<vpImagePoint> imPts;
63 for (int i = 0; i < 3; i++) {
64 double x = i*10;
65 imPts.push_back(vpImagePoint(a*x + b, x));
66 std::cout << "imPts: (" << imPts.back().get_u() << ", " << imPts.back().get_v() << ")" << std::endl;
67 }
68
69 double A = 0, B = 0, C = 0;
70 double error = vpMath::lineFitting(imPts, A, B, C);
71 std::cout << "error: " << error << std::endl;
72 std::cout << "a: " << a << " ; b: " << b << std::endl;
73 std::cout << "A: " << A << " ; B: " << B << " ; C: " << C << std::endl;
74 double a_est = 0, b_est = 0;
75 convertLineEquation(A, B, C, a_est, b_est);
76 std::cout << "-A/B: " << a_est << " ; -C/B: " << b_est << std::endl;
77
78 CHECK(a == Approx(a_est).margin(1e-6));
79 CHECK(b == Approx(b_est).epsilon(1e-6));
80}
81
82TEST_CASE("Line fitting", "[line_fitting]") {
83 std::cout << "\nLine fitting" << std::endl;
84 double a = -4.68, b = 21.456;
85 std::vector<vpImagePoint> imPts;
86 const int nbPoints = 10;
87 for (int i = 0; i < nbPoints; i++) {
88 double x = i*10;
89 double y = a*x + b;
90 imPts.push_back(vpImagePoint(y, x));
91 std::cout << "imPts: (" << imPts.back().get_u() << ", " << imPts.back().get_v() << ")" << std::endl;
92 }
93
94 double A = 0, B = 0, C = 0;
95 double error = vpMath::lineFitting(imPts, A, B, C);
96 std::cout << "error: " << error << std::endl;
97 std::cout << "a: " << a << " ; b: " << b << std::endl;
98 std::cout << "A: " << A << " ; B: " << B << " ; C: " << C << std::endl;
99 double a_est = 0, b_est = 0;
100 convertLineEquation(A, B, C, a_est, b_est);
101 std::cout << "-A/B: " << a_est << " ; -C/B: " << b_est << std::endl;
102
103 CHECK(a == Approx(a_est).epsilon(1e-6));
104 CHECK(b == Approx(b_est).epsilon(1e-6));
105}
106
107TEST_CASE("Line fitting - Gaussian noise", "[line_fitting]") {
108 std::cout << "\nLine fitting - Gaussian noise" << std::endl;
109 const double sigma = 3, mean = 0;
110 vpGaussRand gauss(sigma, mean);
111
112 double a = -4.68, b = 21.456;
113 std::vector<vpImagePoint> imPts;
114 const int nbPoints = 10;
115 for (int i = 0; i < nbPoints; i++) {
116 double x = i*10;
117 double y = a*x + b;
118 imPts.push_back(vpImagePoint(y + gauss(), x + gauss()));
119 std::cout << "x: " << x << " ; y: " << y
120 << " ; imPts: (" << imPts.back().get_u() << ", " << imPts.back().get_v() << ")" << std::endl;
121 }
122
123 double A = 0, B = 0, C = 0;
124 double error = vpMath::lineFitting(imPts, A, B, C);
125 std::cout << "error: " << error << std::endl;
126 std::cout << "a: " << a << " ; b: " << b << std::endl;
127 std::cout << "A: " << A << " ; B: " << B << " ; C: " << C << std::endl;
128 double a_est = 0, b_est = 0;
129 convertLineEquation(A, B, C, a_est, b_est);
130 std::cout << "-A/B: " << a_est << " ; -C/B: " << b_est << std::endl;
131
132 REQUIRE(error < sigma);
133}
134
135int main(int argc, char *argv[])
136{
137 Catch::Session session; // There must be exactly one instance
138
139 // Let Catch (using Clara) parse the command line
140 session.applyCommandLine(argc, argv);
141
142 int numFailed = session.run();
143
144 // numFailed is clamped to 255 as some unices only use the lower 8 bits.
145 // This clamping has already been applied, so just return it here
146 // You can also do any post run clean-up here
147 return numFailed;
148}
149#else
150#include <iostream>
151
152int main()
153{
154 return 0;
155}
156#endif
Class for generating random number with normal probability density.
Definition: vpGaussRand.h:121
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static double lineFitting(const std::vector< vpImagePoint > &imPts, double &a, double &b, double &c)
Definition: vpMath.cpp:328