Visual Servoing Platform  version 3.6.1 under development (2024-12-03)
vpFeatureLuminanceMapping.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  * Luminance dimensionality reduction features
32  */
33 
34 #include <visp3/visual_features/vpFeatureLuminanceMapping.h>
35 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
36 #ifdef VISP_HAVE_MODULE_IO
37 #include <visp3/io/vpImageIo.h>
38 #endif
39 BEGIN_VISP_NAMESPACE
40 
41 // vpLuminanceMapping
42 
44 {
45  const unsigned h = I.getHeight();
46  const unsigned w = I.getWidth();
47  if (h < 2 * border || w < 2 * border) {
48  throw vpException(vpException::dimensionError, "Image is smaller than required border crop");
49  }
50  Ivec.resize((h - 2 * border) * (w - 2 * border));
51  unsigned l = 0;
52  for (unsigned i = border; i < h - border; ++i) {
53  for (unsigned j = border; j < w - border; ++j) {
54  Ivec[l++] = (double)I[i][j];
55  }
56  }
57 }
58 
60 {
61  const unsigned h = I.getHeight();
62  const unsigned w = I.getWidth();
63  if (h < 2 * border || w < 2 * border) {
64  throw vpException(vpException::dimensionError, "Image is smaller than required border crop");
65  }
66  Imat.resize((h - 2 * border), (w - 2 * border), false, false);
67  for (unsigned i = border; i < h - border; ++i) {
68  for (unsigned j = border; j < w - border; ++j) {
69  Imat[i - border][j - border] = (double)I[i][j];
70  }
71  }
72 }
73 
74 // vpLuminancePCA
75 
76 vpLuminancePCA::vpLuminancePCA(const std::shared_ptr<vpMatrix> &basis, const std::shared_ptr<vpColVector> &mean, const vpColVector &explainedVariance)
77  : vpLuminanceMapping(basis->getRows())
78 {
79  m_Ih = m_Iw = 0;
80  init(basis, mean, explainedVariance);
81 }
82 
83 void vpLuminancePCA::init(const std::shared_ptr<vpMatrix> &basis, const std::shared_ptr<vpColVector> &mean, const vpColVector &variance)
84 {
85  if (basis->getCols() != mean->getRows()) {
86  throw vpException(vpException::dimensionError, "PCA mean and basis should have the same number of inputs");
87  }
88  if (variance.getRows() != basis->getRows()) {
89  throw vpException(vpException::dimensionError, "PCA explained variance should have the same size as the subspace");
90  }
91  m_mappingSize = basis->getRows();
92  m_basis = basis;
93  m_mean = mean;
94  m_explainedVariance = variance;
96 }
97 
99 {
100  *this = other;
101 }
102 
104 {
105  m_basis = other.m_basis;
106  m_mean = other.m_mean;
107  m_explainedVariance = other.m_explainedVariance;
109  m_border = other.m_border;
110  m_Ivec = other.m_Ivec;
111  m_Ih = other.m_Ih;
112  m_Iw = other.m_Iw;
113 
114  return *this;
115 }
116 
118 {
119  m_Ih = I.getHeight() - 2 * m_border;
120  m_Iw = I.getWidth() - 2 * m_border;
121  imageAsVector(I, m_Ivec, m_border);
122 
123  m_Ivec -= *m_mean;
124  s = (*m_basis) * m_Ivec;
125 }
126 
128 {
129  const vpColVector vI = ((*m_basis).transpose() * s + (*m_mean));
130  I.resize(m_Ih, m_Iw);
131  // Vector to image
132  for (unsigned int i = 0; i < m_Ih; ++i) {
133  for (unsigned int j = 0; j < m_Iw; ++j) {
134  I[i][j] = static_cast<unsigned char>(vI[i * m_Iw + j]);
135  }
136  }
137 }
138 
140 {
141  L = (*m_basis) * LI;
142 }
143 
144 vpLuminancePCA vpLuminancePCA::load(const std::string &basisFilename, const std::string &meanFilename, const std::string &explainedVarianceFile)
145 {
146  std::shared_ptr<vpMatrix> basis = std::make_shared<vpMatrix>();
147  std::shared_ptr<vpColVector> mean = std::make_shared<vpColVector>();
148  vpColVector explainedVariance;
149  vpMatrix::loadMatrix(basisFilename, *basis, true);
150  vpMatrix::loadMatrix(meanFilename, *mean, true);
151  vpMatrix::loadMatrix(explainedVarianceFile, explainedVariance, true);
152 
153  if (mean->getCols() > 1) {
155  "Read something that was not a column vector when trying to load the PCA mean vector");
156  }
157  if (explainedVariance.getCols() > 1) {
159  "Read something that was not a column vector when trying to load the PCA components explained variance");
160  }
161  if (basis->getCols() != mean->getRows()) {
162  std::stringstream ss;
163  ss << "Error when loading PCA from binary files";
164  ss << "The basis matrix had dimensions (" << basis->getRows() << ", " << basis->getCols() << ")";
165  ss << " and the mean vector had size " << mean->getRows() << ".";
166  ss << "You may be loading data from two different PCAs";
167  throw vpException(vpException::dimensionError, ss.str());
168  }
169 
170  return vpLuminancePCA(basis, mean, explainedVariance);
171 }
172 
173 void vpLuminancePCA::save(const std::string &basisFilename, const std::string &meanFilename, const std::string &explainedVarianceFile) const
174 {
175  if (m_basis.get() == nullptr || m_mean.get() == nullptr) {
177  "Tried to save a PCA projection that was uninitialized");
178  }
179  if (m_basis->size() == 0 || m_mean->getCols() == 0 || m_basis->getCols() != m_mean->getRows()) {
181  "Tried to save a PCA projection but there are issues with the basis and mean dimensions");
182  }
183  vpMatrix::saveMatrix(basisFilename, *m_basis, true);
184  vpMatrix::saveMatrix(meanFilename, *m_mean, true);
185  vpMatrix::saveMatrix(explainedVarianceFile, m_explainedVariance, true);
186 }
187 
188 vpLuminancePCA vpLuminancePCA::learn(const std::vector<vpImage<unsigned char>> &images, const unsigned int projectionSize, const unsigned int border)
189 {
190  vpMatrix matrix;
191  for (unsigned int i = 0; i < static_cast<unsigned int>(images.size()); ++i) {
192  const vpImage<unsigned char> &I = images[i];
193  if (i == 0) {
194  matrix.resize(static_cast<unsigned int>(images.size()), (I.getHeight() - 2 * border) * (I.getWidth() - 2 * border));
195  }
196  if ((I.getHeight() - 2 * border) * (I.getWidth() - 2 * border) != matrix.getCols()) {
197  throw vpException(vpException::badValue, "Not all images have the same dimensions when learning pca");
198  }
199  for (unsigned j = border; j < I.getHeight() - border; ++j) {
200  for (unsigned k = border; k < I.getWidth() - border; ++k) {
201  matrix[i][(j - border) * (I.getWidth() - 2 * border) + k - border] = I[j][k];
202  }
203  }
204  }
205 
206  return vpLuminancePCA::learn(matrix.transpose(), projectionSize);
207 }
208 
209 #ifdef VISP_HAVE_MODULE_IO
210 vpLuminancePCA vpLuminancePCA::learn(const std::vector<std::string> &imageFiles, const unsigned int projectionSize, const unsigned int border)
211 {
212  vpMatrix matrix;
214  for (unsigned int i = 0; i < static_cast<unsigned int>(imageFiles.size()); ++i) {
215  vpImageIo::read(I, imageFiles[i]);
216  if (i == 0) {
217  matrix.resize(static_cast<unsigned int>(imageFiles.size()), (I.getHeight() - 2 * border) * (I.getWidth() - 2 * border));
218  }
219  if ((I.getHeight() - 2 * border) * (I.getWidth() - 2 * border) != matrix.getCols()) {
220  throw vpException(vpException::badValue, "Not all images have the same dimensions when learning pca");
221  }
222  for (unsigned j = border; j < I.getHeight() - border; ++j) {
223  for (unsigned k = border; k < I.getWidth() - border; ++k) {
224  matrix[i][(j - border) * (I.getWidth() - 2 * border) + k - border] = I[j][k];
225  }
226  }
227  }
228  return vpLuminancePCA::learn(matrix.transpose(), projectionSize);
229 }
230 #endif
231 
232 vpLuminancePCA vpLuminancePCA::learn(const vpMatrix &images, const unsigned int projectionSize)
233 {
234  if (projectionSize > images.getRows() || projectionSize > images.getCols()) {
235  throw vpException(vpException::badValue, "Cannot use a subspace greater than the data dimensions (number of pixels or images)");
236  }
237  if (images.getRows() < images.getCols()) {
238  throw vpException(vpException::badValue, "Cannot compute SVD when there are more images (columns) than pixels (rows)");
239  }
240  // Mean computation
241  vpColVector mean(images.getRows(), 0.0);
242  for (unsigned i = 0; i < images.getCols(); ++i) {
243  mean += images.getCol(i);
244  }
245  mean /= images.getCols();
246 
247  // Before SVD, center data
248  vpMatrix centered(images.getRows(), images.getCols());
249  for (unsigned i = 0; i < centered.getRows(); ++i) {
250  for (unsigned j = 0; j < centered.getCols(); ++j) {
251  centered[i][j] = images[i][j] - mean[i];
252  }
253  }
254 
255  vpColVector eigenValues;
256  vpMatrix V;
257  centered.svd(eigenValues, V);
258  vpMatrix U(centered.getRows(), projectionSize);
259  for (unsigned i = 0; i < centered.getRows(); ++i) {
260  for (unsigned j = 0; j < projectionSize; ++j) {
261  U[i][j] = centered[i][j];
262  }
263  }
264  double cumEigenValues = eigenValues.sum();
265  vpColVector componentsExplainedVar(eigenValues, 0, projectionSize);
266  componentsExplainedVar /= cumEigenValues;
267  std::shared_ptr<vpMatrix> basis = std::make_shared<vpMatrix>(U.t());
268  std::shared_ptr<vpColVector> meanPtr = std::make_shared<vpColVector>(mean);
269  return vpLuminancePCA(basis, meanPtr, componentsExplainedVar);
270 }
271 
272 //vpMatrixZigZagIndex
274 
275 void vpLuminanceDCT::vpMatrixZigZagIndex::init(unsigned rows, unsigned cols)
276 {
277  // Adapted from https://www.geeksforgeeks.org/print-matrix-in-zig-zag-fashion/
278  m_colIndex.resize(rows * cols);
279  m_rowIndex.resize(rows * cols);
280  m_rows = rows;
281  m_cols = cols;
282  int rowCount = static_cast<int>(rows);
283  int colCount = static_cast<int>(cols);
284 
285  unsigned int index = 0;
286  int row = 0, col = 0;
287 
288  bool row_inc = 0;
289 
290  int mindim = std::min(rowCount, colCount);
291  for (int len = 1; len <= mindim; ++len) {
292  for (int i = 0; i < len; ++i) {
293  m_rowIndex[index] = row;
294  m_colIndex[index] = col;
295  ++index;
296  if (i + 1 == len) {
297  break;
298  }
299 
300  if (row_inc) {
301  ++row;
302  --col;
303  }
304  else {
305  --row;
306  ++col;
307  }
308  }
309 
310  if (len == mindim) {
311  break;
312  }
313 
314  if (row_inc)
315  ++row, row_inc = false;
316  else
317  ++col, row_inc = true;
318  }
319 
320  // Update the indexes of row and col variable
321  if (row == 0) {
322  if (col == rowCount - 1) {
323  ++row;
324  }
325  else {
326  ++col;
327  }
328  row_inc = 1;
329  }
330  else {
331  if (row == colCount - 1) {
332  ++col;
333  }
334  else {
335  ++row;
336  }
337  row_inc = 0;
338  }
339 
340  // Print the next half zig-zag pattern
341  int maxdim = std::max(rowCount, rowCount) - 1;
342  for (int len, diag = maxdim; diag > 0; --diag) {
343 
344  if (diag > mindim) {
345  len = mindim;
346  }
347  else {
348  len = diag;
349  }
350 
351  for (int i = 0; i < len; ++i) {
352  m_rowIndex[index] = row;
353  m_colIndex[index] = col;
354  ++index;
355 
356  if (i + 1 == len) {
357  break;
358  }
359 
360  if (row_inc) {
361  ++row;
362  --col;
363  }
364  else {
365  ++col;
366  --row;
367  }
368  }
369 
370  if (row == 0 || col == rowCount - 1) {
371  if (col == rowCount - 1) {
372  ++row;
373  }
374  else {
375  ++col;
376  }
377  row_inc = true;
378  }
379 
380  else if (col == 0 || row == colCount - 1) {
381  if (row == colCount - 1) {
382  ++col;
383  }
384  else {
385  ++row;
386  }
387  row_inc = false;
388  }
389  }
390 }
391 
392 void vpLuminanceDCT::vpMatrixZigZagIndex::getValues(const vpMatrix &m, unsigned int start, unsigned int end, vpColVector &s) const
393 {
394  if (m.getRows() != m_rows || m.getCols() != m_cols) {
395  throw vpException(vpException::dimensionError, "Input matrix has wrong dimensions");
396  }
397 
398  if (end <= start) {
399  throw vpException(vpException::dimensionError, "End index should be > to the start index");
400  }
401 
402  s.resize(end - start, false);
403 
404  for (unsigned index = start; index < end; ++index) {
405  s[index - start] = m[m_rowIndex[index]][m_colIndex[index]];
406  }
407 }
408 
409 void vpLuminanceDCT::vpMatrixZigZagIndex::setValues(const vpColVector &s, unsigned int start, vpMatrix &m) const
410 {
411  if (m.getRows() != m_rows || m.getCols() != m_cols) {
412  throw vpException(vpException::dimensionError, "Input matrix has wrong dimensions");
413  }
414 
415  if (start + s.size() > m.size()) {
416  throw vpException(vpException::dimensionError, "Start index combined to vector size exceeds matrix size");
417  }
418 
419  for (unsigned index = start; index < start + s.size(); ++index) {
420  m[m_rowIndex[index]][m_colIndex[index]] = s[index - start];
421  }
422 }
423 
424 // vpLuminanceDCT
425 
427 {
428  *this = other;
429 }
430 
432 {
433  m_Ih = I.getHeight() - 2 * m_border;
434  m_Iw = I.getWidth() - 2 * m_border;
435  if (m_Imat.getCols() != m_Ih || m_Imat.getRows() != m_Iw) {
436  computeDCTMatrices(m_Ih, m_Iw);
438  }
440  m_dct = m_Dcols * m_Imat * m_Drows;
442 }
443 
444 void vpLuminanceDCT::computeDCTMatrix(vpMatrix &D, unsigned int n) const
445 {
446  D.resize(n, n, false, false);
447  for (unsigned i = 0; i < n; i++) {
448  D[0][i] = 1.0 / sqrt(n);
449  }
450  double alpha = sqrt(2./(n));
451  for (unsigned int i = 1; i < n; i++) {
452  for (unsigned int j = 0; j < n; j++) {
453  D[i][j] = alpha*cos((2 * j + 1) * i * M_PI / (2.0 * n));
454  }
455  }
456 }
457 
458 void vpLuminanceDCT::computeDCTMatrices(unsigned int rows, unsigned int cols)
459 {
460  computeDCTMatrix(m_Dcols, rows);
461  computeDCTMatrix(m_Drows, cols);
463 }
464 
466 {
467  vpMatrix dctCut(m_dct.getRows(), m_dct.getCols(), 0.0);
468  m_zigzag.setValues(s, 0, dctCut);
469  const vpMatrix Ir = m_Dcols.t() * dctCut * m_Drows.t();
470  I.resize(Ir.getRows(), Ir.getCols());
471  for (unsigned int i = 0; i < I.getRows(); ++i) {
472  for (unsigned int j = 0; j < I.getCols(); ++j) {
473  I[i][j] = static_cast<unsigned char>(std::max(0.0, std::min(Ir[i][j], 255.0)));
474  }
475  }
476 }
477 
479 {
480  const vpMatrix LIT = LI.t();
481  for (unsigned int dof = 0; dof < 6; ++dof) {
482  m_dIdrPlanes[dof].resize(m_Ih, m_Iw, false, false);
483  memcpy(m_dIdrPlanes[dof].data, LIT[dof], m_Ih * m_Iw * sizeof(double));
484  }
485 
486  L.resize(m_mappingSize, 6, false, false);
487  vpMatrix dTddof(m_Ih, m_Iw);
488  vpColVector column;
489  for (unsigned int dof = 0; dof < 6; ++dof) {
490  dTddof = m_Dcols * m_dIdrPlanes[dof] * m_Drows;
491  m_zigzag.getValues(dTddof, 0, m_mappingSize, column);
492  for (unsigned int row = 0; row < L.getRows(); ++row) {
493  L[row][dof] = column[row];
494  }
495  }
496 }
497 
498 // Feature luminance mapping
499 
501 unsigned int h, unsigned int w, double Z, std::shared_ptr<vpLuminanceMapping> mapping)
502 {
503  init(cam, h, w, Z, mapping);
504 }
505 
506 vpFeatureLuminanceMapping::vpFeatureLuminanceMapping(const vpFeatureLuminance &luminance, std::shared_ptr<vpLuminanceMapping> mapping)
507 {
508  init(luminance, mapping);
509 }
511 {
512  *this = f;
513 }
514 
516 {
517  dim_s = 0;
518  m_featI.init(0, 0, 0.0);
519  m_mapping = nullptr;
520 }
521 
523  const vpCameraParameters &cam, unsigned int h, unsigned int w, double Z,
524  std::shared_ptr<vpLuminanceMapping> mapping)
525 {
526  m_featI.init(h, w, Z);
527  m_featI.setCameraParameters(cam);
528  m_mapping = mapping;
529  m_mapping->setBorder(m_featI.getBorder());
530  dim_s = m_mapping->getProjectionSize();
531  s.resize(dim_s, true);
532 }
533 void vpFeatureLuminanceMapping::init(const vpFeatureLuminance &luminance, std::shared_ptr<vpLuminanceMapping> mapping)
534 {
535  m_featI = luminance;
536  m_mapping = mapping;
537  dim_s = m_mapping->getProjectionSize();
538  m_mapping->setBorder(m_featI.getBorder());
539  s.resize(dim_s, true);
540 }
541 
543 {
544  dim_s = f.dim_s;
545  s = f.s;
546  m_mapping = f.m_mapping;
547  m_featI = f.m_featI;
548  return *this;
549 }
551 {
552  return new vpFeatureLuminanceMapping(*this);
553 }
554 
556 {
557  m_featI.buildFrom(I);
558  m_featI.interaction(m_LI);
559  m_mapping->map(I, s);
560 }
561 
563 {
564  if (select != FEATURE_ALL) {
565  throw vpException(vpException::notImplementedError, "cannot compute error on subset of a mapping");
566  }
567  vpColVector e(dim_s);
568  error(s_star, e);
569  return e;
570 }
571 
573 {
574  e.resize(dim_s, false);
575  for (unsigned int i = 0; i < dim_s; i++) {
576  e[i] = s[i] - s_star[i];
577  }
578 }
579 
581 {
582  if (select != FEATURE_ALL) {
583  throw vpException(vpException::notImplementedError, "cannot compute interaction matrix for a subset of a mapping");
584  }
585  vpMatrix dsdr(dim_s, 6);
586  interaction(dsdr);
587  return dsdr;
588 }
590 {
591  L.resize(dim_s, 6, false, false);
592  m_featI.interaction(m_LI);
593  m_mapping->interaction(I, m_LI, s, L);
594 }
595 
596 void vpFeatureLuminanceMapping::print(unsigned int /*select*/) const
597 {
598  std::cout << s << std::endl;
599 }
600 END_VISP_NAMESPACE
601 #endif // C++11
unsigned int getCols() const
Definition: vpArray2D.h:337
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:362
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
unsigned int getRows() const
Definition: vpArray2D.h:347
class that defines what is a visual feature
vpColVector s
State of the visual feature.
unsigned int dim_s
Dimension of the visual feature.
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
double sum() const
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
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
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition: vpException.h:74
@ dimensionError
Bad dimension.
Definition: vpException.h:71
@ notImplementedError
Not implemented.
Definition: vpException.h:69
Class to combine luminance features (photometric servoing)
vpColVector error(const vpBasicFeature &s_star, unsigned int select=FEATURE_ALL) VP_OVERRIDE
void buildFrom(vpImage< unsigned char > &I)
vpMatrix interaction(unsigned int select=FEATURE_ALL) VP_OVERRIDE
Compute the interaction matrix from a subset of the possible features.
vpFeatureLuminanceMapping(const vpCameraParameters &cam, unsigned int h, unsigned int w, double Z, const std::shared_ptr< vpLuminanceMapping > mapping)
void print(unsigned int select=FEATURE_ALL) const VP_OVERRIDE
Print the name of the feature.
vpFeatureLuminanceMapping * duplicate() const VP_OVERRIDE
vpFeatureLuminanceMapping & operator=(const vpFeatureLuminanceMapping &f)
Class that defines the image luminance visual feature.
vpFeatureLuminance & buildFrom(vpImage< unsigned char > &I)
void init(unsigned int _nbr, unsigned int _nbc, double _Z)
vpMatrix interaction(unsigned int select=FEATURE_ALL) VP_OVERRIDE
static const int DEFAULT_BORDER
void setCameraParameters(const vpCameraParameters &_cam)
unsigned int getBorder() const
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:147
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
unsigned int getCols() const
Definition: vpImage.h:171
unsigned int getHeight() const
Definition: vpImage.h:181
unsigned int getRows() const
Definition: vpImage.h:212
void init(unsigned rows, unsigned cols)
Initialize the ZigZag object. Computes and stores the zigzag indexing for a given matrix size.
void setValues(const vpColVector &s, unsigned int start, vpMatrix &m) const
set the values in the matrix, according to the values stored in the vector s and the zigzag indexing ...
void getValues(const vpMatrix &m, unsigned int start, unsigned int end, vpColVector &s) const
Fill the vector s with (end - start) values, according to the zigzag matrix indexing strategy.
Implementation of .
void inverse(const vpColVector &s, vpImage< unsigned char > &I) VP_OVERRIDE
Reconstruct I from a representation s.
vpMatrix m_Dcols
DCT representation of the image.
vpLuminanceDCT::vpMatrixZigZagIndex m_zigzag
Luminance interaction matrix, seen as six image planes.
vpMatrix m_dct
Image as a matrix.
void map(const vpImage< unsigned char > &I, vpColVector &s) VP_OVERRIDE
Map an image I to a representation s. This representation s has getProjectionSize() rows.
void interaction(const vpImage< unsigned char > &I, const vpMatrix &LI, const vpColVector &s, vpMatrix &L) VP_OVERRIDE
Compute the interaction matrix associated with the representation s.
vpMatrix m_Imat
image dimensions (without borders)
std::array< vpMatrix, 6 > m_dIdrPlanes
the computed DCT matrices. The separable property of DCt is used so that a 1D DCT is computed on rows...
vpLuminanceDCT(const unsigned int k)
Build a new DCT object.
Base class for functions that map an image and its interaction matrix to a different domain.
unsigned int getProjectionSize() const
Returns the size of the space to which an image is mapped to.
static void imageAsMatrix(const vpImage< unsigned char > &I, vpMatrix &Imat, unsigned border)
static void imageAsVector(const vpImage< unsigned char > &I, vpColVector &Ivec, unsigned border)
unsigned m_border
Final vector size.
Implementation of .
static vpLuminancePCA learn(const std::vector< vpImage< unsigned char >> &images, const unsigned int projectionSize, const unsigned int imageBorder=0)
Compute a new Principal Component Analysis on set of images.
void inverse(const vpColVector &s, vpImage< unsigned char > &I) VP_OVERRIDE
Reconstruct I from a representation s.
void save(const std::string &basisFilename, const std::string &meanFileName, const std::string &explainedVarianceFile) const
Save the PCA basis to multiple text files, for later use via the load function.
void map(const vpImage< unsigned char > &I, vpColVector &s) VP_OVERRIDE
Map an image I to a representation s. This representation s has getProjectionSize() rows.
void init(const std::shared_ptr< vpMatrix > &basis, const std::shared_ptr< vpColVector > &mean, const vpColVector &variance)
Initialize the PCA object with a basis, mean and explained variance vector.
void interaction(const vpImage< unsigned char > &I, const vpMatrix &LI, const vpColVector &s, vpMatrix &L) VP_OVERRIDE
Compute the interaction matrix associated with the representation s.
static vpLuminancePCA load(const std::string &basisFilename, const std::string &meanFileName, const std::string &explainedVarianceFile)
Save the PCA basis to multiple text files, for later use via the load function.
vpLuminancePCA & operator=(const vpLuminancePCA &other)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static bool loadMatrix(const std::string &filename, vpArray2D< double > &M, bool binary=false, char *header=nullptr)
Definition: vpMatrix.h:829
void svd(vpColVector &w, vpMatrix &V)
vpColVector getCol(unsigned int j) const
Definition: vpMatrix.cpp:548
vpMatrix transpose() const
static bool saveMatrix(const std::string &filename, const vpArray2D< double > &M, bool binary=false, const char *header="")
Definition: vpMatrix.h:985
vpMatrix t() const