void RPCA::fit(const cv::Mat1f & descr) { // make data zero mean cv::reduce(descr, mean, 0, CV_REDUCE_AVG); cv::Mat1f X(descr.rows, descr.cols); #ifdef USE_TBB tbb::parallel_for(int32_t(0), X.rows, [&](int32_t y) { X.row(y) = descr.row(y) - mean; } ); #else for( int32_t y = 0; y < X.rows; y++){ X.row(y) = descr.row(y) - mean; } #endif cv::Mat1f U, S, V; cv::SVD::compute(X, S, U, V); cv::pow(S, 2, variance); variance /= X.rows; if (n_components <= 0) { n_components = X.cols; } components = V.rowRange(0, n_components); if(variance.rows < n_components) { whiten = false; } else { variance = variance.rowRange(0, n_components); } this->dataLoaded = true; }
void RPCA::transform(const cv::Mat1f & descr, cv::Mat1f & out) const { if(descr.cols != mean.cols) { std::stringstream s; s << "Input and mean data missmatch." << std::endl; s << "Input: " << descr.size() << " Mean: " << mean.size() << std::endl; throw pl::DimensionalityReductionError(s.str(), currentMethod, currentLine); } else if(descr.cols != components.cols) { std::stringstream s; s << "Input and transformation data missmatch." << std::endl; s << "Input: " << descr.size() << " Transform: " << components.size() << std::endl; throw pl::DimensionalityReductionError(s.str(), currentMethod, currentLine); } // make data zero-mean cv::Mat1f X(descr.rows,descr.cols); #ifdef USE_TBB tbb::parallel_for(int32_t(0), X.rows, [&](int32_t i) { X.row(i) = descr.row(i) - mean; } ); #else for( int32_t y = 0; y < X.rows; y++){ X.row(y) = descr.row(y) - mean; } #endif // the actual transformation X = X * components.t(); // whiten the data if ( whiten ) { cv::Mat1f var_reg = variance.clone(); var_reg = var_reg.reshape(1, 1); if ( reg > 0.0 ) var_reg += reg; cv::sqrt(var_reg, var_reg); #ifdef USE_TBB tbb::parallel_for(int32_t(0), X.rows, [&](int32_t i) { cv::Mat1f row = X.row(i); row /= var_reg; } ); #else for( int32_t i = 0; i < X.rows; i++ ) { cv::Mat1f row = X.row(i); row /= var_reg; } #endif } out = X; }