Add new files for plugin management

This commit is contained in:
manupap1 2014-11-11 22:39:20 +01:00
parent 15532e2a03
commit 199f399caf
6 changed files with 805 additions and 0 deletions

232
src/zm_detector.cpp Normal file
View File

@ -0,0 +1,232 @@
#include "zm_detector.h"
/*!\fn Detector::Detector(const Detector& source)
* \param source is the object to copy
*/
Detector::Detector(const Detector& source)
: m_sDetectionCause(source.m_sDetectionCause),
m_fMinAlarmScore(source.m_fMinAlarmScore),
m_fMaxAlarmScore(source.m_fMaxAlarmScore),
m_fImageScaleFactor(source.m_fImageScaleFactor),
m_nNewWidth(source.m_nNewWidth),
m_nNewHeight(source.m_nNewHeight),
m_sLogPrefix(source.m_sLogPrefix),
m_sConfigSectionName(source.m_sConfigSectionName),
m_vnPluginZones(source.m_vnPluginZones)
{
m_bIsPluginEnabled = false;
}
/*!\fn Detector& ImageAnalyser::Detector::operator=(const ImageAnalyser::Detector& source)
* \param source is the object to copy
*/
Detector& Detector::operator=(const Detector& source)
{
m_sDetectionCause = source.m_sDetectionCause;
m_fMinAlarmScore = source.m_fMinAlarmScore;
m_fMaxAlarmScore = source.m_fMaxAlarmScore;
m_fImageScaleFactor = source.m_fImageScaleFactor;
m_sLogPrefix = source.m_sLogPrefix;
m_nNewWidth = source.m_nNewWidth;
m_nNewHeight = source.m_nNewHeight;
m_sConfigSectionName = source.m_sConfigSectionName;
m_vnPluginZones = source.m_vnPluginZones;
return *this;
}
/*!\fn Detector::getDetectionCause()
* return detection cause as string
*/
string Detector::getDetectionCause()
{
return m_sDetectionCause;
}
/*!\fn Detector::getConfigSectionName()
* return plugin name as string
*/
string Detector::getPluginName()
{
return m_sConfigSectionName;
}
/*!\fn Detector::EnablePlugin(vector<int> zoneList)
* \param vnZoneList is the list of enabled zones for the plugin
*/
void Detector::EnablePlugin(vector<unsigned int> vnZoneList)
{
m_vnPluginZones = vnZoneList;
m_bIsPluginEnabled = true;
}
/*!\fn Detector::getPluginZones()
* \return the list of zone which have the plugin enabled
*/
vector<unsigned int> Detector::getPluginZones()
{
return m_vnPluginZones;
}
/*! \fn Detector::log(int nLogLevel, string sLevel, string sMessage)
*/
void Detector::log(int nLogLevel, string sLevel, string sMessage)
{
string sMessageToLog = sLevel + string(" [") + m_sLogPrefix + string(": ") + sMessage + string("]");
syslog(nLogLevel, "%s", sMessageToLog.c_str());
}
/*! \fn int Detector::Detect(const Image &image, Event::StringSet &zoneSet)
* \param zmImage is an image to detect faces on
* \param zoneSet is set of zone names (see zm_zone.h)
* \param score is the detection score
* \return true if detection is effective
*/
bool Detector::Detect(const Image &zmImage, Zone** zones, Event::StringSet &zoneSet, unsigned int &score)
{
bool alarm = false;
char szMessage[100];
score = 0;
if (!m_bIsPluginEnabled) return (alarm);
// Check preclusive zones first
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
{
Zone *zone = zones[*it];
if (!zone->IsPreclusive())
continue;
if (zone->IsPostProcEnabled() && !zone->IsPostProcInProgress())
continue;
sprintf(szMessage, "Checking preclusive zone %s", zone->Label());
log(LOG_DEBUG, "DEBUG", szMessage);
if (checkZone(zone, *it, &zmImage))
{
alarm = true;
score += zone->Score();
zoneSet.insert(zone->Text());
if (zone->IsPostProcEnabled())
{
zone->StopPostProcessing();
sprintf(szMessage, "Zone is alarmed, zone score = %d (post-processing)", zone->Score());
}
else
{
sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score());
}
log(LOG_DEBUG, "DEBUG", szMessage);
}
}
if ( alarm )
{
alarm = false;
score = 0;
}
else
{
// Find all alarm pixels in active zones
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
{
Zone *zone = zones[*it];
if (!zone->IsActive())
continue;
if (zone->IsPostProcEnabled() && !zone->IsPostProcInProgress())
continue;
if (checkZone(zone, *it, &zmImage))
{
alarm = true;
score += zone->Score();
zoneSet.insert(zone->Text());
if (zone->IsPostProcEnabled())
{
zone->StopPostProcessing();
sprintf(szMessage, "Zone is alarmed, zone score = %d (post-processing)", zone->Score());
}
else
{
zone->SetAlarm();
sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score());
}
log(LOG_DEBUG, "DEBUG", szMessage);
}
}
if ( alarm )
{
// Checking inclusive zones
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
{
Zone *zone = zones[*it];
if (!zone->IsInclusive())
continue;
if (zone->IsPostProcEnabled() && !zone->IsPostProcInProgress())
continue;
sprintf(szMessage, "Checking inclusive zone %s", zone->Label());
log(LOG_DEBUG, "DEBUG", szMessage);
if (checkZone(zone, *it, &zmImage))
{
alarm = true;
score += zone->Score();
zoneSet.insert(zone->Text());
if (zone->IsPostProcEnabled())
{
zone->StopPostProcessing();
sprintf(szMessage, "Zone is alarmed, zone score = %d (post-processing)", zone->Score());
}
else
{
zone->SetAlarm();
sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score());
}
log(LOG_DEBUG, "DEBUG", szMessage);
}
}
}
else
{
// Find all alarm pixels in exclusive zones
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
{
Zone *zone = zones[*it];
if (!zone->IsExclusive())
continue;
if (zone->IsPostProcEnabled() && !zone->IsPostProcInProgress())
continue;
sprintf(szMessage, "Checking exclusive zone %s", zone->Label());
log(LOG_DEBUG, "DEBUG", szMessage);
if (checkZone(zone, *it, &zmImage))
{
alarm = true;
score += zone->Score();
zoneSet.insert(zone->Text());
if (zone->IsPostProcEnabled())
{
zone->StopPostProcessing();
sprintf(szMessage, "Zone is alarmed, zone score = %d (post-processing)", zone->Score());
}
else
{
zone->SetAlarm();
sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score());
}
log(LOG_DEBUG, "DEBUG", szMessage);
}
}
}
}
return alarm;
}

137
src/zm_detector.h Normal file
View File

@ -0,0 +1,137 @@
#ifndef ZM_DETECTOR_H
#define ZM_DETECTOR_H
#include <string>
#include <algorithm>
#include <syslog.h>
#include <libgen.h>
#include "zm_image.h"
#include "zm_zone.h"
#include "zm_event.h"
#define DEFAULT_DETECTION_CAUSE "Object Detected"
#define DEFAULT_MIN_ALARM_SCORE 1.0
#define DEFAULT_MAX_ALARM_SCORE 99.0
#define DEFAULT_IMAGE_SCALE_FACTOR 1.0
#define DEFAULT_LOG_PREFIX "ZM PLUGIN"
#define LOG_LEVEL LOG_NOTICE
#define DEFAULT_CONFIGFILE_SECTION "libzm_vscvl_plugin"
using namespace std;
//! Base class for object detectors, defined in plugins.
class Detector
{
public:
//! Destructor
virtual ~Detector() {}
//! Default constructor
Detector()
{
m_sLogPrefix = DEFAULT_LOG_PREFIX;
m_sDetectionCause = DEFAULT_DETECTION_CAUSE;
m_fMinAlarmScore = DEFAULT_MIN_ALARM_SCORE;
m_fMaxAlarmScore = DEFAULT_MAX_ALARM_SCORE;
m_fImageScaleFactor = DEFAULT_IMAGE_SCALE_FACTOR;
m_sConfigSectionName = DEFAULT_CONFIGFILE_SECTION;
m_nNewWidth = 0;
m_nNewHeight = 0;
}
//! Constructor with section name parameter.
Detector(string sPluginFileName)
{
m_sLogPrefix = DEFAULT_LOG_PREFIX;
char* szPluginFileName = strdup(sPluginFileName.c_str());
string sPluginFileNameName = string(basename(szPluginFileName));
size_t idx = sPluginFileNameName.rfind('.');
if (idx == string::npos)
m_sConfigSectionName = sPluginFileNameName;
else
m_sConfigSectionName = sPluginFileNameName.substr(0, idx);
m_sDetectionCause = DEFAULT_DETECTION_CAUSE;
m_fMinAlarmScore = DEFAULT_MIN_ALARM_SCORE;
m_fMaxAlarmScore = DEFAULT_MAX_ALARM_SCORE;
m_fImageScaleFactor = DEFAULT_IMAGE_SCALE_FACTOR;
m_nNewWidth = 0;
m_nNewHeight = 0;
}
//! Copy constructor
Detector(const Detector& source);
//! Assignment operator
Detector& operator=(const Detector& source);
//! Detect (in an image later)
bool Detect(const Image &image, Zone** zones, Event::StringSet &zoneSet, unsigned int &score);
//! Load detector's parameters.
virtual int loadConfig(string sConfigFileName, map<unsigned int,map<string,string> > mapPluginConf) = 0;
//! Returns detection case string.
string getDetectionCause();
//! Returns plugin name as string.
string getPluginName();
//! Enable the plugin for the given zones.
void EnablePlugin(vector<unsigned int> zoneList);
//! Return the list of enabled zones
vector<unsigned int> getPluginZones();
protected:
//! Do detection inside one given zone.
virtual bool checkZone(Zone *zone, unsigned int n_zone, const Image *zmImage) = 0;
//! Log messages to the SYSLOG.
void log(int, string sLevel, string sMessage);
//! String to be shown as detection cause for event.
string m_sDetectionCause;
//! Minimum score value to consider frame as to be alarmed.
double m_fMinAlarmScore;
//! Maximum score value to consider frame as to be alarmed.
double m_fMaxAlarmScore;
//! Maximum allowed width of frame image.
double m_fImageScaleFactor;
//! Width of image to resize.
int m_nNewWidth;
//! Height of image to resize.
int m_nNewHeight;
//! String prefix for SYSLOG messages.
string m_sLogPrefix;
//! Name of config file section to search parameters.
string m_sConfigSectionName;
//! List of zones enabled for the plugin
vector<unsigned int> m_vnPluginZones;
//! Plugin status regarding zone settings
bool m_bIsPluginEnabled;
};
#endif // ZM_DETECTOR_H

105
src/zm_plugin.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "zm_plugin.h"
/*!\fn Plugin::Plugin(const std::string &sFilename)
* \param sFilename is the name of plugin file to load
*/
Plugin::Plugin(const std::string &sFilename)
: m_sPluginFileName(sFilename),
m_hDLL(0),
m_pDLLRefCount(0),
m_pfnGetEngineVersion(0),
m_pfnRegisterPlugin(0)
{
// Try to load the plugin as a dynamic library
m_hDLL = dlopen(sFilename.c_str(), RTLD_LAZY|RTLD_GLOBAL);
if(!m_hDLL) // if library hasn't been loaded successfully
{
throw runtime_error(string("Could not load '") + sFilename + "'");
}
// Locate the plugin's exported functions
try
{
m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(dlsym(m_hDLL, "getEngineVersion"));
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(dlsym(m_hDLL, "registerPlugin"));
// If the functions aren't found, we're going to assume this is
// a plain simple DLL and not one of our plugins
if(!m_pfnGetEngineVersion || ! m_pfnRegisterPlugin)
throw runtime_error(string("'") + sFilename + "' is not a valid plugin");
// Initialize a new DLL reference counter
m_pDLLRefCount = new size_t(1);
}
catch(runtime_error &ex)
{
dlclose(m_hDLL);
throw ex;
}
catch(...)
{
dlclose(m_hDLL);
throw runtime_error(string("Unknown exception while loading plugin '") + sFilename + string("'"));
}
}
/*!\fn Plugin::Plugin(const Plugin &Other)
* \param Other is the other plugin instance to copy
*/
Plugin::Plugin(const Plugin &Other)
: m_sPluginFileName(Other.m_sPluginFileName),
m_hDLL(Other.m_hDLL),
m_pDLLRefCount(Other.m_pDLLRefCount),
m_pfnGetEngineVersion(Other.m_pfnGetEngineVersion),
m_pfnRegisterPlugin(Other.m_pfnRegisterPlugin)
{
// Increase DLL reference counter
++*m_pDLLRefCount;
}
/*!\fn Plugin::operator=(const Plugin &Other)
* \param Other is the other plugin instance to copy
* return copy of object
*/
Plugin& Plugin::operator=(const Plugin &Other)
{
m_hDLL = Other.m_hDLL;
m_pfnGetEngineVersion = Other.m_pfnGetEngineVersion;
m_pfnRegisterPlugin = Other.m_pfnRegisterPlugin;
m_pDLLRefCount = Other.m_pDLLRefCount;
m_sPluginFileName = Other.m_sPluginFileName;
// Increase DLL reference counter
++*m_pDLLRefCount;
return *this;
}
Plugin::~Plugin()
{
// Only unload the DLL if there are no more references to it
if(!--*m_pDLLRefCount)
{
delete m_pDLLRefCount;
dlclose(m_hDLL);
}
}
/*!\fn Plugin::registerPlugin(PluginManager &K)
* \param K is the pointer to plugin manager
*/
void Plugin::registerPlugin(PluginManager &K)
{
m_pfnRegisterPlugin(K, m_sPluginFileName);
}

77
src/zm_plugin.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef ZM_PLUGIN_H
#define ZM_PLUGIN_H
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdexcept>
using namespace std;
class PluginManager;
//! Signature for the version query function
typedef int fnGetEngineVersion();
//! Signature for the plugin's registration function
typedef void fnRegisterPlugin(PluginManager &, string);
//! Representation of a plugin.
/*! Use for loading plugin's shared library
* and registration of it to the PluginManager.
*/
class Plugin
{
public:
//! Initialize and load plugin
Plugin(const std::string &sFilename);
//! Copy existing plugin instance
Plugin(const Plugin &Other);
//! Operator =.
Plugin &operator =(const Plugin &Other);
//! Unload a plugin
~Plugin();
//! Query the plugin for its expected engine version
int getEngineVersion() const { return m_pfnGetEngineVersion();}
//! Register the plugin to a PluginManager
void registerPlugin(PluginManager &K);
private:
//! Shared file name.
string m_sPluginFileName;
//! DLL handle
void* m_hDLL;
//! Number of references to the DLL
size_t *m_pDLLRefCount;
//! Version query function
fnGetEngineVersion *m_pfnGetEngineVersion;
//! Plugin registration function
fnRegisterPlugin *m_pfnRegisterPlugin;
};
#endif //ZM_PLUGIN_H

160
src/zm_plugin_manager.cpp Normal file
View File

@ -0,0 +1,160 @@
#include "zm_plugin_manager.h"
/*! \fn file_select(const struct direct *entry)
* A functor for selection of files with specified extension.
* \param entry is file structure
* \return 1 if file match selection criteria and
* 0 otherwise.
* NOTE: file extension is specified by PluginManager::m_sPluginExt
* static variable.
*/
int file_select(const struct direct *entry)
{
char *ptr;
if ((strcmp(entry->d_name, ".")== 0) || (strcmp(entry->d_name, "..") == 0))
return 0;
// Check for filename extensions.
ptr = rindex((char*)entry->d_name, '.');
if ((ptr != NULL) && (strcmp(ptr, (PluginManager::m_sPluginExt).c_str()) == 0))
return 1;
else
return 0;
}
/*! \fn join_paths(const string& p1, const string& p2)
* \param p1 is the first part of desired path
* \param p2 is the second part of desired path
* \return joined path string.
*/
string join_paths(const string& p1, const string& p2)
{
char sep = '/';
string tmp = p1;
#ifdef _WIN32
sep = '\\';
#endif
if (p1[p1.length()] != sep)
{ // Need to add a path separator
tmp += sep;
return(tmp + p2);
}
else
return(p1 + p2);
}
string PluginManager::m_sPluginExt = DEFAULT_PLUGIN_EXT;
PluginManager::PluginManager() {}
PluginManager::PluginManager(
int nMonitorId
) :
m_ImageAnalyser( nMonitorId )
{}
/*!\fn PluginManager::loadPlugin(const string &sFilename))
* \param sFilename is the name of plugin file to load
*/
bool PluginManager::loadPlugin(const string &sFilename)
{
try
{
if(m_LoadedPlugins.find(sFilename) == m_LoadedPlugins.end())
m_LoadedPlugins.insert(PluginMap::value_type(sFilename, Plugin(sFilename))).first->second.registerPlugin(*this);
}
catch(runtime_error &ex)
{
Error("Runtime error: %s", ex.what());
return false;
}
catch(...)
{
Error("Unknown exception. Could not load %s.", sFilename.c_str());
return false;
}
return true;
}
/*!\fn PluginManager::findPlugins(const string &sPath, bool loadPlugins)
* \param sPath is the path to folder to search plugins
* \param loadPlugins is a flag to allow loading of plugins
* \param nNumPlugLoaded is the number of loaded plugins
* \return the number of found plugins
*/
int PluginManager::findPlugins(const string sPath, bool loadPlugins, unsigned int& nNumPlugLoaded)
{
struct direct **files;
int count = scandir(sPath.c_str(), &files, file_select, alphasort);
if(count <= 0) count = 0;
for (int i = 0; i < count; ++i)
{
string sFileName = string(files[i]->d_name);
string sFullPath = join_paths(sPath, sFileName);
size_t idx = sFileName.rfind('.');
if (idx != string::npos)
sFileName = sFileName.substr(0, idx);
bool IsPluginRegistered = false;
if(config.load_plugins || loadPlugins)
{
Info("Loading plugin %s ... ", sFullPath.c_str());
IsPluginRegistered = loadPlugin(sFullPath);
}
mapPluginReg.insert( pair<string,bool>(sFileName, IsPluginRegistered) );
if (IsPluginRegistered) nNumPlugLoaded++;
}
return count;
}
/*!\fn PluginManager::configurePlugins(string sConfigFileName)
* \param sConfigFileName is the path to the configuration file, where parameters for all plugins are given.
* \param bDoNativeDet is true if native detection will be performed
*/
void PluginManager::configurePlugins(string sConfigFileName, bool bDoNativeDet)
{
m_ImageAnalyser.configurePlugins(sConfigFileName, bDoNativeDet);
}
/*!\fn PluginManager::getPluginsGenConf(map<string,pGenConf>& mapPluginGenConf)
* \param mapPluginGenConf is the map of general settings for the plugins
* \param mapPluginZoneConf is the map of zone settings for the plugins
* \return the number of found plugins
*/
unsigned long PluginManager::getPluginsGenConf(map<string,pGenConf>& mapPluginGenConf)
{
for (map<string,bool>::iterator it = mapPluginReg.begin() ; it != mapPluginReg.end(); ++it)
{
pGenConf plugGenConf;
m_ImageAnalyser.getRegPluginGenConf( it->first, plugGenConf );
plugGenConf.Registered = it->second;
mapPluginGenConf.insert( pair<string,pGenConf>(it->first, plugGenConf) );
}
return mapPluginGenConf.size();
}
/*!\fn PluginManager::getPluginZoneConf(string sPluginName, PluginZoneConf& mapPluginZoneConf)
* \param mapPluginZoneConf is the map of zone settings for the plugin
*/
void PluginManager::getPluginZoneConf(string sPluginName, PluginZoneConf& mapPluginZoneConf)
{
m_ImageAnalyser.getRegPluginZoneConf( sPluginName, mapPluginZoneConf );
}

94
src/zm_plugin_manager.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef ZM_PLUGIN_MANAGER_H
#define ZM_PLUGIN_MANAGER_H
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <map>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/param.h>
#include <unistd.h>
#include "zm_image_analyser.h"
#include "zm_detector.h"
#include "zm_plugin.h"
using namespace std;
#define ZM_ENGINE_VERSION 24
//! Map of plugins by their associated file names.
typedef std::map<std::string, Plugin> PluginMap;
//! External function for sorting of files in directory.
extern int alphasort();
//! Function to select files with plugins by extension.
int file_select(const struct direct *entry);
//! Join two path strings.
string join_paths(const string& p1, const string& p2);
//! Class for managing all loaded plugins.
class PluginManager
{
public:
//! Default constructor.
PluginManager();
//! Constructor with parameters
PluginManager(int nMonitorId);
//! Access the image analyser.
ImageAnalyser &getImageAnalyser() {return m_ImageAnalyser;}
//! Loads a plugin.
bool loadPlugin(const string &sFilename);
//! Find all plugins from given directory, load them if required and
//! return the number of found plugins and the number of loaded plugins
int findPlugins(const string sPath, bool loadPlugins, unsigned int& nNumPlugLoaded);
//! Get general settings of plugins
unsigned long getPluginsGenConf(map<string,pGenConf>& mapPluginGenConf);
//! Get zone settings of a plugin
void getPluginZoneConf(string sPluginName, PluginZoneConf& mapPluginZoneConf);
//! Configure all loaded plugins using given configuration file.
void configurePlugins(string sConfigFileName, bool bDoNativeDet);
//! Set plugin extension.
void setPluginExt(string sPluginExt) { m_sPluginExt = sPluginExt; }
//! Extension for zm plugins.
static string m_sPluginExt;
private:
//! All plugins currently loaded.
PluginMap m_LoadedPlugins;
//! The image analyser.
ImageAnalyser m_ImageAnalyser;
//! Plugin list
map<string,bool> mapPluginReg;
};
#endif //ZM_PLUGIN_MANAGER_H