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>
47 if (h < 2 * border || w < 2 * border) {
50 Ivec.
resize((h - 2 * border) * (w - 2 * border));
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];
63 if (h < 2 * border || w < 2 * border) {
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];
80 init(basis, mean, explainedVariance);
85 if (basis->getCols() != mean->getRows()) {
88 if (variance.
getRows() != basis->getRows()) {
94 m_explainedVariance = variance;
105 m_basis = other.m_basis;
106 m_mean = other.m_mean;
107 m_explainedVariance = other.m_explainedVariance;
110 m_Ivec = other.m_Ivec;
124 s = (*m_basis) * m_Ivec;
129 const vpColVector vI = ((*m_basis).transpose() * s + (*m_mean));
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]);
146 std::shared_ptr<vpMatrix> basis = std::make_shared<vpMatrix>();
147 std::shared_ptr<vpColVector> mean = std::make_shared<vpColVector>();
153 if (mean->getCols() > 1) {
155 "Read something that was not a column vector when trying to load the PCA mean vector");
157 if (explainedVariance.
getCols() > 1) {
159 "Read something that was not a column vector when trying to load the PCA components explained variance");
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";
173 void vpLuminancePCA::save(
const std::string &basisFilename,
const std::string &meanFilename,
const std::string &explainedVarianceFile)
const
175 if (m_basis.get() ==
nullptr || m_mean.get() ==
nullptr) {
177 "Tried to save a PCA projection that was uninitialized");
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");
191 for (
unsigned int i = 0; i < static_cast<unsigned int>(images.size()); ++i) {
194 matrix.
resize(
static_cast<unsigned int>(images.size()), (I.
getHeight() - 2 * border) * (I.
getWidth() - 2 * border));
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];
209 #ifdef VISP_HAVE_MODULE_IO
214 for (
unsigned int i = 0; i < static_cast<unsigned int>(imageFiles.size()); ++i) {
217 matrix.
resize(
static_cast<unsigned int>(imageFiles.size()), (I.
getHeight() - 2 * border) * (I.
getWidth() - 2 * border));
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];
234 if (projectionSize > images.
getRows() || projectionSize > images.
getCols()) {
242 for (
unsigned i = 0; i < images.
getCols(); ++i) {
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];
257 centered.
svd(eigenValues, V);
259 for (
unsigned i = 0; i < centered.
getRows(); ++i) {
260 for (
unsigned j = 0; j < projectionSize; ++j) {
261 U[i][j] = centered[i][j];
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);
278 m_colIndex.resize(rows * cols);
279 m_rowIndex.resize(rows * cols);
282 int rowCount =
static_cast<int>(rows);
283 int colCount =
static_cast<int>(cols);
285 unsigned int index = 0;
286 int row = 0, col = 0;
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;
315 ++row, row_inc =
false;
317 ++col, row_inc =
true;
322 if (col == rowCount - 1) {
331 if (row == colCount - 1) {
341 int maxdim = std::max(rowCount, rowCount) - 1;
342 for (
int len, diag = maxdim; diag > 0; --diag) {
351 for (
int i = 0; i < len; ++i) {
352 m_rowIndex[index] = row;
353 m_colIndex[index] = col;
370 if (row == 0 || col == rowCount - 1) {
371 if (col == rowCount - 1) {
380 else if (col == 0 || row == colCount - 1) {
381 if (row == colCount - 1) {
402 s.
resize(end - start,
false);
404 for (
unsigned index = start; index < end; ++index) {
405 s[index - start] = m[m_rowIndex[index]][m_colIndex[index]];
419 for (
unsigned index = start; index < start + s.
size(); ++index) {
420 m[m_rowIndex[index]][m_colIndex[index]] = s[index - start];
444 void vpLuminanceDCT::computeDCTMatrix(
vpMatrix &D,
unsigned int n)
const
446 D.resize(n, n,
false,
false);
447 for (
unsigned i = 0; i < n; i++) {
448 D[0][i] = 1.0 / sqrt(n);
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));
458 void vpLuminanceDCT::computeDCTMatrices(
unsigned int rows,
unsigned int cols)
460 computeDCTMatrix(
m_Dcols, rows);
461 computeDCTMatrix(
m_Drows, cols);
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)));
481 for (
unsigned int dof = 0; dof < 6; ++dof) {
489 for (
unsigned int dof = 0; dof < 6; ++dof) {
492 for (
unsigned int row = 0; row < L.getRows(); ++row) {
493 L[row][dof] = column[row];
501 unsigned int h,
unsigned int w,
double Z, std::shared_ptr<vpLuminanceMapping> mapping)
503 init(cam, h, w, Z, mapping);
508 init(luminance, mapping);
518 m_featI.
init(0, 0, 0.0);
524 std::shared_ptr<vpLuminanceMapping> mapping)
526 m_featI.
init(h, w, Z);
529 m_mapping->setBorder(m_featI.
getBorder());
530 dim_s = m_mapping->getProjectionSize();
537 dim_s = m_mapping->getProjectionSize();
538 m_mapping->setBorder(m_featI.
getBorder());
546 m_mapping = f.m_mapping;
559 m_mapping->map(I,
s);
575 for (
unsigned int i = 0; i <
dim_s; i++) {
576 e[i] =
s[i] - s_star[i];
591 L.resize(
dim_s, 6,
false,
false);
593 m_mapping->interaction(I, m_LI,
s, L);
598 std::cout <<
s << std::endl;
unsigned int getCols() const
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int size() const
Return the number of elements of the 2D array.
unsigned int getRows() const
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.
void resize(unsigned int i, bool flagNullify=true)
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ notInitialized
Used to indicate that a parameter is not initialized.
@ dimensionError
Bad dimension.
@ notImplementedError
Not implemented.
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)
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getCols() const
unsigned int getHeight() const
unsigned int getRows() const
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.
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.
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.
static bool loadMatrix(const std::string &filename, vpArray2D< double > &M, bool binary=false, char *header=nullptr)
void svd(vpColVector &w, vpMatrix &V)
vpColVector getCol(unsigned int j) const
vpMatrix transpose() const
static bool saveMatrix(const std::string &filename, const vpArray2D< double > &M, bool binary=false, const char *header="")