From e2f24f43c982365e1483ad3b3e73c0f5b5bb3b7e Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Sun, 10 Aug 2014 01:54:16 +0400 Subject: [PATCH] added some basic functionality needed by the new face module (moved from the old "contrib") --- modules/core/include/opencv2/core.hpp | 54 + modules/core/src/lda.cpp | 1119 +++++++++++++++++ modules/core/src/matmul.cpp | 1 - modules/imgproc/doc/colormaps.rst | 107 ++ modules/imgproc/doc/imgproc.rst | 1 + .../doc/pics/colormaps/colorscale_autumn.jpg | Bin 0 -> 1352 bytes .../doc/pics/colormaps/colorscale_bone.jpg | Bin 0 -> 1325 bytes .../doc/pics/colormaps/colorscale_cool.jpg | Bin 0 -> 1325 bytes .../doc/pics/colormaps/colorscale_hot.jpg | Bin 0 -> 1403 bytes .../doc/pics/colormaps/colorscale_hsv.jpg | Bin 0 -> 1690 bytes .../doc/pics/colormaps/colorscale_jet.jpg | Bin 0 -> 1579 bytes .../doc/pics/colormaps/colorscale_mkpj1.jpg | Bin 0 -> 1569 bytes .../doc/pics/colormaps/colorscale_mkpj2.jpg | Bin 0 -> 1517 bytes .../doc/pics/colormaps/colorscale_ocean.jpg | Bin 0 -> 1430 bytes .../doc/pics/colormaps/colorscale_pink.jpg | Bin 0 -> 1390 bytes .../doc/pics/colormaps/colorscale_rainbow.jpg | Bin 0 -> 1524 bytes .../doc/pics/colormaps/colorscale_spring.jpg | Bin 0 -> 1254 bytes .../doc/pics/colormaps/colorscale_summer.jpg | Bin 0 -> 1345 bytes .../doc/pics/colormaps/colorscale_winter.jpg | Bin 0 -> 1238 bytes modules/imgproc/include/opencv2/imgproc.hpp | 18 + modules/imgproc/src/colormap.cpp | 530 ++++++++ modules/python/common.cmake | 2 +- 22 files changed, 1830 insertions(+), 2 deletions(-) create mode 100644 modules/core/src/lda.cpp create mode 100644 modules/imgproc/doc/colormaps.rst create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_autumn.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_bone.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_cool.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_hot.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_hsv.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_jet.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_mkpj1.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_mkpj2.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_ocean.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_pink.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_rainbow.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_spring.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_summer.jpg create mode 100644 modules/imgproc/doc/pics/colormaps/colorscale_winter.jpg create mode 100644 modules/imgproc/src/colormap.cpp diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index b5249c9f50..773ee82d64 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -690,7 +690,61 @@ public: Mat mean; //!< mean value subtracted before the projection and added after the back projection }; +// Linear Discriminant Analysis +class CV_EXPORTS LDA +{ +public: + // Initializes a LDA with num_components (default 0) and specifies how + // samples are aligned (default dataAsRow=true). + explicit LDA(int num_components = 0); + // Initializes and performs a Discriminant Analysis with Fisher's + // Optimization Criterion on given data in src and corresponding labels + // in labels. If 0 (or less) number of components are given, they are + // automatically determined for given data in computation. + LDA(InputArrayOfArrays src, InputArray labels, int num_components = 0); + + // Serializes this object to a given filename. + void save(const String& filename) const; + + // Deserializes this object from a given filename. + void load(const String& filename); + + // Serializes this object to a given cv::FileStorage. + void save(FileStorage& fs) const; + + // Deserializes this object from a given cv::FileStorage. + void load(const FileStorage& node); + + // Destructor. + ~LDA(); + + //! Compute the discriminants for data in src and labels. + void compute(InputArrayOfArrays src, InputArray labels); + + // Projects samples into the LDA subspace. + Mat project(InputArray src); + + // Reconstructs projections from the LDA subspace. + Mat reconstruct(InputArray src); + + // Returns the eigenvectors of this LDA. + Mat eigenvectors() const { return _eigenvectors; } + + // Returns the eigenvalues of this LDA. + Mat eigenvalues() const { return _eigenvalues; } + + static Mat subspaceProject(InputArray W, InputArray mean, InputArray src); + static Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); + +protected: + bool _dataAsRow; + int _num_components; + Mat _eigenvectors; + Mat _eigenvalues; + + void lda(InputArrayOfArrays src, InputArray labels); +}; /*! Singular Value Decomposition class diff --git a/modules/core/src/lda.cpp b/modules/core/src/lda.cpp new file mode 100644 index 0000000000..5e20b5e6a1 --- /dev/null +++ b/modules/core/src/lda.cpp @@ -0,0 +1,1119 @@ +/* + * Copyright (c) 2011. Philipp Wagner . + * Released to public domain under terms of the BSD Simplified license. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * See + */ + +#include "precomp.hpp" +#include +#include +#include + +namespace cv +{ + +// Removes duplicate elements in a given vector. +template +inline std::vector<_Tp> remove_dups(const std::vector<_Tp>& src) { + typedef typename std::set<_Tp>::const_iterator constSetIterator; + typedef typename std::vector<_Tp>::const_iterator constVecIterator; + std::set<_Tp> set_elems; + for (constVecIterator it = src.begin(); it != src.end(); ++it) + set_elems.insert(*it); + std::vector<_Tp> elems; + for (constSetIterator it = set_elems.begin(); it != set_elems.end(); ++it) + elems.push_back(*it); + return elems; +} + +static Mat argsort(InputArray _src, bool ascending=true) +{ + Mat src = _src.getMat(); + if (src.rows != 1 && src.cols != 1) { + String error_message = "Wrong shape of input matrix! Expected a matrix with one row or column."; + CV_Error(Error::StsBadArg, error_message); + } + int flags = SORT_EVERY_ROW | (ascending ? SORT_ASCENDING : SORT_DESCENDING); + Mat sorted_indices; + sortIdx(src.reshape(1,1),sorted_indices,flags); + return sorted_indices; +} + +static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double beta=0) { + // make sure the input data is a vector of matrices or vector of vector + if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) { + String error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; + CV_Error(Error::StsBadArg, error_message); + } + // number of samples + size_t n = src.total(); + // return empty matrix if no matrices given + if(n == 0) + return Mat(); + // dimensionality of (reshaped) samples + size_t d = src.getMat(0).total(); + // create data matrix + Mat data((int)n, (int)d, rtype); + // now copy data + for(int i = 0; i < (int)n; i++) { + // make sure data can be reshaped, throw exception if not! + if(src.getMat(i).total() != d) { + String error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, (int)d, (int)src.getMat(i).total()); + CV_Error(Error::StsBadArg, error_message); + } + // get a hold of the current row + Mat xi = data.row(i); + // make reshape happy by cloning for non-continuous matrices + if(src.getMat(i).isContinuous()) { + src.getMat(i).reshape(1, 1).convertTo(xi, rtype, alpha, beta); + } else { + src.getMat(i).clone().reshape(1, 1).convertTo(xi, rtype, alpha, beta); + } + } + return data; +} + +static void sortMatrixColumnsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) { + if(_indices.getMat().type() != CV_32SC1) { + CV_Error(Error::StsUnsupportedFormat, "cv::sortColumnsByIndices only works on integer indices!"); + } + Mat src = _src.getMat(); + std::vector indices = _indices.getMat(); + _dst.create(src.rows, src.cols, src.type()); + Mat dst = _dst.getMat(); + for(size_t idx = 0; idx < indices.size(); idx++) { + Mat originalCol = src.col(indices[idx]); + Mat sortedCol = dst.col((int)idx); + originalCol.copyTo(sortedCol); + } +} + +static Mat sortMatrixColumnsByIndices(InputArray src, InputArray indices) { + Mat dst; + sortMatrixColumnsByIndices(src, indices, dst); + return dst; +} + + +template static bool +isSymmetric_(InputArray src) { + Mat _src = src.getMat(); + if(_src.cols != _src.rows) + return false; + for (int i = 0; i < _src.rows; i++) { + for (int j = 0; j < _src.cols; j++) { + _Tp a = _src.at<_Tp> (i, j); + _Tp b = _src.at<_Tp> (j, i); + if (a != b) { + return false; + } + } + } + return true; +} + +template static bool +isSymmetric_(InputArray src, double eps) { + Mat _src = src.getMat(); + if(_src.cols != _src.rows) + return false; + for (int i = 0; i < _src.rows; i++) { + for (int j = 0; j < _src.cols; j++) { + _Tp a = _src.at<_Tp> (i, j); + _Tp b = _src.at<_Tp> (j, i); + if (std::abs(a - b) > eps) { + return false; + } + } + } + return true; +} + +static bool isSymmetric(InputArray src, double eps=1e-16) +{ + Mat m = src.getMat(); + switch (m.type()) { + case CV_8SC1: return isSymmetric_(m); break; + case CV_8UC1: + return isSymmetric_(m); break; + case CV_16SC1: + return isSymmetric_(m); break; + case CV_16UC1: + return isSymmetric_(m); break; + case CV_32SC1: + return isSymmetric_(m); break; + case CV_32FC1: + return isSymmetric_(m, eps); break; + case CV_64FC1: + return isSymmetric_(m, eps); break; + default: + break; + } + return false; +} + + +//------------------------------------------------------------------------------ +// cv::subspaceProject +//------------------------------------------------------------------------------ +Mat LDA::subspaceProject(InputArray _W, InputArray _mean, InputArray _src) { + // get data matrices + Mat W = _W.getMat(); + Mat mean = _mean.getMat(); + Mat src = _src.getMat(); + // get number of samples and dimension + int n = src.rows; + int d = src.cols; + // make sure the data has the correct shape + if(W.rows != d) { + String error_message = format("Wrong shapes for given matrices. Was size(src) = (%d,%d), size(W) = (%d,%d).", src.rows, src.cols, W.rows, W.cols); + CV_Error(Error::StsBadArg, error_message); + } + // make sure mean is correct if not empty + if(!mean.empty() && (mean.total() != (size_t) d)) { + String error_message = format("Wrong mean shape for the given data matrix. Expected %d, but was %d.", d, mean.total()); + CV_Error(Error::StsBadArg, error_message); + } + // create temporary matrices + Mat X, Y; + // make sure you operate on correct type + src.convertTo(X, W.type()); + // safe to do, because of above assertion + if(!mean.empty()) { + for(int i=0; i + _Tp *alloc_1d(int m) { + return new _Tp[m]; + } + + // Allocates memory. + template + _Tp *alloc_1d(int m, _Tp val) { + _Tp *arr = alloc_1d<_Tp> (m); + for (int i = 0; i < m; i++) + arr[i] = val; + return arr; + } + + // Allocates memory. + template + _Tp **alloc_2d(int m, int _n) { + _Tp **arr = new _Tp*[m]; + for (int i = 0; i < m; i++) + arr[i] = new _Tp[_n]; + return arr; + } + + // Allocates memory. + template + _Tp **alloc_2d(int m, int _n, _Tp val) { + _Tp **arr = alloc_2d<_Tp> (m, _n); + for (int i = 0; i < m; i++) { + for (int j = 0; j < _n; j++) { + arr[i][j] = val; + } + } + return arr; + } + + void cdiv(double xr, double xi, double yr, double yi) { + double r, dv; + if (std::abs(yr) > std::abs(yi)) { + r = yi / yr; + dv = yr + r * yi; + cdivr = (xr + r * xi) / dv; + cdivi = (xi - r * xr) / dv; + } else { + r = yr / yi; + dv = yi + r * yr; + cdivr = (r * xr + xi) / dv; + cdivi = (r * xi - xr) / dv; + } + } + + // Nonsymmetric reduction from Hessenberg to real Schur form. + + void hqr2() { + + // This is derived from the Algol procedure hqr2, + // by Martin and Wilkinson, Handbook for Auto. Comp., + // Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + + // Initialize + int nn = this->n; + int n1 = nn - 1; + int low = 0; + int high = nn - 1; + double eps = std::pow(2.0, -52.0); + double exshift = 0.0; + double p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y; + + // Store roots isolated by balanc and compute matrix norm + + double norm = 0.0; + for (int i = 0; i < nn; i++) { + if (i < low || i > high) { + d[i] = H[i][i]; + e[i] = 0.0; + } + for (int j = std::max(i - 1, 0); j < nn; j++) { + norm = norm + std::abs(H[i][j]); + } + } + + // Outer loop over eigenvalue index + int iter = 0; + while (n1 >= low) { + + // Look for single small sub-diagonal element + int l = n1; + while (l > low) { + s = std::abs(H[l - 1][l - 1]) + std::abs(H[l][l]); + if (s == 0.0) { + s = norm; + } + if (std::abs(H[l][l - 1]) < eps * s) { + break; + } + l--; + } + + // Check for convergence + // One root found + + if (l == n1) { + H[n1][n1] = H[n1][n1] + exshift; + d[n1] = H[n1][n1]; + e[n1] = 0.0; + n1--; + iter = 0; + + // Two roots found + + } else if (l == n1 - 1) { + w = H[n1][n1 - 1] * H[n1 - 1][n1]; + p = (H[n1 - 1][n1 - 1] - H[n1][n1]) / 2.0; + q = p * p + w; + z = std::sqrt(std::abs(q)); + H[n1][n1] = H[n1][n1] + exshift; + H[n1 - 1][n1 - 1] = H[n1 - 1][n1 - 1] + exshift; + x = H[n1][n1]; + + // Real pair + + if (q >= 0) { + if (p >= 0) { + z = p + z; + } else { + z = p - z; + } + d[n1 - 1] = x + z; + d[n1] = d[n1 - 1]; + if (z != 0.0) { + d[n1] = x - w / z; + } + e[n1 - 1] = 0.0; + e[n1] = 0.0; + x = H[n1][n1 - 1]; + s = std::abs(x) + std::abs(z); + p = x / s; + q = z / s; + r = std::sqrt(p * p + q * q); + p = p / r; + q = q / r; + + // Row modification + + for (int j = n1 - 1; j < nn; j++) { + z = H[n1 - 1][j]; + H[n1 - 1][j] = q * z + p * H[n1][j]; + H[n1][j] = q * H[n1][j] - p * z; + } + + // Column modification + + for (int i = 0; i <= n1; i++) { + z = H[i][n1 - 1]; + H[i][n1 - 1] = q * z + p * H[i][n1]; + H[i][n1] = q * H[i][n1] - p * z; + } + + // Accumulate transformations + + for (int i = low; i <= high; i++) { + z = V[i][n1 - 1]; + V[i][n1 - 1] = q * z + p * V[i][n1]; + V[i][n1] = q * V[i][n1] - p * z; + } + + // Complex pair + + } else { + d[n1 - 1] = x + p; + d[n1] = x + p; + e[n1 - 1] = z; + e[n1] = -z; + } + n1 = n1 - 2; + iter = 0; + + // No convergence yet + + } else { + + // Form shift + + x = H[n1][n1]; + y = 0.0; + w = 0.0; + if (l < n1) { + y = H[n1 - 1][n1 - 1]; + w = H[n1][n1 - 1] * H[n1 - 1][n1]; + } + + // Wilkinson's original ad hoc shift + + if (iter == 10) { + exshift += x; + for (int i = low; i <= n1; i++) { + H[i][i] -= x; + } + s = std::abs(H[n1][n1 - 1]) + std::abs(H[n1 - 1][n1 - 2]); + x = y = 0.75 * s; + w = -0.4375 * s * s; + } + + // MATLAB's new ad hoc shift + + if (iter == 30) { + s = (y - x) / 2.0; + s = s * s + w; + if (s > 0) { + s = std::sqrt(s); + if (y < x) { + s = -s; + } + s = x - w / ((y - x) / 2.0 + s); + for (int i = low; i <= n1; i++) { + H[i][i] -= s; + } + exshift += s; + x = y = w = 0.964; + } + } + + iter = iter + 1; // (Could check iteration count here.) + + // Look for two consecutive small sub-diagonal elements + int m = n1 - 2; + while (m >= l) { + z = H[m][m]; + r = x - z; + s = y - z; + p = (r * s - w) / H[m + 1][m] + H[m][m + 1]; + q = H[m + 1][m + 1] - z - r - s; + r = H[m + 2][m + 1]; + s = std::abs(p) + std::abs(q) + std::abs(r); + p = p / s; + q = q / s; + r = r / s; + if (m == l) { + break; + } + if (std::abs(H[m][m - 1]) * (std::abs(q) + std::abs(r)) < eps * (std::abs(p) + * (std::abs(H[m - 1][m - 1]) + std::abs(z) + std::abs( + H[m + 1][m + 1])))) { + break; + } + m--; + } + + for (int i = m + 2; i <= n1; i++) { + H[i][i - 2] = 0.0; + if (i > m + 2) { + H[i][i - 3] = 0.0; + } + } + + // Double QR step involving rows l:n and columns m:n + + for (int k = m; k <= n1 - 1; k++) { + bool notlast = (k != n1 - 1); + if (k != m) { + p = H[k][k - 1]; + q = H[k + 1][k - 1]; + r = (notlast ? H[k + 2][k - 1] : 0.0); + x = std::abs(p) + std::abs(q) + std::abs(r); + if (x != 0.0) { + p = p / x; + q = q / x; + r = r / x; + } + } + if (x == 0.0) { + break; + } + s = std::sqrt(p * p + q * q + r * r); + if (p < 0) { + s = -s; + } + if (s != 0) { + if (k != m) { + H[k][k - 1] = -s * x; + } else if (l != m) { + H[k][k - 1] = -H[k][k - 1]; + } + p = p + s; + x = p / s; + y = q / s; + z = r / s; + q = q / p; + r = r / p; + + // Row modification + + for (int j = k; j < nn; j++) { + p = H[k][j] + q * H[k + 1][j]; + if (notlast) { + p = p + r * H[k + 2][j]; + H[k + 2][j] = H[k + 2][j] - p * z; + } + H[k][j] = H[k][j] - p * x; + H[k + 1][j] = H[k + 1][j] - p * y; + } + + // Column modification + + for (int i = 0; i <= std::min(n1, k + 3); i++) { + p = x * H[i][k] + y * H[i][k + 1]; + if (notlast) { + p = p + z * H[i][k + 2]; + H[i][k + 2] = H[i][k + 2] - p * r; + } + H[i][k] = H[i][k] - p; + H[i][k + 1] = H[i][k + 1] - p * q; + } + + // Accumulate transformations + + for (int i = low; i <= high; i++) { + p = x * V[i][k] + y * V[i][k + 1]; + if (notlast) { + p = p + z * V[i][k + 2]; + V[i][k + 2] = V[i][k + 2] - p * r; + } + V[i][k] = V[i][k] - p; + V[i][k + 1] = V[i][k + 1] - p * q; + } + } // (s != 0) + } // k loop + } // check convergence + } // while (n1 >= low) + + // Backsubstitute to find vectors of upper triangular form + + if (norm == 0.0) { + return; + } + + for (n1 = nn - 1; n1 >= 0; n1--) { + p = d[n1]; + q = e[n1]; + + // Real vector + + if (q == 0) { + int l = n1; + H[n1][n1] = 1.0; + for (int i = n1 - 1; i >= 0; i--) { + w = H[i][i] - p; + r = 0.0; + for (int j = l; j <= n1; j++) { + r = r + H[i][j] * H[j][n1]; + } + if (e[i] < 0.0) { + z = w; + s = r; + } else { + l = i; + if (e[i] == 0.0) { + if (w != 0.0) { + H[i][n1] = -r / w; + } else { + H[i][n1] = -r / (eps * norm); + } + + // Solve real equations + + } else { + x = H[i][i + 1]; + y = H[i + 1][i]; + q = (d[i] - p) * (d[i] - p) + e[i] * e[i]; + t = (x * s - z * r) / q; + H[i][n1] = t; + if (std::abs(x) > std::abs(z)) { + H[i + 1][n1] = (-r - w * t) / x; + } else { + H[i + 1][n1] = (-s - y * t) / z; + } + } + + // Overflow control + + t = std::abs(H[i][n1]); + if ((eps * t) * t > 1) { + for (int j = i; j <= n1; j++) { + H[j][n1] = H[j][n1] / t; + } + } + } + } + // Complex vector + } else if (q < 0) { + int l = n1 - 1; + + // Last vector component imaginary so matrix is triangular + + if (std::abs(H[n1][n1 - 1]) > std::abs(H[n1 - 1][n1])) { + H[n1 - 1][n1 - 1] = q / H[n1][n1 - 1]; + H[n1 - 1][n1] = -(H[n1][n1] - p) / H[n1][n1 - 1]; + } else { + cdiv(0.0, -H[n1 - 1][n1], H[n1 - 1][n1 - 1] - p, q); + H[n1 - 1][n1 - 1] = cdivr; + H[n1 - 1][n1] = cdivi; + } + H[n1][n1 - 1] = 0.0; + H[n1][n1] = 1.0; + for (int i = n1 - 2; i >= 0; i--) { + double ra, sa, vr, vi; + ra = 0.0; + sa = 0.0; + for (int j = l; j <= n1; j++) { + ra = ra + H[i][j] * H[j][n1 - 1]; + sa = sa + H[i][j] * H[j][n1]; + } + w = H[i][i] - p; + + if (e[i] < 0.0) { + z = w; + r = ra; + s = sa; + } else { + l = i; + if (e[i] == 0) { + cdiv(-ra, -sa, w, q); + H[i][n1 - 1] = cdivr; + H[i][n1] = cdivi; + } else { + + // Solve complex equations + + x = H[i][i + 1]; + y = H[i + 1][i]; + vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q; + vi = (d[i] - p) * 2.0 * q; + if (vr == 0.0 && vi == 0.0) { + vr = eps * norm * (std::abs(w) + std::abs(q) + std::abs(x) + + std::abs(y) + std::abs(z)); + } + cdiv(x * r - z * ra + q * sa, + x * s - z * sa - q * ra, vr, vi); + H[i][n1 - 1] = cdivr; + H[i][n1] = cdivi; + if (std::abs(x) > (std::abs(z) + std::abs(q))) { + H[i + 1][n1 - 1] = (-ra - w * H[i][n1 - 1] + q + * H[i][n1]) / x; + H[i + 1][n1] = (-sa - w * H[i][n1] - q * H[i][n1 + - 1]) / x; + } else { + cdiv(-r - y * H[i][n1 - 1], -s - y * H[i][n1], z, + q); + H[i + 1][n1 - 1] = cdivr; + H[i + 1][n1] = cdivi; + } + } + + // Overflow control + + t = std::max(std::abs(H[i][n1 - 1]), std::abs(H[i][n1])); + if ((eps * t) * t > 1) { + for (int j = i; j <= n1; j++) { + H[j][n1 - 1] = H[j][n1 - 1] / t; + H[j][n1] = H[j][n1] / t; + } + } + } + } + } + } + + // Vectors of isolated roots + + for (int i = 0; i < nn; i++) { + if (i < low || i > high) { + for (int j = i; j < nn; j++) { + V[i][j] = H[i][j]; + } + } + } + + // Back transformation to get eigenvectors of original matrix + + for (int j = nn - 1; j >= low; j--) { + for (int i = low; i <= high; i++) { + z = 0.0; + for (int k = low; k <= std::min(j, high); k++) { + z = z + V[i][k] * H[k][j]; + } + V[i][j] = z; + } + } + } + + // Nonsymmetric reduction to Hessenberg form. + void orthes() { + // This is derived from the Algol procedures orthes and ortran, + // by Martin and Wilkinson, Handbook for Auto. Comp., + // Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutines in EISPACK. + int low = 0; + int high = n - 1; + + for (int m = low + 1; m <= high - 1; m++) { + + // Scale column. + + double scale = 0.0; + for (int i = m; i <= high; i++) { + scale = scale + std::abs(H[i][m - 1]); + } + if (scale != 0.0) { + + // Compute Householder transformation. + + double h = 0.0; + for (int i = high; i >= m; i--) { + ort[i] = H[i][m - 1] / scale; + h += ort[i] * ort[i]; + } + double g = std::sqrt(h); + if (ort[m] > 0) { + g = -g; + } + h = h - ort[m] * g; + ort[m] = ort[m] - g; + + // Apply Householder similarity transformation + // H = (I-u*u'/h)*H*(I-u*u')/h) + + for (int j = m; j < n; j++) { + double f = 0.0; + for (int i = high; i >= m; i--) { + f += ort[i] * H[i][j]; + } + f = f / h; + for (int i = m; i <= high; i++) { + H[i][j] -= f * ort[i]; + } + } + + for (int i = 0; i <= high; i++) { + double f = 0.0; + for (int j = high; j >= m; j--) { + f += ort[j] * H[i][j]; + } + f = f / h; + for (int j = m; j <= high; j++) { + H[i][j] -= f * ort[j]; + } + } + ort[m] = scale * ort[m]; + H[m][m - 1] = scale * g; + } + } + + // Accumulate transformations (Algol's ortran). + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + V[i][j] = (i == j ? 1.0 : 0.0); + } + } + + for (int m = high - 1; m >= low + 1; m--) { + if (H[m][m - 1] != 0.0) { + for (int i = m + 1; i <= high; i++) { + ort[i] = H[i][m - 1]; + } + for (int j = m; j <= high; j++) { + double g = 0.0; + for (int i = m; i <= high; i++) { + g += ort[i] * V[i][j]; + } + // Double division avoids possible underflow + g = (g / ort[m]) / H[m][m - 1]; + for (int i = m; i <= high; i++) { + V[i][j] += g * ort[i]; + } + } + } + } + } + + // Releases all internal working memory. + void release() { + // releases the working data + delete[] d; + delete[] e; + delete[] ort; + for (int i = 0; i < n; i++) { + delete[] H[i]; + delete[] V[i]; + } + delete[] H; + delete[] V; + } + + // Computes the Eigenvalue Decomposition for a matrix given in H. + void compute() { + // Allocate memory for the working data. + V = alloc_2d (n, n, 0.0); + d = alloc_1d (n); + e = alloc_1d (n); + ort = alloc_1d (n); + // Reduce to Hessenberg form. + orthes(); + // Reduce Hessenberg to real Schur form. + hqr2(); + // Copy eigenvalues to OpenCV Matrix. + _eigenvalues.create(1, n, CV_64FC1); + for (int i = 0; i < n; i++) { + _eigenvalues.at (0, i) = d[i]; + } + // Copy eigenvectors to OpenCV Matrix. + _eigenvectors.create(n, n, CV_64FC1); + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + _eigenvectors.at (i, j) = V[i][j]; + // Deallocate the memory by releasing all internal working data. + release(); + } + +public: + EigenvalueDecomposition() + : n(0) { } + + // Initializes & computes the Eigenvalue Decomposition for a general matrix + // given in src. This function is a port of the EigenvalueSolver in JAMA, + // which has been released to public domain by The MathWorks and the + // National Institute of Standards and Technology (NIST). + EigenvalueDecomposition(InputArray src) { + compute(src); + } + + // This function computes the Eigenvalue Decomposition for a general matrix + // given in src. This function is a port of the EigenvalueSolver in JAMA, + // which has been released to public domain by The MathWorks and the + // National Institute of Standards and Technology (NIST). + void compute(InputArray src) + { + if(isSymmetric(src)) { + // Fall back to OpenCV for a symmetric matrix! + cv::eigen(src, _eigenvalues, _eigenvectors); + } else { + Mat tmp; + // Convert the given input matrix to double. Is there any way to + // prevent allocating the temporary memory? Only used for copying + // into working memory and deallocated after. + src.getMat().convertTo(tmp, CV_64FC1); + // Get dimension of the matrix. + this->n = tmp.cols; + // Allocate the matrix data to work on. + this->H = alloc_2d (n, n); + // Now safely copy the data. + for (int i = 0; i < tmp.rows; i++) { + for (int j = 0; j < tmp.cols; j++) { + this->H[i][j] = tmp.at(i, j); + } + } + // Deallocates the temporary matrix before computing. + tmp.release(); + // Performs the eigenvalue decomposition of H. + compute(); + } + } + + ~EigenvalueDecomposition() {} + + // Returns the eigenvalues of the Eigenvalue Decomposition. + Mat eigenvalues() { return _eigenvalues; } + // Returns the eigenvectors of the Eigenvalue Decomposition. + Mat eigenvectors() { return _eigenvectors; } +}; + + +//------------------------------------------------------------------------------ +// Linear Discriminant Analysis implementation +//------------------------------------------------------------------------------ + +LDA::LDA(int num_components) : _num_components(num_components) { } + +LDA::LDA(InputArrayOfArrays src, InputArray labels, int num_components) : _num_components(num_components) +{ + this->compute(src, labels); //! compute eigenvectors and eigenvalues +} + +LDA::~LDA() {} + +void LDA::save(const String& filename) const +{ + FileStorage fs(filename, FileStorage::WRITE); + if (!fs.isOpened()) { + CV_Error(Error::StsError, "File can't be opened for writing!"); + } + this->save(fs); + fs.release(); +} + +// Deserializes this object from a given filename. +void LDA::load(const String& filename) { + FileStorage fs(filename, FileStorage::READ); + if (!fs.isOpened()) + CV_Error(Error::StsError, "File can't be opened for writing!"); + this->load(fs); + fs.release(); +} + +// Serializes this object to a given FileStorage. +void LDA::save(FileStorage& fs) const { + // write matrices + fs << "num_components" << _num_components; + fs << "eigenvalues" << _eigenvalues; + fs << "eigenvectors" << _eigenvectors; +} + +// Deserializes this object from a given FileStorage. +void LDA::load(const FileStorage& fs) { + //read matrices + fs["num_components"] >> _num_components; + fs["eigenvalues"] >> _eigenvalues; + fs["eigenvectors"] >> _eigenvectors; +} + +void LDA::lda(InputArrayOfArrays _src, InputArray _lbls) { + // get data + Mat src = _src.getMat(); + std::vector labels; + // safely copy the labels + { + Mat tmp = _lbls.getMat(); + for(unsigned int i = 0; i < tmp.total(); i++) { + labels.push_back(tmp.at(i)); + } + } + // turn into row sampled matrix + Mat data; + // ensure working matrix is double precision + src.convertTo(data, CV_64FC1); + // maps the labels, so they're ascending: [0,1,...,C] + std::vector mapped_labels(labels.size()); + std::vector num2label = remove_dups(labels); + std::map label2num; + for (int i = 0; i < (int)num2label.size(); i++) + label2num[num2label[i]] = i; + for (size_t i = 0; i < labels.size(); i++) + mapped_labels[i] = label2num[labels[i]]; + // get sample size, dimension + int N = data.rows; + int D = data.cols; + // number of unique labels + int C = (int)num2label.size(); + // we can't do a LDA on one class, what do you + // want to separate from each other then? + if(C == 1) { + String error_message = "At least two classes are needed to perform a LDA. Reason: Only one class was given!"; + CV_Error(Error::StsBadArg, error_message); + } + // throw error if less labels, than samples + if (labels.size() != static_cast(N)) { + String error_message = format("The number of samples must equal the number of labels. Given %d labels, %d samples. ", labels.size(), N); + CV_Error(Error::StsBadArg, error_message); + } + // warn if within-classes scatter matrix becomes singular + if (N < D) { + std::cout << "Warning: Less observations than feature dimension given!" + << "Computation will probably fail." + << std::endl; + } + // clip number of components to be a valid number + if ((_num_components <= 0) || (_num_components > (C - 1))) { + _num_components = (C - 1); + } + // holds the mean over all classes + Mat meanTotal = Mat::zeros(1, D, data.type()); + // holds the mean for each class + std::vector meanClass(C); + std::vector numClass(C); + // initialize + for (int i = 0; i < C; i++) { + numClass[i] = 0; + meanClass[i] = Mat::zeros(1, D, data.type()); //! Dx1 image vector + } + // calculate sums + for (int i = 0; i < N; i++) { + Mat instance = data.row(i); + int classIdx = mapped_labels[i]; + add(meanTotal, instance, meanTotal); + add(meanClass[classIdx], instance, meanClass[classIdx]); + numClass[classIdx]++; + } + // calculate total mean + meanTotal.convertTo(meanTotal, meanTotal.type(), 1.0 / static_cast (N)); + // calculate class means + for (int i = 0; i < C; i++) { + meanClass[i].convertTo(meanClass[i], meanClass[i].type(), 1.0 / static_cast (numClass[i])); + } + // subtract class means + for (int i = 0; i < N; i++) { + int classIdx = mapped_labels[i]; + Mat instance = data.row(i); + subtract(instance, meanClass[classIdx], instance); + } + // calculate within-classes scatter + Mat Sw = Mat::zeros(D, D, data.type()); + mulTransposed(data, Sw, true); + // calculate between-classes scatter + Mat Sb = Mat::zeros(D, D, data.type()); + for (int i = 0; i < C; i++) { + Mat tmp; + subtract(meanClass[i], meanTotal, tmp); + mulTransposed(tmp, tmp, true); + add(Sb, tmp, Sb); + } + // invert Sw + Mat Swi = Sw.inv(); + // M = inv(Sw)*Sb + Mat M; + gemm(Swi, Sb, 1.0, Mat(), 0.0, M); + EigenvalueDecomposition es(M); + _eigenvalues = es.eigenvalues(); + _eigenvectors = es.eigenvectors(); + // reshape eigenvalues, so they are stored by column + _eigenvalues = _eigenvalues.reshape(1, 1); + // get sorted indices descending by their eigenvalue + std::vector sorted_indices = argsort(_eigenvalues, false); + // now sort eigenvalues and eigenvectors accordingly + _eigenvalues = sortMatrixColumnsByIndices(_eigenvalues, sorted_indices); + _eigenvectors = sortMatrixColumnsByIndices(_eigenvectors, sorted_indices); + // and now take only the num_components and we're out! + _eigenvalues = Mat(_eigenvalues, Range::all(), Range(0, _num_components)); + _eigenvectors = Mat(_eigenvectors, Range::all(), Range(0, _num_components)); +} + +void LDA::compute(InputArrayOfArrays _src, InputArray _lbls) { + switch(_src.kind()) { + case _InputArray::STD_VECTOR_MAT: + lda(asRowMatrix(_src, CV_64FC1), _lbls); + break; + case _InputArray::MAT: + lda(_src.getMat(), _lbls); + break; + default: + String error_message= format("InputArray Datatype %d is not supported.", _src.kind()); + CV_Error(Error::StsBadArg, error_message); + break; + } +} + +// Projects samples into the LDA subspace. +Mat LDA::project(InputArray src) { + return subspaceProject(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); +} + +// Reconstructs projections from the LDA subspace. +Mat LDA::reconstruct(InputArray src) { + return subspaceReconstruct(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); +} + +} diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index b3c04a6bf3..99711e2587 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -3295,7 +3295,6 @@ void cv::PCABackProject(InputArray data, InputArray mean, pca.backProject(data, result); } - /****************************************************************************************\ * Earlier API * \****************************************************************************************/ diff --git a/modules/imgproc/doc/colormaps.rst b/modules/imgproc/doc/colormaps.rst new file mode 100644 index 0000000000..9881d84ff2 --- /dev/null +++ b/modules/imgproc/doc/colormaps.rst @@ -0,0 +1,107 @@ +ColorMaps in OpenCV +=================== + +applyColorMap +--------------------- + +Applies a GNU Octave/MATLAB equivalent colormap on a given image. + +.. ocv:function:: void applyColorMap(InputArray src, OutputArray dst, int colormap) + + :param src: The source image, grayscale or colored does not matter. + :param dst: The result is the colormapped source image. Note: :ocv:func:`Mat::create` is called on dst. + :param colormap: The colormap to apply, see the list of available colormaps below. + +Currently the following GNU Octave/MATLAB equivalent colormaps are implemented: + +.. code-block:: cpp + + enum + { + COLORMAP_AUTUMN = 0, + COLORMAP_BONE = 1, + COLORMAP_JET = 2, + COLORMAP_WINTER = 3, + COLORMAP_RAINBOW = 4, + COLORMAP_OCEAN = 5, + COLORMAP_SUMMER = 6, + COLORMAP_SPRING = 7, + COLORMAP_COOL = 8, + COLORMAP_HSV = 9, + COLORMAP_PINK = 10, + COLORMAP_HOT = 11 + } + + +Description +----------- + +The human perception isn't built for observing fine changes in grayscale images. Human eyes are more sensitive to observing changes between colors, so you often need to recolor your grayscale images to get a clue about them. OpenCV now comes with various colormaps to enhance the visualization in your computer vision application. + +In OpenCV 2.4 you only need :ocv:func:`applyColorMap` to apply a colormap on a given image. The following sample code reads the path to an image from command line, applies a Jet colormap on it and shows the result: + +.. code-block:: cpp + + #include + #include + #include + + using namespace cv; + + int main(int argc, const char *argv[]) { + // Get the path to the image, if it was given + // if no arguments were given. + String filename; + if (argc > 1) { + filename = String(argv[1]); + } + // The following lines show how to apply a colormap on a given image + // and show it with cv::imshow example with an image. An exception is + // thrown if the path to the image is invalid. + if(!filename.empty()) { + Mat img0 = imread(filename); + // Throw an exception, if the image can't be read: + if(img0.empty()) { + CV_Error(CV_StsBadArg, "Sample image is empty. Please adjust your path, so it points to a valid input image!"); + } + // Holds the colormap version of the image: + Mat cm_img0; + // Apply the colormap: + applyColorMap(img0, cm_img0, COLORMAP_JET); + // Show the result: + imshow("cm_img0", cm_img0); + waitKey(0); + } + + return 0; + } + +And here are the color scales for each of the available colormaps: + ++-----------------------+---------------------------------------------------+ +| Class | Scale | ++=======================+===================================================+ +| COLORMAP_AUTUMN | .. image:: pics/colormaps/colorscale_autumn.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_BONE | .. image:: pics/colormaps/colorscale_bone.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_COOL | .. image:: pics/colormaps/colorscale_cool.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_HOT | .. image:: pics/colormaps/colorscale_hot.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_HSV | .. image:: pics/colormaps/colorscale_hsv.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_JET | .. image:: pics/colormaps/colorscale_jet.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_OCEAN | .. image:: pics/colormaps/colorscale_ocean.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_PINK | .. image:: pics/colormaps/colorscale_pink.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_RAINBOW | .. image:: pics/colormaps/colorscale_rainbow.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_SPRING | .. image:: pics/colormaps/colorscale_spring.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_SUMMER | .. image:: pics/colormaps/colorscale_summer.jpg | ++-----------------------+---------------------------------------------------+ +| COLORMAP_WINTER | .. image:: pics/colormaps/colorscale_winter.jpg | ++-----------------------+---------------------------------------------------+ diff --git a/modules/imgproc/doc/imgproc.rst b/modules/imgproc/doc/imgproc.rst index acaebc4753..93b1cd9f6e 100644 --- a/modules/imgproc/doc/imgproc.rst +++ b/modules/imgproc/doc/imgproc.rst @@ -10,6 +10,7 @@ imgproc. Image Processing filtering geometric_transformations miscellaneous_transformations + colormaps histograms structural_analysis_and_shape_descriptors motion_analysis_and_object_tracking diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_autumn.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_autumn.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c1c8a29b8de2a44d6fe6e646dfd039dd26bcb24 GIT binary patch literal 1352 zcmbVKZ)_7~7{BYacWpN_I$-KPP#J704Ida=)s2i4bjYbSMc26-S;BC`<75epmTqPt zFh$W13*Ze{QyI>BV^Ejb-f+u^B1L4-2<>P`Cs8V!`)k&@&e<62^R}xbh7am;8Y4i6R^!ZuD5L~hWl||2C1oTTe<_8Wq!biM z%2VVDB?|aTO;M(zA9P9Ls6<8(G9^V)@sj_v#J<8*a%>rn5qK6RQQ?FNkGU~5;FQJT z0oX*~5<)5?DS(jz1>z!rPY?iF28f}$0roMeN|wHSjgDMw*hXdTUXpv@$Z7eC4P6(P zZn-(Va&6_Fg9>HF!;d_gnVs|a6Hl(n%hx{j^fLt;pM9=))AO6@S6(eKmcCZTY=6C~ zddC~=&f2{u^FB*medF8j9D4V?!|xwG_95SV{KUzYkJ~=6e=4+}>G<5~61&fT(bN0& zCHLiTu6%p7-|HK=a%=h3n8@XW8Xk-6XIe~%(wh-We$$V&yhB*+5_ z@xmqh;3ZU2+441Hy3Rmt+r2m|_keuKh9jrDE-F^6-7>wja?ed=#>%|A*t56eJO0SGqm1^ud5-qAM@#wgGoe7!~s!kn3)HYV}(ypfT9sylP0}QRNHR|V2O$Ye$ zTDLpXY=d&hR0*^Xff+WATSQM`McV{iuF(eCp;(}2xHm04WN!(q-?{oN015qSEGHWE zfz~Me8D`I2t7sf!%(hM5zK%ODXY|-Xp2-+?$ho?}Z-Z{f%D1~eV}mAjqRoO%tvirb zi1VJPvG8-%cI2)`FIth8G;+5Wbwpzzpj2*Bh0dJrD~Gqng|q_iF;N$`UAd82aiwDF383NJD#LCRf%Eivc4pu@E@&5pWAP0jSBLg#|5(ASU zBeNjm|04|YKzFi&odL?6mQqXwbzED#l4gO`Kd};u4Zls%q*Qnp!5NX66=_R?aT2 zZtfnQUcn)uVc`*xQOPN(Y3Ui6S;Zx#W#tu>Rn0A}ZS5VMU6UqHnL2IyjG40*Enc#8 z+42=DS8dw7W$U)>J9h3mboj{8W5-XNJay^vm8;jT-?(|};iJb-o<4j2;^nK4pFV&2 z`tAFVpT9u<0{IgLu=-07=r1Nv9I%7@#mH0+#LR*$tcr$gLXLs#iG{*SMvWXIP7@by zJjkhR9P~jnspuk?n2O0m)sG;rfqh1t$C}9U8QfzCf8Ao>VP*tI9*!ngS(g~{BTD3>?tsMG6EDw1it;=4SM_zRQ&3_G@-zX4}n z^)Hm3Cd+J5Y0$|2?|)G|++CVv=Y z->YTn8!u$;UA^d1_T0nPqE?ez)UC&MKUA_1+z9fvlcviaeGLWrb z&UME;n+bH-;>%XLiOTcR-Ita4uPuqn&w5^RuJh}P4W*b1&O{ z`m4PNXt>R}$h?v$Ux?aSFSgvf+R~RfS8ne2X}e^NSNsaMU0(ZiUAxaKyQ$qbcDXw) z`?jvx_ifBSpj&v&x2EczcLSRGSNvrx-^{CaQ_mxqQ~G|z^0oWEjb)pCYv*6{ttC?V zSx4Vgne;y>0|wr;Z?kW0$N`2MT0_k14tOG@pYq-6|em}U5F`{|2?|)wB7ORx*a*5I}`tyf@72a;o7(6 zTT6q5Z@d5nVW#Q1m!L4tdX{Y42MnQDxvAe>i)ZC$z4)?zmp1#(v&IWAgDkB|cU@QP z19aBKmvhB7OgwK43}p3dyL8RB7Vk=T`E}hDm{L-TJzi`%zh}P}C;-pBgaz}wbe-*1 zx@r)$;4nVqZgQ^Q@Aqk7cwMR0o_BfQr|ZtkO69$dzKK;{0E`Y$0M|o8ZPT>pi-D&8 e>;3`?|M_0e5zJHWwR-K&sBw|>%~s0&|4jgO{5tOd literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_cool.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_cool.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4253efb99d463ed63e4d70c09ddd09522315d9d8 GIT binary patch literal 1325 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 Mt}!SmyB+QL3w;MAcmMzZ literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_jet.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_jet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea273a570528421024a2fc720876e2a50892adfb GIT binary patch literal 1579 zcmbV~ZBP?e6oz;62?2`{qE@Ypf>?+hihv*k?kE*BRT+&C0ZB%oB7~2kfCxiUrD%mw z{Aem*O+*c-F>X;2Welk(ppJ?OhCmq9fJBm@O(b9p3F&SW>yQ4hJv;Z@v$N;yecySm zz1#jAm`aOU9R+|O0D#B?*n5FU00W|dW(*oQESm8+92Q5w69|q)bao;Torwg3lZ%rx z2@Rxjbs@Q;FX&I+k7DpxES^Lp5FIW5DcS!7$WFjq5Ws@-0Sp<$l0o|&z!TAlcgRD; zz7G(C#o-A=M1~8}&@dH|kHsRQ@rYuiyBPTn;K=xC^8%I=+}Cd*&d>2!yyr-blh=y+ zTa*nlgLmN89ebTg(`U^5a@GQ$g=vAv}^o_A`j7{+g$tgc< zOWmH9zB4y3e^v9r@9Y?bs> zD0`Tnlz9klkudbk=D7qwrg7VbfD{`x^ zN)qTeC{?{qp>-T%6@}_J3k6w^9u*)j=UYzPQC=38 z`?aHKfyIX5gqMn)7f9aqJ{@%!lvnZYFi4;!H;f#t9Bg;4utl>~6pf*Y1rvo;+&k#p(_%HW|;jxP51`XeD z=o!rF3~;PPDKy7iu;Ghtv^_Apj^`JqmO>>4m}Y=iS{T)4 zx)~ywV3LU?mYJrGd2Xf3tyCF@_ikIx6KmqKKK}8K zNJk)2KD@?p%wT*w-55TepPwJm%&Sj*TuhxiiJ1%K?2|{V^LXkb;bp|fMIedsMlkc0 zmxW#$asW>5)hAAmXl|&OEUe%xm(udxRu zDZ8a*cA&xt2Ra~YKb_E3g+z{B++V;)?vHpB4l**LEXa))iHg|>Z&@?XQoHstlzumC z&JvVbm4c(abRtg2;XTkvbCpA(-^esZf7Q~HiRUeh08uWKpdHPs({64PKen-Te#D literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_mkpj1.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_mkpj1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d7e936397f1f5a4b96e4a4783bcbc02ca7a12fb0 GIT binary patch literal 1569 zcmbV~e^ioJ7{_0Ji)Khxu2pi<%58M!DN9RBj=5~H(o-#&Oy$%{My^d$!Zh&oL!o(A zYt5Q#>Z~y`2b@x}KxGBhma_!bF7Fed( zkN>{^ArwYW+mHsKP!NOy59EIUr9x;F63C230*gUr92Seg;&FIf>o^Y8daUu575 zjW8e}zEEf$7#K1Zw_quLM#^Tw_QLR}We0<1u07Fk@ftBYZp+xL9eeKu&tAA3UgSWm z1)TjmV~75ivzNwR`7%P&Fem^ILxyOOmo1dQ%uw2zdTib`y@G0!n`e*hyOKfTvcx>W{Hact{BF^v{>i*TRg#=kj^ouuj;QGmy=%O) z%q3+PK>7fZ9#FZgiKeT%4vUXkIX1D)50$EFLu|2n_3EyD>?c=SZ+>cYQs{ccv#iVQ z1bvINjA6;%)Z^)xZ{=k9p-_&o_@_=9EKN$U_D*O`8K#xI1_?*U&!-!{_hjyoq`0Ki z+{44HJKjyrv|`v?Su5G>lv2|bXE;54D!p4;o?IBO4=B|Vy1sQvXw8rB7IQxIX`Cy( z<63n%jSI49A_44S5G`-JOm3l#A}*+lvga<&()o_Z^v{bGDHDKsGQUq|*XGO}&5jXu zj54gNa;?4$AjgPQhEPl77cSY5HfOZbK}z!&tozxiu8s9O3j|S9((G6ft!g;OfMkVO zNEQ#nItP)@>@28T@H`P-oqDgMQl$>_L-WCgbug86c2_N_=aN8pJ?tgUWs&t2oMG1J zjq=`OTfNcGOA0AOV+qeD<>dk%*|9>wh=B_awkd}4%HqbK4mO(HMdv+W%UtD@MZAJ6 z;MH(x)Gkl$pin8-tJI(uJO(0cYjVo$8ufmGV$#M@(U#mvU~^&nL)o~-#2C(|2-SyF zcMeW=Iq(aO*@#Lk$EWV@Q){d$~krV%-M7K1sB8@C6_K=xn5FQR$g)Aro38p_g>BY zUmrYF*EcjaHMg|3X*yqbb-(H9)xI?h4jE0uW{cJ4;Bs(I=pVTVFc;F10nWjNKyu)N zBA_vImtd!osko?}?(>%J$4^^z;=JsRlb7#C{q*RhXU;R``)L*!9BAWY{|@ZH|04SX z>`$&X;EF=P;h_kC1V+SqQp8xkBK!8Jm(AHwi!x=u^=TP#QtoOas>pIhA*I%mFu2HjY<6~?h4(tEL^7(` zWaDh8F7|^!m5*S()(g}X`!AS=wPTkw zi5cGM(s%_fvHDWmaADo<5g)7l3(Hyi@lbvK3$|Lw8M~6}VZ7K5fh*D{GIkAV_3eG$ z!4NRe!h3>@S2sbRv#9WCrj|KvS)j-@hM7X5Jg(F+I7~Nn$s${`EF}4b%ILepCKAWA z8?SzKOQMbB@O>KdcxN_y+m-6#vPGs!eup-Kahf|^{9Hs%YoA?SX`ZEJ2|5Sl5IDxg z{&nJ?3Nv^O46=_AGk?M9hz)d^g?K?gW(B-Tm5m1Ti2H3J#_14<{W+)s0v^jHmvy%Y zy-JEvI!Q2Tuk;{yv0CAyVyoCk-$1~fBpPaOeZEBz(j-^-^dIi_o5*n=)<1c0-Vy;cA^<y+CO$U*PPiv8y2<|rwmjD=2w)yY#cgM&?OU=5d6D015dS0J}J~X`7;A@^O)CAv9ikA(HhObzx4XuPgI9nL4Jer#IgXQZZ6QMCG zAaE~|p6jNTFWkltocU1Ro0@Z$(^T3oCyHa4CTaBXo|~DyvF#=j>UO`6u`jA3FbyXU*v{$qS69IgckF_Ir*YEXM*Am{&XA5Sr6&n$ F{T;Jd&d2}& literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_ocean.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_ocean.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11d771f71d269bd399032ce6a01a2d2d234d23dd GIT binary patch literal 1430 zcmex=iF;N$`UAd82aiwDF383NJD#LCRf%Eivc4pu@E@&5pWAP0jSBLg#|5(ASU zBeNjm|04|YKzFi&odL?6mQqXwbzED#l4gO`Kd};u4Zls%q*Qnp!5NX66=_R?aT2 zZtfnQUcn)uVc`*xQOPN(Y3Ui6S;Zx#W#tu>Rn0A}ZS5VMU6UqHnL2IyjG40*Enc#8 z+42=DS8dw7W$U)>J9h3mboj{8W5-XNJay^vm8;jT-?(|};iJb-o<4j2;^nK4pFV&2 z`tAFVpT9u<0{IgLu=-07=r1Nv9I%7@#mH0+#LR*$tcr$gLXLs#iG{*SMvWXIP7@by zJjkhR9P~jnspuk?n2O0m)sG;rfqh1t$C}9U8QfzCf8Ao>VP*tI9iYRn{1cCr zTJf51|M_(tQ1)MK_I$AL3zK{IpI@70=Pr8%!rTQ>Qx8_N0IVkcogElYOz@>%EQj_pp8S zLbcQ4cUj-(D~VqL)Ej>osMSjUN_geN^$*w2KQceP@kRMQkbSYw+pX4L2xotIZuJ+@ zdlkj2{<1<%{>OfK{lg&jd!kaMf3$#6v7D!BlZyWy&DU3IGdsVx+E(?it!0xq`OY&a zq*N8iI{L=8ihrrc{F0FD3$;KEi}p41qypn`(Y(3#Qc1NJ{r%?mf;D*OfB(-Qb^CI4 znCkxff3ov^-^N|B6RG^Mz5y7HS1)AlT@4K2aK~leR@p^^!}jXlW#9fY*llfI_HFH3 zP&_R7DU%)y31LXk1EUZgJ(-K26oTUs7*h~6&%c0T3KBibYUWw51lqCx{MwRR;=c}l z{kQeZOJtt$5C7>a{{-*)aQ(yeN^qzg{E_`5d(VgGp})937OL+BhTJ{bSNo%Y0e!V@ z>%kx8tNsFI--rIXe*TgF<^wr>-w*EwiPAKvT!0u2BCrPiF;N$`UAd82aiwDF383NJD#LCRf%Eivc4pu@E@&5pWAP0jSBLg#|5(ASU zBeNjm|04|YKzFi&odL?6mQqXwbzED#l4gO`Kd};u4Zls%q*Qnp!5NX66=_R?aT2 zZtfnQUcn)uVc`*xQOPN(Y3Ui6S;Zx#W#tu>Rn0A}ZS5VMU6UqHnL2IyjG40*Enc#8 z+42=DS8dw7W$U)>J9h3mboj{8W5-XNJay^vm8;jT-?(|};iJb-o<4j2;^nK4pFV&2 z`tAFVpT9u<0{IgLu=-07=r1Nv9I%7@#mH0+#LR*$tcr$gLXLs#iG{*SMvWXIP7@by zJjkhR9P~jnspuk?n2O0m)sG;rfqh1t$C}9U8QfzCf8Ao>VP*tI9_ri<3Ku7&&LU+njK zv&HXzV9X}Fw$5vrw(gg9#i}p(b=`EyS9!0OCG(nJ$9%H&V)tHJdoh-6?&S~b>b-t1 z+Qn(cA5O)=&1axqZ|H7-MU;I z7G$0ICO>no|D|2B*4r=bd~3Y&SGe=?vR~n*&ODC$mwlBFj^0&&SF{z*IvVhCbzWXX ziG0*;pb>}UvLn9z3fns0|JbIS>RRon^UEJccs!c-=JJ-``+MWJzWfo&?Z5lS)!%XR zTgwvrJjEBh()wdtFSU?8F#O@`AJ_LfFPzhTZ7=(!^-*8{um)~@VK=qv`uYdjw-%&) z*E@Xq!|DqqqHc2YTjQD+tdHw^;$8eB8Bg$s+9}^ZP{Z+lkNw5EsW&s`?pw6uKL3~a zrDaj-`772%$~(KfHkr5hWvt%h3$@v^E>-m}E!pMo_;p>S+*0PHm-f9_*X;N5N4PyK z9@ac5zij^HKf{i#yAy#Lxcz^3M{kp5zqYA*?v=B<`5&%bYrYj6K$&}2YszlTz%WjN zMZ=SsPp+Ej*tcz4^Piz@V-A$Db4lga?WS+4YqOIsFHMHV!n29bu9&WY2708K?Y^mN z(=UHqqf+Q!mU*l8{;~D9zWmW@U4HjZ*5CF1hjtqrSLwb`Dq1JEzc-+H#p(}V|771= zc;TGu>$v8Z;cKh@F|D}uMc!*~_Vo{m4tIuXis}-TD6} E04&UFH2?qr literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_rainbow.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_rainbow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9565527aecdc16f4e7fe559c2168a5b0fb6edf9f GIT binary patch literal 1524 zcmbV}e^AqP7{|ZccR%LbECw}n$D)RV(H)P&!8ih*Kv-TxTN?t=mPjDj z*xT6Jp$0q$dpig8fHqmVip9e)-i}BhE|>hL&H58WvVpc>AQ-a^!jdpB31htrQNWz| zP$E0{ozj3aJKb=iG}UuxsA zx30zYpkijbZ+u#gt)1Jt^&8whU-f$Jb#FiaHv-<=^H#{d(6IO3-+$oHM^Vw#!$)Yx zj-NAettIZ+!y%;7cPEP{B_AUf^W;puU1r6U90~7hZ{Ggx9S@j zWp`Tdw%u#*`1zNf`wx1Rs=j{p(D2BUKSrO9jZf%i=k$j81*6G~>OytCuz%D=0=lp$ z10t#mgFOWnOv2%}?jkq`M-t;w$=i0Hv2oeUFRg2__3%A7;~Jl)uyfn)H{_{9r7bJ_ zcfxZ1m$Fr1f9X;~4loA5gGmqqnaH7ILB)MZ&29~rbyv*PxH3I$X-~TW8JPUFS~VuD z5qDdmyvEIBDO*jMQMDa2i!LW{!&^g^+$a5zAu;mYkrcL5(8Q0Rom4s2?AEvwv{S`^ zcE;YLeN`|DMeX^^|_nm(5Hc=@XSa;1#^(@m+prB!#w)9UOEqGFxbjG%)>r!_jJG_%dBXmLo4mT{y+j|hzQ zQ=548j~gs0%^B{4oDqZEFyEgYV#+S$DcUt$%~@Ta zTJP~&U{tSMI?D5&7^LaDT-hnLS)u}2z4CTrpx+|JV|vz6F?xB2Ha2ls{H0#gxQY%E+X%H{Ge3IyipCJR0psc&Ta$cPK;ndNk zOKO>8fRwA;QH_Sj{2upqCpXuK?te-RuAG-#YGWg;j*NUXb_K+cm1~TEf(f4Lyp|mC zcYan#@F@F`Wlg6{$jevDrkso{KKSW$Fp%TvXr$USn)qND9!haU4=AFJu_+ZzXl};l zYUrO7Dp(g39H&~g%qJ9}qFf%Ohu_{eMbFDuH(1Eh40kW4@j9>b*_`iyFt4zi%c@my ziYn4*KEVcYedt6`vF`BPTxVCcGFdbc(Q}POcj}Rhuex$hiB4c*IA_~_mnZG5Ij>w) zF>2Y&C;oDSK>$FBo`Wg^iMZMYF#^bb49J$eAj@#E+!JeJv`2jkcq7#DP5w(JvgzS& zE5y$Uyx&HT(V&284FC`|+N=^7YihWx#fz;Gb+bX*R|d8u56caJ@z~%2z<5F8tD}aQ zsb<%qsy-9t*71$yozJ2a^5PaIMK?Q0)1H3mV1?ezge|?GYO_5jg^AMY8ebtZ5HAyf v@EQP>PPn9Qv;;`g-BXyRChDR2rgKR`5JN$qG_PEn%M@2lWv$U6*8V>MZbHuy literal 0 HcmV?d00001 diff --git a/modules/imgproc/doc/pics/colormaps/colorscale_spring.jpg b/modules/imgproc/doc/pics/colormaps/colorscale_spring.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ada03a160deff66b1f19022dad4e429580a94a6e GIT binary patch literal 1254 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 createGeneralizedHoughGuil(); //! Performs linear blending of two images CV_EXPORTS void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst); +enum +{ + COLORMAP_AUTUMN = 0, + COLORMAP_BONE = 1, + COLORMAP_JET = 2, + COLORMAP_WINTER = 3, + COLORMAP_RAINBOW = 4, + COLORMAP_OCEAN = 5, + COLORMAP_SUMMER = 6, + COLORMAP_SPRING = 7, + COLORMAP_COOL = 8, + COLORMAP_HSV = 9, + COLORMAP_PINK = 10, + COLORMAP_HOT = 11 +}; + +CV_EXPORTS_W void applyColorMap(InputArray src, OutputArray dst, int colormap); + } // cv #endif diff --git a/modules/imgproc/src/colormap.cpp b/modules/imgproc/src/colormap.cpp new file mode 100644 index 0000000000..08ff44a5c6 --- /dev/null +++ b/modules/imgproc/src/colormap.cpp @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2011. Philipp Wagner . + * Released to public domain under terms of the BSD Simplified license. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * See + */ +#include "precomp.hpp" +#include + +#ifdef _MSC_VER +#pragma warning( disable: 4305 ) +#endif + +namespace cv +{ + +static Mat linspace(float x0, float x1, int n) +{ + Mat pts(n, 1, CV_32FC1); + float step = (x1-x0)/(n-1); + for(int i = 0; i < n; i++) + pts.at(i,0) = x0+i*step; + return pts; +} + +//------------------------------------------------------------------------------ +// cv::sortMatrixRowsByIndices +//------------------------------------------------------------------------------ +static void sortMatrixRowsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) +{ + if(_indices.getMat().type() != CV_32SC1) + CV_Error(Error::StsUnsupportedFormat, "cv::sortRowsByIndices only works on integer indices!"); + Mat src = _src.getMat(); + std::vector indices = _indices.getMat(); + _dst.create(src.rows, src.cols, src.type()); + Mat dst = _dst.getMat(); + for(size_t idx = 0; idx < indices.size(); idx++) { + Mat originalRow = src.row(indices[idx]); + Mat sortedRow = dst.row((int)idx); + originalRow.copyTo(sortedRow); + } +} + +static Mat sortMatrixRowsByIndices(InputArray src, InputArray indices) +{ + Mat dst; + sortMatrixRowsByIndices(src, indices, dst); + return dst; +} + + +static Mat argsort(InputArray _src, bool ascending=true) +{ + Mat src = _src.getMat(); + if (src.rows != 1 && src.cols != 1) + CV_Error(Error::StsBadArg, "cv::argsort only sorts 1D matrices."); + int flags = SORT_EVERY_ROW | (ascending ? SORT_ASCENDING : SORT_DESCENDING); + Mat sorted_indices; + sortIdx(src.reshape(1,1),sorted_indices,flags); + return sorted_indices; +} + +template static +Mat interp1_(const Mat& X_, const Mat& Y_, const Mat& XI) +{ + int n = XI.rows; + // sort input table + std::vector sort_indices = argsort(X_); + + Mat X = sortMatrixRowsByIndices(X_,sort_indices); + Mat Y = sortMatrixRowsByIndices(Y_,sort_indices); + // interpolated values + Mat yi = Mat::zeros(XI.size(), XI.type()); + for(int i = 0; i < n; i++) { + int c = 0; + int low = 0; + int high = X.rows - 1; + // set bounds + if(XI.at<_Tp>(i,0) < X.at<_Tp>(low, 0)) + high = 1; + if(XI.at<_Tp>(i,0) > X.at<_Tp>(high, 0)) + low = high - 1; + // binary search + while((high-low)>1) { + c = low + ((high - low) >> 1); + if(XI.at<_Tp>(i,0) > X.at<_Tp>(c,0)) { + low = c; + } else { + high = c; + } + } + // linear interpolation + yi.at<_Tp>(i,0) += Y.at<_Tp>(low,0) + + (XI.at<_Tp>(i,0) - X.at<_Tp>(low,0)) + * (Y.at<_Tp>(high,0) - Y.at<_Tp>(low,0)) + / (X.at<_Tp>(high,0) - X.at<_Tp>(low,0)); + } + return yi; +} + +static Mat interp1(InputArray _x, InputArray _Y, InputArray _xi) +{ + // get matrices + Mat x = _x.getMat(); + Mat Y = _Y.getMat(); + Mat xi = _xi.getMat(); + // check types & alignment + CV_Assert((x.type() == Y.type()) && (Y.type() == xi.type())); + CV_Assert((x.cols == 1) && (x.rows == Y.rows) && (x.cols == Y.cols)); + // call templated interp1 + switch(x.type()) { + case CV_8SC1: return interp1_(x,Y,xi); break; + case CV_8UC1: return interp1_(x,Y,xi); break; + case CV_16SC1: return interp1_(x,Y,xi); break; + case CV_16UC1: return interp1_(x,Y,xi); break; + case CV_32SC1: return interp1_(x,Y,xi); break; + case CV_32FC1: return interp1_(x,Y,xi); break; + case CV_64FC1: return interp1_(x,Y,xi); break; + default: CV_Error(Error::StsUnsupportedFormat, ""); break; + } + return Mat(); +} + +namespace colormap +{ + + class ColorMap { + + protected: + Mat _lut; + + public: + virtual ~ColorMap() {} + + // Applies the colormap on a given image. + // + // This function expects BGR-aligned data of type CV_8UC1 or + // CV_8UC3. If the wrong image type is given, the original image + // will be returned. + // + // Throws an error for wrong-aligned lookup table, which must be + // of size 256 in the latest OpenCV release (2.3.1). + void operator()(InputArray src, OutputArray dst) const; + + // Setup base map to interpolate from. + virtual void init(int n) = 0; + + // Interpolates from a base colormap. + static Mat linear_colormap(InputArray X, + InputArray r, InputArray g, InputArray b, + int n) { + return linear_colormap(X,r,g,b,linspace(0,1,n)); + } + + // Interpolates from a base colormap. + static Mat linear_colormap(InputArray X, + InputArray r, InputArray g, InputArray b, + float begin, float end, float n) { + return linear_colormap(X,r,g,b,linspace(begin,end, cvRound(n))); + } + + // Interpolates from a base colormap. + static Mat linear_colormap(InputArray X, + InputArray r, InputArray g, InputArray b, + InputArray xi); + }; + + // Equals the GNU Octave colormap "autumn". + class Autumn : public ColorMap { + public: + Autumn() : ColorMap() { + init(256); + } + + Autumn(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "bone". + class Bone : public ColorMap { + public: + Bone() : ColorMap() { + init(256); + } + + Bone(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3333333333333333, 0.3472222222222222, 0.3611111111111111, 0.375, 0.3888888888888888, 0.4027777777777777, 0.4166666666666666, 0.4305555555555555, 0.4444444444444444, 0.4583333333333333, 0.4722222222222222, 0.4861111111111112, 0.5, 0.5138888888888888, 0.5277777777777778, 0.5416666666666667, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.611111111111111, 0.6249999999999999, 0.6388888888888888, 0.6527777777777778, 0.6726190476190474, 0.6944444444444442, 0.7162698412698412, 0.7380952380952381, 0.7599206349206349, 0.7817460317460316, 0.8035714285714286, 0.8253968253968254, 0.8472222222222221, 0.8690476190476188, 0.8908730158730158, 0.9126984126984128, 0.9345238095238095, 0.9563492063492063, 0.978174603174603, 1}; + float g[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3353174603174602, 0.3544973544973544, 0.3736772486772486, 0.3928571428571428, 0.412037037037037, 0.4312169312169312, 0.4503968253968254, 0.4695767195767195, 0.4887566137566137, 0.5079365079365078, 0.5271164021164021, 0.5462962962962963, 0.5654761904761904, 0.5846560846560845, 0.6038359788359787, 0.623015873015873, 0.6421957671957671, 0.6613756613756612, 0.6805555555555555, 0.6997354497354497, 0.7189153439153438, 0.7380952380952379, 0.7572751322751322, 0.7764550264550264, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; + float b[] = { 0, 0.01917989417989418, 0.03835978835978836, 0.05753968253968253, 0.07671957671957672, 0.09589947089947089, 0.1150793650793651, 0.1342592592592592, 0.1534391534391534, 0.1726190476190476, 0.1917989417989418, 0.210978835978836, 0.2301587301587301, 0.2493386243386243, 0.2685185185185185, 0.2876984126984127, 0.3068783068783069, 0.326058201058201, 0.3452380952380952, 0.3644179894179894, 0.3835978835978835, 0.4027777777777777, 0.4219576719576719, 0.4411375661375661, 0.4583333333333333, 0.4722222222222222, 0.4861111111111111, 0.5, 0.5138888888888888, 0.5277777777777777, 0.5416666666666666, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.6111111111111112, 0.625, 0.6388888888888888, 0.6527777777777778, 0.6666666666666667, 0.6805555555555556, 0.6944444444444444, 0.7083333333333333, 0.7222222222222222, 0.736111111111111, 0.7499999999999999, 0.7638888888888888, 0.7777777777777778, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + + + + // Equals the GNU Octave colormap "jet". + class Jet : public ColorMap { + + public: + Jet() { + init(256); + } + Jet(int n) : ColorMap() { + init(n); + } + + void init(int n) { + // breakpoints + Mat X = linspace(0,1,256); + // define the basemap + float r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00588235294117645,0.02156862745098032,0.03725490196078418,0.05294117647058827,0.06862745098039214,0.084313725490196,0.1000000000000001,0.115686274509804,0.1313725490196078,0.1470588235294117,0.1627450980392156,0.1784313725490196,0.1941176470588235,0.2098039215686274,0.2254901960784315,0.2411764705882353,0.2568627450980392,0.2725490196078431,0.2882352941176469,0.303921568627451,0.3196078431372549,0.3352941176470587,0.3509803921568628,0.3666666666666667,0.3823529411764706,0.3980392156862744,0.4137254901960783,0.4294117647058824,0.4450980392156862,0.4607843137254901,0.4764705882352942,0.4921568627450981,0.5078431372549019,0.5235294117647058,0.5392156862745097,0.5549019607843135,0.5705882352941174,0.5862745098039217,0.6019607843137256,0.6176470588235294,0.6333333333333333,0.6490196078431372,0.664705882352941,0.6803921568627449,0.6960784313725492,0.7117647058823531,0.7274509803921569,0.7431372549019608,0.7588235294117647,0.7745098039215685,0.7901960784313724,0.8058823529411763,0.8215686274509801,0.8372549019607844,0.8529411764705883,0.8686274509803922,0.884313725490196,0.8999999999999999,0.9156862745098038,0.9313725490196076,0.947058823529412,0.9627450980392158,0.9784313725490197,0.9941176470588236,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9862745098039216,0.9705882352941178,0.9549019607843139,0.93921568627451,0.9235294117647062,0.9078431372549018,0.892156862745098,0.8764705882352941,0.8607843137254902,0.8450980392156864,0.8294117647058825,0.8137254901960786,0.7980392156862743,0.7823529411764705,0.7666666666666666,0.7509803921568627,0.7352941176470589,0.719607843137255,0.7039215686274511,0.6882352941176473,0.6725490196078434,0.6568627450980391,0.6411764705882352,0.6254901960784314,0.6098039215686275,0.5941176470588236,0.5784313725490198,0.5627450980392159,0.5470588235294116,0.5313725490196077,0.5156862745098039,0.5}; + float g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001960784313725483,0.01764705882352935,0.03333333333333333,0.0490196078431373,0.06470588235294117,0.08039215686274503,0.09607843137254901,0.111764705882353,0.1274509803921569,0.1431372549019607,0.1588235294117647,0.1745098039215687,0.1901960784313725,0.2058823529411764,0.2215686274509804,0.2372549019607844,0.2529411764705882,0.2686274509803921,0.2843137254901961,0.3,0.3156862745098039,0.3313725490196078,0.3470588235294118,0.3627450980392157,0.3784313725490196,0.3941176470588235,0.4098039215686274,0.4254901960784314,0.4411764705882353,0.4568627450980391,0.4725490196078431,0.4882352941176471,0.503921568627451,0.5196078431372548,0.5352941176470587,0.5509803921568628,0.5666666666666667,0.5823529411764705,0.5980392156862746,0.6137254901960785,0.6294117647058823,0.6450980392156862,0.6607843137254901,0.6764705882352942,0.692156862745098,0.7078431372549019,0.723529411764706,0.7392156862745098,0.7549019607843137,0.7705882352941176,0.7862745098039214,0.8019607843137255,0.8176470588235294,0.8333333333333333,0.8490196078431373,0.8647058823529412,0.8803921568627451,0.8960784313725489,0.9117647058823528,0.9274509803921569,0.9431372549019608,0.9588235294117646,0.9745098039215687,0.9901960784313726,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9901960784313726,0.9745098039215687,0.9588235294117649,0.943137254901961,0.9274509803921571,0.9117647058823528,0.8960784313725489,0.8803921568627451,0.8647058823529412,0.8490196078431373,0.8333333333333335,0.8176470588235296,0.8019607843137253,0.7862745098039214,0.7705882352941176,0.7549019607843137,0.7392156862745098,0.723529411764706,0.7078431372549021,0.6921568627450982,0.6764705882352944,0.6607843137254901,0.6450980392156862,0.6294117647058823,0.6137254901960785,0.5980392156862746,0.5823529411764707,0.5666666666666669,0.5509803921568626,0.5352941176470587,0.5196078431372548,0.503921568627451,0.4882352941176471,0.4725490196078432,0.4568627450980394,0.4411764705882355,0.4254901960784316,0.4098039215686273,0.3941176470588235,0.3784313725490196,0.3627450980392157,0.3470588235294119,0.331372549019608,0.3156862745098041,0.2999999999999998,0.284313725490196,0.2686274509803921,0.2529411764705882,0.2372549019607844,0.2215686274509805,0.2058823529411766,0.1901960784313728,0.1745098039215689,0.1588235294117646,0.1431372549019607,0.1274509803921569,0.111764705882353,0.09607843137254912,0.08039215686274526,0.06470588235294139,0.04901960784313708,0.03333333333333321,0.01764705882352935,0.001960784313725483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + float b[] = {0.5,0.5156862745098039,0.5313725490196078,0.5470588235294118,0.5627450980392157,0.5784313725490196,0.5941176470588235,0.6098039215686275,0.6254901960784314,0.6411764705882352,0.6568627450980392,0.6725490196078432,0.6882352941176471,0.7039215686274509,0.7196078431372549,0.7352941176470589,0.7509803921568627,0.7666666666666666,0.7823529411764706,0.7980392156862746,0.8137254901960784,0.8294117647058823,0.8450980392156863,0.8607843137254902,0.8764705882352941,0.892156862745098,0.907843137254902,0.9235294117647059,0.9392156862745098,0.9549019607843137,0.9705882352941176,0.9862745098039216,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9941176470588236,0.9784313725490197,0.9627450980392158,0.9470588235294117,0.9313725490196079,0.915686274509804,0.8999999999999999,0.884313725490196,0.8686274509803922,0.8529411764705883,0.8372549019607844,0.8215686274509804,0.8058823529411765,0.7901960784313726,0.7745098039215685,0.7588235294117647,0.7431372549019608,0.7274509803921569,0.7117647058823531,0.696078431372549,0.6803921568627451,0.6647058823529413,0.6490196078431372,0.6333333333333333,0.6176470588235294,0.6019607843137256,0.5862745098039217,0.5705882352941176,0.5549019607843138,0.5392156862745099,0.5235294117647058,0.5078431372549019,0.4921568627450981,0.4764705882352942,0.4607843137254903,0.4450980392156865,0.4294117647058826,0.4137254901960783,0.3980392156862744,0.3823529411764706,0.3666666666666667,0.3509803921568628,0.335294117647059,0.3196078431372551,0.3039215686274508,0.2882352941176469,0.2725490196078431,0.2568627450980392,0.2411764705882353,0.2254901960784315,0.2098039215686276,0.1941176470588237,0.1784313725490199,0.1627450980392156,0.1470588235294117,0.1313725490196078,0.115686274509804,0.1000000000000001,0.08431372549019622,0.06862745098039236,0.05294117647058805,0.03725490196078418,0.02156862745098032,0.00588235294117645,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + // now build lookup table + this->_lut = ColorMap::linear_colormap(X, + Mat(256,1, CV_32FC1, r).clone(), // red + Mat(256,1, CV_32FC1, g).clone(), // green + Mat(256,1, CV_32FC1, b).clone(), // blue + n); + } + }; + + // Equals the GNU Octave colormap "winter". + class Winter : public ColorMap { + public: + Winter() : ColorMap() { + init(256); + } + + Winter(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + float g[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; + float b[] = {1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5}; + Mat X = linspace(0,1,11); + this->_lut = ColorMap::linear_colormap(X, + Mat(11,1, CV_32FC1, r).clone(), // red + Mat(11,1, CV_32FC1, g).clone(), // green + Mat(11,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "rainbow". + class Rainbow : public ColorMap { + public: + Rainbow() : ColorMap() { + init(256); + } + + Rainbow(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9365079365079367, 0.8571428571428572, 0.7777777777777777, 0.6984126984126986, 0.6190476190476191, 0.53968253968254, 0.4603174603174605, 0.3809523809523814, 0.3015873015873018, 0.2222222222222223, 0.1428571428571432, 0.06349206349206415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603208, 0.08465608465608465, 0.1375661375661377, 0.1904761904761907, 0.2433862433862437, 0.2962962962962963, 0.3492063492063493, 0.4021164021164023, 0.4550264550264553, 0.5079365079365079, 0.5608465608465609, 0.6137566137566139, 0.666666666666667}; + float g[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9841269841269842, 0.9047619047619047, 0.8253968253968256, 0.7460317460317465, 0.666666666666667, 0.587301587301587, 0.5079365079365079, 0.4285714285714288, 0.3492063492063493, 0.2698412698412698, 0.1904761904761907, 0.1111111111111116, 0.03174603174603208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01587301587301582, 0.09523809523809534, 0.1746031746031744, 0.2539682539682535, 0.333333333333333, 0.412698412698413, 0.4920634920634921, 0.5714285714285712, 0.6507936507936507, 0.7301587301587302, 0.8095238095238093, 0.8888888888888884, 0.9682539682539679, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "ocean". + class Ocean : public ColorMap { + public: + Ocean() : ColorMap() { + init(256); + } + + Ocean(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904762, 0.09523809523809523, 0.1428571428571428, 0.1904761904761905, 0.2380952380952381, 0.2857142857142857, 0.3333333333333333, 0.3809523809523809, 0.4285714285714285, 0.4761904761904762, 0.5238095238095238, 0.5714285714285714, 0.6190476190476191, 0.6666666666666666, 0.7142857142857143, 0.7619047619047619, 0.8095238095238095, 0.8571428571428571, 0.9047619047619048, 0.9523809523809523, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02380952380952381, 0.04761904761904762, 0.07142857142857142, 0.09523809523809523, 0.119047619047619, 0.1428571428571428, 0.1666666666666667, 0.1904761904761905, 0.2142857142857143, 0.2380952380952381, 0.2619047619047619, 0.2857142857142857, 0.3095238095238095, 0.3333333333333333, 0.3571428571428572, 0.3809523809523809, 0.4047619047619048, 0.4285714285714285, 0.4523809523809524, 0.4761904761904762, 0.5, 0.5238095238095238, 0.5476190476190477, 0.5714285714285714, 0.5952380952380952, 0.6190476190476191, 0.6428571428571429, 0.6666666666666666, 0.6904761904761905, 0.7142857142857143, 0.7380952380952381, 0.7619047619047619, 0.7857142857142857, 0.8095238095238095, 0.8333333333333334, 0.8571428571428571, 0.8809523809523809, 0.9047619047619048, 0.9285714285714286, 0.9523809523809523, 0.9761904761904762, 1}; + float b[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "summer". + class Summer : public ColorMap { + public: + Summer() : ColorMap() { + init(256); + } + + Summer(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float g[] = { 0.5, 0.5079365079365079, 0.5158730158730158, 0.5238095238095238, 0.5317460317460317, 0.5396825396825397, 0.5476190476190477, 0.5555555555555556, 0.5634920634920635, 0.5714285714285714, 0.5793650793650793, 0.5873015873015873, 0.5952380952380952, 0.6031746031746031, 0.6111111111111112, 0.6190476190476191, 0.626984126984127, 0.6349206349206349, 0.6428571428571428, 0.6507936507936508, 0.6587301587301587, 0.6666666666666666, 0.6746031746031746, 0.6825396825396826, 0.6904761904761905, 0.6984126984126984, 0.7063492063492063, 0.7142857142857143, 0.7222222222222222, 0.7301587301587301, 0.7380952380952381, 0.746031746031746, 0.753968253968254, 0.7619047619047619, 0.7698412698412698, 0.7777777777777778, 0.7857142857142857, 0.7936507936507937, 0.8015873015873016, 0.8095238095238095, 0.8174603174603174, 0.8253968253968254, 0.8333333333333333, 0.8412698412698413, 0.8492063492063492, 0.8571428571428572, 0.8650793650793651, 0.873015873015873, 0.8809523809523809, 0.8888888888888888, 0.8968253968253967, 0.9047619047619048, 0.9126984126984127, 0.9206349206349207, 0.9285714285714286, 0.9365079365079365, 0.9444444444444444, 0.9523809523809523, 0.9603174603174602, 0.9682539682539683, 0.9761904761904762, 0.9841269841269842, 0.9920634920634921, 1}; + float b[] = { 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "spring". + class Spring : public ColorMap { + public: + Spring() : ColorMap() { + init(256); + } + + Spring(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float b[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "cool". + class Cool : public ColorMap { + public: + Cool() : ColorMap() { + init(256); + } + + Cool(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float g[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + float b[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "hsv". + class HSV : public ColorMap { + public: + HSV() : ColorMap() { + init(256); + } + + HSV(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428568, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904763, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.0952380952380949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809557, 0.1904761904761905, 0.2857142857142854, 0.3809523809523809, 0.4761904761904765, 0.5714285714285714, 0.6666666666666663, 0.7619047619047619, 0.8571428571428574, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047619, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523814, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "pink". + class Pink : public ColorMap { + public: + Pink() : ColorMap() { + init(256); + } + + Pink(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0.1571348402636772, 0.2222222222222222, 0.2721655269759087, 0.3142696805273544, 0.3513641844631533, 0.3849001794597505, 0.415739709641549, 0.4444444444444444, 0.4714045207910317, 0.4969039949999532, 0.5211573066470477, 0.5443310539518174, 0.5665577237325317, 0.5879447357921312, 0.6085806194501846, 0.6285393610547089, 0.6478835438717, 0.6666666666666666, 0.6849348892187751, 0.7027283689263065, 0.7200822998230956, 0.7370277311900888, 0.753592220347252, 0.7663560447348133, 0.7732293307186413, 0.7800420555749596, 0.7867957924694432, 0.7934920476158722, 0.8001322641986387, 0.8067178260046388, 0.8132500607904444, 0.8197302434079591, 0.8261595987094034, 0.8325393042503717, 0.8388704928078611, 0.8451542547285166, 0.8513916401208816, 0.8575836609041332, 0.8637312927246217, 0.8698354767504924, 0.8758971213537393, 0.8819171036881968, 0.8878962711712378, 0.8938354428762595, 0.8997354108424372, 0.9055969413076769, 0.9114207758701963, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; + float g[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5091750772173156, 0.5328701692569688, 0.5555555555555556, 0.5773502691896257, 0.5983516452371671, 0.6186404847588913, 0.6382847385042254, 0.6573421981221795, 0.6758625033664688, 0.6938886664887108, 0.7114582486036499, 0.7286042804780002, 0.7453559924999299, 0.7617394000445604, 0.7777777777777778, 0.7934920476158723, 0.8089010988089465, 0.8240220541217402, 0.8388704928078611, 0.8534606386520677, 0.8678055195451838, 0.8819171036881968, 0.8958064164776166, 0.9094836413191612, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; + float b[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5039526306789697, 0.5143444998736397, 0.5245305283129621, 0.5345224838248488, 0.5443310539518174, 0.5539659798925444, 0.563436169819011, 0.5727497953228163, 0.5819143739626463, 0.5909368402852788, 0.5998236072282915, 0.6085806194501846, 0.6172133998483676, 0.6257270902992705, 0.6341264874742278, 0.642416074439621, 0.6506000486323554, 0.6586823467062358, 0.6666666666666666, 0.6745564876468501, 0.6823550876255453, 0.6900655593423541, 0.6976908246297114, 0.7052336473499384, 0.7237468644557459, 0.7453559924999298, 0.7663560447348133, 0.7867957924694432, 0.8067178260046388, 0.8261595987094034, 0.8451542547285166, 0.8637312927246217, 0.8819171036881968, 0.8997354108424372, 0.9172076325837248, 0.9343531843023135, 0.9511897312113418, 0.9677334015667416, 0.9839989676081821, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + // Equals the GNU Octave colormap "hot". + class Hot : public ColorMap { + public: + Hot() : ColorMap() { + init(256); + } + + Hot(int n) : ColorMap() { + init(n); + } + + void init(int n) { + float r[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603163, 0.0714285714285714, 0.1111111111111112, 0.1507936507936507, 0.1904761904761905, 0.23015873015873, 0.2698412698412698, 0.3095238095238093, 0.3492063492063491, 0.3888888888888888, 0.4285714285714284, 0.4682539682539679, 0.5079365079365079, 0.5476190476190477, 0.5873015873015872, 0.6269841269841268, 0.6666666666666665, 0.7063492063492065, 0.746031746031746, 0.7857142857142856, 0.8253968253968254, 0.8650793650793651, 0.9047619047619047, 0.9444444444444442, 0.984126984126984, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904745, 0.1269841269841265, 0.2063492063492056, 0.2857142857142856, 0.3650793650793656, 0.4444444444444446, 0.5238095238095237, 0.6031746031746028, 0.6825396825396828, 0.7619047619047619, 0.8412698412698409, 0.92063492063492, 1}; + Mat X = linspace(0,1,64); + this->_lut = ColorMap::linear_colormap(X, + Mat(64,1, CV_32FC1, r).clone(), // red + Mat(64,1, CV_32FC1, g).clone(), // green + Mat(64,1, CV_32FC1, b).clone(), // blue + n); // number of sample points + } + }; + + void ColorMap::operator()(InputArray _src, OutputArray _dst) const + { + if(_lut.total() != 256) + CV_Error(Error::StsAssert, "cv::LUT only supports tables of size 256."); + Mat src = _src.getMat(); + // Return original matrix if wrong type is given (is fail loud better here?) + if(src.type() != CV_8UC1 && src.type() != CV_8UC3) + { + src.copyTo(_dst); + return; + } + // Turn into a BGR matrix into its grayscale representation. + if(src.type() == CV_8UC3) + cvtColor(src.clone(), src, COLOR_BGR2GRAY); + cvtColor(src.clone(), src, COLOR_GRAY2BGR); + // Apply the ColorMap. + LUT(src, _lut, _dst); + } + + Mat ColorMap::linear_colormap(InputArray X, + InputArray r, InputArray g, InputArray b, + InputArray xi) { + Mat lut, lut8; + Mat planes[] = { + interp1(X, b, xi), + interp1(X, g, xi), + interp1(X, r, xi)}; + merge(planes, 3, lut); + lut.convertTo(lut8, CV_8U, 255.); + return lut8; + } + + } + + void applyColorMap(InputArray src, OutputArray dst, int colormap) + { + colormap::ColorMap* cm = + colormap == COLORMAP_AUTUMN ? (colormap::ColorMap*)(new colormap::Autumn) : + colormap == COLORMAP_BONE ? (colormap::ColorMap*)(new colormap::Bone) : + colormap == COLORMAP_COOL ? (colormap::ColorMap*)(new colormap::Cool) : + colormap == COLORMAP_HOT ? (colormap::ColorMap*)(new colormap::Hot) : + colormap == COLORMAP_HSV ? (colormap::ColorMap*)(new colormap::HSV) : + colormap == COLORMAP_JET ? (colormap::ColorMap*)(new colormap::Jet) : + colormap == COLORMAP_OCEAN ? (colormap::ColorMap*)(new colormap::Ocean) : + colormap == COLORMAP_PINK ? (colormap::ColorMap*)(new colormap::Pink) : + colormap == COLORMAP_RAINBOW ? (colormap::ColorMap*)(new colormap::Rainbow) : + colormap == COLORMAP_SPRING ? (colormap::ColorMap*)(new colormap::Spring) : + colormap == COLORMAP_SUMMER ? (colormap::ColorMap*)(new colormap::Summer) : + colormap == COLORMAP_WINTER ? (colormap::ColorMap*)(new colormap::Winter) : 0; + + if( !cm ) + CV_Error( Error::StsBadArg, "Unknown colormap id; use one of COLORMAP_*"); + + (*cm)(src, dst); + + delete cm; + } +} diff --git a/modules/python/common.cmake b/modules/python/common.cmake index 2343c64e8b..d9a0bc18bd 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -15,10 +15,10 @@ endforeach(mp) # module blacklist ocv_list_filterout(candidate_deps "^opencv_cud(a|ev)") ocv_list_filterout(candidate_deps "^opencv_adas$") +ocv_list_filterout(candidate_deps "^opencv_face$") ocv_list_filterout(candidate_deps "^opencv_matlab$") ocv_list_filterout(candidate_deps "^opencv_tracking$") - ocv_add_module(${MODULE_NAME} BINDINGS OPTIONAL ${candidate_deps}) ocv_module_include_directories(