Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
testMatrixConvolution.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Test matrix convolution.
32  */
33 
39 #include <visp3/core/vpMatrix.h>
40 #include <visp3/core/vpTime.h>
41 
42 #ifdef ENABLE_VISP_NAMESPACE
43 using namespace VISP_NAMESPACE_NAME;
44 #endif
45 
46 namespace
47 {
48 bool compareMatrix(const vpMatrix &m, const double *const array)
49 {
50  for (unsigned int i = 0; i < m.getRows(); i++) {
51  for (unsigned int j = 0; j < m.getCols(); j++) {
52  if (!vpMath::equal(m[i][j], array[i * m.getCols() + j], std::numeric_limits<double>::epsilon()))
53  return false;
54  }
55  }
56 
57  return true;
58 }
59 } // namespace
60 
61 int main()
62 {
63  try {
64  {
65  vpMatrix A(4, 4);
66  A[0][0] = 16;
67  A[0][1] = 2;
68  A[0][2] = 3;
69  A[0][3] = 13;
70  A[1][0] = 5;
71  A[1][1] = 11;
72  A[1][2] = 10;
73  A[1][3] = 8;
74  A[2][0] = 9;
75  A[2][1] = 7;
76  A[2][2] = 6;
77  A[2][3] = 12;
78  A[3][0] = 4;
79  A[3][1] = 14;
80  A[3][2] = 15;
81  A[3][3] = 1;
82 
83  vpMatrix B(2, 2);
84  B[0][0] = 1;
85  B[0][1] = 3;
86  B[1][0] = 4;
87  B[1][1] = 2;
88 
89  {
90  vpMatrix res = vpMatrix::conv2(A, B, "full");
91  double ground_truth[5 * 5] = { 16, 50, 9, 22, 39, 69, 66, 59, 96, 50, 29, 88, 89,
92  82, 52, 40, 72, 95, 106, 27, 16, 64, 88, 34, 2 };
93 
94  std::cout << "A:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, full):\n" << res << std::endl;
95 
96  if (res.getRows() != 5 || res.getCols() != 5 || !compareMatrix(res, ground_truth)) {
97  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
98  }
99  }
100  {
101  vpMatrix res = vpMatrix::conv2(A, B, "same");
102  double ground_truth[4 * 4] = { 66, 59, 96, 50, 88, 89, 82, 52, 72, 95, 106, 27, 64, 88, 34, 2 };
103 
104  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, same):\n" << res << std::endl;
105 
106  if (res.getRows() != 4 || res.getCols() != 4 || !compareMatrix(res, ground_truth)) {
107  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
108  }
109  }
110  {
111  vpMatrix res = vpMatrix::conv2(A, B, "valid");
112  double ground_truth[3 * 3] = { 66, 59, 96, 88, 89, 82, 72, 95, 106 };
113 
114  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, valid):\n" << res << std::endl;
115 
116  if (res.getRows() != 3 || res.getCols() != 3 || !compareMatrix(res, ground_truth)) {
117  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
118  }
119  }
120  }
121 
122  {
123  vpMatrix A(2, 6);
124  for (unsigned int i = 0; i < A.getRows(); i++)
125  for (unsigned int j = 0; j < A.getCols(); j++)
126  A[i][j] = i * A.getCols() + j;
127 
128  vpMatrix B(4, 2);
129  for (unsigned int i = 0; i < B.getRows(); i++)
130  for (unsigned int j = 0; j < B.getCols(); j++)
131  B[i][j] = i * B.getCols() + j;
132 
133  {
134  vpMatrix res = vpMatrix::conv2(A, B, "full");
135  double ground_truth[5 * 7] = { 0, 0, 1, 2, 3, 4, 5, 0, 8, 14, 20, 26, 32, 26, 12, 36, 50, 64,
136  78, 92, 58, 24, 64, 86, 108, 130, 152, 90, 36, 84, 97, 110, 123, 136, 77 };
137 
138  std::cout << "A:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, full):\n" << res << std::endl;
139 
140  if (res.getRows() != 5 || res.getCols() != 7 || !compareMatrix(res, ground_truth)) {
141  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
142  }
143  }
144  {
145  vpMatrix res = vpMatrix::conv2(A, B, "same");
146  double ground_truth[2 * 6] = { 36, 50, 64, 78, 92, 58, 64, 86, 108, 130, 152, 90 };
147 
148  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, same):\n" << res << std::endl;
149 
150  if (res.getRows() != 2 || res.getCols() != 6 || !compareMatrix(res, ground_truth)) {
151  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
152  }
153  }
154  {
155  vpMatrix res = vpMatrix::conv2(A, B, "valid");
156 
157  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, valid):\n" << res << std::endl;
158 
159  if (res.getRows() != 0 || res.getCols() != 0) {
160  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
161  }
162  }
163 
164  {
165  vpMatrix res = vpMatrix::conv2(B, A, "full");
166  double ground_truth[5 * 7] = { 0, 0, 1, 2, 3, 4, 5, 0, 8, 14, 20, 26, 32, 26, 12, 36, 50, 64,
167  78, 92, 58, 24, 64, 86, 108, 130, 152, 90, 36, 84, 97, 110, 123, 136, 77 };
168 
169  std::cout << "A:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(B, A, full):\n" << res << std::endl;
170 
171  if (res.getRows() != 5 || res.getCols() != 7 || !compareMatrix(res, ground_truth)) {
172  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
173  }
174  }
175  {
176  vpMatrix res = vpMatrix::conv2(B, A, "same");
177  double ground_truth[4 * 2] = { 20, 26, 64, 78, 108, 130, 110, 123 };
178 
179  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(B, A, same):\n" << res << std::endl;
180 
181  if (res.getRows() != 4 || res.getCols() != 2 || !compareMatrix(res, ground_truth)) {
182  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
183  }
184  }
185  {
186  vpMatrix res = vpMatrix::conv2(B, A, "valid");
187 
188  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(B, A, valid):\n" << res << std::endl;
189 
190  if (res.getRows() != 0 || res.getCols() != 0) {
191  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
192  }
193  }
194  }
195 
196  {
197  vpMatrix A(4, 4);
198  A[0][0] = 16;
199  A[0][1] = 2;
200  A[0][2] = 3;
201  A[0][3] = 13;
202  A[1][0] = 5;
203  A[1][1] = 11;
204  A[1][2] = 10;
205  A[1][3] = 8;
206  A[2][0] = 9;
207  A[2][1] = 7;
208  A[2][2] = 6;
209  A[2][3] = 12;
210  A[3][0] = 4;
211  A[3][1] = 14;
212  A[3][2] = 15;
213  A[3][3] = 1;
214 
215  vpMatrix B(3, 3);
216  B[0][0] = 8;
217  B[0][1] = 1;
218  B[0][2] = 6;
219  B[1][0] = 3;
220  B[1][1] = 5;
221  B[1][2] = 7;
222  B[2][0] = 4;
223  B[2][1] = 9;
224  B[2][2] = 2;
225 
226  {
227  vpMatrix res = vpMatrix::conv2(A, B, "full");
228  double ground_truth[6 * 6] = { 128, 32, 122, 119, 31, 78, 88, 179, 252, 208, 154, 139,
229  151, 275, 291, 378, 281, 154, 79, 271, 423, 366, 285, 106,
230  48, 171, 248, 292, 230, 31, 16, 92, 194, 167, 39, 2 };
231 
232  std::cout << "A:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, full):\n" << res << std::endl;
233 
234  if (res.getRows() != 6 || res.getCols() != 6 || !compareMatrix(res, ground_truth)) {
235  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
236  }
237  }
238  {
239  vpMatrix res = vpMatrix::conv2(A, B, "same");
240  double ground_truth[4 * 4] = { 179, 252, 208, 154, 275, 291, 378, 281, 271, 423, 366, 285, 171, 248, 292, 230 };
241 
242  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, same):\n" << res << std::endl;
243 
244  if (res.getRows() != 4 || res.getCols() != 4 || !compareMatrix(res, ground_truth)) {
245  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
246  }
247  }
248  {
249  vpMatrix res = vpMatrix::conv2(A, B, "valid");
250  double ground_truth[2 * 2] = { 291, 378, 423, 366 };
251 
252  std::cout << "\nA:\n" << A << "\nB:\n" << B << "\nvpMatrix::conv2(A, B, valid):\n" << res << std::endl;
253 
254  if (res.getRows() != 2 || res.getCols() != 2 || !compareMatrix(res, ground_truth)) {
255  throw vpException(vpException::badValue, "Issue with vpMatrix::conv2()");
256  }
257  }
258  }
259  }
260  catch (const vpException &e) {
261  std::cout << "Catch an exception: " << e.what() << std::endl;
262  return EXIT_FAILURE;
263  }
264 }
unsigned int getCols() const
Definition: vpArray2D.h:337
unsigned int getRows() const
Definition: vpArray2D.h:347
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
const char * what() const
Definition: vpException.cpp:71
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:458
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static vpMatrix conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode)