/* * Gaussian Kernel Regression model container class * * Author: Andrew Salamon * * Copyright (c) 2008 Machine Perception Laboratory * University of California San Diego. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "GKR_Models.h" #include #include #include #include #include #include #include #include namespace GKR { Models::Models() : training(false), GKR(false), logistic(false), temporal(false) { } Models::~Models() { } void Models::setLabels( const std::vector &_labels ) { labels = _labels; trainer.setLabels( _labels ); } void Models::setFlags( bool _train, bool _GKR, bool _log, bool _temp ) { training = _train; GKR = _GKR; logistic = _log; temporal = _temp; } void Models::setTraining( bool _training ) { training = _training; } bool Models::getTraining() { return training; } void Models::setGKR( bool _GKR ) { GKR = _GKR; } bool Models::getGKR() { return GKR; } void Models::setLogistic( bool _logistic ) { logistic = _logistic; } bool Models::getLogistic() { return logistic; } void Models::setTemporal( bool _temporal ) { temporal = _temporal; } bool Models::getTemporal() { return temporal; } void Models::loadModels( const std::string &path ) { models.clear(); std::ifstream ifs( path.c_str() ); boost::archive::xml_iarchive xml(ifs); xml >> boost::serialization::make_nvp( "GKR_Test", models ); } void Models::saveModels( const std::string &path ) { // probably ought to have a flag to make sure we've actually trained models std::ofstream ofs( path.c_str() ); boost::archive::xml_oarchive xml(ofs); xml << boost::serialization::make_nvp( "GKR_Test", models ); } bool Models::setCKFValues( CKFmap &values ) { static const unsigned int stride(6); for( CKFmap::iterator iter = values.begin(), last = values.end(); iter != last; ++iter ) { if( iter->second.size() != stride ) return false; } for( CKFmap::iterator iter = values.begin(), last = values.end(); iter != last; ++iter ) { std::string AUID( iter->first ); std::vector &valvec = iter->second; if( models.find( AUID ) == models.end() ) { GKR::Model _model( AUID ); models[_model.getID()] = _model; } // Order is: alpha, beta, S_x, S_y, S_0, Y_0, models[AUID].initLogisticValues( valvec[0], valvec[1] ); models[AUID].initTemporalValues( valvec[2], valvec[3], valvec[4], valvec[5] ); } return true; } bool Models::loadCKFValues( const std::string &path ) { CKFmap values; std::ifstream ifs( path.c_str() ); boost::archive::xml_iarchive xml(ifs); xml >> boost::serialization::make_nvp( "CKF_Settings", values ); return setCKFValues( values ); } void Models::saveCKFValues( const std::string &path ) { CKFmap values; for( std::map< std::string, Model >::iterator iter = models.begin(), last = models.end(); iter != last; ++iter ) { std::string AUID( iter->first ); GKR::Model &model = iter->second; std::vector valvec = model.getCKFValues(); values[ AUID ] = valvec; } std::ofstream ofs( path.c_str() ); boost::archive::xml_oarchive xml(ofs); xml << boost::serialization::make_nvp( "CKF_Settings", values ); } std::vector Models::addFrame( const std::vector &pose, const std::vector &aus, bool didFindFace ) { std::vector results; if( !didFindFace ) { if( !training && temporal ) { // use knowledge of previous values to guess at the current one. for( unsigned int i = 0; i < labels.size(); ++i ) { std::pair newValue = models[labels[i]].CKF( false, 0.0 ); results.push_back( newValue.first ); } } return results; } if( aus.size() != labels.size() ) throw badAUData(); if( 3 != pose.size() ) throw badPose(); if( training ) { trainer.addFrame( pose, aus ); } else { Matrix2d onePose( boost::extents[1][3] ); // Fill a matrix with this frame's pose data for( unsigned int ind = 0; ind < pose.size(); ++ind ) { onePose[0][ind] = pose[ind]; } for( unsigned int i = 0; i < aus.size(); ++i ) { float newAU = aus[i]; if( GKR ) { if( models[labels[i]].predict( onePose ) ) { Matrix2d pred = models[labels[i]].getPrediction(); newAU = newAU - pred[0][0]; } } if( logistic ) newAU = models[labels[i]].logistic( newAU ); if( temporal ) { std::pair newValue = models[labels[i]].CKF( true, newAU ); newAU = newValue.first; } results.push_back( newAU ); } } return results; } void Models::train() { trainer.train( models ); } void clearModel( std::pair< const std::string, Model > &entry ) { entry.second.clear(); } void Models::clearTraining() { trainer.clear(); // std::for_each( models.begin(), models.end(), clearModel ); } } // end namespace GKR