forked from LuisTbx/Skin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathskindetector.cpp
109 lines (99 loc) · 2.88 KB
/
skindetector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "skindetector.h"
//Constructurs
SkinDetector::SkinDetector()
{
this->covariance = (cv::Mat_<float>(2,2) << 0.0038,-0.0009,-0.0009, 0.0009 );
this->mean = (cv::Mat_<float>(2,1) << 0.4404, 0.3111);
cv::invert(covariance, inverse_covariance);
this->threshold = 0.33f;
}
SkinDetector::SkinDetector(cv::Mat _mcovariance, cv::Mat _mean, float _mthreshold)
: covariance(_mcovariance), threshold(_mthreshold),
mean(_mean)
{
cv::invert(covariance, inverse_covariance);
}
SkinDetector::SkinDetector(cv::Mat _mcovariance, cv::Mat _minverse_covariance, cv::Mat _mean, float _mthreshold)
: covariance(_mcovariance), inverse_covariance(_minverse_covariance),
threshold(_mthreshold), mean(_mean)
{
}
// Destructor
SkinDetector::~SkinDetector()
{
covariance.release();
inverse_covariance.release();
mean.release();
bgr_img.release();
skin_map.release();
for (unsigned int ii=0; ii<layers.size(); ii++)
layers[ii].release();
layers.clear();
}
// Setters
void SkinDetector::set_threshold(float _mthreshold)
{
this-> threshold = _mthreshold;
}
void SkinDetector::set_covariance(cv::Mat _mcovariance)
{
this->covariance = _mcovariance.clone();
cv::invert(covariance, inverse_covariance);
}
void SkinDetector::set_bgr_image(cv::Mat _bgr_image)
{
if(_bgr_image.data)
this->bgr_img = _bgr_image.clone();
}
void SkinDetector::set_mean(cv::Mat _mean)
{
this->mean = _mean.clone();
}
// Getters
cv::Mat SkinDetector::get_covariance()
{
return this->covariance.clone();
}
cv::Mat SkinDetector::get_inverse_covariance()
{
return this-> inverse_covariance.clone();
}
cv::Mat SkinDetector::get_mean()
{
return this->mean.clone();
}
cv::Mat SkinDetector::get_skin_map()
{
normalize_image();
cv::Mat gate;
gate = -0.5f * (((n_r.mul(n_r))*inverse_covariance.at<float>(0,0))
+ (2*inverse_covariance.at<float>(0,1)*(n_r.mul(n_g)))
+ ((n_g.mul(n_g))*inverse_covariance.at<float>(1,1)));
exp(gate,gate);
cv::threshold(gate, skin_map, threshold, 255, CV_THRESH_BINARY);
skin_map.convertTo(skin_map,CV_8U);
gate.release();
return skin_map.clone();
}
float SkinDetector::get_threshold()
{
return this->threshold;
}
// self functions
void SkinDetector::normalize_image()
{
// Allocate temporal image
cv::Mat temp;
bgr_img.convertTo(temp, CV_32F);
// split image into channels
cv::split(temp, layers);
// Change color space to normalized rgb: b = B / B+G+R, g = G/ B+G+R, r = R/ B+G+R
// we kep only the two important components for skin detection G and R
n_g = (layers[1] / (layers[0]+layers[1]+layers[2])) - mean.at<float>(0,1);
n_r = (layers[2] / (layers[0]+layers[1]+layers[2])) - mean.at<float>(0,0);
// free memory
for (auto ii=0; ii<layers.size(); ii++)
layers[ii].release();
layers.clear();
temp.release();
}