Compare commits
158 Commits
1.36.12_he
...
feature-pl
Author | SHA1 | Date |
---|---|---|
Isaac Connor | bf6ca1547d | |
SteveGilvarry | 8cec795cc2 | |
SteveGilvarry | 25abe2aafd | |
SteveGilvarry | 20c295ad0c | |
Steve Gilvarry | b3e18cd8ff | |
SteveGilvarry | e089805276 | |
SteveGilvarry | 8e603690c9 | |
SteveGilvarry | 76ec7a4c51 | |
SteveGilvarry | fed8ea90a5 | |
SteveGilvarry | 2a323f6605 | |
SteveGilvarry | ea9457d7f5 | |
SteveGilvarry | 56de7aaccd | |
SteveGilvarry | f853059ff4 | |
SteveGilvarry | a700cbffdb | |
Emmanuel Papin | 3d15eaace7 | |
Emmanuel Papin | 520e0d8664 | |
Emmanuel Papin | 9ee7d67056 | |
Emmanuel Papin | b294569147 | |
Emmanuel Papin | 1fb6ed8a06 | |
Emmanuel Papin | a32a0f2752 | |
Emmanuel Papin | 717bd7fbfb | |
Emmanuel Papin | 6574a128de | |
Emmanuel Papin | 2acfe5b395 | |
Emmanuel Papin | c6b081696d | |
Emmanuel Papin | be3c431192 | |
Emmanuel Papin | 717710f444 | |
Emmanuel Papin | 7e8648d563 | |
Emmanuel Papin | e2957702b5 | |
Emmanuel Papin | 1b42dd90ef | |
Emmanuel Papin | 90fd90ae1e | |
Emmanuel Papin | 5492fd9e93 | |
Emmanuel Papin | a8524d9b3b | |
Emmanuel Papin | ded38268a4 | |
Emmanuel Papin | e3eee72abf | |
Emmanuel Papin | 3f20a08d16 | |
Emmanuel Papin | 905237d7a6 | |
Emmanuel Papin | 872fead1fa | |
Emmanuel Papin | 33f7342cec | |
Emmanuel Papin | de2ec868b4 | |
Emmanuel Papin | 746deece73 | |
Emmanuel Papin | eff56664c3 | |
Emmanuel Papin | 0135b90cf6 | |
Emmanuel Papin | eb9e01eb00 | |
Emmanuel Papin | 2b770b2f58 | |
Emmanuel Papin | 0241f844d2 | |
Emmanuel Papin | 775da60382 | |
Emmanuel Papin | 7766ec4c72 | |
Emmanuel Papin | 676968ed04 | |
Emmanuel Papin | 6b2c435460 | |
Emmanuel Papin | 49116a27d7 | |
Emmanuel Papin | 6a8eb03f0a | |
Emmanuel Papin | 96ebac4f49 | |
Emmanuel Papin | 55d974a0b3 | |
Emmanuel Papin | 5283369ed6 | |
Emmanuel Papin | 630c8f335f | |
Emmanuel Papin | 56b724e161 | |
Emmanuel Papin | 63158ebe7d | |
Emmanuel Papin | 7fd2f367c6 | |
Emmanuel Papin | 0988eaeb06 | |
Emmanuel Papin | a4e4db31bc | |
Emmanuel Papin | 40c3ba1ed3 | |
Emmanuel Papin | cdcac7726b | |
Emmanuel Papin | 0840d31011 | |
Emmanuel Papin | b1dbb23f13 | |
Emmanuel Papin | 9929233e75 | |
Emmanuel Papin | 5060fc490f | |
Emmanuel Papin | 8610f48afd | |
Emmanuel Papin | e7b1ab54df | |
Emmanuel Papin | bfef99fc6f | |
Emmanuel Papin | 7c0dfe9a5b | |
Emmanuel Papin | 4bbf1439bb | |
Emmanuel Papin | cd16b7168e | |
Emmanuel Papin | 9360837d38 | |
Emmanuel Papin | 35ed0b475c | |
Emmanuel Papin | a7b912b1b5 | |
Emmanuel Papin | 7906307580 | |
Emmanuel Papin | 53c8a3073f | |
Emmanuel Papin | 9cc53883ab | |
Emmanuel Papin | 70a062a609 | |
Emmanuel Papin | 2227d9c852 | |
Emmanuel Papin | abddb5d916 | |
Emmanuel Papin | ce90a37bb8 | |
Emmanuel Papin | 77138c48d2 | |
Emmanuel Papin | b5ab290e78 | |
Emmanuel Papin | 72d1581f44 | |
Emmanuel Papin | 491df7671d | |
Emmanuel Papin | 39e6de8f68 | |
Emmanuel Papin | f551b50ec0 | |
Emmanuel Papin | 7fc359e940 | |
Emmanuel Papin | 8619ed1322 | |
Emmanuel Papin | cdfb4b4bb5 | |
Emmanuel Papin | ee259be366 | |
Emmanuel Papin | d070b36aec | |
Emmanuel Papin | 091b31ae93 | |
Emmanuel Papin | 45edab3ad9 | |
Emmanuel Papin | a9986d6aa0 | |
Emmanuel Papin | e08c706d3c | |
Emmanuel Papin | 54d8e103d9 | |
Emmanuel Papin | fe0476f36b | |
Emmanuel Papin | d9bcf3aeef | |
Emmanuel Papin | 7c3ddece88 | |
Emmanuel Papin | bc89082548 | |
Emmanuel Papin | c1d7d7c744 | |
Emmanuel Papin | d2b1bfae13 | |
Emmanuel Papin | db61f93c35 | |
Emmanuel Papin | 39d270a8c3 | |
Emmanuel Papin | cb3b8a901e | |
Emmanuel Papin | 3b4d08be81 | |
Emmanuel Papin | f79887d453 | |
Emmanuel Papin | b4f35c20f1 | |
Emmanuel Papin | f339518787 | |
Emmanuel Papin | bff7fc1e2e | |
Emmanuel Papin | 208c72b25e | |
Emmanuel Papin | f1ce69a8c1 | |
Emmanuel Papin | 7bc44a22e6 | |
Emmanuel Papin | 82ef0edac3 | |
Emmanuel Papin | d961831355 | |
Emmanuel Papin | ee6fda5c67 | |
Emmanuel Papin | 3d65f2150d | |
Emmanuel Papin | a3473b8414 | |
Emmanuel Papin | 3a51926954 | |
Emmanuel Papin | c7fb522563 | |
Emmanuel Papin | e37793f79a | |
Emmanuel Papin | 9e39924095 | |
Emmanuel Papin | a4c01435d7 | |
Emmanuel Papin | dde1e13f22 | |
Emmanuel Papin | b5aa7371ad | |
Emmanuel Papin | 06e31f807f | |
Emmanuel Papin | 166b4586aa | |
Emmanuel Papin | fab48b904f | |
Emmanuel Papin | 123326c299 | |
Emmanuel Papin | ef452cb986 | |
Emmanuel Papin | a03b3ce4e0 | |
Emmanuel Papin | ecd9ab95eb | |
Emmanuel Papin | e7f1c8b5d8 | |
manupap1 | dac1756d0d | |
manupap1 | cee8b77bec | |
manupap1 | eae1357a45 | |
manupap1 | 6d083fef10 | |
manupap1 | 2a3068cfa7 | |
manupap1 | f4bdee108f | |
manupap1 | 2033918b24 | |
manupap1 | 7ff86427b3 | |
manupap1 | 65915c10e3 | |
manupap1 | 003fafbf7d | |
manupap1 | 731fa96fdf | |
manupap1 | 12f0177f14 | |
manupap1 | 2796995d29 | |
manupap1 | 199f399caf | |
manupap1 | 15532e2a03 | |
manupap1 | 5d5d9c5009 | |
manupap1 | 217aafee5a | |
manupap1 | 0d430b5f4f | |
manupap1 | 9bfc64c4f9 | |
manupap1 | 03d03bda21 | |
manupap1 | e60c3d552c | |
manupap1 | 26608afa2d | |
manupap1 | 93a29545ce |
|
@ -20,11 +20,16 @@ config.log
|
|||
config.status
|
||||
config.sub
|
||||
db/zm_create.sql
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/*
|
||||
misc/apache.conf
|
||||
misc/com.zoneminder.systemctl.policy
|
||||
misc/com.zoneminder.systemctl.rules
|
||||
misc/libzoneminder.pc
|
||||
misc/logrotate.conf
|
||||
misc/syslog.conf
|
||||
misc/plugins.conf
|
||||
onvif/modules/MYMETA.json
|
||||
onvif/modules/MYMETA.yml
|
||||
onvif/proxy/MYMETA.json
|
||||
|
@ -56,6 +61,9 @@ scripts/zmvideo.pl
|
|||
scripts/zmwatch.pl
|
||||
scripts/zmx10.pl
|
||||
src/.deps/
|
||||
src/.libs/
|
||||
src/*.la
|
||||
src/*.lo
|
||||
src/*.o
|
||||
src/zm_config.h
|
||||
src/zm_config_defines.h
|
||||
|
|
106
CMakeLists.txt
106
CMakeLists.txt
|
@ -5,6 +5,8 @@
|
|||
cmake_minimum_required (VERSION 2.6)
|
||||
project (zoneminder)
|
||||
set(zoneminder_VERSION "1.29.0")
|
||||
# Engine version is used for external plugin compilation
|
||||
set(ZM_ENGINE_VERSION 29)
|
||||
# make API version a minor of ZM version
|
||||
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")
|
||||
|
||||
|
@ -69,12 +71,14 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
|||
# Modules that we need:
|
||||
include (GNUInstallDirs)
|
||||
include (CheckIncludeFile)
|
||||
include (CheckIncludeFileCXX)
|
||||
include (CheckIncludeFiles)
|
||||
include (CheckFunctionExists)
|
||||
include (CheckPrototypeDefinition_fixed)
|
||||
include (CheckTypeSize)
|
||||
include (CheckStructHasMember)
|
||||
include (CheckSendfile)
|
||||
include (FindPkgConfig)
|
||||
|
||||
# Configuration options
|
||||
mark_as_advanced(
|
||||
|
@ -85,7 +89,13 @@ mark_as_advanced(
|
|||
ZM_PERL_MM_PARMS
|
||||
ZM_PERL_SEARCH_PATH
|
||||
ZM_TARGET_DISTRO
|
||||
ZM_CONFIG_DIR)
|
||||
ZM_CONFIG_DIR
|
||||
ZM_PLUGIN_SUPPORT
|
||||
ZM_PLUGIN_COMPIL
|
||||
ZM_PLUGINSLIBDIR
|
||||
ZM_PLUGINSPKGLIBDIR
|
||||
ZM_PLUGINSCONFDIR
|
||||
ZM_PLUGINSWEBDIR)
|
||||
|
||||
set(ZM_RUNDIR "/var/run/zm" CACHE PATH
|
||||
"Location of transient process files, default: /var/run/zm")
|
||||
|
@ -147,7 +157,28 @@ set(ZM_PERL_SEARCH_PATH "" CACHE PATH
|
|||
where ZM_PERL_MM_PARMS has been modified such that ZoneMinder's Perl modules are
|
||||
installed outside Perl's default search path.")
|
||||
set(ZM_TARGET_DISTRO "" CACHE STRING
|
||||
"Build ZoneMinder for a specific distribution. Currently, valid names are: f22, f23, el6, el7, OS13")
|
||||
"Build ZoneMinder for a specific distribution. Currently, valid names are: f21, f22, el6, el7, OS13")
|
||||
set(ZM_PLUGIN_SUPPORT "OFF" CACHE BOOL
|
||||
"Set to ON to enable plugin support in ZoneMinder. This is EXPERIMENTAL, default: OFF")
|
||||
set(ZM_PLUGIN_COMPIL "OFF" CACHE BOOL
|
||||
"Set to ON to enable compilation of internal plugins. This is EXPERIMENTAL, default: OFF")
|
||||
|
||||
if(ZM_PLUGIN_SUPPORT)
|
||||
set(ZM_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(ZM_PLUGINSLIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}" CACHE PATH
|
||||
"Location of the plugin development library, default: ${CMAKE_INSTALL_LIBDIR}")
|
||||
set(ZM_PLUGINSPKGLIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}/zoneminder/plugins" CACHE PATH
|
||||
"Location of the plugin file, default: <prefix>/${CMAKE_INSTALL_LIBEXECDIR}/zoneminder/plugins")
|
||||
set(ZM_PLUGINSCONFDIR "/${CMAKE_INSTALL_SYSCONFDIR}/plugins.d" CACHE PATH
|
||||
"Location of the plugin configuration files, default: /${CMAKE_INSTALL_SYSCONFDIR}/plugins.d")
|
||||
set(ZM_PLUGINSWEBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/zoneminder/plugins" CACHE PATH
|
||||
"Location of the plugin web files, default: <prefix>/${CMAKE_INSTALL_DATADIR}/zoneminder/plugins")
|
||||
set(ZM_PROJECTNAME ${CMAKE_PROJECT_NAME})
|
||||
set(ZM_PLUGINSEXT ".so" CACHE STRING
|
||||
"Plugin extension, default: .so")
|
||||
add_definitions(-DDEFAULT_PLUGIN_EXT=\"${ZM_PLUGIN_EXT}\")
|
||||
add_definitions(-DZM_PLUGINS_ON=1)
|
||||
endif(ZM_PLUGIN_SUPPORT)
|
||||
|
||||
# Reassign some variables if a target distro has been specified
|
||||
if((ZM_TARGET_DISTRO STREQUAL "f22") OR (ZM_TARGET_DISTRO STREQUAL "f23"))
|
||||
|
@ -247,6 +278,7 @@ find_package(ZLIB)
|
|||
if(ZLIB_FOUND)
|
||||
set(HAVE_LIBZLIB 1)
|
||||
list(APPEND ZM_BIN_LIBS "${ZLIB_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lz")
|
||||
include_directories("${ZLIB_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${ZLIB_INCLUDE_DIR}")
|
||||
check_include_file("zlib.h" HAVE_ZLIB_H)
|
||||
|
@ -262,6 +294,7 @@ if(NOT ZM_NO_CURL)
|
|||
if(CURL_FOUND)
|
||||
set(HAVE_LIBCURL 1)
|
||||
list(APPEND ZM_BIN_LIBS ${CURL_LIBRARIES})
|
||||
set(LIBS "${LIBS} -lcurl")
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS})
|
||||
check_include_file("curl/curl.h" HAVE_CURL_CURL_H)
|
||||
|
@ -276,6 +309,7 @@ find_package(JPEG)
|
|||
if(JPEG_FOUND)
|
||||
set(HAVE_LIBJPEG 1)
|
||||
list(APPEND ZM_BIN_LIBS "${JPEG_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -ljpeg")
|
||||
#link_directories(${JPEG_LIBRARY})
|
||||
include_directories("${JPEG_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${JPEG_INCLUDE_DIR}")
|
||||
|
@ -295,6 +329,7 @@ if(OPENSSL_FOUND)
|
|||
set(HAVE_LIBOPENSSL 1)
|
||||
set(HAVE_LIBCRYPTO 1)
|
||||
list(APPEND ZM_BIN_LIBS "${OPENSSL_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lssl -lcrypto")
|
||||
include_directories("${OPENSSL_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||
check_include_file("openssl/md5.h" HAVE_OPENSSL_MD5_H)
|
||||
|
@ -308,6 +343,7 @@ find_library(PTHREAD_LIBRARIES pthread)
|
|||
if(PTHREAD_LIBRARIES)
|
||||
set(HAVE_LIBPTHREAD 1)
|
||||
list(APPEND ZM_BIN_LIBS "${PTHREAD_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lpthread")
|
||||
find_path(PTHREAD_INCLUDE_DIR pthread.h)
|
||||
if(PTHREAD_INCLUDE_DIR)
|
||||
include_directories("${PTHREAD_INCLUDE_DIR}")
|
||||
|
@ -329,6 +365,7 @@ find_library(PCRE_LIBRARIES pcre)
|
|||
if(PCRE_LIBRARIES)
|
||||
set(HAVE_LIBPCRE 1)
|
||||
list(APPEND ZM_BIN_LIBS "${PCRE_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lpcre")
|
||||
find_path(PCRE_INCLUDE_DIR pcre.h)
|
||||
if(PCRE_INCLUDE_DIR)
|
||||
include_directories("${PCRE_INCLUDE_DIR}")
|
||||
|
@ -346,6 +383,7 @@ find_library(GCRYPT_LIBRARIES gcrypt)
|
|||
if(GCRYPT_LIBRARIES)
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
list(APPEND ZM_BIN_LIBS "${GCRYPT_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lgcrypt")
|
||||
find_path(GCRYPT_INCLUDE_DIR gcrypt.h)
|
||||
if(GCRYPT_INCLUDE_DIR)
|
||||
include_directories("${GCRYPT_INCLUDE_DIR}")
|
||||
|
@ -367,6 +405,7 @@ endif(NOT GNUTLS_LIBRARIES)
|
|||
if(GNUTLS_LIBRARIES)
|
||||
set(HAVE_LIBGNUTLS 1)
|
||||
list(APPEND ZM_BIN_LIBS "${GNUTLS_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lgnutls-openssl")
|
||||
find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h)
|
||||
if(GNUTLS_INCLUDE_DIR)
|
||||
include_directories("${GNUTLS_INCLUDE_DIR}")
|
||||
|
@ -385,6 +424,7 @@ find_library(MYSQLCLIENT_LIBRARIES mysqlclient PATH_SUFFIXES mysql)
|
|||
if(MYSQLCLIENT_LIBRARIES)
|
||||
set(HAVE_LIBMYSQLCLIENT 1)
|
||||
list(APPEND ZM_BIN_LIBS "${MYSQLCLIENT_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lmysqlclient")
|
||||
find_path(MYSQLCLIENT_INCLUDE_DIR mysql/mysql.h)
|
||||
if(MYSQLCLIENT_INCLUDE_DIR)
|
||||
include_directories("${MYSQLCLIENT_INCLUDE_DIR}")
|
||||
|
@ -410,6 +450,7 @@ if(NOT ZM_NO_FFMPEG)
|
|||
if(AVFORMAT_LIBRARIES)
|
||||
set(HAVE_LIBAVFORMAT 1)
|
||||
list(APPEND ZM_BIN_LIBS "${AVFORMAT_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lavformat")
|
||||
find_path(AVFORMAT_INCLUDE_DIR "libavformat/avformat.h" /usr/include/ffmpeg)
|
||||
if(AVFORMAT_INCLUDE_DIR)
|
||||
include_directories("${AVFORMAT_INCLUDE_DIR}")
|
||||
|
@ -427,6 +468,7 @@ if(NOT ZM_NO_FFMPEG)
|
|||
if(AVCODEC_LIBRARIES)
|
||||
set(HAVE_LIBAVCODEC 1)
|
||||
list(APPEND ZM_BIN_LIBS "${AVCODEC_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lavcodec")
|
||||
find_path(AVCODEC_INCLUDE_DIR "libavcodec/avcodec.h" /usr/include/ffmpeg)
|
||||
if(AVCODEC_INCLUDE_DIR)
|
||||
include_directories("${AVCODEC_INCLUDE_DIR}")
|
||||
|
@ -444,6 +486,7 @@ if(NOT ZM_NO_FFMPEG)
|
|||
if(AVDEVICE_LIBRARIES)
|
||||
set(HAVE_LIBAVDEVICE 1)
|
||||
list(APPEND ZM_BIN_LIBS "${AVDEVICE_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lavdevice")
|
||||
find_path(AVDEVICE_INCLUDE_DIR "libavdevice/avdevice.h" /usr/include/ffmpeg)
|
||||
if(AVDEVICE_INCLUDE_DIR)
|
||||
include_directories("${AVDEVICE_INCLUDE_DIR}")
|
||||
|
@ -461,6 +504,7 @@ if(NOT ZM_NO_FFMPEG)
|
|||
if(AVUTIL_LIBRARIES)
|
||||
set(HAVE_LIBAVUTIL 1)
|
||||
list(APPEND ZM_BIN_LIBS "${AVUTIL_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lavutil")
|
||||
find_path(AVUTIL_INCLUDE_DIR "libavutil/avutil.h" /usr/include/ffmpeg)
|
||||
if(AVUTIL_INCLUDE_DIR)
|
||||
include_directories("${AVUTIL_INCLUDE_DIR}")
|
||||
|
@ -479,6 +523,7 @@ if(NOT ZM_NO_FFMPEG)
|
|||
if(SWSCALE_LIBRARIES)
|
||||
set(HAVE_LIBSWSCALE 1)
|
||||
list(APPEND ZM_BIN_LIBS "${SWSCALE_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lswscale")
|
||||
find_path(SWSCALE_INCLUDE_DIR "libswscale/swscale.h" /usr/include/ffmpeg)
|
||||
if(SWSCALE_INCLUDE_DIR)
|
||||
include_directories("${SWSCALE_INCLUDE_DIR}")
|
||||
|
@ -510,6 +555,7 @@ if(NOT ZM_NO_LIBVLC)
|
|||
if(LIBVLC_LIBRARIES)
|
||||
set(HAVE_LIBVLC 1)
|
||||
list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
|
||||
set(LIBS "${LIBS} -lvlc")
|
||||
find_path(LIBVLC_INCLUDE_DIR "vlc/vlc.h")
|
||||
if(LIBVLC_INCLUDE_DIR)
|
||||
include_directories("${LIBVLC_INCLUDE_DIR}")
|
||||
|
@ -523,6 +569,29 @@ if(NOT ZM_NO_LIBVLC)
|
|||
endif(LIBVLC_LIBRARIES)
|
||||
endif(NOT ZM_NO_LIBVLC)
|
||||
|
||||
if(ZM_PLUGIN_COMPIL)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(opencv opencv>=2.3.1)
|
||||
if(NOT opencv_FOUND)
|
||||
message(FATAL_ERROR "opencv.pc not found")
|
||||
endif(NOT opencv_FOUND)
|
||||
else(PKG_CONFIG_FOUND)
|
||||
message(FATAL_ERROR "pkg-config not found")
|
||||
endif(PKG_CONFIG_FOUND)
|
||||
find_package(OpenCV COMPONENTS core imgproc highgui objdetect REQUIRED)
|
||||
if(OpenCV_FOUND)
|
||||
include_directories(${OpenCV_INCLUDE_DIR})
|
||||
else(OpenCV_FOUND)
|
||||
message(FATAL_ERROR "Cannot build application without OpenCV. Please set OpenCV_INCLUDE_DIR.")
|
||||
endif(OpenCV_FOUND)
|
||||
find_package(Boost COMPONENTS program_options REQUIRED)
|
||||
if(Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIR})
|
||||
else(Boost_FOUND)
|
||||
message(FATAL_ERROR "Cannot build application without Boost. Please set Boost_INCLUDE_DIR.")
|
||||
endif(Boost_FOUND)
|
||||
endif(ZM_PLUGIN_COMPIL)
|
||||
|
||||
# *** END OF LIBRARY CHECKS ***
|
||||
|
||||
# Check for gnutls or crypto
|
||||
|
@ -611,6 +680,29 @@ if(HAVE_LIBCRYPTO AND HAVE_OPENSSL_MD5_H AND HAVE_MD5_OPENSSL)
|
|||
set(HAVE_GNUTLS_OPENSSL_H 0)
|
||||
endif(HAVE_LIBCRYPTO AND HAVE_OPENSSL_MD5_H AND HAVE_MD5_OPENSSL)
|
||||
|
||||
if(ZM_PLUGIN_COMPIL)
|
||||
check_include_file_cxx("alpr.h" HAVE_ALPR_H)
|
||||
if(NOT HAVE_ALPR_H)
|
||||
message(FATAL_ERROR "Missing include file alpr.h")
|
||||
endif(NOT HAVE_ALPR_H)
|
||||
check_include_file_cxx("opencv2/core/core.hpp" HAVE_OPENCV2_CORE_CORE_HPP)
|
||||
if(NOT HAVE_OPENCV2_CORE_CORE_HPP)
|
||||
message(FATAL_ERROR "Missing include file opencv2/core/core.hpp")
|
||||
endif(NOT HAVE_OPENCV2_CORE_CORE_HPP)
|
||||
check_include_file_cxx("opencv2/imgproc/imgproc.hpp" HAVE_OPENCV2_IMGPROC_IMGPROC_HPP)
|
||||
if(NOT HAVE_OPENCV2_IMGPROC_IMGPROC_HPP)
|
||||
message(FATAL_ERROR "Missing include file opencv2/imgproc/imgproc.hpp")
|
||||
endif(NOT HAVE_OPENCV2_IMGPROC_IMGPROC_HPP)
|
||||
check_include_file_cxx("boost/algorithm/string.hpp" HAVE_BOOST_ALGORITHM_STRING_HPP)
|
||||
if(NOT HAVE_BOOST_ALGORITHM_STRING_HPP)
|
||||
message(FATAL_ERROR "Missing include file boost/algorithm/string.hpp")
|
||||
endif(NOT HAVE_BOOST_ALGORITHM_STRING_HPP)
|
||||
check_include_file_cxx("boost/program_options.hpp" HAVE_BOOST_PROGRAM_OPTIONS_HPP)
|
||||
if(NOT HAVE_BOOST_PROGRAM_OPTIONS_HPP)
|
||||
message(FATAL_ERROR "Missing include file boost/program_options.hpp")
|
||||
endif(NOT HAVE_BOOST_PROGRAM_OPTIONS_HPP)
|
||||
endif(ZM_PLUGIN_COMPIL)
|
||||
|
||||
# Check for Perl
|
||||
find_package(Perl)
|
||||
if(NOT PERL_FOUND)
|
||||
|
@ -707,6 +799,11 @@ if(ZM_ONVIF)
|
|||
add_subdirectory(onvif)
|
||||
endif(ZM_ONVIF)
|
||||
|
||||
# Enable compilation of internal plugins
|
||||
if(ZM_PLUGIN_COMPIL)
|
||||
add_subdirectory(plugins)
|
||||
endif(ZM_PLUGIN_COMPIL)
|
||||
|
||||
# Process distro subdirectories
|
||||
if((ZM_TARGET_DISTRO STREQUAL "f22") OR (ZM_TARGET_DISTRO STREQUAL "f23"))
|
||||
add_subdirectory(distros/fedora)
|
||||
|
@ -734,6 +831,11 @@ endif(zmconfgen_result EQUAL 0)
|
|||
# Install zm.conf
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm.conf" DESTINATION "${ZM_CONFIG_DIR}")
|
||||
|
||||
if(ZM_PLUGIN_SUPPORT)
|
||||
# Install config.h
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/config.h" DESTINATION include/zoneminder)
|
||||
endif(ZM_PLUGIN_SUPPORT)
|
||||
|
||||
# Uninstall target
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE `PluginsConfig` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`Name` varchar(32) NOT NULL DEFAULT '',
|
||||
`Value` text NOT NULL,
|
||||
`Type` tinytext NOT NULL,
|
||||
`Choices` text default NULL,
|
||||
`Min` int(10) unsigned NULL default NULL,
|
||||
`Max` int(10) unsigned NULL default NULL,
|
||||
`MonitorId` int(10) unsigned NOT NULL,
|
||||
`ZoneId` int(10) unsigned NOT NULL,
|
||||
`pluginName` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `ZoneId` (`ZoneId`),
|
||||
KEY `MonitorId` (`MonitorId`),
|
||||
KEY `Name` (`Name`),
|
||||
KEY `pluginName` (`pluginName`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
ALTER TABLE `Monitors` ADD `DoNativeMotDet` tinyint(3) unsigned NOT NULL default '1' AFTER `Sequence`;
|
|
@ -386,6 +386,7 @@ CREATE TABLE `Monitors` (
|
|||
`WebColour` varchar(32) NOT NULL default 'red',
|
||||
`Exif` tinyint(1) unsigned NOT NULL default '0',
|
||||
`Sequence` smallint(5) unsigned default NULL,
|
||||
`DoNativeMotDet` tinyint(3) unsigned NOT NULL default '1',
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
|
@ -544,6 +545,25 @@ CREATE TABLE `Zones` (
|
|||
KEY `MonitorId` (`MonitorId`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
DROP TABLE IF EXISTS `PluginsConfig`;
|
||||
CREATE TABLE `PluginsConfig` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`Name` varchar(32) NOT NULL DEFAULT '',
|
||||
`Value` text NOT NULL,
|
||||
`Type` tinytext NOT NULL,
|
||||
`Choices` text default NULL,
|
||||
`Min` int(10) unsigned NULL default NULL,
|
||||
`Max` int(10) unsigned NULL default NULL,
|
||||
`MonitorId` int(10) unsigned NOT NULL,
|
||||
`ZoneId` int(10) unsigned NOT NULL,
|
||||
`pluginName` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `ZoneId` (`ZoneId`),
|
||||
KEY `MonitorId` (`MonitorId`),
|
||||
KEY `Name` (`Name`),
|
||||
KEY `pluginName` (`pluginName`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
|
|
|
@ -68,3 +68,11 @@ Description: Debugging symbols for zoneminder.
|
|||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
|
||||
Package: libzoneminder-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Description: Development files for ZoneMinder plugins
|
||||
This package add the necessary files to develop video analysis plugins for
|
||||
the ZoneMinder camera security and surveillance solution.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
usr/include/zoneminder/*
|
||||
usr/lib/*/libzoneminder.a
|
||||
usr/lib/*/pkgconfig/libzoneminder.pc
|
|
@ -28,7 +28,7 @@ endif
|
|||
dh $@ --with quilt,autoreconf
|
||||
|
||||
override_dh_auto_configure:
|
||||
CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" dh_auto_configure -- --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --sysconfdir=/etc/zm --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --with-mysql=/usr --with-mariadb=/usr --with-webdir=/usr/share/zoneminder --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-crashtrace=no --enable-mmap=yes
|
||||
CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" dh_auto_configure -- --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --sysconfdir=/etc/zm --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --with-mysql=/usr --with-mariadb=/usr --with-webdir=/usr/share/zoneminder --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-crashtrace=no --enable-mmap=yes --enable-plugin-support --with-pluginsdir=/usr/lib/zoneminder/plugins
|
||||
|
||||
override_dh_clean:
|
||||
# Add here commands to clean up after the build process.
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
zoneminder (1.28.1+nmu1) experimental; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* Add plugin support
|
||||
|
||||
-- Emmanuel Papin <manupap01@gmail.com> Tue, 27 Jan 2015 19:23:07 +0100
|
||||
|
||||
zoneminder (1.28.0+nmu1) testing; urgency=medium
|
||||
|
||||
* Non-maintainer upload
|
||||
|
|
|
@ -2,7 +2,7 @@ Source: zoneminder
|
|||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Isaac Connor <iconnor@connortechnology.com>
|
||||
Build-Depends: debhelper (>= 9), po-debconf (>= 1.0), dh-systemd (>= 1.5), autoconf, automake, libphp-serialization-perl, libgnutls28-dev, libmysqlclient-dev | libmariadbclient-dev, libdbd-mysql-perl, libdate-manip-perl, libwww-perl, libjpeg8-dev | libjpeg9-dev | libjpeg62-turbo-dev, libpcre3-dev, libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libv4l-dev (>= 0.8.3), libbz2-dev, libtool, libsys-mmap-perl, libnetpbm10-dev, libavdevice-dev, libdevice-serialport-perl, libarchive-zip-perl, libmime-lite-perl, dh-autoreconf, libvlccore-dev, libvlc-dev, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libgcrypt11-dev | libgcrypt20-dev, libpolkit-gobject-1-dev, libdbi-perl, libnet-sftp-foreign-perl, libexpect-perl, libmime-tools-perl
|
||||
Build-Depends: debhelper (>= 9), po-debconf (>= 1.0), dh-systemd (>= 1.5), autoconf, automake, libphp-serialization-perl, libgnutls28-dev, libmysqlclient-dev | libmariadbclient-dev, libdbd-mysql-perl, libdate-manip-perl, libwww-perl, libjpeg8-dev | libjpeg9-dev | libjpeg62-turbo-dev, libpcre3-dev, libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libv4l-dev (>= 0.8.3), libbz2-dev, libtool, libsys-mmap-perl, libnetpbm10-dev, libavdevice-dev, libdevice-serialport-perl, libarchive-zip-perl, libmime-lite-perl, dh-autoreconf, libvlccore-dev, libvlc-dev, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libgcrypt11-dev | libgcrypt20-dev, libpolkit-gobject-1-dev, libdbi-perl, libnet-sftp-foreign-perl, libexpect-perl, libmime-tools-perl, libopenalpr-dev (>= 2.0.0), libboost-program-options1.55-dev, libopencv-dev, libopencv-core-dev, libopencv-imgproc-dev
|
||||
Standards-Version: 3.9.6
|
||||
|
||||
Package: zoneminder
|
||||
|
@ -13,7 +13,9 @@ Depends: ${misc:Depends},
|
|||
zoneminder-database (>= ${source:Version}),
|
||||
zoneminder-core (>= ${binary:Version}),
|
||||
zoneminder-ui-base (>= ${source:Version}),
|
||||
zoneminder-ui-classic (>= ${source:Version})
|
||||
zoneminder-ui-classic (>= ${source:Version}),
|
||||
zoneminder-ui-mobile (>= ${source:Version}),
|
||||
zoneminder-ui-xml (>= ${source:Version})
|
||||
Description: Video camera security and surveillance solution (metapackage)
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
|
@ -38,6 +40,15 @@ Description: Perl libraries for ZoneMinder
|
|||
This package provides the libraries for the perl scripts, it can be used to
|
||||
write custom interfaces as well.
|
||||
|
||||
Package: libzoneminder-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Description: Development library for ZoneMinder plugins
|
||||
ZoneMinder is a video camera security and surveillance solution.
|
||||
.
|
||||
This package provides the necessary files to develop video analysis plugins.
|
||||
|
||||
Package: zoneminder-database
|
||||
Section: database
|
||||
Architecture: all
|
||||
|
@ -101,3 +112,12 @@ Description: Classic web user interface for ZoneMinder
|
|||
ZoneMinder is a video camera security and surveillance solution.
|
||||
.
|
||||
This package provides the classic web user interface.
|
||||
|
||||
Package: libzoneminder-plugin-openalpr
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: zoneminder-core (= ${binary:Version}), ${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
Description: License Plate Recognition plugin with openalpr library
|
||||
This plugin add support for recognition of license plate number in zoneminder
|
||||
with the use of the OpenALPR library.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
usr/include/zoneminder
|
||||
usr/lib/*/libzoneminder.a
|
||||
usr/lib/*/pkgconfig/libzoneminder.pc
|
|
@ -0,0 +1,4 @@
|
|||
usr/lib/zoneminder/plugins/libzm_plugin_openalpr.so
|
||||
usr/share/zoneminder/plugins/libzm_plugin_openalpr/config.php
|
||||
usr/share/zoneminder/plugins/libzm_plugin_openalpr/lang/*_*.php
|
||||
etc/zm/plugins.d/openalpr.conf
|
|
@ -53,7 +53,9 @@ override_dh_auto_configure:
|
|||
--with-mariadb=/usr --with-webdir=/usr/share/zoneminder \
|
||||
--with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin \
|
||||
--with-webuser=www-data --with-webgroup=www-data \
|
||||
--enable-crashtrace=no --enable-mmap=yes $(DEBOPT)
|
||||
--enable-crashtrace=no --enable-mmap=yes $(DEBOPT) \
|
||||
--enable-plugin-support --with-pluginsdir=/usr/lib/zoneminder/plugins \
|
||||
--enable-plugin-compilation=yes
|
||||
|
||||
override_dh_clean:
|
||||
# Add here commands to clean up after the build process.
|
||||
|
@ -72,6 +74,9 @@ override_dh_clean:
|
|||
done || true
|
||||
|
||||
override_dh_install:
|
||||
# Clean up libtool crap
|
||||
find debian/tmp -name '*.la' -exec rm '{}' ';'
|
||||
#
|
||||
dh_install --fail-missing
|
||||
#
|
||||
# NOTE: This is a short-term kludge; hopefully changes in the next
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
etc/zm
|
||||
etc/zm/plugins.conf
|
||||
etc/zm/zm.conf
|
||||
usr/bin
|
||||
usr/share/polkit-1/actions
|
||||
usr/share/polkit-1/rules.d
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
usr/share/zoneminder/db
|
||||
usr/share/dbconfig-common/data/zoneminder/install
|
||||
usr/share/dbconfig-common/data/zoneminder/upgrade/mysql
|
||||
etc/zm/plugins.d
|
||||
usr/share/zoneminder/plugins
|
||||
|
|
|
@ -69,3 +69,11 @@ Description: Debugging symbols for zoneminder.
|
|||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
|
||||
Package: libzoneminder-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Description: Development files for ZoneMinder plugins
|
||||
This package add the necessary files to develop video analysis plugins for
|
||||
the ZoneMinder camera security and surveillance solution.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
usr/include/zoneminder/*
|
||||
usr/lib/*/libzoneminder.a
|
||||
usr/lib/*/pkgconfig/libzoneminder.pc
|
|
@ -22,7 +22,9 @@ override_dh_auto_configure:
|
|||
-DZM_CGIDIR=/usr/lib/zoneminder/cgi-bin \
|
||||
-DZM_WEB_USER=www-data \
|
||||
-DZM_WEB_GROUP=www-data \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=etc/zm
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=etc/zm \
|
||||
-DZM_PLUGIN_SUPPORT=ON \
|
||||
-DZM_PLUGINSPKGLIBDIR=/usr/lib/zoneminder/plugins
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install --buildsystem=cmake
|
||||
|
|
|
@ -16,3 +16,12 @@ configure_file(zoneminder-tmpfiles.conf.in "${CMAKE_CURRENT_BINARY_DIR}/zonemind
|
|||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.zoneminder.systemctl.policy" DESTINATION "${PC_POLKIT_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/polkit-1/actions")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.zoneminder.systemctl.rules" DESTINATION "${PC_POLKIT_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/polkit-1/rules.d")
|
||||
|
||||
if(ZM_PLUGIN_SUPPORT)
|
||||
configure_file(plugins.conf.in "${CMAKE_CURRENT_BINARY_DIR}/plugins.conf" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/plugins.conf" DESTINATION "${ZM_CONFIG_DIR}")
|
||||
include(FindPkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
configure_file(libzoneminder.pc.in "${CMAKE_CURRENT_BINARY_DIR}/libzoneminder.pc" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libzoneminder.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
endif()
|
||||
endif(ZM_PLUGIN_SUPPORT)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
prefix = @ZM_PREFIX@
|
||||
exec_prefix = ${prefix}
|
||||
libdir = @ZM_PLUGINSLIBDIR@
|
||||
pkglibdir = @ZM_PLUGINSPKGLIBDIR@
|
||||
includedir = ${prefix}/include
|
||||
sysconfdir = @ZM_PLUGINSCONFDIR@
|
||||
webdir = @ZM_PLUGINSWEBDIR@
|
||||
|
||||
Name: @ZM_PROJECTNAME@
|
||||
Description: ZoneMinder convenience library for plugin development.
|
||||
Version: @VERSION@
|
||||
Requires:
|
||||
Requires.private:
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lzoneminder @LIBS@
|
||||
Libs.private:
|
||||
Cflags: -I${includedir}/zoneminder
|
|
@ -0,0 +1,13 @@
|
|||
# Zoneminder global configuration file for plugins
|
||||
# Add here a section for each plugins or add separated configuration files
|
||||
# under @PLUGINSCONFDIR@
|
||||
#
|
||||
# Syntax:
|
||||
# [plugin_name_A]
|
||||
# parameter1 = value1
|
||||
# parameter2 = value2
|
||||
# ...
|
||||
# [plugin_name_B]
|
||||
# parameter1 = value1
|
||||
# parameter2 = value2
|
||||
# ...
|
|
@ -0,0 +1,4 @@
|
|||
# CMakeLists.txt for the plugins directory
|
||||
|
||||
# Process subdirectories
|
||||
add_subdirectory(libzm_plugin_openalpr)
|
|
@ -0,0 +1,4 @@
|
|||
AUTOMAKE_OPTIONS = gnu
|
||||
|
||||
SUBDIRS = \
|
||||
libzm_plugin_openalpr
|
|
@ -0,0 +1,6 @@
|
|||
# CMakeLists.txt for openalpr plugin.
|
||||
# Created by Emmanuel Papin (manupap01@gmail.com)
|
||||
|
||||
# Process subdirectories
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(src)
|
|
@ -0,0 +1,5 @@
|
|||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
SUBDIRS = \
|
||||
data \
|
||||
src
|
|
@ -0,0 +1,71 @@
|
|||
libzm-plugin-openalpr
|
||||
=====================
|
||||
|
||||
## Overview
|
||||
|
||||
libzm-plugin-openalpr is a plugin for Automatic Licence Plate Recognition (ALPR).
|
||||
The recognized license plates are added to Zoneminder's event notes.
|
||||
|
||||
## Requirements
|
||||
|
||||
libzm-plugin-openalpr is based on the OpenALPR library.
|
||||
Currently this library is not packaged in distributions but it can be built and installed following the instructions on github project page (https://github.com/openalpr/openalpr).
|
||||
|
||||
## Configuration
|
||||
|
||||
After installation, please make some adjustments in file `/etc/zm/plugins.d/openalpr.conf`.
|
||||
Most of default values can be kept, but if you live in Europe, you can set the `country_code` setting to `eu` to improve reading of plates with EU format
|
||||
|
||||
All the next configuration steps are done through the web interface.
|
||||
|
||||
Firstly, the plugin loading has to be enabled in ZM options (please check the `LOAD_PLUGIN` setting in `Config` tab).
|
||||
|
||||
Then, you can configure the plugin settings from each `Zone` configuration page.
|
||||
|
||||
![Zone](https://github.com/manupap1/libzoneminder-plugin-openalpr/blob/master/misc/zone.png)
|
||||
|
||||
Available plugins are listed with a color code under the `Plugins` row:
|
||||
- `Default color` - Plugin is not enabled for the zone
|
||||
- `Green` - Plugin is enabled for the zone
|
||||
- `Grey` - Plugin loading is disabled (please check `LOAD_PLUGIN` setting in `Config` tab)
|
||||
- `Orange` - Plugin is enabled for the zone but not active (configuration setting mismatch)
|
||||
- `Red` - ZoneMinder failed to load the plugin object (software error)
|
||||
|
||||
Once a plugin object is loaded, the `Plugin` configuration page is accessed by clicking on the plugin name.
|
||||
|
||||
![Plugin](https://github.com/manupap1/libzoneminder-plugin-openalpr/blob/master/misc/plugin.png)
|
||||
|
||||
The first options are available for all plugins:
|
||||
- `Enabled` - A yes/no select box to enable or disable the plugin
|
||||
- `Require Native Detection` - A yes/no select box to specify if native detection is required before to process plugin analysis. This option allow to limit CPU usage by using the plugin for post processing after native detection. This option is recommended for this plugin as it may use a lot of CPU ressources
|
||||
- `Include Native Detection` - A yes/no select box to specify if native detection shall be included in alarm score and image overlay
|
||||
- `Reinit. Native Detection` - A yes/no select box to specify if native detection shall be reinitialized after detection. ZoneMinder's native detection is performed by comparing the current image to a reference image. By design, the reference image is assigned when analysis is activated, and this image is not periodically refreshed. This operating method is not necessarily optimal because some plugins may require native detection only when motion is truly detected (current image different from the previous image). This option is recommended for libzoneminder-plugin-openalpr. For example, without this option enabled, if a vehicle appears and parks in the camera field of view, the native detection will be be triggered as long as the vehicle is parked, and therefore the plugin analysis would be performed for an unnecessary period of time. With this option enabled, the plugin analysis stops when the vehicle stops.
|
||||
- `Alarm Score` - A text box to enter the score provided by the plugin in case of detection
|
||||
|
||||
The next options are specifics to this plugin and can be used to adjust the detection accuracy:
|
||||
- `Minimum Confidence` - A text box to enter the minimum confidence level. All plates with a lower confidence level will be excluded.
|
||||
- `Min. Number of Characters` - A text box to enter the minimum number of characters in a license plate. All plates with a lower number of detected characters will be excluded.
|
||||
- `Max. Number of Characters` - A text box to enter the maximum number of characters in a license plate. All plates with a greater number of detected characters will be excluded.
|
||||
- `List of Targeted Plates` - A list to specify targeted plates (detected plates will have a 100% confidence).
|
||||
- `Detect only Targeted Plates` - A yes/no select box to specify if plates not in target list shall be ignored.
|
||||
- `Strict Targeting` - A yes/no select box to specify if target matching shall be strict (plates must match exactly).
|
||||
- `Assume target matching` - When strict targeting is off plates included in wider strings are detected (within the max. number of characters limit). This yes/no select box allow to specify if such detected plates shall be considered as being equal to the target. If yes is selected, the plugin will report these plates with the target string and with a 100% confidence. If no is selected, the plugin will report these plates individually. This option can be helpfull if the plate format includes a field for a logo which may be considered as a character by openalpr.
|
||||
|
||||
The configuration is saved to the database and applied when clicking on the `Save` button.
|
||||
|
||||
## Using
|
||||
|
||||
When a license plate is detected, this triggers an event with alarmed frame(s).
|
||||
Depending on your configuration settings and video content, an event may contain multiple alarmed frames.
|
||||
|
||||
![Events](https://github.com/manupap1/libzoneminder-plugin-openalpr/blob/master/misc/events.png)
|
||||
|
||||
Licenses plates are stored in the event note field accessible by a click on the event detection cause.
|
||||
|
||||
![Event](https://github.com/manupap1/libzoneminder-plugin-openalpr/blob/master/misc/event.png)
|
||||
|
||||
Alarmed frames are highlighted with the plate's detection area(s).
|
||||
|
||||
![Frame](https://github.com/manupap1/libzoneminder-plugin-openalpr/blob/master/misc/frame.png)
|
||||
|
||||
The detected plate number(s) can be added in email or sms notifications by using the %ED% token in EMAIL_BODY or MESSAGE_BODY option.
|
|
@ -0,0 +1,5 @@
|
|||
# CMakeLists.txt for openalpr plugin.
|
||||
|
||||
install (FILES openalpr.conf DESTINATION ${ZM_PLUGINSCONFDIR})
|
||||
install (FILES config.php DESTINATION "${ZM_PLUGINSWEBDIR}/libzm_plugin_openalpr")
|
||||
install (FILES en_gb.php fr_fr.php DESTINATION "${ZM_PLUGINSWEBDIR}/libzm_plugin_openalpr/lang")
|
|
@ -0,0 +1,14 @@
|
|||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
sysconfdir = @ZM_PLUGINSCONFDIR@
|
||||
sysconf_DATA = \
|
||||
openalpr.conf
|
||||
|
||||
webdir = @ZM_PLUGINSWEBDIR@/libzm_plugin_openalpr
|
||||
dist_web_DATA = \
|
||||
config.php
|
||||
|
||||
langdir = $(webdir)/lang
|
||||
dist_lang_DATA = \
|
||||
en_gb.php \
|
||||
fr_fr.php
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/* *****************************************************************************
|
||||
* Copyright (C) 2014 Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* Authors: Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
* ****************************************************************************/
|
||||
|
||||
$pluginOptions = array(
|
||||
'MinConfidence' => array(
|
||||
'Type' => 'integer',
|
||||
'Min' => '0',
|
||||
'Max' => '100',
|
||||
'Value' => '0',
|
||||
'Require' => array(
|
||||
array(
|
||||
'Name' => 'OnlyTargets',
|
||||
'Value' => 'No',
|
||||
),
|
||||
),
|
||||
),
|
||||
'MinCharacters' => array(
|
||||
'Type' => 'integer',
|
||||
'Min' => '1',
|
||||
'Max' => '20',
|
||||
'Value' => '1',
|
||||
'Require' => array(
|
||||
array(
|
||||
'Name' => 'OnlyTargets',
|
||||
'Value' => 'No',
|
||||
),
|
||||
),
|
||||
),
|
||||
'MaxCharacters' => array(
|
||||
'Type' => 'integer',
|
||||
'Min' => '1',
|
||||
'Max' => '20',
|
||||
'Value' => '20',
|
||||
'Require' => array(
|
||||
array(
|
||||
'Name' => 'StrictTargets',
|
||||
'Value' => 'No',
|
||||
),
|
||||
),
|
||||
),
|
||||
'TargetList' => array(
|
||||
'Type' => 'list',
|
||||
),
|
||||
'OnlyTargets' => array(
|
||||
'Type' => 'select',
|
||||
'Choices' => 'Yes,No',
|
||||
'Value'=> 'No',
|
||||
),
|
||||
'StrictTargets' => array(
|
||||
'Type' => 'select',
|
||||
'Choices' => 'Yes,No',
|
||||
'Value'=> 'No',
|
||||
),
|
||||
'AssumeTargets' => array(
|
||||
'Type' => 'select',
|
||||
'Choices' => 'Yes,No',
|
||||
'Value'=> 'No',
|
||||
'Require' => array(
|
||||
array(
|
||||
'Name' => 'StrictTargets',
|
||||
'Value' => 'No',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
?>
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/* *****************************************************************************
|
||||
* Copyright (C) 2014 Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* Authors: Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
* ****************************************************************************/
|
||||
|
||||
$PLANG = array(
|
||||
'AssumeTargets' => 'Assume target matching',
|
||||
'MaxCharacters' => 'Max. Number of Characters',
|
||||
'MinCharacters' => 'Min. Number of Characters',
|
||||
'MinConfidence' => 'Minimum Confidence',
|
||||
'OnlyTargets' => 'Detect only Targeted Plates',
|
||||
'StrictTargets' => 'Strict Targeting',
|
||||
'TargetList' => 'List of Targeted Plates',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/* *****************************************************************************
|
||||
* Copyright (C) 2014 Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* Authors: Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
* ****************************************************************************/
|
||||
|
||||
$PLANG = array(
|
||||
'AssumeTargets' => 'Supposer la correspondance',
|
||||
'MaxCharacters' => 'Nombre max. de caractères',
|
||||
'MinCharacters' => 'Nombre min. de caractères',
|
||||
'MinConfidence' => 'Confiance minimum',
|
||||
'OnlyTargets' => 'Détecter seul. plaques ciblées',
|
||||
'StrictTargets' => 'Ciblage strict',
|
||||
'TargetList' => 'Liste de plaques ciblées',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,24 @@
|
|||
# The options commented out show the default values
|
||||
|
||||
[libzm_plugin_openalpr]
|
||||
|
||||
# Path to the openalpr.conf file (used by openalpr library)
|
||||
config_file = /etc/openalpr/openalpr.conf
|
||||
|
||||
# Country code to identify (either us for USA or eu for Europe)
|
||||
#country_code = us
|
||||
|
||||
# Attempt to match the plate number against a region template (e.g., md for Maryland, ca for California)
|
||||
#template_region =
|
||||
|
||||
# Max number of possible plate numbers to return
|
||||
#topn = 10
|
||||
|
||||
# Attempt to detect the region of the plate image
|
||||
#detect_region = false
|
||||
|
||||
# Detection cause for ZM events
|
||||
#det_cause = Plate Detected
|
||||
|
||||
# Prefix for plugin entries in ZM log files
|
||||
#log_prefix = OPENALPR PLUGIN
|
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
After Width: | Height: | Size: 700 KiB |
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
|
@ -0,0 +1,17 @@
|
|||
# CMakeLists.txt for openalpr plugin.
|
||||
|
||||
add_library(zm_plugin_openalpr SHARED openalpr_plugin.cpp)
|
||||
include_directories(${zoneminder_SOURCE_DIR}/src ${zoneminder_BINARY_DIR}/src)
|
||||
|
||||
target_link_libraries(
|
||||
zm_plugin_openalpr -lopenalpr -lboost_program_options -lopencv_core
|
||||
-lopencv_imgproc)
|
||||
|
||||
# Do not set the soname when linking the plugin binary.
|
||||
# Definition of a soname version in a plugin prevents some tools
|
||||
# (like dpkg-shlibdeps for debian) to clearly identify the binary as a plugin.
|
||||
# This results in a bunch of unwanted warnings about unresolvable reference to
|
||||
# symbols (which are provided by the program that loads this plugins).
|
||||
set_property(TARGET zm_plugin_openalpr PROPERTY NO_SONAME 1)
|
||||
|
||||
install (TARGETS zm_plugin_openalpr DESTINATION ${ZM_PLUGINSPKGLIBDIR})
|
|
@ -0,0 +1,24 @@
|
|||
AUTOMAKE_OPTIONS = gnu
|
||||
|
||||
pkglibdir = @ZM_PLUGINSPKGLIBDIR@
|
||||
|
||||
pkglib_LTLIBRARIES = libzm_plugin_openalpr.la
|
||||
|
||||
# This prevents to link the plugin with unnecessary libraries
|
||||
LIBS=
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src $(opencv_CFLAGS)
|
||||
|
||||
libzm_plugin_openalpr_la_SOURCES = \
|
||||
openalpr_plugin.cpp
|
||||
|
||||
libzm_plugin_openalpr_la_LDFLAGS = \
|
||||
-avoid-version -module -shared -export-dynamic
|
||||
|
||||
libzm_plugin_openalpr_la_LIBADD = \
|
||||
@OPENALPR_LIBS@ @BOOST_PROGRAM_OPTION_LIBS@ @OPENCV_CORE_LIBS@ \
|
||||
@OPENCV_IMGPROC_LIBS@
|
||||
|
||||
noinst_HEADERS = \
|
||||
openalpr_plugin.h
|
|
@ -0,0 +1,455 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (C) 2014 Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* Authors: Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "openalpr_plugin.h"
|
||||
|
||||
using namespace alpr;
|
||||
using namespace boost::program_options;
|
||||
|
||||
//! Retrieve the engine version we're going to expect
|
||||
extern "C" int getEngineVersion()
|
||||
{
|
||||
return ZM_ENGINE_VERSION;
|
||||
}
|
||||
|
||||
//! Tells us to register our functionality to an engine kernel
|
||||
extern "C" void registerPlugin(PluginManager &PlM, std::string sPluginName)
|
||||
{
|
||||
PlM.getImageAnalyser().addDetector(std::auto_ptr<Detector>(new OpenALPRPlugin(sPluginName)));
|
||||
}
|
||||
|
||||
OpenALPRPlugin::OpenALPRPlugin()
|
||||
: Detector(),
|
||||
m_sConfigFilePath(DEFAULT_CONFIG_FILE),
|
||||
m_sCountry(DEFAULT_COUNTRY_CODE),
|
||||
m_sRegionTemplate(DEFAULT_TEMPLATE_REGION),
|
||||
m_nMaxPlateNumber(DEFAULT_TOPN),
|
||||
m_bRegionIsDet(DEFAULT_DETECT_REGION)
|
||||
{
|
||||
m_sDetectionCause = DEFAULT_DETECTION_CAUSE;
|
||||
m_sLogPrefix = DEFAULT_PLUGIN_LOG_PREFIX;
|
||||
|
||||
Info("%s: Plugin object has been created", m_sLogPrefix.c_str());
|
||||
}
|
||||
|
||||
OpenALPRPlugin::OpenALPRPlugin(std::string sPluginName)
|
||||
: Detector(sPluginName),
|
||||
m_sConfigFilePath(DEFAULT_CONFIG_FILE),
|
||||
m_sCountry(DEFAULT_COUNTRY_CODE),
|
||||
m_sRegionTemplate(DEFAULT_TEMPLATE_REGION),
|
||||
m_nMaxPlateNumber(DEFAULT_TOPN),
|
||||
m_bRegionIsDet(DEFAULT_DETECT_REGION)
|
||||
{
|
||||
m_sDetectionCause = DEFAULT_DETECTION_CAUSE;
|
||||
m_sLogPrefix = DEFAULT_PLUGIN_LOG_PREFIX;
|
||||
|
||||
Info("%s: Plugin object has been created", m_sLogPrefix.c_str());
|
||||
}
|
||||
|
||||
/*! \fn OpenALPRPlugin::loadConfig(std::string sConfigFileName, std::map<unsigned int,std::map<std::string,std::string> > mapPluginConf)
|
||||
* \param sConfigFileName is path to configuration to load parameters from
|
||||
* \param mapPluginConf is the map of configuration parameters for each zone
|
||||
*/
|
||||
int OpenALPRPlugin::loadConfig(std::string sConfigFileName, std::map<unsigned int,std::map<std::string,std::string> > mapPluginConf)
|
||||
{
|
||||
try
|
||||
{
|
||||
options_description config_file("Configuration file options.");
|
||||
variables_map vm;
|
||||
config_file.add_options()
|
||||
((m_sConfigSectionName + std::string(".config_file")).c_str(),
|
||||
value<std::string>()->default_value(DEFAULT_CONFIG_FILE))
|
||||
((m_sConfigSectionName + std::string(".country_code")).c_str(),
|
||||
value<std::string>()->default_value(DEFAULT_COUNTRY_CODE))
|
||||
((m_sConfigSectionName + std::string(".template_region")).c_str(),
|
||||
value<std::string>()->default_value(DEFAULT_TEMPLATE_REGION))
|
||||
((m_sConfigSectionName + std::string(".topn")).c_str(),
|
||||
value<int>()->default_value(DEFAULT_TOPN))
|
||||
((m_sConfigSectionName + std::string(".detect_region")).c_str(),
|
||||
value<bool>()->default_value(DEFAULT_DETECT_REGION))
|
||||
((m_sConfigSectionName + std::string(".det_cause")).c_str(),
|
||||
value<std::string>()->default_value(DEFAULT_DET_CAUSE))
|
||||
((m_sConfigSectionName + std::string(".log_prefix")).c_str(),
|
||||
value<std::string>()->default_value(DEFAULT_PLUGIN_LOG_PREFIX));
|
||||
try
|
||||
{
|
||||
std::ifstream ifs(sConfigFileName.c_str());
|
||||
store(parse_config_file(ifs, config_file, false), vm);
|
||||
notify(vm);
|
||||
}
|
||||
catch(error& er)
|
||||
{
|
||||
Error("%s: Plugin is not configured (%s)", m_sLogPrefix.c_str(), er.what());
|
||||
return 0;
|
||||
}
|
||||
m_sConfigFilePath = vm[(m_sConfigSectionName + std::string(".config_file")).c_str()].as<std::string>();
|
||||
m_sCountry = vm[(m_sConfigSectionName + std::string(".country_code")).c_str()].as<std::string>();
|
||||
m_sRegionTemplate = vm[(m_sConfigSectionName + std::string(".template_region")).c_str()].as<std::string>();
|
||||
m_nMaxPlateNumber = vm[(m_sConfigSectionName + std::string(".topn")).c_str()].as<int>();
|
||||
m_bRegionIsDet = vm[(m_sConfigSectionName + std::string(".detect_region")).c_str()].as<bool>();
|
||||
m_sDetectionCause = vm[(m_sConfigSectionName + std::string(".det_cause")).c_str()].as<std::string>();
|
||||
m_sLogPrefix = vm[(m_sConfigSectionName + std::string(".log_prefix")).c_str()].as<std::string>();
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
Error("%s: Plugin is not configured (%s)", m_sLogPrefix.c_str(), ex.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
pConf pluginConf;
|
||||
for (std::map<unsigned int,std::map<std::string,std::string> >::iterator it = mapPluginConf.begin(); it != mapPluginConf.end(); ++it) {
|
||||
while ( pluginConfig.size() < (it->first + 1) )
|
||||
pluginConfig.push_back(pluginConf);
|
||||
// Overwrite default values with database values
|
||||
for (std::map<std::string,std::string>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
|
||||
if (it2->second.empty()) continue;
|
||||
if (it2->first == "AlarmScore") {
|
||||
pluginConfig[it->first].alarmScore = (unsigned int)strtoul(it2->second.c_str(), NULL, 0);
|
||||
} else if (it2->first == "AssumeTargets") {
|
||||
if (it2->second == "Yes") {
|
||||
pluginConfig[it->first].assumeTargets = true;
|
||||
} else {
|
||||
pluginConfig[it->first].assumeTargets = false;
|
||||
}
|
||||
} else if (it2->first == "MaxCharacters") {
|
||||
pluginConfig[it->first].maxCharacters = (unsigned int)strtoul(it2->second.c_str(), NULL, 0);
|
||||
} else if (it2->first == "MinCharacters") {
|
||||
pluginConfig[it->first].minCharacters = (unsigned int)strtoul(it2->second.c_str(), NULL, 0);
|
||||
} else if (it2->first == "MinConfidence") {
|
||||
pluginConfig[it->first].minConfidence = (unsigned int)strtoul(it2->second.c_str(), NULL, 0);
|
||||
} else if (it2->first == "OnlyTargets") {
|
||||
if (it2->second == "Yes") {
|
||||
pluginConfig[it->first].onlyTargets = true;
|
||||
} else {
|
||||
pluginConfig[it->first].onlyTargets = false;
|
||||
}
|
||||
} else if (it2->first == "StrictTargets") {
|
||||
if (it2->second == "Yes") {
|
||||
pluginConfig[it->first].strictTargets = true;
|
||||
} else {
|
||||
pluginConfig[it->first].strictTargets = false;
|
||||
}
|
||||
} else if (it2->first == "TargetList") {
|
||||
boost::split(pluginConfig[it->first].targetList, it2->second, boost::is_any_of(","));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an instance of class Alpr and set basic configuration
|
||||
ptrAlpr = new Alpr(m_sCountry, m_sConfigFilePath);
|
||||
ptrAlpr->setTopN(m_nMaxPlateNumber);
|
||||
if ( m_bRegionIsDet )
|
||||
ptrAlpr->setDetectRegion(m_bRegionIsDet);
|
||||
if ( !m_sRegionTemplate.empty() )
|
||||
ptrAlpr->setDefaultRegion(m_sRegionTemplate);
|
||||
|
||||
// Initialize some lists
|
||||
int nb_zones = pluginConfig.size();
|
||||
plateList.resize(nb_zones);
|
||||
tmpPlateList.resize(nb_zones);
|
||||
|
||||
if ( ptrAlpr->isLoaded() ) {
|
||||
Info("%s: Plugin is configured", m_sLogPrefix.c_str());
|
||||
} else {
|
||||
Error("%s: Plugin is not configured (%s)", m_sLogPrefix.c_str(), strerror(errno));
|
||||
delete ptrAlpr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
OpenALPRPlugin::~OpenALPRPlugin()
|
||||
{
|
||||
delete ptrAlpr;
|
||||
}
|
||||
|
||||
|
||||
/*! \fn OpenALPRPlugin::OpenALPRPlugin(const OpenALPRPlugin& source)
|
||||
* \param source is the object for copying
|
||||
*/
|
||||
OpenALPRPlugin::OpenALPRPlugin(const OpenALPRPlugin& source)
|
||||
: Detector(source),
|
||||
m_sConfigFilePath(source.m_sConfigFilePath),
|
||||
m_sCountry(source.m_sCountry),
|
||||
m_sRegionTemplate(source.m_sRegionTemplate),
|
||||
m_nMaxPlateNumber(source.m_nMaxPlateNumber),
|
||||
m_bRegionIsDet(source.m_bRegionIsDet)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*! \fn OpenALPRPlugin:: operator=(const OpenALPRPlugin& source)
|
||||
* \param source is the object for copying
|
||||
*/
|
||||
OpenALPRPlugin & OpenALPRPlugin:: operator=(const OpenALPRPlugin& source)
|
||||
{
|
||||
Detector::operator=(source);
|
||||
m_sConfigFilePath = source.m_sConfigFilePath;
|
||||
m_sCountry = source.m_sCountry;
|
||||
m_sRegionTemplate = source.m_sRegionTemplate;
|
||||
m_nMaxPlateNumber = source.m_nMaxPlateNumber;
|
||||
m_bRegionIsDet = source.m_bRegionIsDet;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*! \fn OpenALPRPlugin::onCreateEvent(Zone *zone, unsigned int n_zone, Event *event)
|
||||
* \param zone is a pointer to the zone that triggered the event
|
||||
* \param n_zone is the zone id
|
||||
* \param event is a pointer the new event
|
||||
*/
|
||||
void OpenALPRPlugin::onCreateEvent(Zone *zone, unsigned int n_zone, Event *event)
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Prepare plugin for event %d", m_sLogPrefix.c_str(), zone->Label(), event->Id());
|
||||
|
||||
/* Note: Do not clear the plate list here because in case of post processing
|
||||
* the plate list is filled with results of first detection before
|
||||
* event creation */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*! \fn OpenALPRPlugin::onCloseEvent(Zone *zone, unsigned int n_zone, Event *event, std::string noteText)
|
||||
* \param zone is a pointer to the zone that triggered the event
|
||||
* \param n_zone is the zone id
|
||||
* \param event is a pointer to the event that will be closed
|
||||
* \param noteText is a string that can be used to output text to the event note
|
||||
*/
|
||||
void OpenALPRPlugin::onCloseEvent(Zone *zone, unsigned int n_zone, Event *event, std::string ¬eText)
|
||||
{
|
||||
// Set the number of plates to output and exit if nothing to do
|
||||
unsigned int topn = ( m_nMaxPlateNumber < plateList[n_zone].size() ) ? m_nMaxPlateNumber : plateList[n_zone].size();
|
||||
if (topn == 0) return;
|
||||
|
||||
// Sort plates according confidence level (higher first)
|
||||
sort(plateList[n_zone].begin(), plateList[n_zone].end(), sortByConf());
|
||||
|
||||
Info("%s: Zone %s - Add plates to event %d", m_sLogPrefix.c_str(), zone->Label(), event->Id());
|
||||
|
||||
// Output only the first topn plates to the event note
|
||||
for(unsigned int i=0; i<topn;i++)
|
||||
{
|
||||
std::stringstream plate;
|
||||
plate << plateList[n_zone][i].num << " (" << plateList[n_zone][i].conf << ")";
|
||||
Debug(1, "%s: Zone %s - Plate %s detected", m_sLogPrefix.c_str(), zone->Label(), plate.str().c_str());
|
||||
noteText += " " + plate.str() + "\n";
|
||||
}
|
||||
|
||||
// Reset the lists for next use
|
||||
plateList[n_zone].clear();
|
||||
tmpPlateList[n_zone].clear();
|
||||
}
|
||||
|
||||
|
||||
/*! \fn OpenALPRPlugin::checkZone(Zone *zone, const Image *zmImage)
|
||||
* \param zone is a zone where license plates will be detected
|
||||
* \param n_zone is the zone id
|
||||
* \param zmImage is an image to perform license plate detection (in the form of ZM' Image)
|
||||
* \return true if there were objects detected in given image and false otherwise
|
||||
*/
|
||||
bool OpenALPRPlugin::checkZone(Zone *zone, unsigned int n_zone, const Image *zmImage)
|
||||
{
|
||||
Polygon zone_polygon = Polygon(zone->GetPolygon()); // Polygon of interest of the processed zone.
|
||||
|
||||
Image *pMaskImage = new Image(zmImage->Width(), zmImage->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE );
|
||||
pMaskImage->Fill(BLACK);
|
||||
// An temporary image in the form of ZM for making from it CvMat.
|
||||
// If don't use temp image, after rgb->bgr it will change.
|
||||
Image *tempZmImage = new Image(*zmImage);
|
||||
int imgtype=CV_8UC1;
|
||||
if (tempZmImage->Colours() == ZM_COLOUR_RGB24)
|
||||
imgtype=CV_8UC3;
|
||||
cv::Mat cvInputImage = cv::Mat(
|
||||
tempZmImage->Height(),
|
||||
tempZmImage->Width(),
|
||||
imgtype, (unsigned char*)tempZmImage->Buffer()).clone();
|
||||
if (tempZmImage->Colours() == ZM_COLOUR_RGB24)
|
||||
cvtColor(cvInputImage, cvInputImage, CV_RGB2BGR);
|
||||
|
||||
//Process image
|
||||
//std::vector<unsigned char> buffer;
|
||||
//cv::imencode(".bmp", cvInputImage, buffer);
|
||||
std::vector<AlprRegionOfInterest> regionsOfInterest;
|
||||
regionsOfInterest.push_back(AlprRegionOfInterest(0,0, cvInputImage.cols, cvInputImage.rows));
|
||||
// Region of interest don't work as expected
|
||||
//std::vector<AlprResults> results = ptrAlpr->recognize(buffer, regionsOfInterest);
|
||||
AlprResults results = ptrAlpr->recognize(cvInputImage.data, cvInputImage.elemSize(), cvInputImage.cols, cvInputImage.rows, regionsOfInterest);
|
||||
double score = 0;
|
||||
|
||||
for (unsigned int i = 0; i < results.plates.size(); i++) {
|
||||
int x1 = results.plates[i].plate_points[0].x, y1 = results.plates[i].plate_points[0].y;
|
||||
int x2 = results.plates[i].plate_points[1].x, y2 = results.plates[i].plate_points[1].y;
|
||||
int x3 = results.plates[i].plate_points[2].x, y3 = results.plates[i].plate_points[2].y;
|
||||
int x4 = results.plates[i].plate_points[3].x, y4 = results.plates[i].plate_points[3].y;
|
||||
Coord rectVertCoords[4] = {Coord(x1, y1), Coord(x2, y2), Coord(x3, y3), Coord(x4, y4)};
|
||||
int nNumVertInside = 0;
|
||||
|
||||
for (int p = 0; p < 4; p++)
|
||||
nNumVertInside += zone_polygon.isInside(rectVertCoords[p]);
|
||||
|
||||
// if at least three rectangle coordinates are inside polygon,
|
||||
// consider rectangle as belonging to the zone
|
||||
// otherwise process next object
|
||||
if (nNumVertInside < 3)
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Skip result (outside detection zone)", m_sLogPrefix.c_str(), zone->Label());
|
||||
continue;
|
||||
}
|
||||
|
||||
int cntDetPlates = 0;
|
||||
|
||||
for (unsigned int k = 0; k < results.plates[i].topNPlates.size(); k++)
|
||||
{
|
||||
strPlate detPlate;
|
||||
detPlate.num = results.plates[i].topNPlates[k].characters;
|
||||
detPlate.conf = results.plates[i].topNPlates[k].overall_confidence;
|
||||
|
||||
bool isTarget = false;
|
||||
|
||||
// Check targeted plates first
|
||||
for (std::vector<std::string>::iterator it = pluginConfig[n_zone].targetList.begin(); it != pluginConfig[n_zone].targetList.end(); ++it)
|
||||
{
|
||||
// If plates match, add targeted plate and continue with next detected plate
|
||||
if (*it == detPlate.num)
|
||||
{
|
||||
detPlate.conf = 100;
|
||||
addPlate(zone, n_zone, detPlate);
|
||||
cntDetPlates++;
|
||||
isTarget = true;
|
||||
break;
|
||||
}
|
||||
// Check if targeted plate is a substring of the detected plate
|
||||
else if (detPlate.num.find(*it) != std::string::npos)
|
||||
{
|
||||
// If yes and strict targeting is on, disqualify targeted plate
|
||||
if (pluginConfig[n_zone].strictTargets)
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Skip targeted plate %s (strict targeting is on)", m_sLogPrefix.c_str(), zone->Label(), detPlate.num.c_str());
|
||||
// And continue with next targeted plate (maybe another in the list will strictly match)
|
||||
continue;
|
||||
}
|
||||
// If yes but detected plate has too much characters, disqualify targeted plate
|
||||
if (detPlate.num.size() > pluginConfig[n_zone].maxCharacters)
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Skip targeted plate %s (number of characters is out of range)", m_sLogPrefix.c_str(), zone->Label(), detPlate.num.c_str());
|
||||
// And continue with next detected plate (this one is not valid)
|
||||
break;
|
||||
}
|
||||
// Overwrite detected plate by target if we assume the matching is correct
|
||||
if (pluginConfig[n_zone].assumeTargets)
|
||||
{
|
||||
detPlate.conf = 100;
|
||||
detPlate.num = *it;
|
||||
}
|
||||
// Add targeted plate to list and continue with next detected plate
|
||||
addPlate(zone, n_zone, detPlate);
|
||||
cntDetPlates++;
|
||||
isTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip detected plate if already added or if only targeted plates are accepted
|
||||
if (isTarget || pluginConfig[n_zone].onlyTargets)
|
||||
continue;
|
||||
|
||||
// Disqualify plate if under the minimum confidence level
|
||||
if (detPlate.conf < pluginConfig[n_zone].minConfidence)
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Skip plate %s (under minimum confidence level)", m_sLogPrefix.c_str(), zone->Label(), detPlate.num.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disqualify plate if not enough characters or too much characters
|
||||
if ((detPlate.num.size() < pluginConfig[n_zone].minCharacters)
|
||||
|| (detPlate.num.size() > pluginConfig[n_zone].maxCharacters))
|
||||
{
|
||||
Debug(1, "%s: Zone %s - Skip plate %s (number of characters is out of range)", m_sLogPrefix.c_str(), zone->Label(), detPlate.num.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add plate to list (if already in list, update confidence by adding new value)
|
||||
addPlate(zone, n_zone, detPlate);
|
||||
cntDetPlates++;
|
||||
}
|
||||
|
||||
if (cntDetPlates == 0)
|
||||
continue;
|
||||
|
||||
// Raise an alarm if at least one plate has been detected
|
||||
score = pluginConfig[n_zone].alarmScore;
|
||||
|
||||
// Fill a polygon with object in the mask
|
||||
Polygon platePolygon = Polygon(4, rectVertCoords);
|
||||
pMaskImage->Fill(WHITE, 1, platePolygon);
|
||||
}
|
||||
|
||||
if (score == 0) {
|
||||
delete pMaskImage;
|
||||
delete tempZmImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
zone->SetScore((int)score);
|
||||
|
||||
//Get mask by highlighting contours of objects and overlaying them with previous contours.
|
||||
Rgb alarm_colour = RGB_GREEN;
|
||||
Image *hlZmImage = pMaskImage->HighlightEdges(alarm_colour, ZM_COLOUR_RGB24,
|
||||
ZM_SUBPIX_ORDER_RGB, &zone_polygon.Extent());
|
||||
|
||||
if (zone->Alarmed()) {
|
||||
// if there were previous detection and they have already set up alarm image
|
||||
// then overlay it with current mask
|
||||
Image* pPrevZoneMask = new Image(*(zone->AlarmImage()));
|
||||
pPrevZoneMask->Overlay(*hlZmImage);
|
||||
zone->SetAlarmImage(pPrevZoneMask);
|
||||
delete pPrevZoneMask;
|
||||
} else
|
||||
zone->SetAlarmImage(hlZmImage);
|
||||
|
||||
delete pMaskImage;
|
||||
delete tempZmImage;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool OpenALPRPlugin::addPlate(Zone *zone, unsigned int n_zone, strPlate detPlate)
|
||||
{
|
||||
for (std::vector<strPlate>::iterator it = plateList[n_zone].begin(); it != plateList[n_zone].end(); ++it)
|
||||
{
|
||||
// If plate number exists in the list for this zone
|
||||
if ((*it).num == detPlate.num)
|
||||
{
|
||||
// Add confidence
|
||||
(*it).conf += detPlate.conf;
|
||||
Debug(1, "%s: Zone %s - Raise confidence of plate %s to %f", m_sLogPrefix.c_str(), zone->Label(), (*it).num.c_str(), (*it).conf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new plate for this zone
|
||||
Debug(1, "%s: Zone %s - Add plate %s with confidence %f", m_sLogPrefix.c_str(), zone->Label(), detPlate.num.c_str(), detPlate.conf);
|
||||
plateList[n_zone].push_back(detPlate);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (C) 2014 Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* Authors: Emmanuel Papin <manupap01@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef OPENALPR_PLUGIN_H
|
||||
#define OPENALPR_PLUGIN_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <alpr.h>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/option.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/errors.hpp>
|
||||
|
||||
#include "zm_plugin_manager.h"
|
||||
#include "zm_detector.h"
|
||||
#include "zm_rgb.h"
|
||||
|
||||
#define DEFAULT_CONFIG_FILE "/etc/openalpr/openalpr.conf"
|
||||
#define DEFAULT_COUNTRY_CODE "us"
|
||||
#define DEFAULT_TEMPLATE_REGION ""
|
||||
#define DEFAULT_TOPN 10
|
||||
#define DEFAULT_DETECT_REGION 0
|
||||
#define DEFAULT_DET_CAUSE "Plate Detected"
|
||||
#define DEFAULT_PLUGIN_LOG_PREFIX "OPENALPR PLUGIN"
|
||||
|
||||
#define DEFAULT_ALARM_SCORE 99
|
||||
#define DEFAULT_ASSUME_TARGETS 0
|
||||
#define DEFAULT_MAX_CHARACTERS 99
|
||||
#define DEFAULT_MIN_CHARACTERS 0
|
||||
#define DEFAULT_MIN_CONFIDENCE 0
|
||||
#define DEFAULT_ONLY_TARGETS 0
|
||||
#define DEFAULT_STRICT_TARGETS 0
|
||||
|
||||
//! OpenALPR plugin class.
|
||||
/*! The class derived from Detector.
|
||||
* This class provides license plate detection based on tesseract OCR.
|
||||
*/
|
||||
class OpenALPRPlugin : public Detector {
|
||||
public:
|
||||
|
||||
//! Default Constructor.
|
||||
OpenALPRPlugin();
|
||||
|
||||
//! Constructor.
|
||||
OpenALPRPlugin(std::string sConfigSectionName);
|
||||
|
||||
//! Destructor.
|
||||
virtual ~OpenALPRPlugin();
|
||||
|
||||
//! Copy constructor.
|
||||
OpenALPRPlugin(const OpenALPRPlugin& source);
|
||||
|
||||
//! Overloaded operator=.
|
||||
OpenALPRPlugin& operator=(const OpenALPRPlugin& source);
|
||||
|
||||
int loadConfig(std::string sConfigFileName, std::map<unsigned int,std::map<std::string,std::string> > mapPluginConf);
|
||||
|
||||
protected:
|
||||
|
||||
void onCreateEvent(Zone *zone, unsigned int n_zone, Event *event);
|
||||
void onCloseEvent(Zone *zone, unsigned int n_zone, Event *event, std::string ¬eText);
|
||||
bool checkZone(Zone *zone, unsigned int n_zone, const Image *zmImage);
|
||||
|
||||
std::string m_sConfigFilePath;
|
||||
std::string m_sCountry;
|
||||
std::string m_sRegionTemplate;
|
||||
unsigned int m_nMaxPlateNumber;
|
||||
bool m_bRegionIsDet;
|
||||
|
||||
private:
|
||||
|
||||
alpr::Alpr *ptrAlpr;
|
||||
|
||||
struct pConf
|
||||
{
|
||||
unsigned int alarmScore;
|
||||
bool assumeTargets;
|
||||
unsigned int maxCharacters;
|
||||
unsigned int minCharacters;
|
||||
unsigned int minConfidence;
|
||||
bool onlyTargets;
|
||||
bool strictTargets;
|
||||
std::vector<std::string> targetList;
|
||||
pConf():
|
||||
alarmScore(DEFAULT_ALARM_SCORE),
|
||||
assumeTargets(DEFAULT_ASSUME_TARGETS),
|
||||
maxCharacters(DEFAULT_MAX_CHARACTERS),
|
||||
minCharacters(DEFAULT_MIN_CHARACTERS),
|
||||
minConfidence(DEFAULT_MIN_CONFIDENCE),
|
||||
onlyTargets(DEFAULT_ONLY_TARGETS),
|
||||
strictTargets(DEFAULT_STRICT_TARGETS)
|
||||
{}
|
||||
};
|
||||
|
||||
std::vector<pConf> pluginConfig;
|
||||
|
||||
struct strPlate
|
||||
{
|
||||
std::string num;
|
||||
float conf;
|
||||
};
|
||||
|
||||
struct sortByConf
|
||||
{
|
||||
bool operator()(const strPlate a, const strPlate b) const
|
||||
{
|
||||
return a.conf > b.conf;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::vector<strPlate> > plateList;
|
||||
std::vector<std::vector<std::string> > tmpPlateList;
|
||||
|
||||
bool addPlate(Zone *zone, unsigned int n_zone, strPlate detPlate);
|
||||
|
||||
};
|
||||
#endif // OPENALPR_PLUGIN_H
|
|
@ -3825,6 +3825,58 @@ body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% s
|
|||
readonly => 1,
|
||||
category => "dynamic",
|
||||
},
|
||||
{
|
||||
name => "ZM_PATH_PLUGINS",
|
||||
default => "@ZM_PLUGINSPKGLIBDIR@",
|
||||
description => "Path to the plugin folder",
|
||||
help => "3d-party plugins have to be placed here.",
|
||||
type => $types{abs_path},
|
||||
category => "paths",
|
||||
},
|
||||
{
|
||||
name => "ZM_PLUGIN_EXTENSION",
|
||||
default => "@ZM_PLUGINSEXT@",
|
||||
description => "Default extension of plugins to found.",
|
||||
help => "Default extension of plugins to found.",
|
||||
type => $types{rel_path},
|
||||
category => "paths",
|
||||
},
|
||||
{
|
||||
name => "ZM_PLUGINS_CONFIG_PATH",
|
||||
default => "@SYSCONFDIR@/plugins.conf",
|
||||
description => "Path to the config file for plugins.",
|
||||
help => "Path to the config file for plugins.",
|
||||
type => $types{abs_path},
|
||||
category => "paths",
|
||||
},
|
||||
{
|
||||
name => "ZM_PLUGINS_CONFIG_DIR",
|
||||
default => "@ZM_PLUGINSCONFDIR@",
|
||||
description => "Path to the config folder for plugins.",
|
||||
help => "Path to the config folder for plugins.",
|
||||
type => $types{abs_path},
|
||||
category => "paths",
|
||||
},
|
||||
{
|
||||
name => "ZM_LOAD_PLUGINS",
|
||||
default => "no",
|
||||
description => "Load and use 3d-party plugins",
|
||||
help => "3d-party plugins will be loaded and used for analysing.",
|
||||
type => $types{boolean},
|
||||
category => "config",
|
||||
},
|
||||
{
|
||||
name => "ZM_TURNOFF_NATIVE_ANALYSIS",
|
||||
default => "no",
|
||||
description => "Turn native ZM\'s image analysis possibility off",
|
||||
help => qqq("
|
||||
Image analysis with ZM\'s motion detected function will be turned
|
||||
off. Only detection functions from loaded plugins will be used.
|
||||
Note, that if no plugins have be loaded, no detection will be done.
|
||||
"),
|
||||
type => $types{boolean},
|
||||
category => "config",
|
||||
},
|
||||
);
|
||||
|
||||
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
||||
|
|
|
@ -6,6 +6,22 @@ configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
|
|||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_zone.cpp)
|
||||
|
||||
if(ZM_PLUGIN_SUPPORT)
|
||||
set(ZM_BIN_SRC_FILES ${ZM_BIN_SRC_FILES} zm_detector.cpp zm_image_analyser.cpp zm_plugin.cpp zm_plugin_manager.cpp)
|
||||
endif(ZM_PLUGIN_SUPPORT)
|
||||
|
||||
# with -fPIC
|
||||
IF(UNIX AND NOT WIN32)
|
||||
FIND_PROGRAM(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin )
|
||||
IF(CMAKE_UNAME)
|
||||
EXEC_PROGRAM(uname ARGS -m OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR} CACHE INTERNAL "processor type (i386 and x86_64)")
|
||||
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
ENDIF(CMAKE_UNAME)
|
||||
ENDIF(UNIX AND NOT WIN32)
|
||||
|
||||
# A fix for cmake recompiling the source files for every target.
|
||||
add_library(zm STATIC ${ZM_BIN_SRC_FILES})
|
||||
|
||||
|
@ -15,11 +31,11 @@ add_executable(zmu zmu.cpp)
|
|||
add_executable(zmf zmf.cpp)
|
||||
add_executable(zms zms.cpp)
|
||||
|
||||
target_link_libraries(zmc zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zma zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmu zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmf zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmc -ldl zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zma -ldl zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmu -ldl zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zmf -ldl zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
target_link_libraries(zms -ldl zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS})
|
||||
|
||||
# Generate man files for the binaries destined for the bin folder
|
||||
FOREACH(CBINARY zma zmc zmf zmu)
|
||||
|
@ -31,3 +47,8 @@ install(TARGETS zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE O
|
|||
install(CODE "execute_process(COMMAND ln -sf zms nph-zms WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})" )
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nph-zms DESTINATION "${ZM_CGIDIR}")
|
||||
|
||||
if(ZM_PLUGIN_SUPPORT)
|
||||
install(FILES jinclude.h zm_db.h zm_detector.h zm_logger.h zm_poly.h zm_mem_utils.h zm_box.h zm_ffmpeg.h zm_plugin_manager.h zm_plugin.h zm_jpeg.h zm_mpeg.h zm_image_analyser.h zm_zone.h zm_rgb.h zm_utils.h zm_event.h zm_stream.h zm_coord.h zm_image.h DESTINATION include/zoneminder)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" "${CMAKE_CURRENT_BINARY_DIR}/zm_config_defines.h" DESTINATION include/zoneminder)
|
||||
install(TARGETS zoneminder ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif(ZM_PLUGIN_SUPPORT)
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef ZM_BOX_H
|
||||
#define ZM_BOX_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_coord.h"
|
||||
|
||||
#ifndef SOLARIS
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef ZM_BUFFER_H
|
||||
#define ZM_BUFFER_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_logger.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define ZM_COMMS_H
|
||||
|
||||
#include "zm_exception.h"
|
||||
#include "zm_logger.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -142,8 +142,6 @@ void zmLoadConfig()
|
|||
}
|
||||
}
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *const p_type )
|
||||
{
|
||||
name = new char[strlen(p_name)+1];
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#define ZM_CONFIG "@ZM_CONFIG@" // Path to config file
|
||||
#define ZM_VERSION "@VERSION@" // ZoneMinder Version
|
||||
#define ZM_ENGINE_VERSION @ZM_ENGINE_VERSION@ // ZoneMinder engine Version
|
||||
|
||||
#define ZM_HAS_V4L1 @ZM_HAS_V4L1@
|
||||
#define ZM_HAS_V4L2 @ZM_HAS_V4L2@
|
||||
|
@ -42,6 +43,8 @@
|
|||
#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT)
|
||||
#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS)
|
||||
|
||||
#define ZM_NOTES_MAX_SIZE 4096 // The maximum size of a note
|
||||
|
||||
#define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP
|
||||
#define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#ifndef ZM_COORD_H
|
||||
#define ZM_COORD_H
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
//
|
||||
// Class used for storing an x,y pair, i.e. a coordinate
|
||||
//
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
#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
|
||||
*/
|
||||
std::string Detector::getDetectionCause()
|
||||
{
|
||||
return m_sDetectionCause;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn Detector::getConfigSectionName()
|
||||
* return plugin name as string
|
||||
*/
|
||||
std::string Detector::getPluginName()
|
||||
{
|
||||
return m_sConfigSectionName;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn Detector::EnablePlugin(std::vector<int> zoneList)
|
||||
* \param vnZoneList is the list of enabled zones for the plugin
|
||||
*/
|
||||
void Detector::EnablePlugin(std::vector<unsigned int> vnZoneList)
|
||||
{
|
||||
m_vnPluginZones = vnZoneList;
|
||||
m_bIsPluginEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn Detector::getPluginZones()
|
||||
* \return the list of zone which have the plugin enabled
|
||||
*/
|
||||
std::vector<unsigned int> Detector::getPluginZones()
|
||||
{
|
||||
return m_vnPluginZones;
|
||||
}
|
||||
|
||||
|
||||
/*! \fn Detector::log(int nLogLevel, std::string sLevel, std::string sMessage)
|
||||
*/
|
||||
void Detector::log(int nLogLevel, std::string sLevel, std::string sMessage)
|
||||
{
|
||||
std::string sMessageToLog = sLevel + std::string(" [") + m_sLogPrefix + std::string(": ") + sMessage + std::string("]");
|
||||
syslog(nLogLevel, "%s", sMessageToLog.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! \fn int Detector::Detect(const Image &zmImage, Zone** zones, unsigned int &score)
|
||||
* \param zmImage is an image to detect faces on
|
||||
* \param zones is the array of detection zones
|
||||
* \param score is the detection score
|
||||
* \return true if detection is effective
|
||||
*/
|
||||
bool Detector::Detect(const Image &zmImage, Zone** zones, 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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void Detector::_onCreateEvent(Zone** zones, Event* event)
|
||||
{
|
||||
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
|
||||
{
|
||||
onCreateEvent(zones[*it], *it, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Detector::_onCloseEvent(Zone** zones, Event* event)
|
||||
{
|
||||
for(std::vector<unsigned int>::iterator it = m_vnPluginZones.begin(); it != m_vnPluginZones.end(); ++it)
|
||||
{
|
||||
std::string noteText = " [Zone ";
|
||||
noteText += zones[*it]->Label();
|
||||
noteText += "]\n";
|
||||
|
||||
onCloseEvent(zones[*it], *it, event, noteText);
|
||||
|
||||
Event::StringSet noteSet;
|
||||
noteSet.insert(noteText);
|
||||
Event::StringSetMap noteSetMap;
|
||||
noteSetMap[m_sDetectionCause] = noteSet;
|
||||
event->updateNotes(noteSetMap);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
#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"
|
||||
|
||||
|
||||
|
||||
//! 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(std::string sPluginFileName)
|
||||
{
|
||||
m_sLogPrefix = DEFAULT_LOG_PREFIX;
|
||||
|
||||
char* szPluginFileName = strdup(sPluginFileName.c_str());
|
||||
|
||||
std::string sPluginFileNameName = std::string(basename(szPluginFileName));
|
||||
|
||||
size_t idx = sPluginFileNameName.rfind('.');
|
||||
|
||||
if (idx == std::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, unsigned int &score);
|
||||
|
||||
void _onCreateEvent(Zone** zones, Event *event);
|
||||
void _onCloseEvent(Zone** zones, Event *event);
|
||||
|
||||
//! Load detector's parameters.
|
||||
virtual int loadConfig(std::string sConfigFileName, std::map<unsigned int,std::map<std::string,std::string> > mapPluginConf) = 0;
|
||||
|
||||
//! Returns detection case string.
|
||||
std::string getDetectionCause();
|
||||
|
||||
//! Returns plugin name as string.
|
||||
std::string getPluginName();
|
||||
|
||||
//! Enable the plugin for the given zones.
|
||||
void EnablePlugin(std::vector<unsigned int> zoneList);
|
||||
|
||||
//! Return the list of enabled zones
|
||||
std::vector<unsigned int> getPluginZones();
|
||||
|
||||
protected:
|
||||
|
||||
//! Do detection inside one given zone.
|
||||
virtual bool checkZone(Zone *zone, unsigned int n_zone, const Image *zmImage) = 0;
|
||||
|
||||
virtual void onCreateEvent(Zone *zone, unsigned int n_zone, Event *event) = 0;
|
||||
virtual void onCloseEvent(Zone *zone, unsigned int n_zone, Event *event, std::string ¬eText) = 0;
|
||||
|
||||
//! Log messages to the SYSLOG.
|
||||
void log(int, std::string sLevel, std::string sMessage);
|
||||
|
||||
//! String to be shown as detection cause for event.
|
||||
std::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.
|
||||
std::string m_sLogPrefix;
|
||||
|
||||
//! Name of config file section to search parameters.
|
||||
std::string m_sConfigSectionName;
|
||||
|
||||
//! List of zones enabled for the plugin
|
||||
std::vector<unsigned int> m_vnPluginZones;
|
||||
|
||||
//! Plugin status regarding zone settings
|
||||
bool m_bIsPluginEnabled;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // ZM_DETECTOR_H
|
146
src/zm_event.cpp
146
src/zm_event.cpp
|
@ -35,6 +35,7 @@
|
|||
#include "zm_signal.h"
|
||||
#include "zm_event.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
// sendfile tricks
|
||||
extern "C"
|
||||
|
@ -69,6 +70,8 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
|
|||
|
||||
std::string notes;
|
||||
createNotes( notes );
|
||||
static char escapedNotes[ZM_NOTES_MAX_SIZE*2 + 1];
|
||||
mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() );
|
||||
|
||||
bool untimedEvent = false;
|
||||
if ( !start_time.tv_sec )
|
||||
|
@ -77,10 +80,10 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
|
|||
gettimeofday( &start_time, 0 );
|
||||
}
|
||||
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
static char sql[ZM_SQL_LGE_BUFSIZ];
|
||||
|
||||
struct tm *stime = localtime( &start_time.tv_sec );
|
||||
snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str() );
|
||||
snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), escapedNotes );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't insert event: %s", mysql_error( &dbconn ) );
|
||||
|
@ -194,7 +197,7 @@ Event::~Event()
|
|||
struct DeltaTimeval delta_time;
|
||||
DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 );
|
||||
|
||||
snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id );
|
||||
snprintf( sql, sizeof(sql), "update Events set Name='%s%d', Cause='%s', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, cause.c_str(), end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't update event: %s", mysql_error( &dbconn ) );
|
||||
|
@ -208,15 +211,138 @@ void Event::createNotes( std::string ¬es )
|
|||
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ )
|
||||
{
|
||||
notes += mapIter->first;
|
||||
notes += ": ";
|
||||
notes += ":\n";
|
||||
const StringSet &stringSet = mapIter->second;
|
||||
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ )
|
||||
{
|
||||
if ( setIter != stringSet.begin() )
|
||||
notes += ", ";
|
||||
notes += *setIter;
|
||||
}
|
||||
}
|
||||
if (notes.length() > ZM_NOTES_MAX_SIZE)
|
||||
{
|
||||
std::string sTrunc = "... (content truncated)";
|
||||
notes = notes.substr(0, (ZM_NOTES_MAX_SIZE - sTrunc.length()));
|
||||
notes += sTrunc;
|
||||
}
|
||||
}
|
||||
|
||||
void Event::AddCause( const std::string new_cause )
|
||||
{
|
||||
if ( cause.find( new_cause ) == std::string::npos )
|
||||
{
|
||||
if ( cause.length() )
|
||||
cause += ", ";
|
||||
cause += new_cause;
|
||||
}
|
||||
}
|
||||
|
||||
void Event::Close()
|
||||
{
|
||||
if ( ( tot_score == 0 ) && ( alarm_frames == 0 ) )
|
||||
{
|
||||
Info( "Delete event's data (empty event)" );
|
||||
DeleteData();
|
||||
}
|
||||
}
|
||||
|
||||
// This is the transcription of JavaScript function DeleteEvent()
|
||||
void Event::DeleteData()
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
snprintf( sql, sizeof(sql), "DELETE FROM `Events` WHERE `Id` = %d;", id );
|
||||
if ( mysql_query( &dbconn, sql) )
|
||||
{
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
||||
if ( !config.opt_fast_delete )
|
||||
{
|
||||
snprintf( sql, sizeof(sql), "DELETE FROM `Stats` WHERE `EventId` = %d;", id );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
||||
snprintf( sql, sizeof(sql), "DELETE FROM `Frames` WHERE `EventId` = %d;", id );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
||||
static char dir_events[PATH_MAX] = "";
|
||||
if ( config.dir_events[0] == '/' )
|
||||
snprintf( dir_events, sizeof(dir_events), "%s/%d", config.dir_events, monitor->Id() );
|
||||
else
|
||||
snprintf( dir_events, sizeof(dir_events), "%s/%s/%d", staticConfig.PATH_WEB.c_str(), config.dir_events, monitor->Id() );
|
||||
|
||||
if ( config.use_deep_storage )
|
||||
{
|
||||
static char event_glob[PATH_MAX] = "";
|
||||
snprintf( event_glob, sizeof(event_glob), "%s/%d/*/*/*/.%d", dir_events, monitor->Id(), id );
|
||||
|
||||
glob_t pglob;
|
||||
if( glob( event_glob, GLOB_ONLYDIR, 0, &pglob ) == 0 )
|
||||
{
|
||||
char *event_path = pglob.gl_pathv[0];
|
||||
static char link[PATH_MAX] = "";
|
||||
|
||||
ssize_t len;
|
||||
if ( ( len = readlink(event_path, link, sizeof(link)-1 ) ) )
|
||||
{
|
||||
link[len] = '\0';
|
||||
int last_slash = strrchr( event_path, '/' ) - event_path;
|
||||
|
||||
char base_path[PATH_MAX] = "";
|
||||
strncpy(base_path, event_path, last_slash);
|
||||
|
||||
static char link_path[PATH_MAX] = "";
|
||||
snprintf( link_path, sizeof(link_path), "%s/%s", base_path, link );
|
||||
|
||||
// Delete linked folder (remove_dir is called with second
|
||||
// argument = true to force deletion of folder content)
|
||||
if (remove_dir(link_path, true, false) < 0)
|
||||
return;
|
||||
|
||||
// Delete symlink
|
||||
if (unlink(event_path) < 0)
|
||||
return;
|
||||
|
||||
// Now we have successfully deleted all files related to the
|
||||
// event we can do some cleaning on the storage directory
|
||||
// The storage folders are scanned from deep to root and
|
||||
// deleted if empty
|
||||
for(size_t i=strlen(link_path)-1; i>strlen(dir_events); i--)
|
||||
{
|
||||
if(link_path[i] != '/')
|
||||
continue;
|
||||
|
||||
char del_path[PATH_MAX] = "";
|
||||
strncpy(del_path, link_path, i);
|
||||
|
||||
// Deletion is stopped at first non empty folder
|
||||
// encountered
|
||||
if(remove_dir(del_path, false, false) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete broken symlink
|
||||
unlink(event_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static char event_path[PATH_MAX] = "";
|
||||
snprintf(event_path, sizeof(event_path), "%s/%d/%d", dir_events, monitor->Id(), id);
|
||||
remove_dir(event_path, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Event::sd = -1;
|
||||
|
@ -426,12 +552,12 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
|
|||
std::string notes;
|
||||
createNotes( notes );
|
||||
|
||||
Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() );
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
Debug( 2, "Updating notes for event %d", id );
|
||||
static char sql[ZM_SQL_LGE_BUFSIZ];
|
||||
#if USE_PREPARED_SQL
|
||||
static MYSQL_STMT *stmt = 0;
|
||||
|
||||
char notesStr[ZM_SQL_MED_BUFSIZ] = "";
|
||||
char notesStr[ZM_NOTES_MAX_SIZE] = "";
|
||||
unsigned long notesLen = 0;
|
||||
|
||||
if ( !stmt )
|
||||
|
@ -480,7 +606,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
|
|||
Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) );
|
||||
}
|
||||
#else
|
||||
static char escapedNotes[ZM_SQL_MED_BUFSIZ];
|
||||
static char escapedNotes[ZM_NOTES_MAX_SIZE*2 + 1];
|
||||
|
||||
mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() );
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_stream.h"
|
||||
|
||||
|
@ -128,13 +127,16 @@ public:
|
|||
bool SendFrameImage( const Image *image, bool alarm_frame=false );
|
||||
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
|
||||
|
||||
void updateNotes( const StringSetMap &stringSetMap );
|
||||
void updateNotes( const StringSetMap &stringSetMap );
|
||||
|
||||
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
|
||||
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
|
||||
void AddCause( const std::string new_cause );
|
||||
void Close();
|
||||
|
||||
private:
|
||||
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
|
||||
void DeleteData();
|
||||
|
||||
public:
|
||||
static const char *getSubPath( struct tm *time )
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#ifndef ZM_EXCEPTION_H
|
||||
#define ZM_EXCEPTION_H
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class Exception
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef ZM_FFMPEG_H
|
||||
#define ZM_FFMPEG_H
|
||||
#include <stdint.h>
|
||||
#include "zm.h"
|
||||
|
||||
#include "zm_image.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef ZM_IMAGE_H
|
||||
#define ZM_IMAGE_H
|
||||
|
||||
#include "zm.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "zm_jpeg.h"
|
||||
|
@ -31,6 +30,7 @@ extern "C"
|
|||
#include "zm_poly.h"
|
||||
#include "zm_mem_utils.h"
|
||||
#include "zm_utils.h"
|
||||
#include "zm_logger.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
#include "zm_image_analyser.h"
|
||||
|
||||
|
||||
ImageAnalyser::ImageAnalyser( int nMonitorId )
|
||||
{
|
||||
if ( nMonitorId > 0 )
|
||||
{
|
||||
m_nMonitorId = nMonitorId;
|
||||
m_bIsAnalyserEnabled = getMonitorZones();
|
||||
}
|
||||
else
|
||||
m_bIsAnalyserEnabled = false;
|
||||
m_bIsNativeDetEnabled = false;
|
||||
}
|
||||
|
||||
/*!\fn ImageAnalyser::ImageAnalyser(const ImageAnalyser& source)
|
||||
* \param source is the object to copy
|
||||
|
@ -31,34 +41,465 @@ ImageAnalyser::~ImageAnalyser()
|
|||
delete *It;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause)
|
||||
* \param comp_image is the image to analyse
|
||||
* \param zones is the zones array to analyse
|
||||
* \param n_numZones is the number of zones
|
||||
* \param noteSetMap is the map of events descriptions
|
||||
* \param det_cause is a string describing detection cause
|
||||
*/
|
||||
int ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause)
|
||||
void ImageAnalyser::onCreateEvent(Zone** zones, Event* event)
|
||||
{
|
||||
Event::StringSet zoneSet;
|
||||
int score = 0;
|
||||
|
||||
for(DetectorsList::iterator It = m_Detectors.begin();
|
||||
for ( DetectorsList::iterator It = m_Detectors.begin();
|
||||
It != m_Detectors.end();
|
||||
++It)
|
||||
++It )
|
||||
{
|
||||
int detect_score = (*It)->Detect(comp_image, zones, n_numZones, zoneSet);
|
||||
if (detect_score)
|
||||
{
|
||||
score += detect_score;
|
||||
noteSetMap[(*It)->getDetectionCause()] = zoneSet;
|
||||
if (det_cause.length())
|
||||
det_cause += ", ";
|
||||
det_cause += (*It)->getDetectionCause();
|
||||
}
|
||||
(*It)->_onCreateEvent(zones, event);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
void ImageAnalyser::onCloseEvent(Zone** zones, Event* event)
|
||||
{
|
||||
for ( DetectorsList::iterator It = m_Detectors.begin();
|
||||
It != m_Detectors.end();
|
||||
++It )
|
||||
{
|
||||
(*It)->_onCloseEvent(zones, event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!\fn ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, Event::StringSetMap noteSetMap, std::string& det_cause, unsigned int& score)
|
||||
* \param comp_image is the image to analyse
|
||||
* \param zones is the zones array to analyse
|
||||
* \param noteSetMap is the map of events descriptions
|
||||
* \param det_cause is a string describing detection cause
|
||||
* \param score is the plugin score
|
||||
*/
|
||||
bool ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, Event::StringSetMap& noteSetMap, std::string& det_cause, unsigned int& score)
|
||||
{
|
||||
Event::StringSet zoneSet;
|
||||
score = 0;
|
||||
bool alarm = false;
|
||||
|
||||
for ( DetectorsList::iterator It = m_Detectors.begin();
|
||||
It != m_Detectors.end();
|
||||
++It )
|
||||
{
|
||||
unsigned int detect_score = 0;
|
||||
if ( (*It)->Detect( comp_image, zones, detect_score ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += detect_score;
|
||||
std::string new_cause = (*It)->getDetectionCause();
|
||||
noteSetMap[new_cause] = zoneSet;
|
||||
if ( det_cause.find( new_cause ) == std::string::npos )
|
||||
{
|
||||
if ( det_cause.length() )
|
||||
det_cause += ", ";
|
||||
det_cause += new_cause;
|
||||
}
|
||||
}
|
||||
}
|
||||
return alarm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::configurePlugins(std::string sConfigFileName, bool bDoNativeDet)
|
||||
*\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 ImageAnalyser::configurePlugins(std::string sConfigFileName, bool bDoNativeDet)
|
||||
{
|
||||
std::string sLoadedPlugins;
|
||||
if ( !m_bIsAnalyserEnabled ) return;
|
||||
m_bIsNativeDetEnabled = bDoNativeDet;
|
||||
for ( DetectorsList::iterator It = m_Detectors.begin(); It != m_Detectors.end(); ++It )
|
||||
{
|
||||
std::string sPluginName = (*It)->getPluginName();
|
||||
try
|
||||
{
|
||||
if ( isValidConfigFile( sPluginName, sConfigFileName ) )
|
||||
{
|
||||
Info("Configure plugin '%s' with config file '%s'.", sPluginName.c_str(), sConfigFileName.c_str());
|
||||
std::map<unsigned int,std::map<std::string,std::string> > mapPluginConf;
|
||||
std::vector<unsigned int> vnPluginZones;
|
||||
bool plugEnabled = getEnabledZonesForPlugin( sPluginName, vnPluginZones );
|
||||
if ( getPluginConfig( sPluginName, vnPluginZones, mapPluginConf )
|
||||
&& (*It)->loadConfig( sConfigFileName, mapPluginConf ) )
|
||||
{
|
||||
mapRegPluginGenConf[sPluginName].Configured = true;
|
||||
if ( plugEnabled )
|
||||
{
|
||||
(*It)->EnablePlugin( vnPluginZones );
|
||||
if ( sLoadedPlugins.length() )
|
||||
sLoadedPlugins += ", ";
|
||||
sLoadedPlugins += "'" + sPluginName + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Error("Plugin '%s' couldn't be loaded", sPluginName.c_str());
|
||||
}
|
||||
}
|
||||
getZonesConfig( sLoadedPlugins );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::isValidConfigFile(std::string sPluginName, std::string sConfigFileName)
|
||||
* \param sPluginName is the name of the plugin (filename without extension)
|
||||
* \param sConfigFileName is the path to the configuration file which should include configuration directives for the plugin
|
||||
* \return true if the config file contains the right section name
|
||||
*/
|
||||
bool ImageAnalyser::isValidConfigFile(std::string sPluginName, std::string sConfigFileName)
|
||||
{
|
||||
std::ifstream ifs(sConfigFileName.c_str());
|
||||
std::string line;
|
||||
bool rtnVal = false;
|
||||
while (getline(ifs, line))
|
||||
{
|
||||
if (line == "[" + sPluginName + "]")
|
||||
{
|
||||
rtnVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ifs.close();
|
||||
return rtnVal;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getMonitorZones()
|
||||
* \return true if at least a zone is configured for the monitor
|
||||
*/
|
||||
bool ImageAnalyser::getMonitorZones()
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
// We use the same ordering as in Monitor::Load
|
||||
snprintf(sql, sizeof(sql), "SELECT `Id`, `Name`, `Type` FROM `Zones` WHERE `MonitorId` = %d ORDER BY `Type`, `Id`;", m_nMonitorId);
|
||||
|
||||
if (mysql_query(&dbconn, sql))
|
||||
{
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if (!result)
|
||||
{
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
if (mysql_num_rows(result) > 0)
|
||||
{
|
||||
for (unsigned int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++)
|
||||
{
|
||||
if (mysql_errno(&dbconn))
|
||||
{
|
||||
Error("Can't fetch row: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
zSetting zone;
|
||||
zone.id = (unsigned int)strtoul(dbrow[0], NULL, 0);
|
||||
zone.name = std::string(dbrow[1]);
|
||||
zone.type = std::string(dbrow[2]);
|
||||
m_vMonitorZones.push_back(zone);
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
return ( m_vMonitorZones.size() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getPluginConfig(std::string sPluginName, std::vector<unsigned int> vnPluginZones, std::map<unsigned int,std::map<std::string,std::string> >& mapPluginConf)
|
||||
* \param sPluginName is the name of the plugin (filename without extension)
|
||||
* \param vnPluginZones is a vector containing the index of zones enabled for the plugin (not the zone Id in the database)
|
||||
* \param mapPluginConf is the map filled with configuration parameters for the plugin
|
||||
* \return true if all found parameters are applied to the map
|
||||
*/
|
||||
bool ImageAnalyser::getPluginConfig(std::string sPluginName, std::vector<unsigned int> vnPluginZones, std::map<unsigned int,std::map<std::string,std::string> >& mapPluginConf)
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
// Get plugin configuration parameters from `PluginsConfig` table
|
||||
snprintf(sql, sizeof(sql), "SELECT `ZoneId`, `Name`, `Value` FROM `PluginsConfig` WHERE `MonitorId`=%d AND `pluginName`='%s' ORDER BY `ZoneId` ASC;", m_nMonitorId, sPluginName.c_str());
|
||||
|
||||
if (mysql_query(&dbconn, sql))
|
||||
{
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if (!result)
|
||||
{
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
size_t nParamCnt = 0;
|
||||
size_t nParamNum = mysql_num_rows(result);
|
||||
|
||||
if (nParamNum > 0)
|
||||
{
|
||||
std::vector<MYSQL_ROW> vRows;
|
||||
for (unsigned int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++)
|
||||
{
|
||||
if (mysql_errno(&dbconn))
|
||||
{
|
||||
Error("Can't fetch row: %s", mysql_error(&dbconn));
|
||||
mysql_free_result(result);
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
vRows.push_back(dbrow);
|
||||
}
|
||||
// Iterate over the zones
|
||||
for (size_t i = 0; i < m_vMonitorZones.size(); i++)
|
||||
{
|
||||
// Iterate over the configuration parameters
|
||||
for (std::vector<MYSQL_ROW>::iterator it = vRows.begin(); it != vRows.end(); it++)
|
||||
{
|
||||
// Add the parameter to the map if the zone id is found
|
||||
if ( (unsigned int)strtoul((*it)[0], NULL, 0) == m_vMonitorZones[i].id )
|
||||
{
|
||||
nParamCnt++;
|
||||
std::string name((*it)[1]);
|
||||
std::string value((*it)[2]);
|
||||
if((name == "Enabled") && (value == "Yes")) {
|
||||
mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].Enabled = true;
|
||||
} else if((name == "RequireNatDet") && (value == "Yes")) {
|
||||
mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].RequireNatDet = true;
|
||||
} else if((name == "IncludeNatDet") && (value == "Yes")) {
|
||||
mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].IncludeNatDet = true;
|
||||
} else if((name == "ReInitNatDet") && (value == "Yes")) {
|
||||
mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].ReInitNatDet = true;
|
||||
}
|
||||
// Keep only enabled zones in mapPluginConf
|
||||
if (binary_search(vnPluginZones.begin(), vnPluginZones.end(), i)) {
|
||||
mapPluginConf[i][name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].Enabled
|
||||
&& mapRegPluginZoneConf[sPluginName][m_vMonitorZones[i].id].RequireNatDet
|
||||
&& !m_bIsNativeDetEnabled )
|
||||
Warning("Plugin '%s' will never enter in alarm because native detection is required but not enabled", sPluginName.c_str());
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
return ( nParamNum == nParamCnt );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getEnabledZonesForPlugin(std::string sPluginName, std::vector<unsigned int>& vnPluginZones)
|
||||
* \param sPluginName is the name of the plugin (filename without extension)
|
||||
* \param vnPluginZones is the vector list filled with zones enabled for this plugin
|
||||
* \return true if at least one active or exclusive zone exist
|
||||
*/
|
||||
bool ImageAnalyser::getEnabledZonesForPlugin(std::string sPluginName, std::vector<unsigned int>& vnPluginZones)
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
bool bPluginEnabled = false;
|
||||
std::string sZones;
|
||||
|
||||
// Get the sorted list of zones ids which have the plugin enabled
|
||||
snprintf(sql, sizeof(sql), "SELECT `ZoneId` FROM `PluginsConfig` WHERE `MonitorId`=%d AND `pluginName`='%s' AND `Name`='Enabled' AND `Value`='yes' ORDER BY `ZoneId` ASC;", m_nMonitorId, sPluginName.c_str());
|
||||
|
||||
if (mysql_query( &dbconn, sql))
|
||||
{
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if (!result)
|
||||
{
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
if (mysql_num_rows(result) > 0)
|
||||
{
|
||||
std::vector<unsigned int> vnEnabledZoneIds;
|
||||
for (unsigned int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++)
|
||||
{
|
||||
if (mysql_errno(&dbconn))
|
||||
{
|
||||
Error("Can't fetch row: %s", mysql_error(&dbconn));
|
||||
mysql_free_result(result);
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
vnEnabledZoneIds.push_back(atoi(dbrow[0]));
|
||||
}
|
||||
|
||||
// Iterate over the zones
|
||||
for (size_t i = 0; i < m_vMonitorZones.size(); i++)
|
||||
{
|
||||
if (binary_search(vnEnabledZoneIds.begin(), vnEnabledZoneIds.end(), m_vMonitorZones[i].id))
|
||||
{
|
||||
// Add the index to the vector if the zone id is found
|
||||
vnPluginZones.push_back(i);
|
||||
std::string sZoneType = m_vMonitorZones[i].type;
|
||||
if ((sZoneType == "Active") || (sZoneType == "Exclusive"))
|
||||
bPluginEnabled = true;
|
||||
if ( sZones.length() )
|
||||
sZones += ", ";
|
||||
sZones += m_vMonitorZones[i].name + " (" + sZoneType + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
if (bPluginEnabled)
|
||||
{
|
||||
Info("Plugin '%s' is enabled for zone(s): %s", sPluginName.c_str(), sZones.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Info("Plugin '%s' is disabled (not enabled for any active or exclusive zones)", sPluginName.c_str());
|
||||
}
|
||||
return bPluginEnabled;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getZonesConfig(std::string sLoadedPlugins)
|
||||
* \param sLoadedPlugins is the formatted list of loaded plugins
|
||||
*/
|
||||
bool ImageAnalyser::getZonesConfig(std::string sLoadedPlugins)
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
if ( !sLoadedPlugins.length() ) return false;
|
||||
|
||||
// Get the sorted list of zones and which have a setting enabled
|
||||
snprintf(sql, sizeof(sql), "SELECT DISTINCT `ZoneId`, `Name` FROM `PluginsConfig` WHERE `MonitorId` = %d AND `pluginName` IN (%s) AND `Name` IN ('RequireNatDet', 'IncludeNatDet', 'ReInitNatDet') AND `Value` = 'yes' ORDER BY `ZoneId` ASC;", m_nMonitorId, sLoadedPlugins.c_str());
|
||||
if (mysql_query(&dbconn, sql))
|
||||
{
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if (!result)
|
||||
{
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
if (mysql_num_rows(result) > 0)
|
||||
{
|
||||
std::vector<zIdName> vSettings;
|
||||
for (unsigned int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++)
|
||||
{
|
||||
if (mysql_errno(&dbconn))
|
||||
{
|
||||
Error("Can't fetch row: %s", mysql_error(&dbconn));
|
||||
mysql_free_result(result);
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
zIdName setting;
|
||||
setting.zoneId = (unsigned int)strtoul(dbrow[0], NULL, 0);
|
||||
setting.name = dbrow[1];
|
||||
vSettings.push_back(setting);
|
||||
}
|
||||
|
||||
// Iterate over the zones and add the index to the vector if the zone id is found
|
||||
for (size_t i = 0; i != m_vMonitorZones.size(); i++)
|
||||
{
|
||||
zConf zoneConf;
|
||||
for (std::vector<zIdName>::iterator it = vSettings.begin(); it != vSettings.end(); it++)
|
||||
{
|
||||
if (it->zoneId == m_vMonitorZones[i].id)
|
||||
{
|
||||
if (it->name == "RequireNatDet")
|
||||
zoneConf.RequireNatDet = true;
|
||||
else if (it->name == "IncludeNatDet")
|
||||
zoneConf.IncludeNatDet = true;
|
||||
else if (it->name == "ReInitNatDet")
|
||||
zoneConf.ReInitNatDet = true;
|
||||
}
|
||||
}
|
||||
m_vZonesConfig.push_back(zoneConf);
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getZoneConfig(int nZone, zConf& zoneConf)
|
||||
* \param nZone is the zone index (not the id in sql database)
|
||||
* \param zoneConf is a structure filled with the plugin settings of nZone
|
||||
*/
|
||||
bool ImageAnalyser::getZoneConfig(unsigned int nZone, zConf& zoneConf)
|
||||
{
|
||||
if (nZone < m_vZonesConfig.size())
|
||||
zoneConf = m_vZonesConfig[nZone];
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getRegPluginGenConf(std::string sPluginName, pGenConf& regPluginGenConf)
|
||||
* \param sPluginName is the name of the plugin (filename without extension)
|
||||
* \param regPluginGenConf is a structure filled with the general settings of the plugin
|
||||
* \return false if no setting is found
|
||||
*/
|
||||
bool ImageAnalyser::getRegPluginGenConf(std::string sPluginName, pGenConf& regPluginGenConf)
|
||||
{
|
||||
std::map<std::string,pGenConf>::iterator it = mapRegPluginGenConf.find( sPluginName );
|
||||
if ( it == mapRegPluginGenConf.end() )
|
||||
return false;
|
||||
regPluginGenConf = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn ImageAnalyser::getRegPluginZoneConf(std::string sPluginName, PluginZoneConf& regPluginZoneConf)
|
||||
* \param sPluginName is the name of the plugin (filename without extension)
|
||||
* \param regPluginZoneConf is a map filled with the zone settings of the plugin
|
||||
*/
|
||||
void ImageAnalyser::getRegPluginZoneConf(std::string sPluginName, PluginZoneConf& regPluginZoneConf)
|
||||
{
|
||||
std::map<std::string,PluginZoneConf>::iterator it = mapRegPluginZoneConf.find( sPluginName );
|
||||
|
||||
if ( it != mapRegPluginZoneConf.end() )
|
||||
regPluginZoneConf = it->second;
|
||||
|
||||
pZoneConf empty;
|
||||
|
||||
for (size_t i = 0; i != m_vMonitorZones.size(); i++)
|
||||
{
|
||||
PluginZoneConf::iterator it2 = regPluginZoneConf.find( m_vMonitorZones[i].id );
|
||||
if ( it2 == regPluginZoneConf.end() )
|
||||
regPluginZoneConf[m_vMonitorZones[i].id] = empty;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageAnalyser::cleanupPlugins()
|
||||
{
|
||||
|
||||
std::string sPluginsToKeep;
|
||||
std::string sRequest;
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
for ( DetectorsList::iterator It = m_Detectors.begin(); It != m_Detectors.end(); ++It )
|
||||
{
|
||||
if ( sPluginsToKeep.length() )
|
||||
sPluginsToKeep += ", ";
|
||||
sPluginsToKeep += "'" + (*It)->getPluginName() + "'";
|
||||
}
|
||||
|
||||
if ( sPluginsToKeep.length() )
|
||||
sRequest = " AND `pluginName` NOT IN (" + sPluginsToKeep + ")";
|
||||
|
||||
snprintf(sql, sizeof(sql), "DELETE FROM `PluginsConfig` WHERE `MonitorId` = %d%s;", m_nMonitorId, sRequest.c_str());
|
||||
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't delete plugin: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,57 @@
|
|||
#ifndef ZM_IMAGE_ANALYSER_H
|
||||
#define ZM_IMAGE_ANALYSER_H
|
||||
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_detector.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_zone.h"
|
||||
#include "zm_event.h"
|
||||
#include "zm_db.h"
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
//! List of available detectors.
|
||||
typedef std::list<Detector *> DetectorsList;
|
||||
|
||||
//! A structure to store the general configuration of a plugin
|
||||
struct pGenConf {
|
||||
bool Registered;
|
||||
bool Configured;
|
||||
pGenConf():
|
||||
Registered(false),
|
||||
Configured(false)
|
||||
{}
|
||||
};
|
||||
|
||||
//! A structure to store the zone configuration of a plugin
|
||||
struct pZoneConf {
|
||||
bool Enabled;
|
||||
bool RequireNatDet;
|
||||
bool IncludeNatDet;
|
||||
bool ReInitNatDet;
|
||||
pZoneConf():
|
||||
Enabled(false),
|
||||
RequireNatDet(false),
|
||||
IncludeNatDet(false),
|
||||
ReInitNatDet(false)
|
||||
{}
|
||||
};
|
||||
|
||||
//! Map of zone configuration for a plugin
|
||||
typedef std::map<unsigned int,pZoneConf> PluginZoneConf;
|
||||
|
||||
//! Class for handling image detection.
|
||||
class ImageAnalyser {
|
||||
public:
|
||||
|
||||
//!Default constructor.
|
||||
ImageAnalyser() {};
|
||||
ImageAnalyser( int nMonitorId = 0 );
|
||||
|
||||
//! Destructor.
|
||||
~ImageAnalyser();
|
||||
|
@ -35,8 +62,86 @@ class ImageAnalyser {
|
|||
//! Overloaded operator=.
|
||||
ImageAnalyser& operator=(const ImageAnalyser& source);
|
||||
|
||||
private:
|
||||
//! Adds new plugin's detector to the list of detectors.
|
||||
void addDetector(std::auto_ptr<Detector> Det)
|
||||
{
|
||||
m_Detectors.push_back(Det.release());
|
||||
}
|
||||
|
||||
void onCreateEvent(Zone** zones, Event* event);
|
||||
void onCloseEvent(Zone** zones, Event* event);
|
||||
|
||||
//! Do detection in an image by calling all available detectors.
|
||||
bool DoDetection(const Image &comp_image, Zone** zones, Event::StringSetMap& noteSetMap, std::string& det_cause, unsigned int& score);
|
||||
|
||||
//! Configure all loaded plugins using given configuration file.
|
||||
void configurePlugins(std::string sConfigFileName, bool bDoNativeDet = 0);
|
||||
|
||||
//! Check if the configuration file contains the right section name
|
||||
bool isValidConfigFile(std::string sPluginName, std::string sConfigFileName);
|
||||
|
||||
//! Get index of enabled zones for this monitor (same ordering as in Monitor::Load)
|
||||
bool getMonitorZones();
|
||||
|
||||
//! Get plugin configuration from database
|
||||
bool getPluginConfig(std::string sPluginName, std::vector<unsigned int> vnPluginZones, std::map<unsigned int,std::map<std::string,std::string> >& mapPluginConf);
|
||||
|
||||
//! Get enabled zones for the plugin
|
||||
bool getEnabledZonesForPlugin(std::string sPluginName, std::vector<unsigned int>& vnPluginZones);
|
||||
|
||||
//! Get zones configuration from database
|
||||
bool getZonesConfig(std::string sLoadedPlugins);
|
||||
|
||||
//! Get Zone configuration from this class
|
||||
bool getZoneConfig(unsigned int nZone, zConf& zoneConf);
|
||||
|
||||
//! Get the general settings of a registered plugin
|
||||
bool getRegPluginGenConf(std::string sPluginName, pGenConf& regPluginGenConf);
|
||||
|
||||
//! Get the zone settings of a registered plugin
|
||||
void getRegPluginZoneConf(std::string sPluginName, PluginZoneConf& regPluginZoneConf);
|
||||
|
||||
//! Remove from db plugins no longer detected
|
||||
void cleanupPlugins();
|
||||
|
||||
private:
|
||||
|
||||
//! All available detectors.
|
||||
DetectorsList m_Detectors;
|
||||
|
||||
//! The monitor id
|
||||
int m_nMonitorId;
|
||||
|
||||
//! Native detection is enabled
|
||||
bool m_bIsNativeDetEnabled;
|
||||
|
||||
//! Analyser is enabled
|
||||
bool m_bIsAnalyserEnabled;
|
||||
|
||||
//! A structure to store a plugin parameter
|
||||
struct zIdName {
|
||||
unsigned int zoneId;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
//! A vector filled with parameters of zones
|
||||
std::vector<zConf> m_vZonesConfig;
|
||||
|
||||
//! A structure to store basic settings of a zone
|
||||
struct zSetting {
|
||||
unsigned int id;
|
||||
std::string name;
|
||||
std::string type;
|
||||
};
|
||||
|
||||
//! A vector filled with settings of zones enabled for the monitor
|
||||
std::vector<zSetting> m_vMonitorZones;
|
||||
|
||||
//! A map to store the general configuration of registered plugins
|
||||
std::map<std::string,pGenConf> mapRegPluginGenConf;
|
||||
|
||||
//! A map to store the zone configuration of registered plugins
|
||||
std::map<std::string,PluginZoneConf> mapRegPluginZoneConf;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef ZM_LOCAL_CAMERA_H
|
||||
#define ZM_LOCAL_CAMERA_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_camera.h"
|
||||
#include "zm_image.h"
|
||||
|
||||
|
|
|
@ -39,9 +39,6 @@
|
|||
bool Logger::smInitialised = false;
|
||||
Logger *Logger::smInstance = 0;
|
||||
|
||||
Logger::StringMap Logger::smCodes;
|
||||
Logger::IntMap Logger::smSyslogPriorities;
|
||||
|
||||
#if 0
|
||||
static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 )
|
||||
{
|
||||
|
|
|
@ -84,8 +84,8 @@ private:
|
|||
static bool smInitialised;
|
||||
static Logger *smInstance;
|
||||
|
||||
static StringMap smCodes;
|
||||
static IntMap smSyslogPriorities;
|
||||
StringMap smCodes;
|
||||
IntMap smSyslogPriorities;
|
||||
|
||||
private:
|
||||
bool mInitialised;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#define ZM_MEM_UTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "zm.h"
|
||||
|
||||
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
|
||||
uint8_t* retptr;
|
||||
|
|
|
@ -70,6 +70,23 @@ std::vector<std::string> split(const std::string &s, char delim) {
|
|||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
#if ZM_PLUGINS_ON
|
||||
int conf_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, ".conf") == 0))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif // ZM_PLUGINS_ON
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
@ -301,7 +318,8 @@ Monitor::Monitor(
|
|||
bool p_embed_exif,
|
||||
Purpose p_purpose,
|
||||
int p_n_zones,
|
||||
Zone *p_zones[]
|
||||
Zone *p_zones[],
|
||||
int p_DoNativeMotDet
|
||||
) : id( p_id ),
|
||||
server_id( p_server_id ),
|
||||
function( (Function)p_function ),
|
||||
|
@ -340,7 +358,9 @@ Monitor::Monitor(
|
|||
zones( p_zones ),
|
||||
timestamps( 0 ),
|
||||
images( 0 ),
|
||||
privacy_bitmask( NULL )
|
||||
privacy_bitmask( NULL ),
|
||||
iDoNativeMotDet( p_DoNativeMotDet ),
|
||||
ThePluginManager( p_id )
|
||||
{
|
||||
strncpy( name, p_name, sizeof(name)-1 );
|
||||
|
||||
|
@ -435,9 +455,35 @@ Monitor::Monitor(
|
|||
shared_data->alarm_y = -1;
|
||||
}
|
||||
|
||||
#if ZM_PLUGINS_ON
|
||||
if ( ( purpose == QUERY_PLUGINS ) || ( config.load_plugins && ( purpose == ANALYSIS ) ) )
|
||||
{
|
||||
Info("Load plugins from the directory %s ... ", config.path_plugins);
|
||||
ThePluginManager.setPluginExt(std::string(config.plugin_extension));
|
||||
unsigned int nNumPlugLoaded = 0;
|
||||
unsigned int nNumPlugFound = ThePluginManager.findPlugins(
|
||||
std::string(config.path_plugins), (purpose == ANALYSIS), nNumPlugLoaded );
|
||||
Info("Found %u plugin(s) - %u loaded", nNumPlugFound, nNumPlugLoaded);
|
||||
if (nNumPlugFound > 0)
|
||||
{
|
||||
ThePluginManager.configurePlugins(
|
||||
std::string(config.plugins_config_path),
|
||||
(!config.turnoff_native_analysis && iDoNativeMotDet));
|
||||
struct direct **files;
|
||||
int count = scandir(config.plugins_config_dir, &files, conf_select, alphasort);
|
||||
if (count > 0)
|
||||
Info("Load plugin configuration files from directory %s ... ", config.plugins_config_dir);
|
||||
for (int i = 0; i < count; ++i)
|
||||
ThePluginManager.configurePlugins(
|
||||
join_paths(config.plugins_config_dir, files[i]->d_name),
|
||||
(!config.turnoff_native_analysis && iDoNativeMotDet));
|
||||
}
|
||||
}
|
||||
#endif // ZM_PLUGINS_ON
|
||||
|
||||
if ( ( ! mem_ptr ) || ! shared_data->valid )
|
||||
{
|
||||
if ( purpose != QUERY )
|
||||
if ( ( purpose != QUERY ) && ( purpose != QUERY_PLUGINS ) )
|
||||
{
|
||||
Error( "Shared data not initialised by capture daemon for monitor %s", name );
|
||||
exit( -1 );
|
||||
|
@ -697,6 +743,24 @@ void Monitor::AddZones( int p_n_zones, Zone *p_zones[] )
|
|||
delete[] zones;
|
||||
n_zones = p_n_zones;
|
||||
zones = p_zones;
|
||||
for ( int i = 0; i < n_zones; i++ )
|
||||
{
|
||||
if ( purpose == ANALYSIS )
|
||||
{
|
||||
Zone *zone = zones[i];
|
||||
Debug( 4, "Assign reference image of zone %s", zone->Label() );
|
||||
zone->AssignRefImage( width, height, camera->Colours(), camera->SubpixelOrder(),
|
||||
image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize() );
|
||||
#if ZM_PLUGINS_ON
|
||||
zConf zone_conf;
|
||||
if ( ThePluginManager.getImageAnalyser().getZoneConfig( i, zone_conf ) )
|
||||
{
|
||||
Debug( 4, "Configure zone %s for plugins", zone->Label() );
|
||||
zone->SetConfig( zone_conf );
|
||||
}
|
||||
#endif // ZM_PLUGINS_ON
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Monitor::AddPrivacyBitmask( Zone *p_zones[] )
|
||||
|
@ -1354,7 +1418,11 @@ bool Monitor::Analyse()
|
|||
{
|
||||
Info( "Received resume indication at count %d", image_count );
|
||||
shared_data->active = true;
|
||||
ref_image = *snap_image;
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
Debug( 4, "Set reference image of zone %s", zones[n_zone]->Label() );
|
||||
zones[n_zone]->SetRefImage(*snap_image);
|
||||
}
|
||||
ready_count = image_count+(warmup_count/2);
|
||||
shared_data->alarm_x = shared_data->alarm_y = -1;
|
||||
}
|
||||
|
@ -1365,7 +1433,11 @@ bool Monitor::Analyse()
|
|||
{
|
||||
Info( "Auto resuming at count %d", image_count );
|
||||
shared_data->active = true;
|
||||
ref_image = *snap_image;
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
Debug( 4, "Set reference image of zone %s", zones[n_zone]->Label() );
|
||||
zones[n_zone]->SetRefImage(*snap_image);
|
||||
}
|
||||
ready_count = image_count+(warmup_count/2);
|
||||
auto_resume_time = 0;
|
||||
}
|
||||
|
@ -1403,6 +1475,8 @@ bool Monitor::Analyse()
|
|||
cause += ", ";
|
||||
cause += trigger_data->trigger_cause;
|
||||
}
|
||||
else
|
||||
event->AddCause( trigger_data->trigger_cause );
|
||||
Event::StringSet noteSet;
|
||||
noteSet.insert( trigger_data->trigger_text );
|
||||
noteSetMap[trigger_data->trigger_cause] = noteSet;
|
||||
|
@ -1430,39 +1504,85 @@ bool Monitor::Analyse()
|
|||
cause += ", ";
|
||||
cause += SIGNAL_CAUSE;
|
||||
}
|
||||
else
|
||||
event->AddCause( SIGNAL_CAUSE );
|
||||
Event::StringSet noteSet;
|
||||
noteSet.insert( signalText );
|
||||
noteSetMap[SIGNAL_CAUSE] = noteSet;
|
||||
shared_data->state = state = IDLE;
|
||||
shared_data->active = signal;
|
||||
ref_image = *snap_image;
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
Debug( 4, "Set reference image of zone %s", zones[n_zone]->Label() );
|
||||
zones[n_zone]->SetRefImage(*snap_image);
|
||||
}
|
||||
}
|
||||
else if ( signal && Active() && (function == MODECT || function == MOCORD) )
|
||||
{
|
||||
Event::StringSet zoneSet;
|
||||
int motion_score = last_motion_score;
|
||||
if ( !(image_count % (motion_frame_skip+1) ) )
|
||||
#if ZM_PLUGINS_ON
|
||||
if ((config.turnoff_native_analysis && !config.load_plugins) || (!config.turnoff_native_analysis && (iDoNativeMotDet || (!iDoNativeMotDet && !config.load_plugins))) )
|
||||
#else // ZM_PLUGINS_ON
|
||||
if (!config.turnoff_native_analysis && iDoNativeMotDet)
|
||||
#endif // ZM_PLUGINS_ON
|
||||
{
|
||||
// Get new score.
|
||||
motion_score = last_motion_score = DetectMotion( *snap_image, zoneSet );
|
||||
Event::StringSet zoneSet;
|
||||
unsigned int motion_score = last_motion_score;
|
||||
bool alarm = false;
|
||||
if ( !(image_count % (motion_frame_skip+1) ) )
|
||||
{
|
||||
// Get new score.
|
||||
alarm = DetectMotion( *snap_image, zoneSet, motion_score );
|
||||
last_motion_score = motion_score;
|
||||
}
|
||||
//int motion_score = DetectBlack( *snap_image, zoneSet );
|
||||
if ( alarm )
|
||||
{
|
||||
if ( motion_score )
|
||||
{
|
||||
score += motion_score;
|
||||
if ( !event )
|
||||
{
|
||||
if ( cause.length() )
|
||||
cause += ", ";
|
||||
cause += MOTION_CAUSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->AddCause( MOTION_CAUSE );
|
||||
}
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
//int motion_score = DetectBlack( *snap_image, zoneSet );
|
||||
if ( motion_score )
|
||||
else
|
||||
{
|
||||
if ( !event )
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
score += motion_score;
|
||||
if ( cause.length() )
|
||||
cause += ", ";
|
||||
cause += MOTION_CAUSE;
|
||||
zones[n_zone]->ResetStats();
|
||||
}
|
||||
else
|
||||
{
|
||||
score += motion_score;
|
||||
}
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
|
||||
}
|
||||
#if ZM_PLUGINS_ON
|
||||
if (config.load_plugins)
|
||||
{
|
||||
std::string det_cause; // detection cause to fill in plugin's detectors
|
||||
unsigned int plugin_score = 0;
|
||||
if ( ThePluginManager.getImageAnalyser().DoDetection( *snap_image, zones, noteSetMap, det_cause, plugin_score ) )
|
||||
{
|
||||
score += plugin_score;
|
||||
if ( !event )
|
||||
{
|
||||
if ( det_cause.length() )
|
||||
{
|
||||
if ( cause.length() )
|
||||
cause += ", ";
|
||||
cause += det_cause;
|
||||
}
|
||||
}
|
||||
else
|
||||
event->AddCause( det_cause );
|
||||
}
|
||||
}
|
||||
#endif // ZM_PLUGINS_ON
|
||||
shared_data->active = signal;
|
||||
}
|
||||
if ( (!signal_change && signal) && n_linked_monitors > 0 )
|
||||
|
@ -1485,6 +1605,8 @@ bool Monitor::Analyse()
|
|||
first_link = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
event->AddCause( LINKED_CAUSE );
|
||||
noteSet.insert( linked_monitors[i]->Name() );
|
||||
score += 50;
|
||||
}
|
||||
|
@ -1647,7 +1769,10 @@ bool Monitor::Analyse()
|
|||
event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap );
|
||||
}
|
||||
shared_data->last_event = event->Id();
|
||||
|
||||
#if ZM_PLUGINS_ON
|
||||
if (config.load_plugins)
|
||||
ThePluginManager.getImageAnalyser().onCreateEvent( zones, event );
|
||||
#endif // ZM_PLUGINS_ON
|
||||
Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() );
|
||||
|
||||
if ( pre_event_images )
|
||||
|
@ -1820,10 +1945,11 @@ bool Monitor::Analyse()
|
|||
}
|
||||
if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) )
|
||||
{
|
||||
if ( state == ALARM ) {
|
||||
ref_image.Blend( *snap_image, alarm_ref_blend_perc );
|
||||
} else {
|
||||
ref_image.Blend( *snap_image, ref_blend_perc );
|
||||
int ref_blend = ( state == ALARM ) ? alarm_ref_blend_perc : ref_blend_perc;
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
Debug( 4, "Blend reference image of zone %s", zones[n_zone]->Label() );
|
||||
zones[n_zone]->BlendRefImage( *snap_image, ref_blend );
|
||||
}
|
||||
}
|
||||
last_signal = signal;
|
||||
|
@ -1856,7 +1982,7 @@ void Monitor::Reload()
|
|||
closeEvent();
|
||||
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id );
|
||||
snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, DoNativeMotDet, SignalCheckColour from Monitors where Id = '%d'", id );
|
||||
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
|
@ -1903,6 +2029,7 @@ void Monitor::Reload()
|
|||
alarm_ref_blend_perc = atoi(dbrow[index++]);
|
||||
track_motion = atoi(dbrow[index++]);
|
||||
|
||||
iDoNativeMotDet = atoi(dbrow[index++]);
|
||||
|
||||
if ( dbrow[index][0] == '#' )
|
||||
signal_check_colour = strtol(dbrow[index]+1,0,16);
|
||||
|
@ -2048,7 +2175,7 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors )
|
|||
#if ZM_HAS_V4L
|
||||
int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, DoNativeMotDet, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'";
|
||||
if ( device[0] ) {
|
||||
sql += " AND Device='";
|
||||
sql += device;
|
||||
|
@ -2138,6 +2265,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
int alarm_ref_blend_perc = atoi(dbrow[col]); col++;
|
||||
int track_motion = atoi(dbrow[col]); col++;
|
||||
|
||||
int doNativeMotDet = atoi(dbrow[col]); col++;
|
||||
|
||||
int signal_check_colour;
|
||||
if ( dbrow[col][0] == '#' )
|
||||
signal_check_colour = strtol(dbrow[col]+1,0,16);
|
||||
|
@ -2206,7 +2335,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
embed_exif,
|
||||
purpose,
|
||||
0,
|
||||
0
|
||||
0,
|
||||
doNativeMotDet
|
||||
);
|
||||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
|
@ -2228,7 +2358,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
|
||||
int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, DoNativeMotDet from Monitors where Function != 'None' and Type = 'Remote'";
|
||||
if ( staticConfig.SERVER_ID ) {
|
||||
sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
|
||||
}
|
||||
|
@ -2302,6 +2432,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
int track_motion = atoi(dbrow[col]); col++;
|
||||
bool embed_exif = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int doNativeMotDet = atoi(dbrow[col]); col++;
|
||||
|
||||
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
|
||||
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
|
||||
|
||||
|
@ -2385,8 +2517,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
embed_exif,
|
||||
purpose,
|
||||
0,
|
||||
0
|
||||
|
||||
0,
|
||||
doNativeMotDet
|
||||
);
|
||||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
|
@ -2407,7 +2539,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
|
||||
int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, DoNativeMotDet from Monitors where Function != 'None' and Type = 'File'";
|
||||
if ( file[0] ) {
|
||||
sql += " AND Path='";
|
||||
sql += file;
|
||||
|
@ -2477,6 +2609,8 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
int track_motion = atoi(dbrow[col]); col++;
|
||||
bool embed_exif = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int doNativeMotDet = atoi(dbrow[col]); col++;
|
||||
|
||||
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
|
||||
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
|
||||
|
||||
|
@ -2528,7 +2662,8 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
RGB_WHITE,
|
||||
purpose,
|
||||
0,
|
||||
0
|
||||
0,
|
||||
doNativeMotDet
|
||||
);
|
||||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
|
@ -2550,7 +2685,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
#if HAVE_LIBAVFORMAT
|
||||
int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, DoNativeMotDet from Monitors where Function != 'None' and Type = 'Ffmpeg'";
|
||||
if ( file[0] ) {
|
||||
sql += " AND Path = '";
|
||||
sql += file;
|
||||
|
@ -2622,6 +2757,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
int track_motion = atoi(dbrow[col]); col++;
|
||||
bool embed_exif = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int doNativeMotDet = atoi(dbrow[col]); col++;
|
||||
|
||||
int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width);
|
||||
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
|
||||
|
||||
|
@ -2675,7 +2812,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
RGB_WHITE,
|
||||
purpose,
|
||||
0,
|
||||
0
|
||||
0,
|
||||
doNativeMotDet
|
||||
);
|
||||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
|
@ -2697,7 +2835,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
|
||||
Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose )
|
||||
{
|
||||
std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
|
||||
std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, DoNativeMotDet, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
|
||||
|
||||
MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() );
|
||||
if ( ! dbrow ) {
|
||||
|
@ -2784,6 +2922,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
int alarm_ref_blend_perc = atoi(dbrow[col]); col++;
|
||||
int track_motion = atoi(dbrow[col]); col++;
|
||||
|
||||
int doNativeMotDet = atoi(dbrow[col]); col++;
|
||||
|
||||
int signal_check_colour;
|
||||
if ( dbrow[col][0] == '#' )
|
||||
signal_check_colour = strtol(dbrow[col]+1,0,16);
|
||||
|
@ -2989,7 +3129,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
embed_exif,
|
||||
purpose,
|
||||
0,
|
||||
0
|
||||
0,
|
||||
doNativeMotDet
|
||||
|
||||
);
|
||||
|
||||
|
@ -3206,6 +3347,15 @@ bool Monitor::closeEvent()
|
|||
{
|
||||
gettimeofday( &(event->EndTime()), NULL );
|
||||
}
|
||||
#if ZM_PLUGINS_ON
|
||||
// Inform all plugins that we are closing the event
|
||||
if ( config.load_plugins && ( purpose == ANALYSIS ) )
|
||||
{
|
||||
ThePluginManager.getImageAnalyser().onCloseEvent( zones, event );
|
||||
}
|
||||
#endif
|
||||
event->Close();
|
||||
|
||||
delete event;
|
||||
event = 0;
|
||||
return( true );
|
||||
|
@ -3398,33 +3548,32 @@ unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zon
|
|||
|
||||
|
||||
|
||||
unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet )
|
||||
unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet, unsigned int &score )
|
||||
{
|
||||
bool alarm = false;
|
||||
unsigned int score = 0;
|
||||
score = 0;
|
||||
|
||||
if ( n_zones <= 0 ) return( alarm );
|
||||
|
||||
if ( config.record_diag_images )
|
||||
for ( int n_zone = 0; n_zone < n_zones; n_zone++ )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
Zone *zone = zones[n_zone];
|
||||
if ( config.record_diag_images )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id );
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-r.jpg", config.dir_events, id, zone->Id() );
|
||||
zone->WriteRefImage( diag_path );
|
||||
}
|
||||
ref_image.WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
ref_image.Delta( comp_image, &delta_image);
|
||||
Debug( 4, "Set delta image of zone %s", zone->Label() );
|
||||
zone->SetDeltaImage( comp_image );
|
||||
|
||||
if ( config.record_diag_images )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
if ( config.record_diag_images )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id );
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-d.jpg", config.dir_events, id, zone->Id() );
|
||||
zone->WriteDeltaImage( diag_path );
|
||||
}
|
||||
delta_image.WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
// Blank out all exclusion zones
|
||||
|
@ -3439,7 +3588,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Blanking inactive zone %s", zone->Label() );
|
||||
delta_image.Fill( RGB_BLACK, zone->GetPolygon() );
|
||||
zone->FillDeltaImage( RGB_BLACK );
|
||||
}
|
||||
|
||||
// Check preclusive zones first
|
||||
|
@ -3453,13 +3602,16 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
int old_zone_score = zone->Score();
|
||||
bool old_zone_alarmed = zone->Alarmed();
|
||||
Debug( 3, "Checking preclusive zone %s - old score: %d, state: %s", zone->Label(),old_zone_score, zone->Alarmed()?"alarmed":"quiet" );
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
if ( zone->CheckAlarms( &comp_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
zone->SetAlarm();
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
zoneSet.insert( zone->Label() );
|
||||
zoneSet.insert( (" [Zone " + std::string(zone->Label()) + "]\n").c_str() );
|
||||
if ( !zone->IsPostProcEnabled() )
|
||||
{
|
||||
zone->SetAlarm();
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
}
|
||||
//zone->ResetStats();
|
||||
} else {
|
||||
// check if end of alarm
|
||||
|
@ -3497,19 +3649,22 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking active zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
if ( zone->CheckAlarms( &comp_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
zone->SetAlarm();
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
zoneSet.insert( zone->Label() );
|
||||
if ( config.opt_control && track_motion )
|
||||
score += zone->Score();
|
||||
zoneSet.insert( (" [Zone " + std::string(zone->Label()) + "]\n").c_str() );
|
||||
if ( !zone->IsPostProcEnabled() )
|
||||
{
|
||||
if ( (int)zone->Score() > top_score )
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
if ( config.opt_control && track_motion )
|
||||
{
|
||||
top_score = zone->Score();
|
||||
alarm_centre = zone->GetAlarmCentre();
|
||||
if ( (int)zone->Score() > top_score )
|
||||
{
|
||||
top_score = zone->Score();
|
||||
alarm_centre = zone->GetAlarmCentre();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3525,19 +3680,22 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking inclusive zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
if ( zone->CheckAlarms( &comp_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
zone->SetAlarm();
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
zoneSet.insert( zone->Label() );
|
||||
if ( config.opt_control && track_motion )
|
||||
score += zone->Score();
|
||||
zoneSet.insert( (" [Zone " + std::string(zone->Label()) + "]\n").c_str() );
|
||||
if ( !zone->IsPostProcEnabled() )
|
||||
{
|
||||
if ( zone->Score() > (unsigned int)top_score )
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
if ( config.opt_control && track_motion )
|
||||
{
|
||||
top_score = zone->Score();
|
||||
alarm_centre = zone->GetAlarmCentre();
|
||||
if ( zone->Score() > (unsigned int)top_score )
|
||||
{
|
||||
top_score = zone->Score();
|
||||
alarm_centre = zone->GetAlarmCentre();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3554,13 +3712,16 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking exclusive zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
if ( zone->CheckAlarms( &comp_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
zone->SetAlarm();
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
zoneSet.insert( zone->Label() );
|
||||
score += zone->Score();
|
||||
zoneSet.insert( (" [Zone " + std::string(zone->Label()) + "]\n").c_str() );
|
||||
if ( !zone->IsPostProcEnabled() )
|
||||
{
|
||||
Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3981,7 +4142,7 @@ void MonitorStream::processCommand( const CmdMsg *msg )
|
|||
|
||||
DataMsg status_msg;
|
||||
status_msg.msg_type = MSG_DATA_WATCH;
|
||||
memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) );
|
||||
memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) );
|
||||
int nbytes = 0;
|
||||
if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 )
|
||||
{
|
||||
|
@ -4524,3 +4685,35 @@ void Monitor::SingleImageZip( int scale)
|
|||
fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" );
|
||||
fwrite( img_buffer, img_buffer_size, 1, stdout );
|
||||
}
|
||||
#if ZM_PLUGINS_ON
|
||||
void Monitor::DumpPluginStatus()
|
||||
{
|
||||
std::map<std::string,pGenConf> mapPluginGenConf;
|
||||
unsigned int nNumPlugins = ThePluginManager.getPluginsGenConf(mapPluginGenConf);
|
||||
bool bDoNativeDet = !config.turnoff_native_analysis && iDoNativeMotDet;
|
||||
|
||||
if ( nNumPlugins == 0)
|
||||
{
|
||||
printf("No plugin found\n");
|
||||
return;
|
||||
}
|
||||
printf("%79sNATIVE DETECTION\n", " ");
|
||||
printf("PLUGIN NAME%*sREGISTERED CONFIGURED ZONE ENABLED ACTIVE REQUIRE INCLUDE REINIT\n", 19, " ");
|
||||
for (std::map<std::string,pGenConf>::iterator it = mapPluginGenConf.begin() ; it != mapPluginGenConf.end(); ++it)
|
||||
{
|
||||
PluginZoneConf mapPluginZoneConf;
|
||||
ThePluginManager.getPluginZoneConf( it->first, mapPluginZoneConf );
|
||||
int padLen = 34 - it->first.length();
|
||||
if(padLen < 0) padLen = 0;
|
||||
printf("%s%*s%d%*s%d%*s", it->first.c_str(), padLen, " ", it->second.Registered, 10, " ", it->second.Configured, 8, " ");
|
||||
for (PluginZoneConf::iterator it2 = mapPluginZoneConf.begin() ; it2 != mapPluginZoneConf.end(); ++it2)
|
||||
{
|
||||
if (it2 != mapPluginZoneConf.begin())
|
||||
printf("%*s", 54, " ");
|
||||
bool bIsActive = it2->second.Enabled && ( !it2->second.RequireNatDet || ( it2->second.RequireNatDet && bDoNativeDet ) );
|
||||
printf("%d%*s%d%*s%d%*s%d%*s%d%*s%d\n", it2->first, 7, " ", it2->second.Enabled, 7, " ", bIsActive, 8, " ", it2->second.RequireNatDet, 7, " ", it2->second.IncludeNatDet, 6, " ", it2->second.ReInitNatDet);
|
||||
}
|
||||
}
|
||||
ThePluginManager.getImageAnalyser().cleanupPlugins();
|
||||
}
|
||||
#endif // ZM_PLUGINS_ON
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
#include "zm_camera.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
#if ZM_PLUGINS_ON
|
||||
#include "zm_plugin_manager.h"
|
||||
#include "zm_image_analyser.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
|
@ -41,6 +44,9 @@
|
|||
#define MOTION_CAUSE "Motion"
|
||||
#define LINKED_CAUSE "Linked"
|
||||
|
||||
|
||||
int conf_select(const struct direct *entry);
|
||||
|
||||
//
|
||||
// This is the main class for monitors. Each monitor is associated
|
||||
// with a camera and is effectively a collector for events.
|
||||
|
@ -53,6 +59,7 @@ public:
|
|||
typedef enum
|
||||
{
|
||||
QUERY=0,
|
||||
QUERY_PLUGINS,
|
||||
CAPTURE,
|
||||
ANALYSIS
|
||||
} Purpose;
|
||||
|
@ -301,13 +308,20 @@ protected:
|
|||
|
||||
const unsigned char *privacy_bitmask;
|
||||
|
||||
|
||||
int iDoNativeMotDet;
|
||||
#if ZM_PLUGINS_ON
|
||||
PluginManager ThePluginManager;
|
||||
#else
|
||||
int ThePluginManager;
|
||||
#endif
|
||||
int n_linked_monitors;
|
||||
MonitorLink **linked_monitors;
|
||||
|
||||
public:
|
||||
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
|
||||
//bool OurCheckAlarms( Zone *zone, const Image *pImage );
|
||||
Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 );
|
||||
Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0, int p_DoNativeMotDet=1 );
|
||||
~Monitor();
|
||||
|
||||
void AddZones( int p_n_zones, Zone *p_zones[] );
|
||||
|
@ -406,7 +420,7 @@ public:
|
|||
return( camera->PostCapture() );
|
||||
}
|
||||
|
||||
unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet );
|
||||
unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet, unsigned int &score );
|
||||
// DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info.
|
||||
//unsigned int DetectBlack( const Image &comp_image, Event::StringSet &zoneSet );
|
||||
bool CheckSignal( const Image *image );
|
||||
|
@ -422,6 +436,8 @@ public:
|
|||
bool DumpSettings( char *output, bool verbose );
|
||||
void DumpZoneImage( const char *zone_string=0 );
|
||||
|
||||
void DumpPluginStatus();
|
||||
|
||||
#if ZM_HAS_V4L
|
||||
static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose );
|
||||
#endif // ZM_HAS_V4L
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#include "zm_plugin.h"
|
||||
#include "zm_config.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
/*!\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 std::runtime_error("Could not load '" + sFilename + "' (" + dlerror() + ")");
|
||||
}
|
||||
|
||||
// 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 std::runtime_error("'" + sFilename + "' is not a valid plugin");
|
||||
|
||||
// Initialize a new DLL reference counter
|
||||
m_pDLLRefCount = new size_t(1);
|
||||
}
|
||||
catch(std::runtime_error &ex)
|
||||
{
|
||||
dlclose(m_hDLL);
|
||||
throw ex;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
dlclose(m_hDLL);
|
||||
throw std::runtime_error("Unknown exception while loading plugin '" + sFilename + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!\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)
|
||||
{
|
||||
int pluginEngineVersion = m_pfnGetEngineVersion();
|
||||
|
||||
if(pluginEngineVersion == ZM_ENGINE_VERSION)
|
||||
m_pfnRegisterPlugin(K, m_sPluginFileName);
|
||||
else
|
||||
{
|
||||
// Raise an exception to inform the plugin manager that something bad happened
|
||||
std::ostringstream strError;
|
||||
strError << "Could not load '" << m_sPluginFileName
|
||||
<< "' (engine version mistmatch: ZM=" << ZM_ENGINE_VERSION
|
||||
<< " / plugin=" << pluginEngineVersion << ")";
|
||||
throw std::logic_error(strError.str().c_str());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef ZM_PLUGIN_H
|
||||
#define ZM_PLUGIN_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
class PluginManager;
|
||||
|
||||
|
||||
|
||||
//! Signature for the version query function
|
||||
typedef int fnGetEngineVersion();
|
||||
|
||||
//! Signature for the plugin's registration function
|
||||
typedef void fnRegisterPlugin(PluginManager &, std::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.
|
||||
std::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
|
|
@ -0,0 +1,166 @@
|
|||
#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 std::string& p1, const std::string& p2)
|
||||
* \param p1 is the first part of desired path
|
||||
* \param p2 is the second part of desired path
|
||||
* \return joined path string.
|
||||
*/
|
||||
std::string join_paths(const std::string& p1, const std::string& p2)
|
||||
{
|
||||
char sep = '/';
|
||||
std::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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string PluginManager::m_sPluginExt = DEFAULT_PLUGIN_EXT;
|
||||
|
||||
|
||||
PluginManager::PluginManager() {}
|
||||
|
||||
|
||||
PluginManager::PluginManager(
|
||||
int nMonitorId
|
||||
) :
|
||||
m_ImageAnalyser( nMonitorId )
|
||||
{}
|
||||
|
||||
|
||||
|
||||
/*!\fn PluginManager::loadPlugin(const std::string &sFilename))
|
||||
* \param sFilename is the name of plugin file to load
|
||||
*/
|
||||
bool PluginManager::loadPlugin(const std::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(std::runtime_error &ex)
|
||||
{
|
||||
Error("Runtime error: %s.", ex.what());
|
||||
return false;
|
||||
}
|
||||
catch(std::logic_error &el)
|
||||
{
|
||||
Error("Logic error: %s.", el.what());
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Error("Unknown error: Could not load %s.", sFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn PluginManager::findPlugins(const std::string &sPath, bool loadPlugins, unsigned int& nNumPlugLoaded)
|
||||
* \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 std::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)
|
||||
{
|
||||
std::string sFileName = std::string(files[i]->d_name);
|
||||
std::string sFullPath = join_paths(sPath, sFileName);
|
||||
size_t idx = sFileName.rfind('.');
|
||||
if (idx != std::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( std::pair<std::string,bool>(sFileName, IsPluginRegistered) );
|
||||
if (IsPluginRegistered) nNumPlugLoaded++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*!\fn PluginManager::configurePlugins(std::string sConfigFileName, bool bDoNativeDet)
|
||||
* \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(std::string sConfigFileName, bool bDoNativeDet)
|
||||
{
|
||||
m_ImageAnalyser.configurePlugins(sConfigFileName, bDoNativeDet);
|
||||
}
|
||||
|
||||
|
||||
/*!\fn PluginManager::getPluginsGenConf(std::map<std::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(std::map<std::string,pGenConf>& mapPluginGenConf)
|
||||
{
|
||||
for (std::map<std::string,bool>::iterator it = mapPluginReg.begin() ; it != mapPluginReg.end(); ++it)
|
||||
{
|
||||
pGenConf plugGenConf;
|
||||
m_ImageAnalyser.getRegPluginGenConf( it->first, plugGenConf );
|
||||
plugGenConf.Registered = it->second;
|
||||
mapPluginGenConf.insert( std::pair<std::string,pGenConf>(it->first, plugGenConf) );
|
||||
}
|
||||
return mapPluginGenConf.size();
|
||||
}
|
||||
|
||||
|
||||
/*!\fn PluginManager::getPluginZoneConf(std::string sPluginName, PluginZoneConf& mapPluginZoneConf)
|
||||
* \param sPluginName is the plugin name
|
||||
* \param mapPluginZoneConf is the map of zone settings for the plugin
|
||||
*/
|
||||
void PluginManager::getPluginZoneConf(std::string sPluginName, PluginZoneConf& mapPluginZoneConf)
|
||||
{
|
||||
m_ImageAnalyser.getRegPluginZoneConf( sPluginName, mapPluginZoneConf );
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#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"
|
||||
|
||||
|
||||
|
||||
//! 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.
|
||||
std::string join_paths(const std::string& p1, const std::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 std::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 std::string sPath, bool loadPlugins, unsigned int& nNumPlugLoaded);
|
||||
|
||||
//! Get general settings of plugins
|
||||
unsigned long getPluginsGenConf(std::map<std::string,pGenConf>& mapPluginGenConf);
|
||||
|
||||
//! Get zone settings of a plugin
|
||||
void getPluginZoneConf(std::string sPluginName, PluginZoneConf& mapPluginZoneConf);
|
||||
|
||||
//! Configure all loaded plugins using given configuration file.
|
||||
void configurePlugins(std::string sConfigFileName, bool bDoNativeDet);
|
||||
|
||||
//! Set plugin extension.
|
||||
void setPluginExt(std::string sPluginExt) { m_sPluginExt = sPluginExt; }
|
||||
|
||||
//! Extension for zm plugins.
|
||||
static std::string m_sPluginExt;
|
||||
|
||||
private:
|
||||
|
||||
//! All plugins currently loaded.
|
||||
PluginMap m_LoadedPlugins;
|
||||
|
||||
//! The image analyser.
|
||||
ImageAnalyser m_ImageAnalyser;
|
||||
|
||||
//! Plugin list
|
||||
std::map<std::string,bool> mapPluginReg;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //ZM_PLUGIN_MANAGER_H
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef ZM_POLY_H
|
||||
#define ZM_POLY_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_coord.h"
|
||||
#include "zm_box.h"
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
#ifndef ZM_REGEXP_H
|
||||
#define ZM_REGEXP_H
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef ZM_RGB_H
|
||||
#define ZM_RGB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint32_t Rgb; // RGB colour type
|
||||
|
||||
#define WHITE 0xff
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#ifndef ZM_RTP_H
|
||||
#define ZM_RTP_H
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
#define RTP_VERSION 2
|
||||
|
||||
#endif // ZM_RTP_H
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef ZM_RTSP_H
|
||||
#define ZM_RTSP_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_ffmpeg.h"
|
||||
#include "zm_comms.h"
|
||||
#include "zm_thread.h"
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#ifndef ZM_SDP_H
|
||||
#define ZM_SDP_H
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
#include "zm_utils.h"
|
||||
#include "zm_exception.h"
|
||||
#include "zm_ffmpeg.h"
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
#include <ucontext.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "zm.h"
|
||||
|
||||
typedef RETSIGTYPE (SigHandler)( int );
|
||||
|
||||
extern bool zm_reload;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_mpeg.h"
|
||||
|
||||
class Monitor;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef ZM_THREAD_H
|
||||
#define ZM_THREAD_H
|
||||
|
||||
#include "zm_config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -20,7 +20,12 @@
|
|||
#ifndef ZM_TIME_H
|
||||
#define ZM_TIME_H
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_config.h"
|
||||
#include "zm_logger.h"
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
||||
#ifndef ZM_USER_H
|
||||
|
|
|
@ -17,13 +17,17 @@
|
|||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
//
|
||||
|
||||
//#include "zm_logger.h"
|
||||
#include "zm_logger.h"
|
||||
#include "zm.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
|
||||
|
@ -345,3 +349,63 @@ void timespec_diff(struct timespec *start, struct timespec *end, struct timespec
|
|||
}
|
||||
}
|
||||
|
||||
int remove_dir(const char *path, bool force, bool verbose)
|
||||
{
|
||||
DIR *d = opendir(path);
|
||||
size_t path_len = strlen(path);
|
||||
int r = -1;
|
||||
|
||||
if (d)
|
||||
{
|
||||
struct dirent *p;
|
||||
r = 0;
|
||||
|
||||
while (!r && (p=readdir(d)))
|
||||
{
|
||||
int r2 = -1;
|
||||
char *buf;
|
||||
size_t len;
|
||||
|
||||
if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
if (verbose)
|
||||
Error("Can't remove directory '%s/%s': (not empty)", path, p->d_name);
|
||||
return r2;
|
||||
}
|
||||
|
||||
len = path_len + strlen(p->d_name) + 2;
|
||||
buf = (char*)malloc(len);
|
||||
|
||||
if (buf)
|
||||
{
|
||||
struct stat statbuf;
|
||||
snprintf(buf, len, "%s/%s", path, p->d_name);
|
||||
if (!stat(buf, &statbuf))
|
||||
{
|
||||
if (S_ISDIR(statbuf.st_mode))
|
||||
{
|
||||
if (((r2 = remove_dir(buf, force)) < 0) && verbose)
|
||||
Error("Can't remove directory '%s': %s", buf, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((r2 = unlink(buf)) < 0) && verbose)
|
||||
Error("Can't remove file '%s': %s", buf, strerror(errno));
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
r = r2;
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
if ((!r) && ((r = rmdir(path)) < 0) && verbose)
|
||||
Error("Can't remove directory '%s': %s", path, strerror(errno));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,4 +60,6 @@ void timespec_diff(struct timespec *start, struct timespec *end, struct timespec
|
|||
|
||||
extern unsigned int sseversion;
|
||||
|
||||
int remove_dir(const char *path, bool force = false, bool verbose = false);
|
||||
|
||||
#endif // ZM_UTILS_H
|
||||
|
|
134
src/zm_zone.cpp
134
src/zm_zone.cpp
|
@ -60,10 +60,19 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
|
|||
max_blob_size = 0;
|
||||
image = 0;
|
||||
score = 0;
|
||||
post_proc_enabled = false;
|
||||
post_proc_in_progress = false;
|
||||
include_nat_det = true;
|
||||
reinit_nat_det = false;
|
||||
|
||||
overload_count = 0;
|
||||
extend_alarm_count = 0;
|
||||
|
||||
delta_image = Image( monitor->Width(), monitor->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE );
|
||||
ref_image = Image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder());
|
||||
bl_image = Image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder());
|
||||
bl_image.Fill( RGB_BLACK );
|
||||
|
||||
pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE);
|
||||
pg_image->Clear();
|
||||
pg_image->Fill( 0xff, polygon );
|
||||
|
@ -91,14 +100,10 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( config.record_diag_images )
|
||||
if ( config.record_diag_images && (id > 0))
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
|
||||
}
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
|
||||
pg_image->WriteJpeg( diag_path );
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +147,30 @@ void Zone::SetScore(unsigned int nScore)
|
|||
score = nScore;
|
||||
}
|
||||
|
||||
void Zone::AssignRefImage( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size )
|
||||
{
|
||||
ref_image.Assign( p_width, p_height, p_colours, p_subpixelorder, new_buffer, buffer_size);
|
||||
}
|
||||
|
||||
void Zone::SetRefImage(const Image &srcImage)
|
||||
{
|
||||
ref_image = srcImage;
|
||||
}
|
||||
|
||||
void Zone::BlendRefImage( const Image &srcImage, int transparency )
|
||||
{
|
||||
ref_image.Blend( srcImage, transparency );
|
||||
}
|
||||
|
||||
void Zone::SetDeltaImage( const Image &srcImage )
|
||||
{
|
||||
ref_image.Delta( srcImage, &delta_image );
|
||||
}
|
||||
|
||||
void Zone::FillDeltaImage( Rgb colour )
|
||||
{
|
||||
delta_image.Fill( colour, polygon);
|
||||
}
|
||||
|
||||
void Zone::SetAlarmImage(const Image* srcImage)
|
||||
{
|
||||
|
@ -149,6 +178,16 @@ void Zone::SetAlarmImage(const Image* srcImage)
|
|||
image = new Image(*srcImage);
|
||||
}
|
||||
|
||||
bool Zone::WriteRefImage( const char *filename, int quality_override ) const
|
||||
{
|
||||
return ref_image.WriteJpeg( filename, quality_override );
|
||||
}
|
||||
|
||||
bool Zone::WriteDeltaImage( const char *filename, int quality_override ) const
|
||||
{
|
||||
return delta_image.WriteJpeg( filename, quality_override );
|
||||
}
|
||||
|
||||
int Zone::GetOverloadCount()
|
||||
{
|
||||
return overload_count;
|
||||
|
@ -194,9 +233,33 @@ bool Zone::CheckExtendAlarmCount()
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void Zone::SetConfig( zConf zone_conf )
|
||||
{
|
||||
post_proc_enabled = zone_conf.RequireNatDet;
|
||||
include_nat_det = zone_conf.IncludeNatDet;
|
||||
reinit_nat_det = zone_conf.ReInitNatDet;
|
||||
|
||||
if ( post_proc_enabled ) {
|
||||
std::string sMessage;
|
||||
if ( include_nat_det ) {
|
||||
sMessage = "(native detection included";
|
||||
}
|
||||
if ( reinit_nat_det ) {
|
||||
if (sMessage.empty()) {
|
||||
sMessage = "(native detection will be reinitialized";
|
||||
} else {
|
||||
sMessage += ", reinitialization is required";
|
||||
}
|
||||
}
|
||||
if (!sMessage.empty()) {
|
||||
sMessage += ")";
|
||||
}
|
||||
Info("Post processing enabled for zone '%s' %s", label, sMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Zone::CheckAlarms( const Image *delta_image )
|
||||
bool Zone::CheckAlarms( const Image *comp_image )
|
||||
{
|
||||
ResetStats();
|
||||
|
||||
|
@ -205,12 +268,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
|
||||
Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
|
||||
overload_count--;
|
||||
post_proc_in_progress = false;
|
||||
return( false );
|
||||
}
|
||||
|
||||
if ( reinit_nat_det )
|
||||
{
|
||||
Debug( 4, "Update reference image of zone %s", label );
|
||||
ref_image = *comp_image;
|
||||
}
|
||||
|
||||
delete image;
|
||||
// Get the difference image
|
||||
Image *diff_image = image = new Image( *delta_image );
|
||||
Image *diff_image = image = new Image( delta_image );
|
||||
int diff_width = diff_image->Width();
|
||||
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
|
||||
uint8_t* pdiff;
|
||||
|
@ -245,10 +315,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if ( config.record_diag_images )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
|
||||
}
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
|
@ -259,14 +326,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if( alarm_pixels ) {
|
||||
if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
} else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
} else {
|
||||
/* No alarmed pixels */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
@ -342,10 +412,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if ( config.record_diag_images )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
|
||||
}
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
|
@ -354,14 +421,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if( alarm_filter_pixels ) {
|
||||
if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
} else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
} else {
|
||||
/* No filtered pixels */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
@ -583,15 +653,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if ( config.record_diag_images )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
|
||||
}
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
if ( !alarm_blobs )
|
||||
{
|
||||
post_proc_in_progress = false;
|
||||
return( false );
|
||||
}
|
||||
|
||||
|
@ -642,10 +710,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if ( config.record_diag_images )
|
||||
{
|
||||
static char diag_path[PATH_MAX] = "";
|
||||
if ( !diag_path[0] )
|
||||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
|
||||
}
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
|
||||
diff_image->WriteJpeg( diag_path );
|
||||
}
|
||||
Debug( 5, "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs );
|
||||
|
@ -653,14 +718,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
if( alarm_blobs ) {
|
||||
if( min_blobs && (alarm_blobs < min_blobs) ) {
|
||||
/* Not enough pixels alarmed */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
} else if(max_blobs && (alarm_blobs > max_blobs) ) {
|
||||
/* Too many pixels alarmed */
|
||||
overload_count = overload_frames;
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
} else {
|
||||
/* No blobs */
|
||||
post_proc_in_progress = false;
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
@ -797,13 +865,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( monitor->Colours() == ZM_COLOUR_GRAY8 ) {
|
||||
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() );
|
||||
} else {
|
||||
image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() );
|
||||
if ( post_proc_enabled ) {
|
||||
post_proc_in_progress = true;
|
||||
}
|
||||
if ( include_nat_det ) {
|
||||
if( monitor->Colours() == ZM_COLOUR_GRAY8 ) {
|
||||
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() );
|
||||
} else {
|
||||
image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() );
|
||||
}
|
||||
} else {
|
||||
score = 0;
|
||||
image = new Image( bl_image );
|
||||
}
|
||||
|
||||
// Only need to delete this when 'image' becomes detached and points somewhere else
|
||||
delete diff_image;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,19 @@
|
|||
|
||||
class Monitor;
|
||||
|
||||
//! A structure to store the post processing configuration for the zone
|
||||
struct zConf
|
||||
{
|
||||
bool RequireNatDet;
|
||||
bool IncludeNatDet;
|
||||
bool ReInitNatDet;
|
||||
zConf():
|
||||
RequireNatDet(false),
|
||||
IncludeNatDet(false),
|
||||
ReInitNatDet(false)
|
||||
{}
|
||||
};
|
||||
|
||||
//
|
||||
// This describes a 'zone', or an area of an image that has certain
|
||||
// detection characteristics.
|
||||
|
@ -90,9 +103,16 @@ protected:
|
|||
Image *pg_image;
|
||||
Range *ranges;
|
||||
Image *image;
|
||||
Image delta_image;
|
||||
Image ref_image;
|
||||
Image bl_image;
|
||||
|
||||
int overload_count;
|
||||
int extend_alarm_count;
|
||||
bool post_proc_enabled;
|
||||
bool include_nat_det;
|
||||
bool reinit_nat_det;
|
||||
bool post_proc_in_progress;
|
||||
|
||||
protected:
|
||||
void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames, int p_extend_alarm_frames );
|
||||
|
@ -135,7 +155,13 @@ public:
|
|||
inline void ClearAlarm() { alarmed = false; }
|
||||
inline Coord GetAlarmCentre() const { return( alarm_centre ); }
|
||||
inline unsigned int Score() const { return( score ); }
|
||||
|
||||
void SetConfig( zConf zone_conf );
|
||||
inline bool IsPostProcEnabled() const { return post_proc_enabled; }
|
||||
inline bool IsNatDetIncluded() const { return include_nat_det; }
|
||||
inline bool IsNatDetReInitialized() const { return reinit_nat_det; }
|
||||
inline void StartPostProcessing() { post_proc_in_progress = true; }
|
||||
inline void StopPostProcessing() { post_proc_in_progress = false; }
|
||||
inline bool IsPostProcInProgress() { return post_proc_in_progress; }
|
||||
inline void ResetStats()
|
||||
{
|
||||
alarmed = false;
|
||||
|
@ -149,7 +175,7 @@ public:
|
|||
score = 0;
|
||||
}
|
||||
void RecordStats( const Event *event );
|
||||
bool CheckAlarms( const Image *delta_image );
|
||||
bool CheckAlarms( const Image *comp_image );
|
||||
bool DumpSettings( char *output, bool verbose );
|
||||
|
||||
static bool ParsePolygonString( const char *polygon_string, Polygon &polygon );
|
||||
|
@ -167,6 +193,13 @@ public:
|
|||
int GetExtendAlarmFrames();
|
||||
void SetScore(unsigned int nScore);
|
||||
void SetAlarmImage(const Image* srcImage);
|
||||
void AssignRefImage( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size );
|
||||
void SetRefImage( const Image &srcImage);
|
||||
void BlendRefImage( const Image &srcImage, int transparency=12 );
|
||||
void SetDeltaImage( const Image &srcImage );
|
||||
void FillDeltaImage( Rgb colour );
|
||||
bool WriteRefImage( const char *filename, int quality_override=0 ) const;
|
||||
bool WriteDeltaImage( const char *filename, int quality_override=0 ) const;
|
||||
|
||||
inline const Image *getPgImage() const { return( pg_image ); }
|
||||
inline const Range *getRanges() const { return( ranges ); }
|
||||
|
|
|
@ -57,6 +57,8 @@ behind.
|
|||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
void Usage()
|
||||
{
|
||||
fprintf( stderr, "zma -m <monitor_id>\n" );
|
||||
|
|
|
@ -73,6 +73,8 @@ possible, this should run at more or less constant speed.
|
|||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
void Usage()
|
||||
{
|
||||
fprintf( stderr, "zmc -d <device_path> or -r <proto> -H <host> -P <port> -p <path> or -f <file_path> or -m <monitor_id>\n" );
|
||||
|
|
|
@ -71,6 +71,8 @@ them itself.
|
|||
|
||||
#include "zmf.h"
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
int OpenSocket( int monitor_id )
|
||||
{
|
||||
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
||||
|
@ -198,6 +200,7 @@ int main( int argc, char *argv[] )
|
|||
char log_id_string[16];
|
||||
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
|
||||
|
||||
StaticConfig staticConfig;
|
||||
zmLoadConfig();
|
||||
|
||||
logInit( "zmf" );
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
bool ValidateAccess( User *user, int mon_id )
|
||||
{
|
||||
bool allowed = true;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue