core: add utils::findDataFile() / samples::findFile()

pull/12354/head
Alexander Alekhin 8 years ago
parent e5afa62c3d
commit 2fa9bd221d
  1. 44
      modules/core/CMakeLists.txt
  2. 1
      modules/core/include/opencv2/core.hpp
  3. 76
      modules/core/include/opencv2/core/private.hpp
  4. 67
      modules/core/include/opencv2/core/utility.hpp
  5. 7
      modules/core/include/opencv2/core/utils/filesystem.hpp
  6. 398
      modules/core/src/utils/datafile.cpp
  7. 25
      modules/core/src/utils/filesystem.cpp
  8. 67
      modules/core/src/utils/samples.cpp
  9. 18
      modules/core/test/test_utils.cpp
  10. 17
      modules/python/test/test_misc.py

@ -82,3 +82,47 @@ ocv_add_accuracy_tests()
ocv_add_perf_tests()
ocv_install_3rdparty_licenses(SoftFloat "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/SoftFloat/COPYING.txt")
# generate data (samples data) config file
set(OPENCV_DATA_CONFIG_FILE "${CMAKE_BINARY_DIR}/opencv_data_config.hpp")
set(OPENCV_DATA_CONFIG_STR "")
if(CMAKE_INSTALL_PREFIX)
set(OPENCV_DATA_CONFIG_STR "${OPENCV_DATA_CONFIG_STR}
#define OPENCV_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\"
")
endif()
if(OPENCV_OTHER_INSTALL_PATH)
set(OPENCV_DATA_CONFIG_STR "${OPENCV_DATA_CONFIG_STR}
#define OPENCV_DATA_INSTALL_PATH \"${OPENCV_OTHER_INSTALL_PATH}\"
")
endif()
set(OPENCV_DATA_CONFIG_STR "${OPENCV_DATA_CONFIG_STR}
#define OPENCV_BUILD_DIR \"${CMAKE_BINARY_DIR}\"
")
file(RELATIVE_PATH SOURCE_DIR_RELATIVE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR})
set(OPENCV_DATA_CONFIG_STR "${OPENCV_DATA_CONFIG_STR}
#define OPENCV_DATA_BUILD_DIR_SEARCH_PATHS \\
\"${SOURCE_DIR_RELATIVE}/\"
")
if(WIN32)
file(RELATIVE_PATH INSTALL_DATA_DIR_RELATIVE "${CMAKE_INSTALL_PREFIX}/${OPENCV_BIN_INSTALL_PATH}" "${CMAKE_INSTALL_PREFIX}/${OPENCV_OTHER_INSTALL_PATH}")
else()
file(RELATIVE_PATH INSTALL_DATA_DIR_RELATIVE "${CMAKE_INSTALL_PREFIX}/${OPENCV_LIB_INSTALL_PATH}" "${CMAKE_INSTALL_PREFIX}/${OPENCV_OTHER_INSTALL_PATH}")
endif()
list(APPEND OPENCV_INSTALL_DATA_DIR_RELATIVE "${INSTALL_DATA_DIR_RELATIVE}")
string(REPLACE ";" "\",\\\n \"" OPENCV_INSTALL_DATA_DIR_RELATIVE_STR "\"${OPENCV_INSTALL_DATA_DIR_RELATIVE}\"")
set(OPENCV_DATA_CONFIG_STR "${OPENCV_DATA_CONFIG_STR}
#define OPENCV_INSTALL_DATA_DIR_RELATIVE ${OPENCV_INSTALL_DATA_DIR_RELATIVE_STR}
")
if(EXISTS "${OPENCV_DATA_CONFIG_FILE}")
file(READ "${OPENCV_DATA_CONFIG_FILE}" __content)
endif()
if(NOT OPENCV_DATA_CONFIG_STR STREQUAL "${__content}")
file(WRITE "${OPENCV_DATA_CONFIG_FILE}" "${OPENCV_DATA_CONFIG_STR}")
endif()

@ -75,6 +75,7 @@
@defgroup core_utils_sse SSE utilities
@defgroup core_utils_neon NEON utilities
@defgroup core_utils_softfloat Softfloat support
@defgroup core_utils_samples Utility functions for OpenCV samples
@}
@defgroup core_opengl OpenGL interoperability
@defgroup core_ipp Intel IPP Asynchronous C/C++ Converters

@ -801,6 +801,82 @@ CV_EXPORTS InstrNode* getCurrentNode();
#define CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION_();
#endif
namespace cv {
namespace utils {
//! @addtogroup core_utils
//! @{
/** @brief Try to find requested data file
Search directories:
1. Directories passed via `addDataSearchPath()`
2. Check path specified by configuration parameter with "_HINT" suffix (name of environment variable).
3. Check path specified by configuration parameter (name of environment variable).
If parameter value is not empty and nothing is found then stop searching.
4. Detects build/install path based on:
a. current working directory (CWD)
b. and/or binary module location (opencv_core/opencv_world, doesn't work with static linkage)
5. Scan `<source>/{,data}` directories if build directory is detected or the current directory is in source tree.
6. Scan `<install>/share/OpenCV` directory if install directory is detected.
@param relative_path Relative path to data file
@param required Specify "file not found" handling.
If true, function prints information message and raises cv::Exception.
If false, function returns empty result
@param configuration_parameter specify configuration parameter name. Default NULL value means "OPENCV_DATA_PATH".
@return Returns path (absolute or relative to the current directory) or empty string if file is not found
@note Implementation is not thread-safe.
*/
CV_EXPORTS
cv::String findDataFile(const cv::String& relative_path, bool required = true,
const char* configuration_parameter = NULL);
/** @overload
@param relative_path Relative path to data file
@param configuration_parameter specify configuration parameter name. Default NULL value means "OPENCV_DATA_PATH".
@param search_paths override addDataSearchPath() settings.
@param subdir_paths override addDataSearchSubDirectory() settings.
@return Returns path (absolute or relative to the current directory) or empty string if file is not found
@note Implementation is not thread-safe.
*/
CV_EXPORTS
cv::String findDataFile(const cv::String& relative_path,
const char* configuration_parameter,
const std::vector<String>* search_paths,
const std::vector<String>* subdir_paths);
/** @brief Override default search data path by adding new search location
Use this only to override default behavior
Passed paths are used in LIFO order.
@param path Path to used samples data
@note Implementation is not thread-safe.
*/
CV_EXPORTS void addDataSearchPath(const cv::String& path);
/** @brief Append default search data sub directory
General usage is to add OpenCV modules name (`<opencv_contrib>/modules/<name>/data` -> `modules/<name>/data` + `<name>/data`).
Passed subdirectories are used in LIFO order.
@param subdir samples data sub directory
@note Implementation is not thread-safe.
*/
CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir);
//! @}
} // namespace utils
} // namespace cv
//! @endcond
#endif // OPENCV_CORE_PRIVATE_HPP

@ -1274,8 +1274,75 @@ enum FLAGS
CV_EXPORTS void setFlags(FLAGS modeFlags);
static inline void setFlags(int modeFlags) { setFlags((FLAGS)modeFlags); }
CV_EXPORTS FLAGS getFlags();
} // namespace instr
namespace samples {
//! @addtogroup core_utils_samples
// This section describes utility functions for OpenCV samples.
//
// @note Implementation of these utilities is not thread-safe.
//
//! @{
/** @brief Try to find requested data file
Search directories:
1. Directories passed via `addSamplesDataSearchPath()`
2. OPENCV_SAMPLES_DATA_PATH_HINT environment variable
3. OPENCV_SAMPLES_DATA_PATH environment variable
If parameter value is not empty and nothing is found then stop searching.
4. Detects build/install path based on:
a. current working directory (CWD)
b. and/or binary module location (opencv_core/opencv_world, doesn't work with static linkage)
5. Scan `<source>/{,data,samples/data}` directories if build directory is detected or the current directory is in source tree.
6. Scan `<install>/share/OpenCV` directory if install directory is detected.
@see cv::utils::findDataFile
@param relative_path Relative path to data file
@param required Specify "file not found" handling.
If true, function prints information message and raises cv::Exception.
If false, function returns empty result
@param silentMode Disables messages
@return Returns path (absolute or relative to the current directory) or empty string if file is not found
*/
CV_EXPORTS_W cv::String findFile(const cv::String& relative_path, bool required = true, bool silentMode = false);
CV_EXPORTS_W cv::String findFileOrKeep(const cv::String& relative_path, bool silentMode = false);
inline cv::String findFileOrKeep(const cv::String& relative_path, bool silentMode)
{
cv::String res = findFile(relative_path, false, silentMode);
if (res.empty())
return relative_path;
return res;
}
/** @brief Override search data path by adding new search location
Use this only to override default behavior
Passed paths are used in LIFO order.
@param path Path to used samples data
*/
CV_EXPORTS_W void addSamplesDataSearchPath(const cv::String& path);
/** @brief Append samples search data sub directory
General usage is to add OpenCV modules name (`<opencv_contrib>/modules/<name>/samples/data` -> `<name>/samples/data` + `modules/<name>/samples/data`).
Passed subdirectories are used in LIFO order.
@param subdir samples data sub directory
*/
CV_EXPORTS_W void addSamplesDataSearchSubDirectory(const cv::String& subdir);
//! @}
} // namespace samples
namespace utils {
CV_EXPORTS int getThreadID();

@ -16,6 +16,13 @@ CV_EXPORTS void remove_all(const cv::String& path);
CV_EXPORTS cv::String getcwd();
/** @brief Converts path p to a canonical absolute path
* Symlinks are processed if there is support for them on running platform.
*
* @param path input path. Target file/directory should exist.
*/
CV_EXPORTS cv::String canonical(const cv::String& path);
/** Join path components */
CV_EXPORTS cv::String join(const cv::String& base, const cv::String& path);

@ -0,0 +1,398 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "../precomp.hpp"
#include "opencv_data_config.hpp"
#include <vector>
#include <fstream>
#include <opencv2/core/utils/logger.defines.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#include "opencv2/core/utils/logger.hpp"
#include "opencv2/core/utils/filesystem.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef small
#undef min
#undef max
#undef abs
#elif defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC
#include <dlfcn.h>
#endif
#endif
namespace cv { namespace utils {
static cv::Ptr< std::vector<cv::String> > g_data_search_path;
static cv::Ptr< std::vector<cv::String> > g_data_search_subdir;
static std::vector<cv::String>& _getDataSearchPath()
{
if (g_data_search_path.empty())
g_data_search_path.reset(new std::vector<cv::String>());
return *(g_data_search_path.get());
}
static std::vector<cv::String>& _getDataSearchSubDirectory()
{
if (g_data_search_subdir.empty())
{
g_data_search_subdir.reset(new std::vector<cv::String>());
g_data_search_subdir->push_back("data");
g_data_search_subdir->push_back("");
}
return *(g_data_search_subdir.get());
}
CV_EXPORTS void addDataSearchPath(const cv::String& path)
{
if (utils::fs::isDirectory(path))
_getDataSearchPath().push_back(path);
}
CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir)
{
_getDataSearchSubDirectory().push_back(subdir);
}
static bool isPathSep(char c)
{
return c == '/' || c == '\\';
}
static bool isSubDirectory_(const cv::String& base_path, const cv::String& path)
{
size_t N = base_path.size();
if (N == 0)
return false;
if (isPathSep(base_path[N - 1]))
N--;
if (path.size() < N)
return false;
for (size_t i = 0; i < N; i++)
{
if (path[i] == base_path[i])
continue;
if (isPathSep(path[i]) && isPathSep(base_path[i]))
continue;
return false;
}
size_t M = path.size();
if (M > N)
{
if (!isPathSep(path[N]))
return false;
}
return true;
}
static bool isSubDirectory(const cv::String& base_path, const cv::String& path)
{
bool res = isSubDirectory_(base_path, path);
CV_LOG_VERBOSE(NULL, 0, "isSubDirectory(): base: " << base_path << " path: " << path << " => result: " << (res ? "TRUE" : "FALSE"));
return res;
}
static cv::String getModuleLocation(const void* addr)
{
CV_UNUSED(addr);
#ifdef _WIN32
HMODULE m = 0;
#if _WIN32_WINNT >= 0x0501
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCTSTR>(addr),
&m);
#endif
if (m)
{
char path[MAX_PATH];
const size_t path_size = sizeof(path)/sizeof(*path);
size_t sz = GetModuleFileNameA(m, path, path_size); // no unicode support
if (sz > 0 && sz < path_size)
{
path[sz] = '\0';
return cv::String(path);
}
}
#elif defined(__linux__)
std::ifstream fs("/proc/self/maps");
std::string line;
while (std::getline(fs, line, '\n'))
{
long long int addr_begin = 0, addr_end = 0;
if (2 == sscanf(line.c_str(), "%llx-%llx", &addr_begin, &addr_end))
{
if ((intptr_t)addr >= (intptr_t)addr_begin && (intptr_t)addr < (intptr_t)addr_end)
{
size_t pos = line.rfind(" "); // 2 spaces
if (pos == cv::String::npos)
pos = line.rfind(' '); // 1 spaces
else
pos++;
if (pos == cv::String::npos)
{
CV_LOG_DEBUG(NULL, "Can't parse module path: '" << line << '\'');
}
return line.substr(pos + 1);
}
}
}
#elif defined(__APPLE__)
# if TARGET_OS_MAC
Dl_info info;
if (0 != dladdr(addr, &info))
{
return cv::String(info.dli_fname);
}
# endif
#else
// not supported, skip
#endif
return cv::String();
}
cv::String findDataFile(const cv::String& relative_path,
const char* configuration_parameter,
const std::vector<String>* search_paths,
const std::vector<String>* subdir_paths)
{
configuration_parameter = configuration_parameter ? configuration_parameter : "OPENCV_DATA_PATH";
CV_LOG_DEBUG(NULL, cv::format("utils::findDataFile('%s', %s)", relative_path.c_str(), configuration_parameter));
#define TRY_FILE_WITH_PREFIX(prefix) \
{ \
cv::String path = utils::fs::join(prefix, relative_path); \
CV_LOG_DEBUG(NULL, cv::format("... Line %d: trying open '%s'", __LINE__, path.c_str())); \
FILE* f = fopen(path.c_str(), "rb"); \
if(f) { \
fclose(f); \
return path; \
} \
}
// Step 0: check current directory or absolute path at first
TRY_FILE_WITH_PREFIX("");
// Step 1
const std::vector<cv::String>& search_path = search_paths ? *search_paths : _getDataSearchPath();
for(size_t i = search_path.size(); i > 0; i--)
{
const cv::String& prefix = search_path[i - 1];
TRY_FILE_WITH_PREFIX(prefix);
}
const std::vector<cv::String>& search_subdir = subdir_paths ? *subdir_paths : _getDataSearchSubDirectory();
// Step 2
const cv::String configuration_parameter_s(configuration_parameter ? configuration_parameter : "");
const cv::utils::Paths& search_hint = configuration_parameter_s.empty() ? cv::utils::Paths()
: getConfigurationParameterPaths((configuration_parameter_s + "_HINT").c_str());
for (size_t k = 0; k < search_hint.size(); k++)
{
cv::String datapath = search_hint[k];
if (datapath.empty())
continue;
if (utils::fs::isDirectory(datapath))
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): trying " << configuration_parameter << "_HINT=" << datapath);
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
else
{
CV_LOG_WARNING(NULL, configuration_parameter << "_HINT is specified but it is not a directory: " << datapath);
}
}
// Step 3
const cv::utils::Paths& override_paths = configuration_parameter_s.empty() ? cv::utils::Paths()
: getConfigurationParameterPaths(configuration_parameter);
for (size_t k = 0; k < override_paths.size(); k++)
{
cv::String datapath = override_paths[k];
if (datapath.empty())
continue;
if (utils::fs::isDirectory(datapath))
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): trying " << configuration_parameter << "=" << datapath);
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
else
{
CV_LOG_WARNING(NULL, configuration_parameter << " is specified but it is not a directory: " << datapath);
}
}
if (!override_paths.empty())
{
CV_LOG_INFO(NULL, "utils::findDataFile(): can't find data file via " << configuration_parameter << " configuration override: " << relative_path);
return cv::String();
}
// Steps: 4, 5, 6
cv::String cwd = utils::fs::getcwd();
cv::String build_dir(OPENCV_BUILD_DIR);
bool has_tested_build_directory = false;
if (isSubDirectory(build_dir, cwd) || isSubDirectory(utils::fs::canonical(build_dir), utils::fs::canonical(cwd)))
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): the current directory is build sub-directory: " << cwd);
const char* build_subdirs[] = { OPENCV_DATA_BUILD_DIR_SEARCH_PATHS };
for (size_t k = 0; k < sizeof(build_subdirs)/sizeof(build_subdirs[0]); k++)
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): <build>/" << build_subdirs[k]);
cv::String datapath = utils::fs::join(build_dir, build_subdirs[k]);
if (utils::fs::isDirectory(datapath))
{
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
}
has_tested_build_directory = true;
}
cv::String source_dir;
cv::String try_source_dir = cwd;
for (int levels = 0; levels < 3; ++levels)
{
if (utils::fs::exists(utils::fs::join(try_source_dir, "modules/core/include/opencv2/core/version.hpp")))
{
source_dir = try_source_dir;
break;
}
try_source_dir = utils::fs::join(try_source_dir, "/..");
}
if (!source_dir.empty())
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): the current directory is source sub-directory: " << source_dir);
CV_LOG_DEBUG(NULL, "utils::findDataFile(): <source>" << source_dir);
cv::String datapath = source_dir;
if (utils::fs::isDirectory(datapath))
{
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
}
cv::String module_path = getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
if (!has_tested_build_directory &&
(isSubDirectory(build_dir, module_path) || isSubDirectory(utils::fs::canonical(build_dir), utils::fs::canonical(module_path)))
)
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): the binary module directory is build sub-directory: " << module_path);
const char* build_subdirs[] = { OPENCV_DATA_BUILD_DIR_SEARCH_PATHS };
for (size_t k = 0; k < sizeof(build_subdirs)/sizeof(build_subdirs[0]); k++)
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): <build>/" << build_subdirs[k]);
cv::String datapath = utils::fs::join(build_dir, build_subdirs[k]);
if (utils::fs::isDirectory(datapath))
{
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
}
}
#if defined OPENCV_INSTALL_DATA_DIR_RELATIVE
if (!module_path.empty()) // require module path
{
size_t pos = module_path.rfind('/');
if (pos == cv::String::npos)
pos = module_path.rfind('\\');
cv::String module_dir = (pos == cv::String::npos) ? module_path : module_path.substr(0, pos);
const char* install_subdirs[] = { OPENCV_INSTALL_DATA_DIR_RELATIVE };
for (size_t k = 0; k < sizeof(install_subdirs)/sizeof(install_subdirs[0]); k++)
{
cv::String datapath = utils::fs::join(module_dir, install_subdirs[k]);
CV_LOG_DEBUG(NULL, "utils::findDataFile(): trying install path (from binary path): " << datapath);
if (utils::fs::isDirectory(datapath))
{
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
else
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): ... skip, not a valid directory: " << datapath);
}
}
}
#endif
#if defined OPENCV_INSTALL_PREFIX && defined OPENCV_DATA_INSTALL_PATH
cv::String install_dir(OPENCV_INSTALL_PREFIX);
// use core/world module path and verify that library is running from installation directory
// It is neccessary to avoid touching of unrelated common /usr/local path
if (module_path.empty()) // can't determine
module_path = install_dir;
if (isSubDirectory(install_dir, module_path) || isSubDirectory(utils::fs::canonical(install_dir), utils::fs::canonical(module_path)))
{
cv::String datapath = utils::fs::join(install_dir, OPENCV_DATA_INSTALL_PATH);
if (utils::fs::isDirectory(datapath))
{
CV_LOG_DEBUG(NULL, "utils::findDataFile(): trying install path: " << datapath);
for(size_t i = search_subdir.size(); i > 0; i--)
{
const cv::String& subdir = search_subdir[i - 1];
cv::String prefix = utils::fs::join(datapath, subdir);
TRY_FILE_WITH_PREFIX(prefix);
}
}
}
#endif
return cv::String(); // not found
}
cv::String findDataFile(const cv::String& relative_path, bool required, const char* configuration_parameter)
{
CV_LOG_DEBUG(NULL, cv::format("cv::utils::findDataFile('%s', %s, %s)",
relative_path.c_str(), required ? "true" : "false",
configuration_parameter ? configuration_parameter : "NULL"));
cv::String result = cv::utils::findDataFile(relative_path,
configuration_parameter,
NULL,
NULL);
if (result.empty() && required)
CV_Error(cv::Error::StsError, cv::format("OpenCV: Can't find required data file: %s", relative_path.c_str()));
return result;
}
}} // namespace

@ -85,6 +85,20 @@ cv::String join(const cv::String& base, const cv::String& path)
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
cv::String canonical(const cv::String& path)
{
#ifdef _WIN32
const char* result = _fullpath(NULL, path.c_str(), 0);
#else
const char* result = realpath(path.c_str(), NULL);
#endif
if (result)
return cv::String(result);
// no error handling, just return input
return path;
}
bool exists(const cv::String& path)
{
CV_INSTRUMENT_REGION();
@ -543,11 +557,12 @@ cv::String getCacheDirectory(const char* sub_directory_name, const char* configu
#else
#define NOT_IMPLEMENTED CV_Error(Error::StsNotImplemented, "");
CV_EXPORTS bool exists(const cv::String& /*path*/) { NOT_IMPLEMENTED }
CV_EXPORTS void remove_all(const cv::String& /*path*/) { NOT_IMPLEMENTED }
CV_EXPORTS bool createDirectory(const cv::String& /*path*/) { NOT_IMPLEMENTED }
CV_EXPORTS bool createDirectories(const cv::String& /*path*/) { NOT_IMPLEMENTED }
CV_EXPORTS cv::String getCacheDirectory(const char* /*sub_directory_name*/, const char* /*configuration_name = NULL*/) { NOT_IMPLEMENTED }
cv::String canonical(const cv::String& /*path*/) { NOT_IMPLEMENTED }
bool exists(const cv::String& /*path*/) { NOT_IMPLEMENTED }
void remove_all(const cv::String& /*path*/) { NOT_IMPLEMENTED }
bool createDirectory(const cv::String& /*path*/) { NOT_IMPLEMENTED }
bool createDirectories(const cv::String& /*path*/) { NOT_IMPLEMENTED }
cv::String getCacheDirectory(const char* /*sub_directory_name*/, const char* /*configuration_name = NULL*/) { NOT_IMPLEMENTED }
#undef NOT_IMPLEMENTED
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT

@ -0,0 +1,67 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "../precomp.hpp"
#include <vector>
#include <opencv2/core/utils/logger.defines.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#include "opencv2/core/utils/logger.hpp"
#include "opencv2/core/utils/filesystem.hpp"
namespace cv { namespace samples {
static cv::Ptr< std::vector<cv::String> > g_data_search_path;
static cv::Ptr< std::vector<cv::String> > g_data_search_subdir;
static std::vector<cv::String>& _getDataSearchPath()
{
if (g_data_search_path.empty())
g_data_search_path.reset(new std::vector<cv::String>());
return *(g_data_search_path.get());
}
static std::vector<cv::String>& _getDataSearchSubDirectory()
{
if (g_data_search_subdir.empty())
{
g_data_search_subdir.reset(new std::vector<cv::String>());
g_data_search_subdir->push_back("samples/data");
g_data_search_subdir->push_back("data");
g_data_search_subdir->push_back("");
}
return *(g_data_search_subdir.get());
}
CV_EXPORTS void addSamplesDataSearchPath(const cv::String& path)
{
if (utils::fs::isDirectory(path))
_getDataSearchPath().push_back(path);
}
CV_EXPORTS void addSamplesDataSearchSubDirectory(const cv::String& subdir)
{
_getDataSearchSubDirectory().push_back(subdir);
}
cv::String findFile(const cv::String& relative_path, bool required, bool silentMode)
{
CV_LOG_DEBUG(NULL, cv::format("cv::samples::findFile('%s', %s)", relative_path.c_str(), required ? "true" : "false"));
cv::String result = cv::utils::findDataFile(relative_path,
"OPENCV_SAMPLES_DATA_PATH",
&_getDataSearchPath(),
&_getDataSearchSubDirectory());
if (result != relative_path && !silentMode)
{
CV_LOG_WARNING(NULL, "cv::samples::findFile('" << relative_path << "') => '" << result << "'");
}
if (result.empty() && required)
CV_Error(cv::Error::StsError, cv::format("OpenCV samples: Can't find required data file: %s", relative_path.c_str()));
return result;
}
}} // namespace

@ -2,6 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
#include "opencv2/core/utils/logger.hpp"
namespace opencv_test { namespace {
@ -283,4 +284,21 @@ TEST(CommandLineParser, testScalar)
EXPECT_EQ(parser.get<Scalar>("s5"), Scalar(5, -4, 3, 2));
}
TEST(Samples, findFile)
{
cv::utils::logging::LogLevel prev = cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_VERBOSE);
cv::String path;
ASSERT_NO_THROW(path = samples::findFile("lena.jpg", false));
EXPECT_NE(std::string(), path.c_str());
cv::utils::logging::setLogLevel(prev);
}
TEST(Samples, findFile_missing)
{
cv::utils::logging::LogLevel prev = cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_VERBOSE);
cv::String path;
ASSERT_ANY_THROW(path = samples::findFile("non-existed.file", true));
cv::utils::logging::setLogLevel(prev);
}
}} // namespace

@ -84,6 +84,23 @@ class Arguments(NewOpenCVTests):
self.assertEqual(res4, "InputArrayOfArrays: empty()=false kind=0x00050000 flags=0x01050000 total(-1)=3 dims(-1)=1 size(-1)=3x1 type(0)=CV_32FC2 dims(0)=2 size(0)=3x1 type(0)=CV_32FC2")
class SamplesFindFile(NewOpenCVTests):
def test_ExistedFile(self):
res = cv.samples.findFile('lena.jpg', False)
self.assertNotEqual(res, '')
def test_MissingFile(self):
res = cv.samples.findFile('non_existed.file', False)
self.assertEqual(res, '')
def test_MissingFileException(self):
try:
res = cv.samples.findFile('non_existed.file', True)
self.assertEqual("Dead code", 0)
except cv.error as _e:
pass
if __name__ == '__main__':
NewOpenCVTests.bootstrap()

Loading…
Cancel
Save