mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 21:20:18 +08:00
added face recognition algorithms, LDA, colormaps (all by Philipp Wagner)
This commit is contained in:
parent
648669cb81
commit
cec8f719a3
@ -845,6 +845,131 @@ namespace cv
|
||||
bool get_uv(double x, double y, int&u, int&v);
|
||||
void create_map(int M, int N, int R, int S, double ro0, double smin);
|
||||
};
|
||||
|
||||
CV_EXPORTS Mat subspaceProject(InputArray W, InputArray mean, InputArray src);
|
||||
CV_EXPORTS Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src);
|
||||
|
||||
class CV_EXPORTS LDA
|
||||
{
|
||||
public:
|
||||
// Initializes a LDA with num_components (default 0) and specifies how
|
||||
// samples are aligned (default dataAsRow=true).
|
||||
LDA(int num_components = 0) :
|
||||
_num_components(num_components) {};
|
||||
|
||||
// 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(const Mat& src, vector<int> labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components)
|
||||
{
|
||||
this->compute(src, labels); //! compute eigenvectors and eigenvalues
|
||||
}
|
||||
|
||||
// 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(InputArray src, InputArray labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components)
|
||||
{
|
||||
this->compute(src, labels); //! compute eigenvectors and eigenvalues
|
||||
}
|
||||
|
||||
// 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(InputArray 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; }
|
||||
|
||||
protected:
|
||||
bool _dataAsRow;
|
||||
int _num_components;
|
||||
Mat _eigenvectors;
|
||||
Mat _eigenvalues;
|
||||
|
||||
void lda(InputArray src, InputArray labels);
|
||||
};
|
||||
|
||||
class CV_EXPORTS FaceRecognizer
|
||||
{
|
||||
public:
|
||||
//! virtual destructor
|
||||
virtual ~FaceRecognizer() {}
|
||||
|
||||
// Trains a FaceRecognizer.
|
||||
virtual void train(InputArray src, InputArray labels) = 0;
|
||||
|
||||
// Gets a prediction from a FaceRecognizer.
|
||||
virtual int predict(InputArray src) const = 0;
|
||||
|
||||
// Serializes this object to a given filename.
|
||||
virtual void save(const string& filename) const;
|
||||
|
||||
// Deserializes this object from a given filename.
|
||||
virtual void load(const string& filename);
|
||||
|
||||
// Serializes this object to a given cv::FileStorage.
|
||||
virtual void save(FileStorage& fs) const = 0;
|
||||
|
||||
// Deserializes this object from a given cv::FileStorage.
|
||||
virtual void load(const FileStorage& fs) = 0;
|
||||
|
||||
// Returns eigenvectors (if any)
|
||||
virtual Mat eigenvectors() const { return Mat(); }
|
||||
};
|
||||
|
||||
CV_EXPORTS Ptr<FaceRecognizer> createEigenFaceRecognizer(int num_components = 0);
|
||||
CV_EXPORTS Ptr<FaceRecognizer> createFisherFaceRecognizer(int num_components = 0);
|
||||
CV_EXPORTS Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius=1, int neighbors=8,
|
||||
int grid_x=8, int grid_y=8);
|
||||
|
||||
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,
|
||||
COLORMAP_MKPJ1 = 12,
|
||||
COLORMAP_MKPJ2 = 13
|
||||
};
|
||||
|
||||
CV_EXPORTS void applyColorMap(InputArray src, OutputArray dst, int colormap);
|
||||
}
|
||||
|
||||
|
||||
|
587
modules/contrib/src/colormap.cpp
Normal file
587
modules/contrib/src/colormap.cpp
Normal file
@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (c) 2011. Philipp Wagner <bytefish[at]gmx[dot]de>.
|
||||
* 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 <http://www.opensource.org/licenses/bsd-license>
|
||||
*/
|
||||
#include "precomp.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static Mat linspace(float x0, float x1, int n)
|
||||
{
|
||||
Mat pts(n, 1, CV_32FC1);
|
||||
float step = (x1-x0)/floor(n-1);
|
||||
for(int i = 0; i < n; i++)
|
||||
pts.at<float>(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(CV_StsUnsupportedFormat, "cv::sortRowsByIndices only works on integer indices!");
|
||||
Mat src = _src.getMat();
|
||||
vector<int> indices = _indices.getMat();
|
||||
_dst.create(src.rows, src.cols, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
for(int idx = 0; idx < indices.size(); idx++) {
|
||||
Mat originalRow = src.row(indices[idx]);
|
||||
Mat sortedRow = dst.row(idx);
|
||||
originalRow.copyTo(sortedRow);
|
||||
}
|
||||
}
|
||||
|
||||
static Mat sortMatrixRowsByIndices(InputArray src, InputArray indices)
|
||||
{
|
||||
Mat dst;
|
||||
sortMatrixRowsByIndices(src, indices, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
Mat argsort(InputArray _src, bool ascending=true)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
if (src.rows != 1 && src.cols != 1)
|
||||
CV_Error(CV_StsBadArg, "cv::argsort only sorts 1D matrices.");
|
||||
int flags = CV_SORT_EVERY_ROW+(ascending ? CV_SORT_ASCENDING : CV_SORT_DESCENDING);
|
||||
Mat sorted_indices;
|
||||
sortIdx(src.reshape(1,1),sorted_indices,flags);
|
||||
return sorted_indices;
|
||||
}
|
||||
|
||||
template <typename _Tp> static
|
||||
Mat interp1_(const Mat& X_, const Mat& Y_, const Mat& XI)
|
||||
{
|
||||
int n = XI.rows;
|
||||
// sort input table
|
||||
vector<int> 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
|
||||
assert((x.type() == Y.type()) && (Y.type() == xi.type()));
|
||||
assert((x.cols == 1) && (x.rows == Y.rows) && (x.cols == Y.cols));
|
||||
// call templated interp1
|
||||
switch(x.type()) {
|
||||
case CV_8SC1: return interp1_<char>(x,Y,xi); break;
|
||||
case CV_8UC1: return interp1_<unsigned char>(x,Y,xi); break;
|
||||
case CV_16SC1: return interp1_<short>(x,Y,xi); break;
|
||||
case CV_16UC1: return interp1_<unsigned short>(x,Y,xi); break;
|
||||
case CV_32SC1: return interp1_<int>(x,Y,xi); break;
|
||||
case CV_32FC1: return interp1_<float>(x,Y,xi); break;
|
||||
case CV_64FC1: return interp1_<double>(x,Y,xi); break;
|
||||
default: CV_Error(CV_StsUnsupportedFormat, ""); 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,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
|
||||
}
|
||||
};
|
||||
|
||||
// A perceptually improved Jet colormap (MKPJ1) by Matteo Niccoli
|
||||
//
|
||||
// Author's personal website:
|
||||
// http://mycarta.wordpress.com/
|
||||
//
|
||||
// Author's FEX page:
|
||||
// http://www.mathworks.com/matlabcentral/fileexchange/authors/87376
|
||||
//
|
||||
class MKPJ1 : public ColorMap {
|
||||
public:
|
||||
MKPJ1() : ColorMap() {
|
||||
init(256);
|
||||
}
|
||||
|
||||
MKPJ1(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.0476, 0.09710000000000001, 0.1466, 0.1961, 0.2456, 0.2952, 0.3447, 0.3942, 0.4437, 0.4932, 0.5427, 0.5921999999999999, 0.6417, 0.6912, 0.7407, 0.7903, 0.8398, 0.8893, 0.9388, 0.9883, 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.007900000000000001, 0.0574, 0.1069, 0.1564, 0.2059, 0.2555, 0.305, 0.3545, 0.404, 0.4535, 0.503, 0.5525, 0.602, 0.6515, 0.701, 0.7506, 0.8001, 0.8496, 0.8991, 0.9486, 0.9981, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9622000000000001, 0.9127, 0.8632, 0.8137, 0.7642, 0.7146, 0.6651, 0.6156, 0.5661, 0.5165999999999999, 0.4671, 0.4176, 0.3681, 0.3186, 0.2691, 0.2195, 0.17, 0.1205, 0.07099999999999999, 0.0215};
|
||||
float b[] = {0.8594000000000001, 0.9089, 0.9584, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9524, 0.9029, 0.8534, 0.8038999999999999, 0.7544, 0.7048, 0.6553, 0.6058, 0.5563, 0.5068, 0.4573, 0.4078, 0.3583, 0.3088, 0.2593, 0.2097, 0.1602, 0.1107, 0.0612, 0.0117, 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
|
||||
}
|
||||
};
|
||||
|
||||
// A perceptually improved Jet colormap (MKPJ2) by Matteo Niccoli
|
||||
//
|
||||
// Author's personal website:
|
||||
// http://mycarta.wordpress.com/
|
||||
//
|
||||
// Author's FEX page:
|
||||
// http://www.mathworks.com/matlabcentral/fileexchange/authors/87376
|
||||
//
|
||||
class MKPJ2 : public ColorMap {
|
||||
public:
|
||||
MKPJ2() : ColorMap() {
|
||||
init(256);
|
||||
}
|
||||
|
||||
MKPJ2(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.0005, 0.0298, 0.0653, 0.1055, 0.1524, 0.2094, 0.2787, 0.3565, 0.4364, 0.5154, 0.5903, 0.6582, 0.7183, 0.7714, 0.8176, 0.8579, 0.8935999999999999, 0.9254, 0.954, 0.98, 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.0116, 0.09089999999999999, 0.1791, 0.2667, 0.3472, 0.4196, 0.4849, 0.5404, 0.5878, 0.6292, 0.6657999999999999, 0.6988, 0.729, 0.7574, 0.7846, 0.8110000000000001, 0.837, 0.8628, 0.8885, 0.9145, 0.9409999999999999, 0.9687, 0.9975000000000001, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9963, 0.9743000000000001, 0.9537, 0.9344, 0.9162, 0.8987000000000001, 0.8821, 0.8659, 0.85, 0.8343, 0.8186, 0.8025, 0.7859, 0.7683, 0.7491, 0.7276, 0.7026, 0.6728, 0.6363, 0.5915, 0.5346, 0.4602};
|
||||
float b[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9995000000000001, 0.9702, 0.9347, 0.8945, 0.8476, 0.7906, 0.7213000000000001, 0.6435, 0.5636, 0.4846, 0.4097, 0.3418, 0.2817, 0.2286, 0.1824, 0.1421, 0.1064, 0.0746, 0.046, 0.02, 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
|
||||
}
|
||||
};
|
||||
|
||||
void ColorMap::operator()(InputArray _src, OutputArray _dst) const
|
||||
{
|
||||
if(_lut.total() != 256)
|
||||
CV_Error(CV_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, CV_BGR2GRAY);
|
||||
cvtColor(src.clone(), src, CV_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_JET ? (colormap::ColorMap*)(new colormap::Jet) :
|
||||
colormap == COLORMAP_WINTER ? (colormap::ColorMap*)(new colormap::Winter) :
|
||||
colormap == COLORMAP_OCEAN ? (colormap::ColorMap*)(new colormap::Ocean) :
|
||||
colormap == COLORMAP_SUMMER ? (colormap::ColorMap*)(new colormap::Summer) :
|
||||
colormap == COLORMAP_SPRING ? (colormap::ColorMap*)(new colormap::Spring) :
|
||||
colormap == COLORMAP_COOL ? (colormap::ColorMap*)(new colormap::Cool) :
|
||||
colormap == COLORMAP_HSV ? (colormap::ColorMap*)(new colormap::HSV) :
|
||||
colormap == COLORMAP_HOT ? (colormap::ColorMap*)(new colormap::Hot) :
|
||||
colormap == COLORMAP_MKPJ1 ? (colormap::ColorMap*)(new colormap::MKPJ1) :
|
||||
colormap == COLORMAP_MKPJ2 ? (colormap::ColorMap*)(new colormap::MKPJ2) : 0;
|
||||
|
||||
if( !cm )
|
||||
CV_Error( CV_StsBadArg, "Unknown colormap id; use one of COLORMAP_*");
|
||||
|
||||
(*cm)(src, dst);
|
||||
|
||||
delete cm;
|
||||
}
|
||||
}
|
716
modules/contrib/src/facerec.cpp
Normal file
716
modules/contrib/src/facerec.cpp
Normal file
@ -0,0 +1,716 @@
|
||||
/*
|
||||
* Copyright (c) 2011. Philipp Wagner <bytefish[at]gmx[dot]de>.
|
||||
* 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 <http://www.opensource.org/licenses/bsd-license>
|
||||
*/
|
||||
#include "precomp.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
using std::set;
|
||||
|
||||
// Reads a sequence from a FileNode::SEQ with type _Tp into a result vector.
|
||||
template<typename _Tp>
|
||||
inline void readFileNodeList(const FileNode& fn, vector<_Tp>& result) {
|
||||
if (fn.type() == FileNode::SEQ) {
|
||||
for (FileNodeIterator it = fn.begin(); it != fn.end();) {
|
||||
_Tp item;
|
||||
it >> item;
|
||||
result.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes the a list of given items to a cv::FileStorage.
|
||||
template<typename _Tp>
|
||||
inline void writeFileNodeList(FileStorage& fs, const string& name,
|
||||
const vector<_Tp>& items) {
|
||||
// typedefs
|
||||
typedef typename vector<_Tp>::const_iterator constVecIterator;
|
||||
// write the elements in item to fs
|
||||
fs << name << "[";
|
||||
for (constVecIterator it = items.begin(); it != items.end(); ++it) {
|
||||
fs << *it;
|
||||
}
|
||||
fs << "]";
|
||||
}
|
||||
|
||||
static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double beta=0)
|
||||
{
|
||||
// number of samples
|
||||
int n = (int) src.total();
|
||||
// return empty matrix if no data given
|
||||
if(n == 0)
|
||||
return Mat();
|
||||
// dimensionality of samples
|
||||
int d = src.getMat(0).total();
|
||||
// create data matrix
|
||||
Mat data(n, d, rtype);
|
||||
// copy data
|
||||
for(int i = 0; i < n; i++) {
|
||||
Mat xi = data.row(i);
|
||||
src.getMat(i).reshape(1, 1).convertTo(xi, rtype, alpha, beta);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// Removes duplicate elements in a given vector.
|
||||
template<typename _Tp>
|
||||
inline vector<_Tp> remove_dups(const vector<_Tp>& src) {
|
||||
typedef typename set<_Tp>::const_iterator constSetIterator;
|
||||
typedef typename vector<_Tp>::const_iterator constVecIterator;
|
||||
set<_Tp> set_elems;
|
||||
for (constVecIterator it = src.begin(); it != src.end(); ++it)
|
||||
set_elems.insert(*it);
|
||||
vector<_Tp> elems;
|
||||
for (constSetIterator it = set_elems.begin(); it != set_elems.end(); ++it)
|
||||
elems.push_back(*it);
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
// Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of
|
||||
// Cognitive Neuroscience 3 (1991), 71–86.
|
||||
class Eigenfaces : public FaceRecognizer
|
||||
{
|
||||
private:
|
||||
int _num_components;
|
||||
vector<Mat> _projections;
|
||||
vector<int> _labels;
|
||||
Mat _eigenvectors;
|
||||
Mat _eigenvalues;
|
||||
Mat _mean;
|
||||
|
||||
public:
|
||||
using FaceRecognizer::save;
|
||||
using FaceRecognizer::load;
|
||||
|
||||
// Initializes an empty Eigenfaces model.
|
||||
Eigenfaces(int num_components = 0) :
|
||||
_num_components(num_components) { }
|
||||
|
||||
// Initializes and computes an Eigenfaces model with images in src and
|
||||
// corresponding labels in labels. num_components will be kept for
|
||||
// classification.
|
||||
Eigenfaces(InputArray src, InputArray labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components) {
|
||||
train(src, labels);
|
||||
}
|
||||
|
||||
// Computes an Eigenfaces model with images in src and corresponding labels
|
||||
// in labels.
|
||||
void train(InputArray src, InputArray labels);
|
||||
|
||||
// Predicts the label of a query image in src.
|
||||
int predict(const InputArray src) const;
|
||||
|
||||
// See FaceRecognizer::load.
|
||||
void load(const FileStorage& fs);
|
||||
|
||||
// See FaceRecognizer::save.
|
||||
void save(FileStorage& fs) const;
|
||||
|
||||
// Returns the eigenvectors of this PCA.
|
||||
Mat eigenvectors() const { return _eigenvectors; }
|
||||
|
||||
// Returns the eigenvalues of this PCA.
|
||||
Mat eigenvalues() const { return _eigenvalues; }
|
||||
|
||||
// Returns the sample mean of this PCA.
|
||||
Mat mean() const { return _mean; }
|
||||
|
||||
// Returns the number of components used in this PCA.
|
||||
int num_components() const { return _num_components; }
|
||||
};
|
||||
|
||||
// Belhumeur, P. N., Hespanha, J., and Kriegman, D. "Eigenfaces vs. Fisher-
|
||||
// faces: Recognition using class specific linear projection.". IEEE
|
||||
// Transactions on Pattern Analysis and Machine Intelligence 19, 7 (1997),
|
||||
// 711–720.
|
||||
class Fisherfaces: public FaceRecognizer
|
||||
{
|
||||
private:
|
||||
int _num_components;
|
||||
Mat _eigenvectors;
|
||||
Mat _eigenvalues;
|
||||
Mat _mean;
|
||||
vector<Mat> _projections;
|
||||
vector<int> _labels;
|
||||
|
||||
public:
|
||||
using FaceRecognizer::save;
|
||||
using FaceRecognizer::load;
|
||||
|
||||
// Initializes an empty Fisherfaces model.
|
||||
Fisherfaces(int num_components = 0) :
|
||||
_num_components(num_components) {}
|
||||
|
||||
// Initializes and computes a Fisherfaces model with images in src and
|
||||
// corresponding labels in labels. num_components will be kept for
|
||||
// classification.
|
||||
Fisherfaces(InputArray src,
|
||||
InputArray labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components) {
|
||||
train(src, labels);
|
||||
}
|
||||
|
||||
~Fisherfaces() { }
|
||||
|
||||
// Computes a Fisherfaces model with images in src and corresponding labels
|
||||
// in labels.
|
||||
void train(InputArray src, InputArray labels);
|
||||
|
||||
// Predicts the label of a query image in src.
|
||||
int predict(InputArray src) const;
|
||||
|
||||
// See FaceRecognizer::load.
|
||||
virtual void load(const FileStorage& fs);
|
||||
|
||||
// See FaceRecognizer::save.
|
||||
virtual void save(FileStorage& fs) const;
|
||||
|
||||
// Returns the eigenvectors of this Fisherfaces model.
|
||||
Mat eigenvectors() const { return _eigenvectors; }
|
||||
|
||||
// Returns the eigenvalues of this Fisherfaces model.
|
||||
Mat eigenvalues() const { return _eigenvalues; }
|
||||
|
||||
// Returns the sample mean of this Fisherfaces model.
|
||||
Mat mean() const { return _eigenvalues; }
|
||||
|
||||
// Returns the number of components used in this Fisherfaces model.
|
||||
int num_components() const { return _num_components; }
|
||||
};
|
||||
|
||||
// Face Recognition based on Local Binary Patterns.
|
||||
//
|
||||
// TODO Allow to change the distance metric.
|
||||
// TODO Allow to change LBP computation (Extended LBP used right now).
|
||||
// TODO Optimize, Optimize, Optimize!
|
||||
//
|
||||
// Ahonen T, Hadid A. and Pietikäinen M. "Face description with local binary
|
||||
// patterns: Application to face recognition." IEEE Transactions on Pattern
|
||||
// Analysis and Machine Intelligence, 28(12):2037-2041.
|
||||
//
|
||||
class LBPH : public FaceRecognizer
|
||||
{
|
||||
private:
|
||||
int _grid_x;
|
||||
int _grid_y;
|
||||
int _radius;
|
||||
int _neighbors;
|
||||
|
||||
vector<Mat> _histograms;
|
||||
vector<int> _labels;
|
||||
|
||||
public:
|
||||
using FaceRecognizer::save;
|
||||
using FaceRecognizer::load;
|
||||
|
||||
// Initializes this LBPH Model. The current implementation is rather fixed
|
||||
// as it uses the Extended Local Binary Patterns per default.
|
||||
//
|
||||
// radius, neighbors are used in the local binary patterns creation.
|
||||
// grid_x, grid_y control the grid size of the spatial histograms.
|
||||
LBPH(int radius=1, int neighbors=8, int grid_x=8, int grid_y=8) :
|
||||
_grid_x(grid_x),
|
||||
_grid_y(grid_y),
|
||||
_radius(radius),
|
||||
_neighbors(neighbors) {}
|
||||
|
||||
// Initializes and computes this LBPH Model. The current implementation is
|
||||
// rather fixed as it uses the Extended Local Binary Patterns per default.
|
||||
//
|
||||
// (radius=1), (neighbors=8) are used in the local binary patterns creation.
|
||||
// (grid_x=8), (grid_y=8) controls the grid size of the spatial histograms.
|
||||
LBPH(InputArray src,
|
||||
InputArray labels,
|
||||
int radius=1, int neighbors=8,
|
||||
int grid_x=8, int grid_y=8) :
|
||||
_grid_x(grid_x),
|
||||
_grid_y(grid_y),
|
||||
_radius(radius),
|
||||
_neighbors(neighbors) {
|
||||
train(src, labels);
|
||||
}
|
||||
|
||||
~LBPH() { }
|
||||
|
||||
// Computes a LBPH model with images in src and
|
||||
// corresponding labels in labels.
|
||||
void train(InputArray src, InputArray labels);
|
||||
|
||||
// Predicts the label of a query image in src.
|
||||
int predict(InputArray src) const;
|
||||
|
||||
// See FaceRecognizer::load.
|
||||
void load(const FileStorage& fs);
|
||||
|
||||
// See FaceRecognizer::save.
|
||||
void save(FileStorage& fs) const;
|
||||
|
||||
// Getter functions.
|
||||
int neighbors() const { return _neighbors; }
|
||||
int radius() const { return _radius; }
|
||||
int grid_x() const { return _grid_x; }
|
||||
int grid_y() const { return _grid_y; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FaceRecognizer
|
||||
//------------------------------------------------------------------------------
|
||||
void FaceRecognizer::save(const string& filename) const {
|
||||
FileStorage fs(filename, FileStorage::WRITE);
|
||||
if (!fs.isOpened())
|
||||
CV_Error(CV_StsError, "File can't be opened for writing!");
|
||||
this->save(fs);
|
||||
fs.release();
|
||||
}
|
||||
|
||||
void FaceRecognizer::load(const string& filename) {
|
||||
FileStorage fs(filename, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
CV_Error(CV_StsError, "File can't be opened for writing!");
|
||||
this->load(fs);
|
||||
fs.release();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Eigenfaces
|
||||
//------------------------------------------------------------------------------
|
||||
void Eigenfaces::train(InputArray src, InputArray _lbls) {
|
||||
// assert type
|
||||
if(_lbls.getMat().type() != CV_32SC1)
|
||||
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||
// get labels
|
||||
vector<int> labels = _lbls.getMat();
|
||||
// observations in row
|
||||
Mat data = asRowMatrix(src, CV_64FC1);
|
||||
// number of samples
|
||||
int n = data.rows;
|
||||
// dimensionality of data
|
||||
//int d = data.cols;
|
||||
// assert there are as much samples as labels
|
||||
if(n != labels.size())
|
||||
CV_Error(CV_StsBadArg, "The number of samples must equal the number of labels!");
|
||||
// clip number of components to be valid
|
||||
if((_num_components <= 0) || (_num_components > n))
|
||||
_num_components = n;
|
||||
// perform the PCA
|
||||
PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, _num_components);
|
||||
// copy the PCA results
|
||||
_mean = pca.mean.reshape(1,1); // store the mean vector
|
||||
_eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row
|
||||
transpose(pca.eigenvectors, _eigenvectors); // eigenvectors by column
|
||||
_labels = labels; // store labels for prediction
|
||||
// save projections
|
||||
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
|
||||
Mat p = subspaceProject(_eigenvectors, _mean, data.row(sampleIdx));
|
||||
this->_projections.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
int Eigenfaces::predict(InputArray _src) const {
|
||||
// get data
|
||||
Mat src = _src.getMat();
|
||||
// project into PCA subspace
|
||||
Mat q = subspaceProject(_eigenvectors, _mean, src.reshape(1,1));
|
||||
double minDist = DBL_MAX;
|
||||
int minClass = -1;
|
||||
for(int sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
|
||||
double dist = norm(_projections[sampleIdx], q, NORM_L2);
|
||||
if(dist < minDist) {
|
||||
minDist = dist;
|
||||
minClass = _labels[sampleIdx];
|
||||
}
|
||||
}
|
||||
return minClass;
|
||||
}
|
||||
|
||||
void Eigenfaces::load(const FileStorage& fs) {
|
||||
//read matrices
|
||||
fs["num_components"] >> _num_components;
|
||||
fs["mean"] >> _mean;
|
||||
fs["eigenvalues"] >> _eigenvalues;
|
||||
fs["eigenvectors"] >> _eigenvectors;
|
||||
// read sequences
|
||||
readFileNodeList(fs["projections"], _projections);
|
||||
readFileNodeList(fs["labels"], _labels);
|
||||
}
|
||||
|
||||
void Eigenfaces::save(FileStorage& fs) const {
|
||||
// write matrices
|
||||
fs << "num_components" << _num_components;
|
||||
fs << "mean" << _mean;
|
||||
fs << "eigenvalues" << _eigenvalues;
|
||||
fs << "eigenvectors" << _eigenvectors;
|
||||
// write sequences
|
||||
writeFileNodeList(fs, "projections", _projections);
|
||||
writeFileNodeList(fs, "labels", _labels);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Fisherfaces
|
||||
//------------------------------------------------------------------------------
|
||||
void Fisherfaces::train(InputArray src, InputArray _lbls) {
|
||||
if(_lbls.getMat().type() != CV_32SC1)
|
||||
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||
// get data
|
||||
vector<int> labels = _lbls.getMat();
|
||||
Mat data = asRowMatrix(src, CV_64FC1);
|
||||
// dimensionality
|
||||
int N = data.rows; // number of samples
|
||||
//int D = data.cols; // dimension of samples
|
||||
// assert correct data alignment
|
||||
if(labels.size() != N)
|
||||
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||
// compute the Fisherfaces
|
||||
int C = remove_dups(labels).size(); // number of unique classes
|
||||
// clip number of components to be a valid number
|
||||
if((_num_components <= 0) || (_num_components > (C-1)))
|
||||
_num_components = (C-1);
|
||||
// perform a PCA and keep (N-C) components
|
||||
PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, (N-C));
|
||||
// project the data and perform a LDA on it
|
||||
LDA lda(pca.project(data),labels, _num_components);
|
||||
// store the total mean vector
|
||||
_mean = pca.mean.reshape(1,1);
|
||||
// store labels
|
||||
_labels = labels;
|
||||
// store the eigenvalues of the discriminants
|
||||
lda.eigenvalues().convertTo(_eigenvalues, CV_64FC1);
|
||||
// Now calculate the projection matrix as pca.eigenvectors * lda.eigenvectors.
|
||||
// Note: OpenCV stores the eigenvectors by row, so we need to transpose it!
|
||||
gemm(pca.eigenvectors, lda.eigenvectors(), 1.0, Mat(), 0.0, _eigenvectors, CV_GEMM_A_T);
|
||||
// store the projections of the original data
|
||||
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
|
||||
Mat p = subspaceProject(_eigenvectors, _mean, data.row(sampleIdx));
|
||||
_projections.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
int Fisherfaces::predict(InputArray _src) const {
|
||||
Mat src = _src.getMat();
|
||||
// project into LDA subspace
|
||||
Mat q = subspaceProject(_eigenvectors, _mean, src.reshape(1,1));
|
||||
// find 1-nearest neighbor
|
||||
double minDist = DBL_MAX;
|
||||
int minClass = -1;
|
||||
for(int sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
|
||||
double dist = norm(_projections[sampleIdx], q, NORM_L2);
|
||||
if(dist < minDist) {
|
||||
minDist = dist;
|
||||
minClass = _labels[sampleIdx];
|
||||
}
|
||||
}
|
||||
return minClass;
|
||||
}
|
||||
|
||||
|
||||
// See FaceRecognizer::load.
|
||||
void Fisherfaces::load(const FileStorage& fs) {
|
||||
//read matrices
|
||||
fs["num_components"] >> _num_components;
|
||||
fs["mean"] >> _mean;
|
||||
fs["eigenvalues"] >> _eigenvalues;
|
||||
fs["eigenvectors"] >> _eigenvectors;
|
||||
// read sequences
|
||||
readFileNodeList(fs["projections"], _projections);
|
||||
readFileNodeList(fs["labels"], _labels);
|
||||
}
|
||||
|
||||
// See FaceRecognizer::save.
|
||||
void Fisherfaces::save(FileStorage& fs) const {
|
||||
// write matrices
|
||||
fs << "num_components" << _num_components;
|
||||
fs << "mean" << _mean;
|
||||
fs << "eigenvalues" << _eigenvalues;
|
||||
fs << "eigenvectors" << _eigenvectors;
|
||||
// write sequences
|
||||
writeFileNodeList(fs, "projections", _projections);
|
||||
writeFileNodeList(fs, "labels", _labels);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// LBPH
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename _Tp> static
|
||||
void olbp_(InputArray _src, OutputArray _dst) {
|
||||
// get matrices
|
||||
Mat src = _src.getMat();
|
||||
// allocate memory for result
|
||||
_dst.create(src.rows-2, src.cols-2, CV_8UC1);
|
||||
Mat dst = _dst.getMat();
|
||||
// zero the result matrix
|
||||
dst.setTo(0);
|
||||
// calculate patterns
|
||||
for(int i=1;i<src.rows-1;i++) {
|
||||
for(int j=1;j<src.cols-1;j++) {
|
||||
_Tp center = src.at<_Tp>(i,j);
|
||||
unsigned char code = 0;
|
||||
code |= (src.at<_Tp>(i-1,j-1) >= center) << 7;
|
||||
code |= (src.at<_Tp>(i-1,j) >= center) << 6;
|
||||
code |= (src.at<_Tp>(i-1,j+1) >= center) << 5;
|
||||
code |= (src.at<_Tp>(i,j+1) >= center) << 4;
|
||||
code |= (src.at<_Tp>(i+1,j+1) >= center) << 3;
|
||||
code |= (src.at<_Tp>(i+1,j) >= center) << 2;
|
||||
code |= (src.at<_Tp>(i+1,j-1) >= center) << 1;
|
||||
code |= (src.at<_Tp>(i,j-1) >= center) << 0;
|
||||
dst.at<unsigned char>(i-1,j-1) = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// cv::elbp
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename _Tp> static
|
||||
inline void elbp_(InputArray _src, OutputArray _dst, int radius, int neighbors) {
|
||||
//get matrices
|
||||
Mat src = _src.getMat();
|
||||
// allocate memory for result
|
||||
_dst.create(src.rows-2*radius, src.cols-2*radius, CV_32SC1);
|
||||
Mat dst = _dst.getMat();
|
||||
// zero
|
||||
dst.setTo(0);
|
||||
for(int n=0; n<neighbors; n++) {
|
||||
// sample points
|
||||
float x = static_cast<float>(-radius) * sin(2.0*CV_PI*n/static_cast<float>(neighbors));
|
||||
float y = static_cast<float>(radius) * cos(2.0*CV_PI*n/static_cast<float>(neighbors));
|
||||
// relative indices
|
||||
int fx = static_cast<int>(floor(x));
|
||||
int fy = static_cast<int>(floor(y));
|
||||
int cx = static_cast<int>(ceil(x));
|
||||
int cy = static_cast<int>(ceil(y));
|
||||
// fractional part
|
||||
float ty = y - fy;
|
||||
float tx = x - fx;
|
||||
// set interpolation weights
|
||||
float w1 = (1 - tx) * (1 - ty);
|
||||
float w2 = tx * (1 - ty);
|
||||
float w3 = (1 - tx) * ty;
|
||||
float w4 = tx * ty;
|
||||
// iterate through your data
|
||||
for(int i=radius; i < src.rows-radius;i++) {
|
||||
for(int j=radius;j < src.cols-radius;j++) {
|
||||
// calculate interpolated value
|
||||
float t = w1*src.at<_Tp>(i+fy,j+fx) + w2*src.at<_Tp>(i+fy,j+cx) + w3*src.at<_Tp>(i+cy,j+fx) + w4*src.at<_Tp>(i+cy,j+cx);
|
||||
// floating point precision, so check some machine-dependent epsilon
|
||||
dst.at<int>(i-radius,j-radius) += ((t > src.at<_Tp>(i,j)) || (std::abs(t-src.at<_Tp>(i,j)) < std::numeric_limits<float>::epsilon())) << n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void elbp(InputArray src, OutputArray dst, int radius, int neighbors)
|
||||
{
|
||||
switch (src.type()) {
|
||||
case CV_8SC1: elbp_<char>(src,dst, radius, neighbors); break;
|
||||
case CV_8UC1: elbp_<unsigned char>(src, dst, radius, neighbors); break;
|
||||
case CV_16SC1: elbp_<short>(src,dst, radius, neighbors); break;
|
||||
case CV_16UC1: elbp_<unsigned short>(src,dst, radius, neighbors); break;
|
||||
case CV_32SC1: elbp_<int>(src,dst, radius, neighbors); break;
|
||||
case CV_32FC1: elbp_<float>(src,dst, radius, neighbors); break;
|
||||
case CV_64FC1: elbp_<double>(src,dst, radius, neighbors); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static Mat
|
||||
histc_(const Mat& src, int minVal=0, int maxVal=255, bool normed=false)
|
||||
{
|
||||
Mat result;
|
||||
// Establish the number of bins.
|
||||
int histSize = maxVal-minVal+1;
|
||||
// Set the ranges.
|
||||
float range[] = { minVal, maxVal } ;
|
||||
const float* histRange = { range };
|
||||
// calc histogram
|
||||
calcHist(&src, 1, 0, Mat(), result, 1, &histSize, &histRange, true, false);
|
||||
// normalize
|
||||
if(normed) {
|
||||
result /= src.total();
|
||||
}
|
||||
return result.reshape(1,1);
|
||||
}
|
||||
|
||||
static Mat histc(InputArray _src, int minVal, int maxVal, bool normed)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
switch (src.type()) {
|
||||
case CV_8SC1:
|
||||
return histc_(Mat_<float>(src), minVal, maxVal, normed);
|
||||
break;
|
||||
case CV_8UC1:
|
||||
return histc_(src, minVal, maxVal, normed);
|
||||
break;
|
||||
case CV_16SC1:
|
||||
return histc_(Mat_<float>(src), minVal, maxVal, normed);
|
||||
break;
|
||||
case CV_16UC1:
|
||||
return histc_(src, minVal, maxVal, normed);
|
||||
break;
|
||||
case CV_32SC1:
|
||||
return histc_(Mat_<float>(src), minVal, maxVal, normed);
|
||||
break;
|
||||
case CV_32FC1:
|
||||
return histc_(src, minVal, maxVal, normed);
|
||||
break;
|
||||
default:
|
||||
CV_Error(CV_StsUnmatchedFormats, "This type is not implemented yet."); break;
|
||||
}
|
||||
return Mat();
|
||||
}
|
||||
|
||||
|
||||
static Mat spatial_histogram(InputArray _src, int numPatterns,
|
||||
int grid_x, int grid_y, bool normed)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
// calculate LBP patch size
|
||||
int width = static_cast<int>(floor(src.cols/grid_x));
|
||||
int height = static_cast<int>(floor(src.rows/grid_y));
|
||||
// allocate memory for the spatial histogram
|
||||
Mat result = Mat::zeros(grid_x * grid_y, numPatterns, CV_32FC1);
|
||||
// return matrix with zeros if no data was given
|
||||
if(src.empty())
|
||||
return result.reshape(1,1);
|
||||
// initial result_row
|
||||
int resultRowIdx = 0;
|
||||
// iterate through grid
|
||||
for(int i = 0; i < grid_y; i++) {
|
||||
for(int j = 0; j < grid_x; j++) {
|
||||
Mat src_cell = Mat(src, Range(i*height,(i+1)*height), Range(j*width,(j+1)*width));
|
||||
Mat cell_hist = histc(src_cell, 0, (numPatterns-1), true);
|
||||
// copy to the result matrix
|
||||
Mat result_row = result.row(resultRowIdx);
|
||||
cell_hist.reshape(1,1).convertTo(result_row, CV_32FC1);
|
||||
// increase row count in result matrix
|
||||
resultRowIdx++;
|
||||
}
|
||||
}
|
||||
// return result as reshaped feature vector
|
||||
return result.reshape(1,1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// cv::elbp, cv::olbp, cv::varlbp wrapper
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static Mat elbp(InputArray src, int radius, int neighbors) {
|
||||
Mat dst;
|
||||
elbp(src, dst, radius, neighbors);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void LBPH::load(const FileStorage& fs) {
|
||||
fs["radius"] >> _radius;
|
||||
fs["neighbors"] >> _neighbors;
|
||||
fs["grid_x"] >> _grid_x;
|
||||
fs["grid_y"] >> _grid_y;
|
||||
//read matrices
|
||||
readFileNodeList(fs["histograms"], _histograms);
|
||||
readFileNodeList(fs["labels"], _labels);
|
||||
}
|
||||
|
||||
// See FaceRecognizer::save.
|
||||
void LBPH::save(FileStorage& fs) const {
|
||||
fs << "radius" << _radius;
|
||||
fs << "neighbors" << _neighbors;
|
||||
fs << "grid_x" << _grid_x;
|
||||
fs << "grid_y" << _grid_y;
|
||||
// write matrices
|
||||
writeFileNodeList(fs, "histograms", _histograms);
|
||||
writeFileNodeList(fs, "labels", _labels);
|
||||
}
|
||||
|
||||
void LBPH::train(InputArray _src, InputArray _lbls) {
|
||||
if(_src.kind() != _InputArray::STD_VECTOR_MAT && _src.kind() != _InputArray::STD_VECTOR_VECTOR)
|
||||
CV_Error(CV_StsUnsupportedFormat, "LBPH::train expects InputArray::STD_VECTOR_MAT or _InputArray::STD_VECTOR_VECTOR.");
|
||||
// get the vector of matrices
|
||||
vector<Mat> src;
|
||||
_src.getMatVector(src);
|
||||
// turn the label matrix into a vector
|
||||
vector<int> labels = _lbls.getMat();
|
||||
if(labels.size() != src.size())
|
||||
CV_Error(CV_StsUnsupportedFormat, "The number of labels must equal the number of samples.");
|
||||
// store given labels
|
||||
_labels = labels;
|
||||
// store the spatial histograms of the original data
|
||||
for(int sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
|
||||
// calculate lbp image
|
||||
Mat lbp_image = elbp(src[sampleIdx], _radius, _neighbors);
|
||||
// get spatial histogram from this lbp image
|
||||
Mat p = spatial_histogram(
|
||||
lbp_image, /* lbp_image */
|
||||
static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), /* number of possible patterns */
|
||||
_grid_x, /* grid size x */
|
||||
_grid_y, /* grid size y */
|
||||
true);
|
||||
// add to templates
|
||||
_histograms.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int LBPH::predict(InputArray _src) const {
|
||||
Mat src = _src.getMat();
|
||||
// get the spatial histogram from input image
|
||||
Mat lbp_image = elbp(src, _radius, _neighbors);
|
||||
Mat query = spatial_histogram(
|
||||
lbp_image, /* lbp_image */
|
||||
static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), /* number of possible patterns */
|
||||
_grid_x, /* grid size x */
|
||||
_grid_y, /* grid size y */
|
||||
true /* normed histograms */);
|
||||
// find 1-nearest neighbor
|
||||
double minDist = DBL_MAX;
|
||||
int minClass = -1;
|
||||
for(int sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
|
||||
double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
|
||||
if(dist < minDist) {
|
||||
minDist = dist;
|
||||
minClass = _labels[sampleIdx];
|
||||
}
|
||||
}
|
||||
return minClass;
|
||||
}
|
||||
|
||||
|
||||
Ptr<FaceRecognizer> createEigenFaceRecognizer(int num_components)
|
||||
{
|
||||
return new Eigenfaces(num_components);
|
||||
}
|
||||
|
||||
Ptr<FaceRecognizer> createFisherFaceRecognizer(int num_components)
|
||||
{
|
||||
return new Fisherfaces(num_components);
|
||||
}
|
||||
|
||||
Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius, int neighbors,
|
||||
int grid_x, int grid_y)
|
||||
{
|
||||
return new LBPH(radius, neighbors, grid_x, grid_y);
|
||||
}
|
||||
|
||||
}
|
1055
modules/contrib/src/lda.cpp
Normal file
1055
modules/contrib/src/lda.cpp
Normal file
File diff suppressed because it is too large
Load Diff
91
samples/cpp/facerec_demo.cpp
Normal file
91
samples/cpp/facerec_demo.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2011. Philipp Wagner <bytefish[at]gmx[dot]de>.
|
||||
* 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 <http://www.opensource.org/licenses/bsd-license>
|
||||
*/
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
|
||||
std::ifstream file(filename.c_str(), ifstream::in);
|
||||
if (!file)
|
||||
throw std::exception();
|
||||
string line, path, classlabel;
|
||||
while (getline(file, line)) {
|
||||
stringstream liness(line);
|
||||
getline(liness, path, separator);
|
||||
getline(liness, classlabel);
|
||||
images.push_back(imread(path, 0));
|
||||
labels.push_back(atoi(classlabel.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
// check for command line arguments
|
||||
if (argc != 2) {
|
||||
cout << "usage: " << argv[0] << " <csv.ext>" << endl;
|
||||
exit(1);
|
||||
}
|
||||
// path to your CSV
|
||||
string fn_csv = string(argv[1]);
|
||||
// images and corresponding labels
|
||||
vector<Mat> images;
|
||||
vector<int> labels;
|
||||
// read in the data
|
||||
try {
|
||||
read_csv(fn_csv, images, labels);
|
||||
} catch (exception& e) {
|
||||
cerr << "Error opening file \"" << fn_csv << "\"." << endl;
|
||||
exit(1);
|
||||
}
|
||||
// get width and height
|
||||
//int width = images[0].cols;
|
||||
int height = images[0].rows;
|
||||
// get test instances
|
||||
Mat testSample = images[images.size() - 1];
|
||||
int testLabel = labels[labels.size() - 1];
|
||||
// ... and delete last element
|
||||
images.pop_back();
|
||||
labels.pop_back();
|
||||
// build the Fisherfaces model
|
||||
Ptr<FaceRecognizer> model = createFisherFaceRecognizer();
|
||||
model->train(images, labels);
|
||||
// test model
|
||||
int predicted = model->predict(testSample);
|
||||
cout << "predicted class = " << predicted << endl;
|
||||
cout << "actual class = " << testLabel << endl;
|
||||
// get the eigenvectors
|
||||
Mat W = model->eigenvectors();
|
||||
// show first 10 fisherfaces
|
||||
for (int i = 0; i < min(10, W.cols); i++) {
|
||||
// get eigenvector #i
|
||||
Mat ev = W.col(i).clone();
|
||||
// reshape to original site
|
||||
Mat grayscale, cgrayscale;
|
||||
cvtColor(ev.reshape(1, height), grayscale, COLOR_BGR2GRAY);
|
||||
// show image (with Jet colormap)
|
||||
applyColorMap(grayscale, cgrayscale, COLORMAP_JET);
|
||||
imshow(format("%d", i), cgrayscale);
|
||||
}
|
||||
waitKey(0);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user