/* * PluginController * * 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 "PluginController.h" #include #include #include "FeatureAlignment.hpp" #include "SVMPlugin.h" #include "FeaturePlugin.h" #include "AfterFacePlugin.h" #include "FacePlugin.h" #include "StandardOutput.h" #include "PosePlugin.h" #include "FeatureImproverPlugin.h" #include "IntervalMean.h" #include "IntervalCRP.h" #ifndef NO_PATCH_PLUGIN #include "PatchPlugin.h" #endif #ifdef SMILES #include "SmilePlugin.h" #endif #ifdef BLINKS #include "BlinkPlugin.h" #endif #ifdef USE_SOBI #include "SOBIPlugin.h" #endif #ifdef USE_GKR #include "GKRPlugin.h" #endif #ifdef USE_GENDER #include "GenderPlugin.h" #endif #ifdef USE_GLASSES #include "GlassesPlugin.h" #endif namespace CERT { /** Known plugin types (steps). * Each is defined by a string constant. */ namespace PluginSteps { /// An unknown plugin. Also used by the special FaceFinder plugin. const std::string unknown("MPT_PluginStep_NoStep"); /// Plugins that run sometime after a face has been found, but usually also after SVM's run. const std::string afterFaces("MPT_PluginStep_AfterFaces"); /// Plugins that use SVM weights to calculate AU values. const std::string SVM("MPT_PluginStep_SVM"); /// Plugins that define a 'feature', e.g. eye, nose, etc. const std::string Feature("MPT_PluginStep_Features"); /// Plugins that operate on the results of other plugins for post processing. Guaranteed to run after all plugins except Output plugins and other PostProcess plugins. const std::string PostProcess("MPT_PluginStep_PostProcess"); /// Plugins that output the results of other plugins. const std::string Output("MPT_PluginStep_Output"); } static PluginController *controller = NULL; PluginController * PluginController::getPluginController( const std::string &configPath ) { if( !controller ) { Config *config = NULL; if( configPath.length() > 0 ) config = new Config( configPath ); controller = new PluginController; if( config ) controller->loadPluginsFromConfig( config ); } return controller; } void PluginController::cleanup() { if( controller ) delete controller; controller = NULL; } std::vector PluginController::knownPluginTypes() { std::vector types; types.push_back( std::string("Feature") ); types.push_back( std::string("SVM") ); types.push_back( std::string("facedetector") ); types.push_back( std::string("Output") ); types.push_back( std::string("posedetector") ); types.push_back( std::string("featureimprover") ); types.push_back( std::string("intervalmean") ); types.push_back( std::string("intervalcrp") ); #ifdef SMILES types.push_back( std::string("smiledetector") ); #endif #ifdef BLINKS types.push_back( std::string("blinkdetector") ); #endif #ifdef USE_SOBI types.push_back( std::string("sobiplugin") ); #endif #ifdef USE_GKR types.push_back( std::string("gkrplugin") ); #endif #ifdef USE_GENDER types.push_back( std::string("genderdetector") ); #endif #ifdef USE_GLASSES types.push_back( std::string("glassesdetector") ); #endif return types; } PluginController::PluginController() : faceDetector(NULL) { } PluginController::PluginController( PluginController &other ) : faceDetector(NULL) { for( unsigned int ind = 0; ind < other.plugins.size(); ++ind ) { plugins.push_back( other.plugins[ind]->copy() ); } if( other.faceDetector ) faceDetector = dynamic_cast( other.faceDetector->copy() ); config = other.config;; } PluginController::~PluginController() { for( containerType::iterator pluginIter = plugins.begin(), lastPlugin = plugins.end(); pluginIter != lastPlugin; ++pluginIter ) { if( NULL != *pluginIter ) delete *pluginIter; } } bool PluginController::loadPluginsFromConfig( Config *_config ) { config = boost::shared_ptr(_config); std::vector items = config->getItems(); for( std::vector::iterator configIter = items.begin(), lastConfig = items.end(); configIter != lastConfig; ++configIter ) { ConfigItem *item = *configIter; if( PluginSteps::SVM == item->getPluginType() ) { addPlugin( new SVMPlugin( item ) ); } else if( PluginSteps::Feature == item->getPluginType() ) { if( "featureimprover" == item->getInternalName() ) { addPlugin( new FeatureImproverPlugin( item ) ); } else { addPlugin( new FeaturePlugin( item ) ); } } else if( PluginSteps::unknown == item->getPluginType() ) { if( !faceDetector && ("facedetector" == item->getInternalName()) ) { faceDetector = new FacePlugin( item ); addPlugin( faceDetector ); } } else if( PluginSteps::afterFaces == item->getPluginType() ) { if( "smiledetector" == item->getInternalName() ) { #ifdef SMILES addPlugin( new SmilePlugin( item ) ); #endif } else if( "posedetector" == item->getInternalName() ) { addPlugin( new PosePlugin( item ) ); } else if( "intervalmean" == item->getInternalName() ) { addPlugin( new IntervalMean( item ) ); } else if( "intervalcrp" == item->getInternalName() ) { addPlugin( new IntervalCRP( item ) ); } else if( "blinkdetector" == item->getInternalName() ) { #ifdef BLINKS addPlugin( new BlinkPlugin( item ) ); #endif } else if( "genderdetector" == item->getInternalName() ) { #ifdef USE_GENDER addPlugin( new GenderPlugin( item ) ); #endif } else if( "glassesdetector" == item->getInternalName() ) { #ifdef USE_GLASSES addPlugin( new GlassesPlugin( item ) ); #endif } } else if( PluginSteps::PostProcess == item->getPluginType() ) { if( "sobiplugin" == item->getInternalName() ) { #ifdef USE_SOBI addPlugin( new SOBIPlugin( item ) ); #endif } else if( "gkrplugin" == item->getInternalName() ) { #ifdef USE_GKR addPlugin( new GKRPlugin( item ) ); #endif } } else if( PluginSteps::Output == item->getPluginType() ) { if( "standardoutput" == item->getInternalName() ) { addPlugin( new StandardOutput( item ) ); } } } // Add any built-in plugins that don't use config settings. #ifndef NO_PATCH_PLUGIN addPlugin( new PatchPlugin( NULL ) ); #endif return true; } void PluginController::addPlugin( PluginBase *plugin ) { PluginBase *existing = pluginWithID( plugin->id(), false ); if( NULL == existing ) plugins.push_back( plugin ); else delete plugin; } void PluginController::removePlugin( PluginBase *plugin ) { containerType::iterator loc = std::find( plugins.begin(), plugins.end(), plugin ); if( loc != plugins.end() ) plugins.erase( loc ); } void PluginController::removePlugin( const std::string &pluginID ) { for( containerType::iterator pluginIter = plugins.begin(), lastPlugin = plugins.end(); pluginIter != lastPlugin; ++pluginIter ) { if( (*pluginIter)->id() == pluginID ) { plugins.erase( pluginIter ); return; } } } PluginController::containerType PluginController::pluginsForStep( const PluginStep &step, bool enabledOnly ) { containerType stepPlugins; for( containerType::iterator pluginIter = plugins.begin(), lastPlugin = plugins.end(); pluginIter != lastPlugin; ++pluginIter ) { if( ((*pluginIter)->step() == step) && (!enabledOnly || (*pluginIter)->isEnabled()) ) stepPlugins.push_back( *pluginIter ); } return stepPlugins; } PluginController::containerType PluginController::pluginsForSteps( const std::vector &steps, bool enabledOnly ) { containerType stepPlugins; for( containerType::iterator pluginIter = plugins.begin(), lastPlugin = plugins.end(); pluginIter != lastPlugin; ++pluginIter ) { if( steps.end() != std::find( steps.begin(), steps.end(), (*pluginIter)->step() ) ) { if( !enabledOnly || (*pluginIter)->isEnabled() ) stepPlugins.push_back( *pluginIter ); } } return stepPlugins; } PluginBase * PluginController::pluginWithID( const std::string &id, bool enabledOnly ) { for( containerType::iterator pluginIter = plugins.begin(), lastPlugin = plugins.end(); pluginIter != lastPlugin; ++pluginIter ) { if( ((*pluginIter)->id() == id) && (!enabledOnly || (*pluginIter)->isEnabled()) ) return *pluginIter; } return NULL; } FacePlugin * PluginController::getFaceDetector() { if( faceDetector && faceDetector->isEnabled() ) return faceDetector; return NULL; } std::vector< std::string > PluginController::getSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); return global.getValueForKey( name ); } return std::vector(); } bool PluginController::hasStringSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); std::vector< std::string > val = global.getValueForKey( name ); if( val.size() == 1 ) return true; } return false; } std::string PluginController::getStringSetting( const std::string &name ) { std::vector< std::string > vals = getSetting( name ); if( vals.size() == 1 ) return vals[0]; return std::string(""); } bool PluginController::hasIntSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); std::vector< std::string > val = global.getValueForKey( name ); if( val.size() == 1 ) { std::istringstream istr( val[0] ); int test; if( istr >> test ) return true; } } return false; } int PluginController::getIntSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); std::vector< std::string > val = global.getValueForKey( name ); if( val.size() == 1 ) { std::istringstream istr( val[0] ); int test; if( istr >> test ) return test; } } return 0; } bool PluginController::hasMapSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); ConfigItem::PropertyType val = global.getMapForKey( name ); if( val.size() > 0 ) return true; } return false; } ConfigItem::PropertyType PluginController::getMapSetting( const std::string &name ) { if( config ) { ConfigItem &global( config->getGlobalItem() ); ConfigItem::PropertyType val = global.getMapForKey( name ); if( val.size() > 0 ) return val; } return ConfigItem::PropertyType(); } std::string PluginController::getFaceAlignmentMethod() { std::vector< std::string > methods = getSetting( "fdalign" ); if( methods.size() > 0 ) return methods[0]; return ""; } // Move this to FeatureAlignment if we ever need it anyplace else std::vector< std::string > PluginController::validFaceAlignmentMethods() { std::vector< std::string > methods; for( int method = static_cast(FeatureAlignment::begin_methods); method < static_cast(FeatureAlignment::end_methods); ++method ) { methods.push_back( FeatureAlignment::stringFromMethod( static_cast(method) ) ); } return methods; } } // end namespace CERT