Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
cec8f719
Commit
cec8f719
authored
Mar 24, 2012
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added face recognition algorithms, LDA, colormaps (all by Philipp Wagner)
parent
648669cb
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
2574 additions
and
0 deletions
+2574
-0
contrib.hpp
modules/contrib/include/opencv2/contrib/contrib.hpp
+125
-0
colormap.cpp
modules/contrib/src/colormap.cpp
+587
-0
facerec.cpp
modules/contrib/src/facerec.cpp
+716
-0
lda.cpp
modules/contrib/src/lda.cpp
+1055
-0
facerec_demo.cpp
samples/cpp/facerec_demo.cpp
+91
-0
No files found.
modules/contrib/include/opencv2/contrib/contrib.hpp
View file @
cec8f719
...
...
@@ -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
);
}
...
...
modules/contrib/src/colormap.cpp
0 → 100644
View file @
cec8f719
/*
* 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
;
}
}
modules/contrib/src/facerec.cpp
0 → 100644
View file @
cec8f719
/*
* 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
);
}
}
modules/contrib/src/lda.cpp
0 → 100644
View file @
cec8f719
/*
* 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>
#include <map>
#include <set>
namespace
cv
{
using
std
::
map
;
using
std
::
set
;
using
std
::
cout
;
using
std
::
endl
;
// 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
;
}
static
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
;
}
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
;
}
void
sortMatrixColumnsByIndices
(
InputArray
_src
,
InputArray
_indices
,
OutputArray
_dst
)
{
if
(
_indices
.
getMat
().
type
()
!=
CV_32SC1
)
CV_Error
(
CV_StsUnsupportedFormat
,
"cv::sortColumnsByIndices 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
originalCol
=
src
.
col
(
indices
[
idx
]);
Mat
sortedCol
=
dst
.
col
(
idx
);
originalCol
.
copyTo
(
sortedCol
);
}
}
Mat
sortMatrixColumnsByIndices
(
InputArray
src
,
InputArray
indices
)
{
Mat
dst
;
sortMatrixColumnsByIndices
(
src
,
indices
,
dst
);
return
dst
;
}
template
<
typename
_Tp
>
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
<
typename
_Tp
>
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_
<
char
>
(
m
);
break
;
case
CV_8UC1
:
return
isSymmetric_
<
unsigned
char
>
(
m
);
break
;
case
CV_16SC1
:
return
isSymmetric_
<
short
>
(
m
);
break
;
case
CV_16UC1
:
return
isSymmetric_
<
unsigned
short
>
(
m
);
break
;
case
CV_32SC1
:
return
isSymmetric_
<
int
>
(
m
);
break
;
case
CV_32FC1
:
return
isSymmetric_
<
float
>
(
m
,
eps
);
break
;
case
CV_64FC1
:
return
isSymmetric_
<
double
>
(
m
,
eps
);
break
;
default
:
break
;
}
return
false
;
}
//------------------------------------------------------------------------------
// subspace::project
//------------------------------------------------------------------------------
Mat
subspaceProject
(
InputArray
_W
,
InputArray
_mean
,
InputArray
_src
)
{
// get data matrices
Mat
W
=
_W
.
getMat
();
Mat
mean
=
_mean
.
getMat
();
Mat
src
=
_src
.
getMat
();
// create temporary matrices
Mat
X
,
Y
;
// copy data & make sure we are using the correct type
src
.
convertTo
(
X
,
W
.
type
());
// get number of samples and dimension
int
n
=
X
.
rows
;
int
d
=
X
.
cols
;
// center the data if correct aligned sample mean is given
if
(
mean
.
total
()
==
d
)
subtract
(
X
,
repeat
(
mean
.
reshape
(
1
,
1
),
n
,
1
),
X
);
// finally calculate projection as Y = (X-mean)*W
gemm
(
X
,
W
,
1.0
,
Mat
(),
0.0
,
Y
);
return
Y
;
}
//------------------------------------------------------------------------------
// subspace::reconstruct
//------------------------------------------------------------------------------
Mat
subspaceReconstruct
(
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
;
// initalize temporary matrices
Mat
X
,
Y
;
// copy data & make sure we are using the correct type
src
.
convertTo
(
Y
,
W
.
type
());
// calculate the reconstruction
gemm
(
Y
,
W
,
1.0
,
(
d
==
mean
.
total
())
?
repeat
(
mean
.
reshape
(
1
,
1
),
n
,
1
)
:
Mat
(),
(
d
==
mean
.
total
())
?
1.0
:
0.0
,
X
,
GEMM_2_T
);
return
X
;
}
class
EigenvalueDecomposition
{
private
:
// Holds the data dimension.
int
n
;
// Stores real/imag part of a complex division.
double
cdivr
,
cdivi
;
// Pointer to internal memory.
double
*
d
,
*
e
,
*
ort
;
double
**
V
,
**
H
;
// Holds the computed eigenvalues.
Mat
_eigenvalues
;
// Holds the computed eigenvectors.
Mat
_eigenvectors
;
// Allocates memory.
template
<
typename
_Tp
>
_Tp
*
alloc_1d
(
int
m
)
{
return
new
_Tp
[
m
];
}
// Allocates memory.
template
<
typename
_Tp
>
_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
<
typename
_Tp
>
_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
<
typename
_Tp
>
_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
,
d
;
if
(
std
::
abs
(
yr
)
>
std
::
abs
(
yi
))
{
r
=
yi
/
yr
;
d
=
yr
+
r
*
yi
;
cdivr
=
(
xr
+
r
*
xi
)
/
d
;
cdivi
=
(
xi
-
r
*
xr
)
/
d
;
}
else
{
r
=
yr
/
yi
;
d
=
yi
+
r
*
yr
;
cdivr
=
(
r
*
xr
+
xi
)
/
d
;
cdivi
=
(
r
*
xi
-
xr
)
/
d
;
}
}
// 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
n
=
nn
-
1
;
int
low
=
0
;
int
high
=
nn
-
1
;
double
eps
=
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
=
max
(
i
-
1
,
0
);
j
<
nn
;
j
++
)
{
norm
=
norm
+
std
::
abs
(
H
[
i
][
j
]);
}
}
// Outer loop over eigenvalue index
int
iter
=
0
;
while
(
n
>=
low
)
{
// Look for single small sub-diagonal element
int
l
=
n
;
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
==
n
)
{
H
[
n
][
n
]
=
H
[
n
][
n
]
+
exshift
;
d
[
n
]
=
H
[
n
][
n
];
e
[
n
]
=
0.0
;
n
--
;
iter
=
0
;
// Two roots found
}
else
if
(
l
==
n
-
1
)
{
w
=
H
[
n
][
n
-
1
]
*
H
[
n
-
1
][
n
];
p
=
(
H
[
n
-
1
][
n
-
1
]
-
H
[
n
][
n
])
/
2.0
;
q
=
p
*
p
+
w
;
z
=
sqrt
(
std
::
abs
(
q
));
H
[
n
][
n
]
=
H
[
n
][
n
]
+
exshift
;
H
[
n
-
1
][
n
-
1
]
=
H
[
n
-
1
][
n
-
1
]
+
exshift
;
x
=
H
[
n
][
n
];
// Real pair
if
(
q
>=
0
)
{
if
(
p
>=
0
)
{
z
=
p
+
z
;
}
else
{
z
=
p
-
z
;
}
d
[
n
-
1
]
=
x
+
z
;
d
[
n
]
=
d
[
n
-
1
];
if
(
z
!=
0.0
)
{
d
[
n
]
=
x
-
w
/
z
;
}
e
[
n
-
1
]
=
0.0
;
e
[
n
]
=
0.0
;
x
=
H
[
n
][
n
-
1
];
s
=
std
::
abs
(
x
)
+
std
::
abs
(
z
);
p
=
x
/
s
;
q
=
z
/
s
;
r
=
sqrt
(
p
*
p
+
q
*
q
);
p
=
p
/
r
;
q
=
q
/
r
;
// Row modification
for
(
int
j
=
n
-
1
;
j
<
nn
;
j
++
)
{
z
=
H
[
n
-
1
][
j
];
H
[
n
-
1
][
j
]
=
q
*
z
+
p
*
H
[
n
][
j
];
H
[
n
][
j
]
=
q
*
H
[
n
][
j
]
-
p
*
z
;
}
// Column modification
for
(
int
i
=
0
;
i
<=
n
;
i
++
)
{
z
=
H
[
i
][
n
-
1
];
H
[
i
][
n
-
1
]
=
q
*
z
+
p
*
H
[
i
][
n
];
H
[
i
][
n
]
=
q
*
H
[
i
][
n
]
-
p
*
z
;
}
// Accumulate transformations
for
(
int
i
=
low
;
i
<=
high
;
i
++
)
{
z
=
V
[
i
][
n
-
1
];
V
[
i
][
n
-
1
]
=
q
*
z
+
p
*
V
[
i
][
n
];
V
[
i
][
n
]
=
q
*
V
[
i
][
n
]
-
p
*
z
;
}
// Complex pair
}
else
{
d
[
n
-
1
]
=
x
+
p
;
d
[
n
]
=
x
+
p
;
e
[
n
-
1
]
=
z
;
e
[
n
]
=
-
z
;
}
n
=
n
-
2
;
iter
=
0
;
// No convergence yet
}
else
{
// Form shift
x
=
H
[
n
][
n
];
y
=
0.0
;
w
=
0.0
;
if
(
l
<
n
)
{
y
=
H
[
n
-
1
][
n
-
1
];
w
=
H
[
n
][
n
-
1
]
*
H
[
n
-
1
][
n
];
}
// Wilkinson's original ad hoc shift
if
(
iter
==
10
)
{
exshift
+=
x
;
for
(
int
i
=
low
;
i
<=
n
;
i
++
)
{
H
[
i
][
i
]
-=
x
;
}
s
=
std
::
abs
(
H
[
n
][
n
-
1
])
+
std
::
abs
(
H
[
n
-
1
][
n
-
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
=
sqrt
(
s
);
if
(
y
<
x
)
{
s
=
-
s
;
}
s
=
x
-
w
/
((
y
-
x
)
/
2.0
+
s
);
for
(
int
i
=
low
;
i
<=
n
;
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
=
n
-
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
<=
n
;
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
<=
n
-
1
;
k
++
)
{
bool
notlast
=
(
k
!=
n
-
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
=
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
<=
min
(
n
,
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 (n >= low)
// Backsubstitute to find vectors of upper triangular form
if
(
norm
==
0.0
)
{
return
;
}
for
(
n
=
nn
-
1
;
n
>=
0
;
n
--
)
{
p
=
d
[
n
];
q
=
e
[
n
];
// Real vector
if
(
q
==
0
)
{
int
l
=
n
;
H
[
n
][
n
]
=
1.0
;
for
(
int
i
=
n
-
1
;
i
>=
0
;
i
--
)
{
w
=
H
[
i
][
i
]
-
p
;
r
=
0.0
;
for
(
int
j
=
l
;
j
<=
n
;
j
++
)
{
r
=
r
+
H
[
i
][
j
]
*
H
[
j
][
n
];
}
if
(
e
[
i
]
<
0.0
)
{
z
=
w
;
s
=
r
;
}
else
{
l
=
i
;
if
(
e
[
i
]
==
0.0
)
{
if
(
w
!=
0.0
)
{
H
[
i
][
n
]
=
-
r
/
w
;
}
else
{
H
[
i
][
n
]
=
-
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
][
n
]
=
t
;
if
(
std
::
abs
(
x
)
>
std
::
abs
(
z
))
{
H
[
i
+
1
][
n
]
=
(
-
r
-
w
*
t
)
/
x
;
}
else
{
H
[
i
+
1
][
n
]
=
(
-
s
-
y
*
t
)
/
z
;
}
}
// Overflow control
t
=
std
::
abs
(
H
[
i
][
n
]);
if
((
eps
*
t
)
*
t
>
1
)
{
for
(
int
j
=
i
;
j
<=
n
;
j
++
)
{
H
[
j
][
n
]
=
H
[
j
][
n
]
/
t
;
}
}
}
}
// Complex vector
}
else
if
(
q
<
0
)
{
int
l
=
n
-
1
;
// Last vector component imaginary so matrix is triangular
if
(
std
::
abs
(
H
[
n
][
n
-
1
])
>
std
::
abs
(
H
[
n
-
1
][
n
]))
{
H
[
n
-
1
][
n
-
1
]
=
q
/
H
[
n
][
n
-
1
];
H
[
n
-
1
][
n
]
=
-
(
H
[
n
][
n
]
-
p
)
/
H
[
n
][
n
-
1
];
}
else
{
cdiv
(
0.0
,
-
H
[
n
-
1
][
n
],
H
[
n
-
1
][
n
-
1
]
-
p
,
q
);
H
[
n
-
1
][
n
-
1
]
=
cdivr
;
H
[
n
-
1
][
n
]
=
cdivi
;
}
H
[
n
][
n
-
1
]
=
0.0
;
H
[
n
][
n
]
=
1.0
;
for
(
int
i
=
n
-
2
;
i
>=
0
;
i
--
)
{
double
ra
,
sa
,
vr
,
vi
;
ra
=
0.0
;
sa
=
0.0
;
for
(
int
j
=
l
;
j
<=
n
;
j
++
)
{
ra
=
ra
+
H
[
i
][
j
]
*
H
[
j
][
n
-
1
];
sa
=
sa
+
H
[
i
][
j
]
*
H
[
j
][
n
];
}
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
][
n
-
1
]
=
cdivr
;
H
[
i
][
n
]
=
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
][
n
-
1
]
=
cdivr
;
H
[
i
][
n
]
=
cdivi
;
if
(
std
::
abs
(
x
)
>
(
std
::
abs
(
z
)
+
std
::
abs
(
q
)))
{
H
[
i
+
1
][
n
-
1
]
=
(
-
ra
-
w
*
H
[
i
][
n
-
1
]
+
q
*
H
[
i
][
n
])
/
x
;
H
[
i
+
1
][
n
]
=
(
-
sa
-
w
*
H
[
i
][
n
]
-
q
*
H
[
i
][
n
-
1
])
/
x
;
}
else
{
cdiv
(
-
r
-
y
*
H
[
i
][
n
-
1
],
-
s
-
y
*
H
[
i
][
n
],
z
,
q
);
H
[
i
+
1
][
n
-
1
]
=
cdivr
;
H
[
i
+
1
][
n
]
=
cdivi
;
}
}
// Overflow control
t
=
max
(
std
::
abs
(
H
[
i
][
n
-
1
]),
std
::
abs
(
H
[
i
][
n
]));
if
((
eps
*
t
)
*
t
>
1
)
{
for
(
int
j
=
i
;
j
<=
n
;
j
++
)
{
H
[
j
][
n
-
1
]
=
H
[
j
][
n
-
1
]
/
t
;
H
[
j
][
n
]
=
H
[
j
][
n
]
/
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
<=
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
=
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
<
double
>
(
n
,
n
,
0.0
);
d
=
alloc_1d
<
double
>
(
n
);
e
=
alloc_1d
<
double
>
(
n
);
ort
=
alloc_1d
<
double
>
(
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
<
double
>
(
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
<
double
>
(
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
<
double
>
(
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
<
double
>
(
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
//------------------------------------------------------------------------------
void
LDA
::
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
();
}
// Deserializes this object from a given filename.
void
LDA
::
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
();
}
// 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
(
InputArray
_src
,
InputArray
_lbls
)
{
// get data
Mat
src
=
_src
.
getMat
();
vector
<
int
>
labels
=
_lbls
.
getMat
();
// 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]
vector
<
int
>
mapped_labels
(
labels
.
size
());
vector
<
int
>
num2label
=
remove_dups
(
labels
);
map
<
int
,
int
>
label2num
;
for
(
int
i
=
0
;
i
<
num2label
.
size
();
i
++
)
label2num
[
num2label
[
i
]]
=
i
;
for
(
int
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
=
num2label
.
size
();
// throw error if less labels, than samples
if
(
labels
.
size
()
!=
N
)
CV_Error
(
CV_StsBadArg
,
"Error: The number of samples must equal the number of labels."
);
// warn if within-classes scatter matrix becomes singular
if
(
N
<
D
)
cout
<<
"Warning: Less observations than feature dimension given!"
<<
"Computation will probably fail."
<<
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
vector
<
Mat
>
meanClass
(
C
);
vector
<
int
>
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 means
meanTotal
.
convertTo
(
meanTotal
,
meanTotal
.
type
(),
1.0
/
static_cast
<
double
>
(
N
));
for
(
int
i
=
0
;
i
<
C
;
i
++
)
meanClass
[
i
].
convertTo
(
meanClass
[
i
],
meanClass
[
i
].
type
(),
1.0
/
static_cast
<
double
>
(
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
vector
<
int
>
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
(
InputArray
_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
:
CV_Error
(
CV_StsNotImplemented
,
"This data type is not supported by subspace::LDA::compute."
);
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
());
}
}
samples/cpp/facerec_demo.cpp
0 → 100644
View file @
cec8f719
/*
* 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
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment