vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "tracking_online_mil.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
#define sign(s) ((s > 0) ? 1 : ((s < 0) ? -1 : 0))
|
||||
|
||||
template <class T>
|
||||
class SortableElementRev
|
||||
{
|
||||
public:
|
||||
T _val;
|
||||
int _ind;
|
||||
SortableElementRev()
|
||||
: _val(), _ind(0)
|
||||
{
|
||||
}
|
||||
SortableElementRev(T val, int ind)
|
||||
{
|
||||
_val = val;
|
||||
_ind = ind;
|
||||
}
|
||||
bool operator<(SortableElementRev<T>& b)
|
||||
{
|
||||
return (_val < b._val);
|
||||
}
|
||||
};
|
||||
|
||||
static bool CompareSortableElementRev(const SortableElementRev<float>& i, const SortableElementRev<float>& j)
|
||||
{
|
||||
return i._val < j._val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sort_order_des(std::vector<T>& v, std::vector<int>& order)
|
||||
{
|
||||
uint n = (uint)v.size();
|
||||
std::vector<SortableElementRev<T>> v2;
|
||||
v2.resize(n);
|
||||
order.clear();
|
||||
order.resize(n);
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
v2[i]._ind = i;
|
||||
v2[i]._val = v[i];
|
||||
}
|
||||
//std::sort( v2.begin(), v2.end() );
|
||||
std::sort(v2.begin(), v2.end(), CompareSortableElementRev);
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
order[i] = v2[i]._ind;
|
||||
v[i] = v2[i]._val;
|
||||
}
|
||||
}
|
||||
|
||||
//implementations for strong classifier
|
||||
|
||||
ClfMilBoost::Params::Params()
|
||||
{
|
||||
_numSel = 50;
|
||||
_numFeat = 250;
|
||||
_lRate = 0.85f;
|
||||
}
|
||||
|
||||
ClfMilBoost::ClfMilBoost()
|
||||
: _numsamples(0)
|
||||
, _counter(0)
|
||||
{
|
||||
_myParams = ClfMilBoost::Params();
|
||||
_numsamples = 0;
|
||||
}
|
||||
|
||||
ClfMilBoost::~ClfMilBoost()
|
||||
{
|
||||
_selectors.clear();
|
||||
for (size_t i = 0; i < _weakclf.size(); i++)
|
||||
delete _weakclf.at(i);
|
||||
}
|
||||
|
||||
void ClfMilBoost::init(const ClfMilBoost::Params& parameters)
|
||||
{
|
||||
_myParams = parameters;
|
||||
_numsamples = 0;
|
||||
|
||||
//_ftrs = Ftr::generate( _myParams->_ftrParams, _myParams->_numFeat );
|
||||
// if( params->_storeFtrHistory )
|
||||
// Ftr::toViz( _ftrs, "haarftrs" );
|
||||
_weakclf.resize(_myParams._numFeat);
|
||||
for (int k = 0; k < _myParams._numFeat; k++)
|
||||
{
|
||||
_weakclf[k] = new ClfOnlineStump(k);
|
||||
_weakclf[k]->_lRate = _myParams._lRate;
|
||||
}
|
||||
_counter = 0;
|
||||
}
|
||||
|
||||
void ClfMilBoost::update(const Mat& posx, const Mat& negx)
|
||||
{
|
||||
int numneg = negx.rows;
|
||||
int numpos = posx.rows;
|
||||
|
||||
// compute ftrs
|
||||
//if( !posx.ftrsComputed() )
|
||||
// Ftr::compute( posx, _ftrs );
|
||||
//if( !negx.ftrsComputed() )
|
||||
// Ftr::compute( negx, _ftrs );
|
||||
|
||||
// initialize H
|
||||
static std::vector<float> Hpos, Hneg;
|
||||
Hpos.clear();
|
||||
Hneg.clear();
|
||||
Hpos.resize(posx.rows, 0.0f), Hneg.resize(negx.rows, 0.0f);
|
||||
|
||||
_selectors.clear();
|
||||
std::vector<float> posw(posx.rows), negw(negx.rows);
|
||||
std::vector<std::vector<float>> pospred(_weakclf.size()), negpred(_weakclf.size());
|
||||
|
||||
// train all weak classifiers without weights
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int m = 0; m < _myParams._numFeat; m++)
|
||||
{
|
||||
_weakclf[m]->update(posx, negx);
|
||||
pospred[m] = _weakclf[m]->classifySetF(posx);
|
||||
negpred[m] = _weakclf[m]->classifySetF(negx);
|
||||
}
|
||||
|
||||
// pick the best features
|
||||
for (int s = 0; s < _myParams._numSel; s++)
|
||||
{
|
||||
|
||||
// compute errors/likl for all weak clfs
|
||||
std::vector<float> poslikl(_weakclf.size(), 1.0f), neglikl(_weakclf.size()), likl(_weakclf.size());
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int w = 0; w < (int)_weakclf.size(); w++)
|
||||
{
|
||||
float lll = 1.0f;
|
||||
for (int j = 0; j < numpos; j++)
|
||||
lll *= (1 - sigmoid(Hpos[j] + pospred[w][j]));
|
||||
poslikl[w] = (float)-log(1 - lll + 1e-5);
|
||||
|
||||
lll = 0.0f;
|
||||
for (int j = 0; j < numneg; j++)
|
||||
lll += (float)-log(1e-5f + 1 - sigmoid(Hneg[j] + negpred[w][j]));
|
||||
neglikl[w] = lll;
|
||||
|
||||
likl[w] = poslikl[w] / numpos + neglikl[w] / numneg;
|
||||
}
|
||||
|
||||
// pick best weak clf
|
||||
std::vector<int> order;
|
||||
sort_order_des(likl, order);
|
||||
|
||||
// find best weakclf that isn't already included
|
||||
for (uint k = 0; k < order.size(); k++)
|
||||
if (std::count(_selectors.begin(), _selectors.end(), order[k]) == 0)
|
||||
{
|
||||
_selectors.push_back(order[k]);
|
||||
break;
|
||||
}
|
||||
|
||||
// update H = H + h_m
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < posx.rows; k++)
|
||||
Hpos[k] += pospred[_selectors[s]][k];
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < negx.rows; k++)
|
||||
Hneg[k] += negpred[_selectors[s]][k];
|
||||
}
|
||||
|
||||
//if( _myParams->_storeFtrHistory )
|
||||
//for ( uint j = 0; j < _selectors.size(); j++ )
|
||||
// _ftrHist( _selectors[j], _counter ) = 1.0f / ( j + 1 );
|
||||
|
||||
_counter++;
|
||||
/* */
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> ClfMilBoost::classify(const Mat& x, bool logR)
|
||||
{
|
||||
int numsamples = x.rows;
|
||||
std::vector<float> res(numsamples);
|
||||
std::vector<float> tr;
|
||||
|
||||
for (uint w = 0; w < _selectors.size(); w++)
|
||||
{
|
||||
tr = _weakclf[_selectors[w]]->classifySetF(x);
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j = 0; j < numsamples; j++)
|
||||
{
|
||||
res[j] += tr[j];
|
||||
}
|
||||
}
|
||||
|
||||
// return probabilities or log odds ratio
|
||||
if (!logR)
|
||||
{
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j = 0; j < (int)res.size(); j++)
|
||||
{
|
||||
res[j] = sigmoid(res[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//implementations for weak classifier
|
||||
|
||||
ClfOnlineStump::ClfOnlineStump()
|
||||
: _mu0(0), _mu1(0), _sig0(0), _sig1(0)
|
||||
, _q(0)
|
||||
, _s(0)
|
||||
, _log_n1(0), _log_n0(0)
|
||||
, _e1(0), _e0(0)
|
||||
, _lRate(0)
|
||||
{
|
||||
_trained = false;
|
||||
_ind = -1;
|
||||
init();
|
||||
}
|
||||
|
||||
ClfOnlineStump::ClfOnlineStump(int ind)
|
||||
: _mu0(0), _mu1(0), _sig0(0), _sig1(0)
|
||||
, _q(0)
|
||||
, _s(0)
|
||||
, _log_n1(0), _log_n0(0)
|
||||
, _e1(0), _e0(0)
|
||||
, _lRate(0)
|
||||
{
|
||||
_trained = false;
|
||||
_ind = ind;
|
||||
init();
|
||||
}
|
||||
void ClfOnlineStump::init()
|
||||
{
|
||||
_mu0 = 0;
|
||||
_mu1 = 0;
|
||||
_sig0 = 1;
|
||||
_sig1 = 1;
|
||||
_lRate = 0.85f;
|
||||
_trained = false;
|
||||
}
|
||||
|
||||
void ClfOnlineStump::update(const Mat& posx, const Mat& negx, const Mat_<float>& /*posw*/, const Mat_<float>& /*negw*/)
|
||||
{
|
||||
//std::cout << " ClfOnlineStump::update" << _ind << std::endl;
|
||||
float posmu = 0.0, negmu = 0.0;
|
||||
if (posx.cols > 0)
|
||||
posmu = float(mean(posx.col(_ind))[0]);
|
||||
if (negx.cols > 0)
|
||||
negmu = float(mean(negx.col(_ind))[0]);
|
||||
|
||||
if (_trained)
|
||||
{
|
||||
if (posx.cols > 0)
|
||||
{
|
||||
_mu1 = (_lRate * _mu1 + (1 - _lRate) * posmu);
|
||||
cv::Mat diff = posx.col(_ind) - _mu1;
|
||||
_sig1 = _lRate * _sig1 + (1 - _lRate) * float(mean(diff.mul(diff))[0]);
|
||||
}
|
||||
if (negx.cols > 0)
|
||||
{
|
||||
_mu0 = (_lRate * _mu0 + (1 - _lRate) * negmu);
|
||||
cv::Mat diff = negx.col(_ind) - _mu0;
|
||||
_sig0 = _lRate * _sig0 + (1 - _lRate) * float(mean(diff.mul(diff))[0]);
|
||||
}
|
||||
|
||||
_q = (_mu1 - _mu0) / 2;
|
||||
_s = sign(_mu1 - _mu0);
|
||||
_log_n0 = std::log(float(1.0f / std::pow(_sig0, 0.5f)));
|
||||
_log_n1 = std::log(float(1.0f / std::pow(_sig1, 0.5f)));
|
||||
//_e1 = -1.0f/(2.0f*_sig1+1e-99f);
|
||||
//_e0 = -1.0f/(2.0f*_sig0+1e-99f);
|
||||
_e1 = -1.0f / (2.0f * _sig1 + std::numeric_limits<float>::min());
|
||||
_e0 = -1.0f / (2.0f * _sig0 + std::numeric_limits<float>::min());
|
||||
}
|
||||
else
|
||||
{
|
||||
_trained = true;
|
||||
if (posx.cols > 0)
|
||||
{
|
||||
_mu1 = posmu;
|
||||
cv::Scalar scal_mean, scal_std_dev;
|
||||
cv::meanStdDev(posx.col(_ind), scal_mean, scal_std_dev);
|
||||
_sig1 = float(scal_std_dev[0]) * float(scal_std_dev[0]) + 1e-9f;
|
||||
}
|
||||
|
||||
if (negx.cols > 0)
|
||||
{
|
||||
_mu0 = negmu;
|
||||
cv::Scalar scal_mean, scal_std_dev;
|
||||
cv::meanStdDev(negx.col(_ind), scal_mean, scal_std_dev);
|
||||
_sig0 = float(scal_std_dev[0]) * float(scal_std_dev[0]) + 1e-9f;
|
||||
}
|
||||
|
||||
_q = (_mu1 - _mu0) / 2;
|
||||
_s = sign(_mu1 - _mu0);
|
||||
_log_n0 = std::log(float(1.0f / std::pow(_sig0, 0.5f)));
|
||||
_log_n1 = std::log(float(1.0f / std::pow(_sig1, 0.5f)));
|
||||
//_e1 = -1.0f/(2.0f*_sig1+1e-99f);
|
||||
//_e0 = -1.0f/(2.0f*_sig0+1e-99f);
|
||||
_e1 = -1.0f / (2.0f * _sig1 + std::numeric_limits<float>::min());
|
||||
_e0 = -1.0f / (2.0f * _sig0 + std::numeric_limits<float>::min());
|
||||
}
|
||||
}
|
||||
|
||||
bool ClfOnlineStump::classify(const Mat& x, int i)
|
||||
{
|
||||
float xx = x.at<float>(i, _ind);
|
||||
double log_p0 = (xx - _mu0) * (xx - _mu0) * _e0 + _log_n0;
|
||||
double log_p1 = (xx - _mu1) * (xx - _mu1) * _e1 + _log_n1;
|
||||
return log_p1 > log_p0;
|
||||
}
|
||||
|
||||
float ClfOnlineStump::classifyF(const Mat& x, int i)
|
||||
{
|
||||
float xx = x.at<float>(i, _ind);
|
||||
double log_p0 = (xx - _mu0) * (xx - _mu0) * _e0 + _log_n0;
|
||||
double log_p1 = (xx - _mu1) * (xx - _mu1) * _e1 + _log_n1;
|
||||
return float(log_p1 - log_p0);
|
||||
}
|
||||
|
||||
inline std::vector<float> ClfOnlineStump::classifySetF(const Mat& x)
|
||||
{
|
||||
std::vector<float> res(x.rows);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < (int)res.size(); k++)
|
||||
{
|
||||
res[k] = classifyF(x, k);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
Reference in New Issue
Block a user