diff --git a/config/openalpr.conf.in b/config/openalpr.conf.defaults similarity index 100% rename from config/openalpr.conf.in rename to config/openalpr.conf.defaults diff --git a/config/openalpr.conf.user b/config/openalpr.conf.user new file mode 100644 index 0000000..3263d90 --- /dev/null +++ b/config/openalpr.conf.user @@ -0,0 +1,2 @@ +; This configuration file overrides the default values specified +; in ${CMAKE_INSTALL_PREFIX}/share/openalpr/config/openalpr.defaults.conf diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a48798..4d11a61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,8 @@ add_definitions( -DOPENALPR_PATCH_VERSION=${OPENALPR_PATCH_VERSION}) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/") +add_definitions( -DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}") + # TODO: switch to http://www.cmake.org/cmake/help/v2.8.5/cmake.html#module:GNUInstallDirs ? IF (NOT CMAKE_INSTALL_SYSCONFDIR) SET(CMAKE_INSTALL_SYSCONFDIR "/etc") @@ -203,9 +205,12 @@ ENDIF() install (DIRECTORY ${CMAKE_SOURCE_DIR}/../runtime_data DESTINATION ${CMAKE_INSTALL_PREFIX}/share/openalpr) # set runtime_data to reflect the current CMAKE_INSTALL_PREFIX -CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/../config/openalpr.conf.in ${CMAKE_CURRENT_BINARY_DIR}/config/openalpr.conf) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/../config/openalpr.conf.user ${CMAKE_CURRENT_BINARY_DIR}/config/openalpr.conf) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/config/openalpr.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/openalpr/ COMPONENT config) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/../config/openalpr.conf.defaults ${CMAKE_CURRENT_BINARY_DIR}/share/openalpr/config/openalpr.defaults.conf) +install (FILES ${CMAKE_CURRENT_BINARY_DIR}/share/openalpr/config/openalpr.defaults.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/share/openalpr/config COMPONENT config) + IF (WITH_DAEMON) install (TARGETS alprd DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install (FILES ${CMAKE_SOURCE_DIR}/../config/alprd.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/openalpr COMPONENT config) diff --git a/src/openalpr/CMakeLists.txt b/src/openalpr/CMakeLists.txt index a8a2ac0..0177eb5 100644 --- a/src/openalpr/CMakeLists.txt +++ b/src/openalpr/CMakeLists.txt @@ -5,6 +5,7 @@ set(lpr_source_files alpr.cpp alpr_impl.cpp config.cpp + config_helper.cpp detection/detector.cpp detection/detectorcpu.cpp detection/detectorcuda.cpp diff --git a/src/openalpr/config.cpp b/src/openalpr/config.cpp index ca274ee..14d368e 100644 --- a/src/openalpr/config.cpp +++ b/src/openalpr/config.cpp @@ -22,19 +22,14 @@ #include "support/platform.h" #include "simpleini/simpleini.h" #include "utility.h" +#include "config_helper.h" using namespace std; namespace alpr { - - int getInt(CSimpleIniA* ini, std::string section, std::string key, int defaultValue); - float getFloat(CSimpleIniA* ini, std::string section, std::string key, float defaultValue); - std::string getString(CSimpleIniA* ini, std::string section, std::string key, std::string defaultValue); - bool getBoolean(CSimpleIniA* ini, std::string section, std::string key, bool defaultValue); - std::vector getAllFloats(CSimpleIniA* ini, string section, string key); - + Config::Config(const std::string country, const std::string config_file, const std::string runtime_dir) { @@ -85,8 +80,8 @@ namespace alpr std::cerr << "--(!) e.g., /etc/openalpr/openalpr.conf" << endl; return; } - - + + loadCommonValues(config_file_path); if (runtime_dir.compare("") != 0) @@ -153,13 +148,26 @@ namespace alpr void Config::loadCommonValues(string configFile) { + CSimpleIniA* ini = NULL; CSimpleIniA iniObj; - iniObj.LoadFile(configFile.c_str()); - CSimpleIniA* ini = &iniObj; - - runtimeBaseDir = getString(ini, "", "runtime_dir", "/usr/share/openalpr/runtime_data"); + if (fileExists(configFile.c_str())) + { + iniObj.LoadFile(configFile.c_str()); + ini = &iniObj; + } - std::string detectorString = getString(ini, "", "detector", "lbpcpu"); + + CSimpleIniA* defaultIni = NULL; + CSimpleIniA defaultIniObj; + if (fileExists(CONFIG_FILE_TEMPLATE_LOCATION)) + { + defaultIniObj.LoadFile(CONFIG_FILE_TEMPLATE_LOCATION); + defaultIni = &defaultIniObj; + } + + runtimeBaseDir = getString(ini,defaultIni, "", "runtime_dir", DEFAULT_RUNTIME_DATA_DIR); + + std::string detectorString = getString(ini, defaultIni, "", "detector", "lbpcpu"); std::transform(detectorString.begin(), detectorString.end(), detectorString.begin(), ::tolower); if (detectorString.compare("lbpcpu") == 0) @@ -176,50 +184,50 @@ namespace alpr detector = DETECTOR_LBP_CPU; } - detection_iteration_increase = getFloat(ini, "", "detection_iteration_increase", 1.1); - detectionStrictness = getInt(ini, "", "detection_strictness", 3); - maxPlateWidthPercent = getFloat(ini, "", "max_plate_width_percent", 100); - maxPlateHeightPercent = getFloat(ini, "", "max_plate_height_percent", 100); - maxDetectionInputWidth = getInt(ini, "", "max_detection_input_width", 1280); - maxDetectionInputHeight = getInt(ini, "", "max_detection_input_height", 768); + detection_iteration_increase = getFloat(ini, defaultIni, "", "detection_iteration_increase", 1.1); + detectionStrictness = getInt(ini, defaultIni, "", "detection_strictness", 3); + maxPlateWidthPercent = getFloat(ini, defaultIni, "", "max_plate_width_percent", 100); + maxPlateHeightPercent = getFloat(ini, defaultIni, "", "max_plate_height_percent", 100); + maxDetectionInputWidth = getInt(ini, defaultIni, "", "max_detection_input_width", 1280); + maxDetectionInputHeight = getInt(ini, defaultIni, "", "max_detection_input_height", 768); - contrastDetectionThreshold = getFloat(ini, "", "contrast_detection_threshold", 0.3); + contrastDetectionThreshold = getFloat(ini, defaultIni, "", "contrast_detection_threshold", 0.3); - mustMatchPattern = getBoolean(ini, "", "must_match_pattern", false); + mustMatchPattern = getBoolean(ini, defaultIni, "", "must_match_pattern", false); - skipDetection = getBoolean(ini, "", "skip_detection", false); + skipDetection = getBoolean(ini, defaultIni, "", "skip_detection", false); - detection_mask_image = getString(ini, "", "detection_mask_image", ""); + detection_mask_image = getString(ini, defaultIni, "", "detection_mask_image", ""); - analysis_count = getInt(ini, "", "analysis_count", 1); + analysis_count = getInt(ini, defaultIni, "", "analysis_count", 1); - prewarp = getString(ini, "", "prewarp", ""); + prewarp = getString(ini, defaultIni, "", "prewarp", ""); - maxPlateAngleDegrees = getInt(ini, "", "max_plate_angle_degrees", 15); + maxPlateAngleDegrees = getInt(ini, defaultIni, "", "max_plate_angle_degrees", 15); - ocrImagePercent = getFloat(ini, "", "ocr_img_size_percent", 100); - stateIdImagePercent = getFloat(ini, "", "state_id_img_size_percent", 100); + ocrImagePercent = getFloat(ini, defaultIni, "", "ocr_img_size_percent", 100); + stateIdImagePercent = getFloat(ini, defaultIni, "", "state_id_img_size_percent", 100); - ocrMinFontSize = getInt(ini, "", "ocr_min_font_point", 100); + ocrMinFontSize = getInt(ini, defaultIni, "", "ocr_min_font_point", 100); - postProcessMinConfidence = getFloat(ini, "", "postprocess_min_confidence", 100); - postProcessConfidenceSkipLevel = getFloat(ini, "", "postprocess_confidence_skip_level", 100); + postProcessMinConfidence = getFloat(ini, defaultIni, "", "postprocess_min_confidence", 100); + postProcessConfidenceSkipLevel = getFloat(ini, defaultIni, "", "postprocess_confidence_skip_level", 100); - debugGeneral = getBoolean(ini, "", "debug_general", false); - debugTiming = getBoolean(ini, "", "debug_timing", false); - debugPrewarp = getBoolean(ini, "", "debug_prewarp", false); - debugDetector = getBoolean(ini, "", "debug_detector", false); - debugStateId = getBoolean(ini, "", "debug_state_id", false); - debugPlateLines = getBoolean(ini, "", "debug_plate_lines", false); - debugPlateCorners = getBoolean(ini, "", "debug_plate_corners", false); - debugCharSegmenter = getBoolean(ini, "", "debug_char_segment", false); - debugCharAnalysis = getBoolean(ini, "", "debug_char_analysis", false); - debugColorFiler = getBoolean(ini, "", "debug_color_filter", false); - debugOcr = getBoolean(ini, "", "debug_ocr", false); - debugPostProcess = getBoolean(ini, "", "debug_postprocess", false); - debugShowImages = getBoolean(ini, "", "debug_show_images", false); - debugPauseOnFrame = getBoolean(ini, "", "debug_pause_on_frame", false); + debugGeneral = getBoolean(ini, defaultIni, "", "debug_general", false); + debugTiming = getBoolean(ini, defaultIni, "", "debug_timing", false); + debugPrewarp = getBoolean(ini, defaultIni, "", "debug_prewarp", false); + debugDetector = getBoolean(ini, defaultIni, "", "debug_detector", false); + debugStateId = getBoolean(ini, defaultIni, "", "debug_state_id", false); + debugPlateLines = getBoolean(ini, defaultIni, "", "debug_plate_lines", false); + debugPlateCorners = getBoolean(ini, defaultIni, "", "debug_plate_corners", false); + debugCharSegmenter = getBoolean(ini, defaultIni, "", "debug_char_segment", false); + debugCharAnalysis = getBoolean(ini, defaultIni, "", "debug_char_analysis", false); + debugColorFiler = getBoolean(ini, defaultIni, "", "debug_color_filter", false); + debugOcr = getBoolean(ini, defaultIni, "", "debug_ocr", false); + debugPostProcess = getBoolean(ini, defaultIni, "", "debug_postprocess", false); + debugShowImages = getBoolean(ini, defaultIni, "", "debug_show_images", false); + debugPauseOnFrame = getBoolean(ini, defaultIni, "", "debug_pause_on_frame", false); } @@ -396,69 +404,6 @@ namespace alpr return true; } - float getFloat(CSimpleIniA* ini, string section, string key, float defaultValue) - { - const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); - if (pszValue == NULL) - { - return defaultValue; - } - - float val = atof(pszValue); - return val; - } - - std::vector getAllFloats(CSimpleIniA* ini, string section, string key) - { - CSimpleIniA::TNamesDepend values; - - ini->GetAllValues(section.c_str(), key.c_str(), values); - - // sort the values into the original load order - values.sort(CSimpleIniA::Entry::LoadOrder()); - - std::vector response; - - // output all of the items - CSimpleIniA::TNamesDepend::const_iterator i; - for (i = values.begin(); i != values.end(); ++i) { - response.push_back(atof(i->pItem)); - } - - return response; - } - - int getInt(CSimpleIniA* ini, string section, string key, int defaultValue) - { - const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); - if (pszValue == NULL) - { - return defaultValue; - } - - int val = atoi(pszValue); - return val; - } - bool getBoolean(CSimpleIniA* ini, string section, string key, bool defaultValue) - { - const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); - if (pszValue == NULL) - { - return defaultValue; - } - - int val = atoi(pszValue); - return val != 0; - } - string getString(CSimpleIniA* ini, string section, string key, string defaultValue) - { - const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); - if (pszValue == NULL) - { - return defaultValue; - } - - string val = string(pszValue); - return val; - } } + + diff --git a/src/openalpr/config_helper.cpp b/src/openalpr/config_helper.cpp new file mode 100644 index 0000000..5310d75 --- /dev/null +++ b/src/openalpr/config_helper.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2015 OpenALPR Technology, Inc. + * Open source Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenALPR. + * + * OpenALPR is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#include "config_helper.h" + +#include + +using namespace std; + +namespace alpr +{ + + float getFloat(CSimpleIniA* ini, string section, string key, float defaultValue) + { + if (ini == NULL) + return defaultValue; + + const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); + if (pszValue == NULL) + { + return defaultValue; + } + + float val = atof(pszValue); + return val; + } + + std::vector getAllFloats(CSimpleIniA* ini, string section, string key) + { + CSimpleIniA::TNamesDepend values; + + ini->GetAllValues(section.c_str(), key.c_str(), values); + + // sort the values into the original load order + values.sort(CSimpleIniA::Entry::LoadOrder()); + + std::vector response; + + // output all of the items + CSimpleIniA::TNamesDepend::const_iterator i; + for (i = values.begin(); i != values.end(); ++i) { + response.push_back(atof(i->pItem)); + } + + return response; + } + + int getInt(CSimpleIniA* ini, string section, string key, int defaultValue) + { + if (ini == NULL) + return defaultValue; + + const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); + if (pszValue == NULL) + { + return defaultValue; + } + + int val = atoi(pszValue); + return val; + } + bool getBoolean(CSimpleIniA* ini, string section, string key, bool defaultValue) + { + if (ini == NULL) + return defaultValue; + + const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); + if (pszValue == NULL) + { + return defaultValue; + } + + int val = atoi(pszValue); + return val != 0; + } + string getString(CSimpleIniA* ini, string section, string key, string defaultValue) + { + if (ini == NULL) + return defaultValue; + + const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); + if (pszValue == NULL) + { + return defaultValue; + } + + string val = string(pszValue); + return val; + } + + bool hasValue(CSimpleIniA* ini, std::string section, std::string key) + { + const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/); + + return pszValue != NULL; + } + + int getInt(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, int defaultValue) + { + if (hasValue(ini, section, key)) + return getInt(ini, section, key, defaultValue); + + if (defaultIni != NULL && hasValue(defaultIni, section, key)) + return getInt(defaultIni, section, key, defaultValue); + + std::cerr << "Missing config value for " << key << std::endl; + + return defaultValue; + } + float getFloat(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, float defaultValue) + { + if (hasValue(ini, section, key)) + return getFloat(ini, section, key, defaultValue); + + if (defaultIni != NULL && hasValue(defaultIni, section, key)) + return getFloat(defaultIni, section, key, defaultValue); + + std::cerr << "Missing config value for " << key << std::endl; + + return defaultValue; + } + std::string getString(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, std::string defaultValue) + { + if (hasValue(ini, section, key)) + return getString(ini, section, key, defaultValue); + + if (defaultIni != NULL && hasValue(defaultIni, section, key)) + return getString(defaultIni, section, key, defaultValue); + + std::cerr << "Missing config value for " << key << std::endl; + return defaultValue; + } + bool getBoolean(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, bool defaultValue) + { + if (hasValue(ini, section, key)) + return getBoolean(ini, section, key, defaultValue); + + if (defaultIni != NULL && hasValue(defaultIni, section, key)) + return getBoolean(defaultIni, section, key, defaultValue); + + std::cerr << "Missing config value for " << key << std::endl; + return defaultValue; + } +} \ No newline at end of file diff --git a/src/openalpr/config_helper.h b/src/openalpr/config_helper.h new file mode 100644 index 0000000..c8d9366 --- /dev/null +++ b/src/openalpr/config_helper.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 OpenALPR Technology, Inc. + * Open source Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenALPR. + * + * OpenALPR is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#ifndef OPENALPR_CONFIG_HELPER_H +#define OPENALPR_CONFIG_HELPER_H + +#include "simpleini/simpleini.h" +#include +#include + +namespace alpr +{ + + bool hasValue(CSimpleIniA* ini, std::string section, std::string key); + + int getInt(CSimpleIniA* ini, std::string section, std::string key, int defaultValue); + float getFloat(CSimpleIniA* ini, std::string section, std::string key, float defaultValue); + std::string getString(CSimpleIniA* ini, std::string section, std::string key, std::string defaultValue); + bool getBoolean(CSimpleIniA* ini, std::string section, std::string key, bool defaultValue); + std::vector getAllFloats(CSimpleIniA* ini, std::string section, std::string key); + + // Checks the ini objects in the order they are placed in the vector + // e.g., second ini object overrides the first if they both have the value + int getInt(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, int defaultValue); + float getFloat(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, float defaultValue); + std::string getString(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, std::string defaultValue); + bool getBoolean(CSimpleIniA* ini, CSimpleIniA* defaultIni, std::string section, std::string key, bool defaultValue); + +} + +#endif /* CONFIG_HELPER_H */ + diff --git a/src/openalpr/constants.h b/src/openalpr/constants.h index e216761..8830d77 100644 --- a/src/openalpr/constants.h +++ b/src/openalpr/constants.h @@ -27,6 +27,11 @@ #define CASCADE_DIR "/region/" #define POSTPROCESS_DIR "/postprocess" +#define DEFAULT_SHARE_DIR INSTALL_PREFIX "/share/openalpr" + +#define DEFAULT_RUNTIME_DATA_DIR DEFAULT_SHARE_DIR "/runtime_data" +#define CONFIG_FILE_TEMPLATE_LOCATION DEFAULT_SHARE_DIR "/config/openalpr.defaults.conf" + #ifndef DEFAULT_CONFIG_FILE #define DEFAULT_CONFIG_FILE "/etc/openalpr/openalpr.conf" #endif