mirror of https://github.com/opencv/opencv.git
commit
22dbcf98c5
237 changed files with 2986 additions and 1656 deletions
@ -1,18 +1,36 @@ |
|||||||
@ECHO OFF |
@ECHO OFF |
||||||
SETLOCAL EnableDelayedExpansion |
|
||||||
|
|
||||||
SET "SCRIPT_DIR=%~dp0" |
SET "SCRIPT_DIR=%~dp0" |
||||||
|
|
||||||
IF NOT DEFINED OPENCV_QUIET ( ECHO Setting vars for OpenCV @OPENCV_VERSION@ ) |
IF NOT DEFINED OPENCV_QUIET ( ECHO Setting vars for OpenCV @OPENCV_VERSION@ ) |
||||||
SET "PATH=!SCRIPT_DIR!\@OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG@;%PATH%" |
SET "PATH=%SCRIPT_DIR%\@OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG@;%PATH%" |
||||||
|
|
||||||
IF NOT DEFINED OPENCV_SKIP_PYTHON ( |
IF NOT DEFINED OPENCV_SKIP_PYTHON CALL :SET_PYTHON |
||||||
SET "PYTHONPATH_OPENCV=!SCRIPT_DIR!\@OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG@" |
|
||||||
IF NOT DEFINED OPENCV_QUIET ( ECHO Append PYTHONPATH: !PYTHONPATH_OPENCV! ) |
SET SCRIPT_DIR= |
||||||
SET "PYTHONPATH=!PYTHONPATH_OPENCV!;%PYTHONPATH%" |
|
||||||
) |
IF NOT [%1] == [] GOTO :RUN_COMMAND |
||||||
|
|
||||||
|
GOTO :EOF |
||||||
|
|
||||||
IF NOT [%1] == [] ( |
:RUN_COMMAND |
||||||
%* |
SET RUN_INTERACTIVE=1 |
||||||
EXIT /B !errorlevel! |
echo %CMDCMDLINE% | find /i "%~0" >nul |
||||||
|
IF NOT errorlevel 1 set RUN_INTERACTIVE=0 |
||||||
|
|
||||||
|
%* |
||||||
|
SET RESULT=%ERRORLEVEL% |
||||||
|
IF %RESULT% NEQ 0 ( |
||||||
|
IF _%RUN_INTERACTIVE%_==_0_ ( IF NOT DEFINED OPENCV_BATCH_MODE ( pause ) ) |
||||||
) |
) |
||||||
|
EXIT /B %RESULT% |
||||||
|
|
||||||
|
:SET_PYTHON |
||||||
|
SET "PYTHONPATH_OPENCV=%SCRIPT_DIR%\@OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG@" |
||||||
|
IF NOT DEFINED OPENCV_QUIET ( ECHO Append PYTHONPATH: %PYTHONPATH_OPENCV% ) |
||||||
|
SET "PYTHONPATH=%PYTHONPATH_OPENCV%;%PYTHONPATH%" |
||||||
|
SET PYTHONPATH_OPENCV= |
||||||
|
EXIT /B |
||||||
|
|
||||||
|
|
||||||
|
:EOF |
||||||
|
@ -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
|
@ -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
|
@ -0,0 +1,759 @@ |
|||||||
|
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||||
|
//
|
||||||
|
// By downloading, copying, installing or using the software you agree to this license.
|
||||||
|
// If you do not agree to this license, do not download, install,
|
||||||
|
// copy or use the software.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// License Agreement
|
||||||
|
// For Open Source Computer Vision Library
|
||||||
|
//
|
||||||
|
// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
|
||||||
|
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||||
|
// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
|
||||||
|
// Third party copyrights are property of their respective owners.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
// are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistribution's of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * The name of the copyright holders may not be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// This software is provided by the copyright holders and contributors "as is" and
|
||||||
|
// any express or implied warranties, including, but not limited to, the implied
|
||||||
|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||||
|
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||||
|
// indirect, incidental, special, exemplary, or consequential damages
|
||||||
|
// (including, but not limited to, procurement of substitute goods or services;
|
||||||
|
// loss of use, data, or profits; or business interruption) however caused
|
||||||
|
// and on any theory of liability, whether in contract, strict liability,
|
||||||
|
// or tort (including negligence or otherwise) arising in any way out of
|
||||||
|
// the use of this software, even if advised of the possibility of such damage.
|
||||||
|
//
|
||||||
|
//M*/
|
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "opencv2/core/hal/intrin.hpp" |
||||||
|
#include "opencl_kernels_imgproc.hpp" |
||||||
|
|
||||||
|
/****************************************************************************************\
|
||||||
|
Bilateral Filtering |
||||||
|
\****************************************************************************************/ |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
|
||||||
|
class BilateralFilter_8u_Invoker : |
||||||
|
public ParallelLoopBody |
||||||
|
{ |
||||||
|
public: |
||||||
|
BilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, int _radius, int _maxk, |
||||||
|
int* _space_ofs, float *_space_weight, float *_color_weight) : |
||||||
|
temp(&_temp), dest(&_dest), radius(_radius), |
||||||
|
maxk(_maxk), space_ofs(_space_ofs), space_weight(_space_weight), color_weight(_color_weight) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
int i, j, cn = dest->channels(), k; |
||||||
|
Size size = dest->size(); |
||||||
|
|
||||||
|
for( i = range.start; i < range.end; i++ ) |
||||||
|
{ |
||||||
|
const uchar* sptr = temp->ptr(i+radius) + radius*cn; |
||||||
|
uchar* dptr = dest->ptr(i); |
||||||
|
|
||||||
|
if( cn == 1 ) |
||||||
|
{ |
||||||
|
AutoBuffer<float> buf(alignSize(size.width, CV_SIMD_WIDTH) + size.width + CV_SIMD_WIDTH - 1); |
||||||
|
memset(buf.data(), 0, buf.size() * sizeof(float)); |
||||||
|
float *sum = alignPtr(buf.data(), CV_SIMD_WIDTH); |
||||||
|
float *wsum = sum + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
for( k = 0; k < maxk; k++ ) |
||||||
|
{ |
||||||
|
const uchar* ksptr = sptr + space_ofs[k]; |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 kweight = vx_setall_f32(space_weight[k]); |
||||||
|
for (; j <= size.width - v_float32::nlanes; j += v_float32::nlanes) |
||||||
|
{ |
||||||
|
v_uint32 val = vx_load_expand_q(ksptr + j); |
||||||
|
v_float32 w = kweight * v_lut(color_weight, v_reinterpret_as_s32(v_absdiff(val, vx_load_expand_q(sptr + j)))); |
||||||
|
v_store_aligned(wsum + j, vx_load_aligned(wsum + j) + w); |
||||||
|
v_store_aligned(sum + j, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val)), w, vx_load_aligned(sum + j))); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++) |
||||||
|
{ |
||||||
|
int val = ksptr[j]; |
||||||
|
float w = space_weight[k] * color_weight[std::abs(val - sptr[j])]; |
||||||
|
wsum[j] += w; |
||||||
|
sum[j] += val * w; |
||||||
|
} |
||||||
|
} |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
for (; j <= size.width - 2*v_float32::nlanes; j += 2*v_float32::nlanes) |
||||||
|
v_pack_u_store(dptr + j, v_pack(v_round(vx_load_aligned(sum + j ) / vx_load_aligned(wsum + j )), |
||||||
|
v_round(vx_load_aligned(sum + j + v_float32::nlanes) / vx_load_aligned(wsum + j + v_float32::nlanes)))); |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++) |
||||||
|
{ |
||||||
|
// overflow is not possible here => there is no need to use cv::saturate_cast
|
||||||
|
CV_DbgAssert(fabs(wsum[j]) > 0); |
||||||
|
dptr[j] = (uchar)cvRound(sum[j]/wsum[j]); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
assert( cn == 3 ); |
||||||
|
AutoBuffer<float> buf(alignSize(size.width, CV_SIMD_WIDTH)*3 + size.width + CV_SIMD_WIDTH - 1); |
||||||
|
memset(buf.data(), 0, buf.size() * sizeof(float)); |
||||||
|
float *sum_b = alignPtr(buf.data(), CV_SIMD_WIDTH); |
||||||
|
float *sum_g = sum_b + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
float *sum_r = sum_g + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
float *wsum = sum_r + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
for(k = 0; k < maxk; k++ ) |
||||||
|
{ |
||||||
|
const uchar* ksptr = sptr + space_ofs[k]; |
||||||
|
const uchar* rsptr = sptr; |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 kweight = vx_setall_f32(space_weight[k]); |
||||||
|
for (; j <= size.width - v_uint8::nlanes; j += v_uint8::nlanes, ksptr += 3*v_uint8::nlanes, rsptr += 3*v_uint8::nlanes) |
||||||
|
{ |
||||||
|
v_uint8 kb, kg, kr, rb, rg, rr; |
||||||
|
v_load_deinterleave(ksptr, kb, kg, kr); |
||||||
|
v_load_deinterleave(rsptr, rb, rg, rr); |
||||||
|
|
||||||
|
v_uint16 b_l, b_h, g_l, g_h, r_l, r_h; |
||||||
|
v_expand(v_absdiff(kb, rb), b_l, b_h); |
||||||
|
v_expand(v_absdiff(kg, rg), g_l, g_h); |
||||||
|
v_expand(v_absdiff(kr, rr), r_l, r_h); |
||||||
|
|
||||||
|
v_uint32 val0, val1, val2, val3; |
||||||
|
v_expand(b_l + g_l + r_l, val0, val1); |
||||||
|
v_expand(b_h + g_h + r_h, val2, val3); |
||||||
|
|
||||||
|
v_expand(kb, b_l, b_h); |
||||||
|
v_expand(kg, g_l, g_h); |
||||||
|
v_expand(kr, r_l, r_h); |
||||||
|
|
||||||
|
v_float32 w0 = kweight * v_lut(color_weight, v_reinterpret_as_s32(val0)); |
||||||
|
v_float32 w1 = kweight * v_lut(color_weight, v_reinterpret_as_s32(val1)); |
||||||
|
v_float32 w2 = kweight * v_lut(color_weight, v_reinterpret_as_s32(val2)); |
||||||
|
v_float32 w3 = kweight * v_lut(color_weight, v_reinterpret_as_s32(val3)); |
||||||
|
v_store_aligned(wsum + j , w0 + vx_load_aligned(wsum + j)); |
||||||
|
v_store_aligned(wsum + j + v_float32::nlanes, w1 + vx_load_aligned(wsum + j + v_float32::nlanes)); |
||||||
|
v_store_aligned(wsum + j + 2*v_float32::nlanes, w2 + vx_load_aligned(wsum + j + 2*v_float32::nlanes)); |
||||||
|
v_store_aligned(wsum + j + 3*v_float32::nlanes, w3 + vx_load_aligned(wsum + j + 3*v_float32::nlanes)); |
||||||
|
v_expand(b_l, val0, val1); |
||||||
|
v_expand(b_h, val2, val3); |
||||||
|
v_store_aligned(sum_b + j , v_muladd(v_cvt_f32(v_reinterpret_as_s32(val0)), w0, vx_load_aligned(sum_b + j))); |
||||||
|
v_store_aligned(sum_b + j + v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val1)), w1, vx_load_aligned(sum_b + j + v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_b + j + 2*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val2)), w2, vx_load_aligned(sum_b + j + 2*v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_b + j + 3*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val3)), w3, vx_load_aligned(sum_b + j + 3*v_float32::nlanes))); |
||||||
|
v_expand(g_l, val0, val1); |
||||||
|
v_expand(g_h, val2, val3); |
||||||
|
v_store_aligned(sum_g + j , v_muladd(v_cvt_f32(v_reinterpret_as_s32(val0)), w0, vx_load_aligned(sum_g + j))); |
||||||
|
v_store_aligned(sum_g + j + v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val1)), w1, vx_load_aligned(sum_g + j + v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_g + j + 2*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val2)), w2, vx_load_aligned(sum_g + j + 2*v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_g + j + 3*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val3)), w3, vx_load_aligned(sum_g + j + 3*v_float32::nlanes))); |
||||||
|
v_expand(r_l, val0, val1); |
||||||
|
v_expand(r_h, val2, val3); |
||||||
|
v_store_aligned(sum_r + j , v_muladd(v_cvt_f32(v_reinterpret_as_s32(val0)), w0, vx_load_aligned(sum_r + j))); |
||||||
|
v_store_aligned(sum_r + j + v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val1)), w1, vx_load_aligned(sum_r + j + v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_r + j + 2*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val2)), w2, vx_load_aligned(sum_r + j + 2*v_float32::nlanes))); |
||||||
|
v_store_aligned(sum_r + j + 3*v_float32::nlanes, v_muladd(v_cvt_f32(v_reinterpret_as_s32(val3)), w3, vx_load_aligned(sum_r + j + 3*v_float32::nlanes))); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for(; j < size.width; j++, ksptr += 3, rsptr += 3) |
||||||
|
{ |
||||||
|
int b = ksptr[0], g = ksptr[1], r = ksptr[2]; |
||||||
|
float w = space_weight[k]*color_weight[std::abs(b - rsptr[0]) + std::abs(g - rsptr[1]) + std::abs(r - rsptr[2])]; |
||||||
|
wsum[j] += w; |
||||||
|
sum_b[j] += b*w; sum_g[j] += g*w; sum_r[j] += r*w; |
||||||
|
} |
||||||
|
} |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 v_one = vx_setall_f32(1.f); |
||||||
|
for(; j <= size.width - v_uint8::nlanes; j += v_uint8::nlanes, dptr += 3*v_uint8::nlanes) |
||||||
|
{ |
||||||
|
v_float32 w0 = v_one / vx_load_aligned(wsum + j); |
||||||
|
v_float32 w1 = v_one / vx_load_aligned(wsum + j + v_float32::nlanes); |
||||||
|
v_float32 w2 = v_one / vx_load_aligned(wsum + j + 2*v_float32::nlanes); |
||||||
|
v_float32 w3 = v_one / vx_load_aligned(wsum + j + 3*v_float32::nlanes); |
||||||
|
|
||||||
|
v_store_interleave(dptr, v_pack_u(v_pack(v_round(w0 * vx_load_aligned(sum_b + j)), |
||||||
|
v_round(w1 * vx_load_aligned(sum_b + j + v_float32::nlanes))), |
||||||
|
v_pack(v_round(w2 * vx_load_aligned(sum_b + j + 2*v_float32::nlanes)), |
||||||
|
v_round(w3 * vx_load_aligned(sum_b + j + 3*v_float32::nlanes)))), |
||||||
|
v_pack_u(v_pack(v_round(w0 * vx_load_aligned(sum_g + j)), |
||||||
|
v_round(w1 * vx_load_aligned(sum_g + j + v_float32::nlanes))), |
||||||
|
v_pack(v_round(w2 * vx_load_aligned(sum_g + j + 2*v_float32::nlanes)), |
||||||
|
v_round(w3 * vx_load_aligned(sum_g + j + 3*v_float32::nlanes)))), |
||||||
|
v_pack_u(v_pack(v_round(w0 * vx_load_aligned(sum_r + j)), |
||||||
|
v_round(w1 * vx_load_aligned(sum_r + j + v_float32::nlanes))), |
||||||
|
v_pack(v_round(w2 * vx_load_aligned(sum_r + j + 2*v_float32::nlanes)), |
||||||
|
v_round(w3 * vx_load_aligned(sum_r + j + 3*v_float32::nlanes))))); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for(; j < size.width; j++) |
||||||
|
{ |
||||||
|
CV_DbgAssert(fabs(wsum[j]) > 0); |
||||||
|
wsum[j] = 1.f/wsum[j]; |
||||||
|
*(dptr++) = (uchar)cvRound(sum_b[j]*wsum[j]); |
||||||
|
*(dptr++) = (uchar)cvRound(sum_g[j]*wsum[j]); |
||||||
|
*(dptr++) = (uchar)cvRound(sum_r[j]*wsum[j]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#if CV_SIMD |
||||||
|
vx_cleanup(); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
const Mat *temp; |
||||||
|
Mat *dest; |
||||||
|
int radius, maxk, *space_ofs; |
||||||
|
float *space_weight, *color_weight; |
||||||
|
}; |
||||||
|
|
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
|
||||||
|
static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, |
||||||
|
double sigma_color, double sigma_space, |
||||||
|
int borderType) |
||||||
|
{ |
||||||
|
#ifdef __ANDROID__ |
||||||
|
if (ocl::Device::getDefault().isNVidia()) |
||||||
|
return false; |
||||||
|
#endif |
||||||
|
|
||||||
|
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); |
||||||
|
int i, j, maxk, radius; |
||||||
|
|
||||||
|
if (depth != CV_8U || cn > 4) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (sigma_color <= 0) |
||||||
|
sigma_color = 1; |
||||||
|
if (sigma_space <= 0) |
||||||
|
sigma_space = 1; |
||||||
|
|
||||||
|
double gauss_color_coeff = -0.5 / (sigma_color * sigma_color); |
||||||
|
double gauss_space_coeff = -0.5 / (sigma_space * sigma_space); |
||||||
|
|
||||||
|
if ( d <= 0 ) |
||||||
|
radius = cvRound(sigma_space * 1.5); |
||||||
|
else |
||||||
|
radius = d / 2; |
||||||
|
radius = MAX(radius, 1); |
||||||
|
d = radius * 2 + 1; |
||||||
|
|
||||||
|
UMat src = _src.getUMat(), dst = _dst.getUMat(), temp; |
||||||
|
if (src.u == dst.u) |
||||||
|
return false; |
||||||
|
|
||||||
|
copyMakeBorder(src, temp, radius, radius, radius, radius, borderType); |
||||||
|
std::vector<float> _space_weight(d * d); |
||||||
|
std::vector<int> _space_ofs(d * d); |
||||||
|
float * const space_weight = &_space_weight[0]; |
||||||
|
int * const space_ofs = &_space_ofs[0]; |
||||||
|
|
||||||
|
// initialize space-related bilateral filter coefficients
|
||||||
|
for( i = -radius, maxk = 0; i <= radius; i++ ) |
||||||
|
for( j = -radius; j <= radius; j++ ) |
||||||
|
{ |
||||||
|
double r = std::sqrt((double)i * i + (double)j * j); |
||||||
|
if ( r > radius ) |
||||||
|
continue; |
||||||
|
space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff); |
||||||
|
space_ofs[maxk++] = (int)(i * temp.step + j * cn); |
||||||
|
} |
||||||
|
|
||||||
|
char cvt[3][40]; |
||||||
|
String cnstr = cn > 1 ? format("%d", cn) : ""; |
||||||
|
String kernelName("bilateral"); |
||||||
|
size_t sizeDiv = 1; |
||||||
|
if ((ocl::Device::getDefault().isIntel()) && |
||||||
|
(ocl::Device::getDefault().type() == ocl::Device::TYPE_GPU)) |
||||||
|
{ |
||||||
|
//Intel GPU
|
||||||
|
if (dst.cols % 4 == 0 && cn == 1) // For single channel x4 sized images.
|
||||||
|
{ |
||||||
|
kernelName = "bilateral_float4"; |
||||||
|
sizeDiv = 4; |
||||||
|
} |
||||||
|
} |
||||||
|
ocl::Kernel k(kernelName.c_str(), ocl::imgproc::bilateral_oclsrc, |
||||||
|
format("-D radius=%d -D maxk=%d -D cn=%d -D int_t=%s -D uint_t=uint%s -D convert_int_t=%s" |
||||||
|
" -D uchar_t=%s -D float_t=%s -D convert_float_t=%s -D convert_uchar_t=%s -D gauss_color_coeff=(float)%f", |
||||||
|
radius, maxk, cn, ocl::typeToStr(CV_32SC(cn)), cnstr.c_str(), |
||||||
|
ocl::convertTypeStr(CV_8U, CV_32S, cn, cvt[0]), |
||||||
|
ocl::typeToStr(type), ocl::typeToStr(CV_32FC(cn)), |
||||||
|
ocl::convertTypeStr(CV_32S, CV_32F, cn, cvt[1]), |
||||||
|
ocl::convertTypeStr(CV_32F, CV_8U, cn, cvt[2]), gauss_color_coeff)); |
||||||
|
if (k.empty()) |
||||||
|
return false; |
||||||
|
|
||||||
|
Mat mspace_weight(1, d * d, CV_32FC1, space_weight); |
||||||
|
Mat mspace_ofs(1, d * d, CV_32SC1, space_ofs); |
||||||
|
UMat ucolor_weight, uspace_weight, uspace_ofs; |
||||||
|
|
||||||
|
mspace_weight.copyTo(uspace_weight); |
||||||
|
mspace_ofs.copyTo(uspace_ofs); |
||||||
|
|
||||||
|
k.args(ocl::KernelArg::ReadOnlyNoSize(temp), ocl::KernelArg::WriteOnly(dst), |
||||||
|
ocl::KernelArg::PtrReadOnly(uspace_weight), |
||||||
|
ocl::KernelArg::PtrReadOnly(uspace_ofs)); |
||||||
|
|
||||||
|
size_t globalsize[2] = { (size_t)dst.cols / sizeDiv, (size_t)dst.rows }; |
||||||
|
return k.run(2, globalsize, NULL, false); |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
static void |
||||||
|
bilateralFilter_8u( const Mat& src, Mat& dst, int d, |
||||||
|
double sigma_color, double sigma_space, |
||||||
|
int borderType ) |
||||||
|
{ |
||||||
|
int cn = src.channels(); |
||||||
|
int i, j, maxk, radius; |
||||||
|
Size size = src.size(); |
||||||
|
|
||||||
|
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data ); |
||||||
|
|
||||||
|
if( sigma_color <= 0 ) |
||||||
|
sigma_color = 1; |
||||||
|
if( sigma_space <= 0 ) |
||||||
|
sigma_space = 1; |
||||||
|
|
||||||
|
double gauss_color_coeff = -0.5/(sigma_color*sigma_color); |
||||||
|
double gauss_space_coeff = -0.5/(sigma_space*sigma_space); |
||||||
|
|
||||||
|
if( d <= 0 ) |
||||||
|
radius = cvRound(sigma_space*1.5); |
||||||
|
else |
||||||
|
radius = d/2; |
||||||
|
radius = MAX(radius, 1); |
||||||
|
d = radius*2 + 1; |
||||||
|
|
||||||
|
Mat temp; |
||||||
|
copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); |
||||||
|
|
||||||
|
std::vector<float> _color_weight(cn*256); |
||||||
|
std::vector<float> _space_weight(d*d); |
||||||
|
std::vector<int> _space_ofs(d*d); |
||||||
|
float* color_weight = &_color_weight[0]; |
||||||
|
float* space_weight = &_space_weight[0]; |
||||||
|
int* space_ofs = &_space_ofs[0]; |
||||||
|
|
||||||
|
// initialize color-related bilateral filter coefficients
|
||||||
|
|
||||||
|
for( i = 0; i < 256*cn; i++ ) |
||||||
|
color_weight[i] = (float)std::exp(i*i*gauss_color_coeff); |
||||||
|
|
||||||
|
// initialize space-related bilateral filter coefficients
|
||||||
|
for( i = -radius, maxk = 0; i <= radius; i++ ) |
||||||
|
{ |
||||||
|
j = -radius; |
||||||
|
|
||||||
|
for( ; j <= radius; j++ ) |
||||||
|
{ |
||||||
|
double r = std::sqrt((double)i*i + (double)j*j); |
||||||
|
if( r > radius ) |
||||||
|
continue; |
||||||
|
space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff); |
||||||
|
space_ofs[maxk++] = (int)(i*temp.step + j*cn); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
BilateralFilter_8u_Invoker body(dst, temp, radius, maxk, space_ofs, space_weight, color_weight); |
||||||
|
parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class BilateralFilter_32f_Invoker : |
||||||
|
public ParallelLoopBody |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
BilateralFilter_32f_Invoker(int _cn, int _radius, int _maxk, int *_space_ofs, |
||||||
|
const Mat& _temp, Mat& _dest, float _scale_index, float *_space_weight, float *_expLUT) : |
||||||
|
cn(_cn), radius(_radius), maxk(_maxk), space_ofs(_space_ofs), |
||||||
|
temp(&_temp), dest(&_dest), scale_index(_scale_index), space_weight(_space_weight), expLUT(_expLUT) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
int i, j, k; |
||||||
|
Size size = dest->size(); |
||||||
|
|
||||||
|
for( i = range.start; i < range.end; i++ ) |
||||||
|
{ |
||||||
|
const float* sptr = temp->ptr<float>(i+radius) + radius*cn; |
||||||
|
float* dptr = dest->ptr<float>(i); |
||||||
|
|
||||||
|
if( cn == 1 ) |
||||||
|
{ |
||||||
|
AutoBuffer<float> buf(alignSize(size.width, CV_SIMD_WIDTH) + size.width + CV_SIMD_WIDTH - 1); |
||||||
|
memset(buf.data(), 0, buf.size() * sizeof(float)); |
||||||
|
float *sum = alignPtr(buf.data(), CV_SIMD_WIDTH); |
||||||
|
float *wsum = sum + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 v_one = vx_setall_f32(1.f); |
||||||
|
v_float32 sindex = vx_setall_f32(scale_index); |
||||||
|
#endif |
||||||
|
for( k = 0; k < maxk; k++ ) |
||||||
|
{ |
||||||
|
const float* ksptr = sptr + space_ofs[k]; |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 kweight = vx_setall_f32(space_weight[k]); |
||||||
|
for (; j <= size.width - v_float32::nlanes; j += v_float32::nlanes) |
||||||
|
{ |
||||||
|
v_float32 val = vx_load(ksptr + j); |
||||||
|
|
||||||
|
v_float32 alpha = v_absdiff(val, vx_load(sptr + j)) * sindex; |
||||||
|
v_int32 idx = v_trunc(alpha); |
||||||
|
alpha -= v_cvt_f32(idx); |
||||||
|
|
||||||
|
v_float32 w = kweight * v_muladd(v_lut(expLUT + 1, idx), alpha, v_lut(expLUT, idx) * (v_one-alpha)); |
||||||
|
v_store_aligned(wsum + j, vx_load_aligned(wsum + j) + w); |
||||||
|
v_store_aligned(sum + j, v_muladd(val, w, vx_load_aligned(sum + j))); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++) |
||||||
|
{ |
||||||
|
float val = ksptr[j]; |
||||||
|
float alpha = std::abs(val - sptr[j]) * scale_index; |
||||||
|
int idx = cvFloor(alpha); |
||||||
|
alpha -= idx; |
||||||
|
float w = space_weight[k] * (expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx])); |
||||||
|
wsum[j] += w; |
||||||
|
sum[j] += val * w; |
||||||
|
} |
||||||
|
} |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
for (; j <= size.width - v_float32::nlanes; j += v_float32::nlanes) |
||||||
|
v_store(dptr + j, vx_load_aligned(sum + j) / vx_load_aligned(wsum + j)); |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++) |
||||||
|
{ |
||||||
|
CV_DbgAssert(fabs(wsum[j]) > 0); |
||||||
|
dptr[j] = sum[j] / wsum[j]; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
CV_Assert( cn == 3 ); |
||||||
|
AutoBuffer<float> buf(alignSize(size.width, CV_SIMD_WIDTH)*3 + size.width + CV_SIMD_WIDTH - 1); |
||||||
|
memset(buf.data(), 0, buf.size() * sizeof(float)); |
||||||
|
float *sum_b = alignPtr(buf.data(), CV_SIMD_WIDTH); |
||||||
|
float *sum_g = sum_b + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
float *sum_r = sum_g + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
float *wsum = sum_r + alignSize(size.width, CV_SIMD_WIDTH); |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 v_one = vx_setall_f32(1.f); |
||||||
|
v_float32 sindex = vx_setall_f32(scale_index); |
||||||
|
#endif |
||||||
|
for (k = 0; k < maxk; k++) |
||||||
|
{ |
||||||
|
const float* ksptr = sptr + space_ofs[k]; |
||||||
|
const float* rsptr = sptr; |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
v_float32 kweight = vx_setall_f32(space_weight[k]); |
||||||
|
for (; j <= size.width - v_float32::nlanes; j += v_float32::nlanes, ksptr += 3*v_float32::nlanes, rsptr += 3*v_float32::nlanes) |
||||||
|
{ |
||||||
|
v_float32 kb, kg, kr, rb, rg, rr; |
||||||
|
v_load_deinterleave(ksptr, kb, kg, kr); |
||||||
|
v_load_deinterleave(rsptr, rb, rg, rr); |
||||||
|
|
||||||
|
v_float32 alpha = (v_absdiff(kb, rb) + v_absdiff(kg, rg) + v_absdiff(kr, rr)) * sindex; |
||||||
|
v_int32 idx = v_trunc(alpha); |
||||||
|
alpha -= v_cvt_f32(idx); |
||||||
|
|
||||||
|
v_float32 w = kweight * v_muladd(v_lut(expLUT + 1, idx), alpha, v_lut(expLUT, idx) * (v_one - alpha)); |
||||||
|
v_store_aligned(wsum + j, vx_load_aligned(wsum + j) + w); |
||||||
|
v_store_aligned(sum_b + j, v_muladd(kb, w, vx_load_aligned(sum_b + j))); |
||||||
|
v_store_aligned(sum_g + j, v_muladd(kg, w, vx_load_aligned(sum_g + j))); |
||||||
|
v_store_aligned(sum_r + j, v_muladd(kr, w, vx_load_aligned(sum_r + j))); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++, ksptr += 3, rsptr += 3) |
||||||
|
{ |
||||||
|
float b = ksptr[0], g = ksptr[1], r = ksptr[2]; |
||||||
|
float alpha = (std::abs(b - rsptr[0]) + std::abs(g - rsptr[1]) + std::abs(r - rsptr[2])) * scale_index; |
||||||
|
int idx = cvFloor(alpha); |
||||||
|
alpha -= idx; |
||||||
|
float w = space_weight[k] * (expLUT[idx] + alpha*(expLUT[idx + 1] - expLUT[idx])); |
||||||
|
wsum[j] += w; |
||||||
|
sum_b[j] += b*w; |
||||||
|
sum_g[j] += g*w; |
||||||
|
sum_r[j] += r*w; |
||||||
|
} |
||||||
|
} |
||||||
|
j = 0; |
||||||
|
#if CV_SIMD |
||||||
|
for (; j <= size.width - v_float32::nlanes; j += v_float32::nlanes, dptr += 3*v_float32::nlanes) |
||||||
|
{ |
||||||
|
v_float32 w = v_one / vx_load_aligned(wsum + j); |
||||||
|
v_store_interleave(dptr, vx_load_aligned(sum_b + j) * w, vx_load_aligned(sum_g + j) * w, vx_load_aligned(sum_r + j) * w); |
||||||
|
} |
||||||
|
#endif |
||||||
|
for (; j < size.width; j++) |
||||||
|
{ |
||||||
|
CV_DbgAssert(fabs(wsum[j]) > 0); |
||||||
|
wsum[j] = 1.f / wsum[j]; |
||||||
|
*(dptr++) = sum_b[j] * wsum[j]; |
||||||
|
*(dptr++) = sum_g[j] * wsum[j]; |
||||||
|
*(dptr++) = sum_r[j] * wsum[j]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#if CV_SIMD |
||||||
|
vx_cleanup(); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
int cn, radius, maxk, *space_ofs; |
||||||
|
const Mat* temp; |
||||||
|
Mat *dest; |
||||||
|
float scale_index, *space_weight, *expLUT; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
static void |
||||||
|
bilateralFilter_32f( const Mat& src, Mat& dst, int d, |
||||||
|
double sigma_color, double sigma_space, |
||||||
|
int borderType ) |
||||||
|
{ |
||||||
|
int cn = src.channels(); |
||||||
|
int i, j, maxk, radius; |
||||||
|
double minValSrc=-1, maxValSrc=1; |
||||||
|
const int kExpNumBinsPerChannel = 1 << 12; |
||||||
|
int kExpNumBins = 0; |
||||||
|
float lastExpVal = 1.f; |
||||||
|
float len, scale_index; |
||||||
|
Size size = src.size(); |
||||||
|
|
||||||
|
CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data ); |
||||||
|
|
||||||
|
if( sigma_color <= 0 ) |
||||||
|
sigma_color = 1; |
||||||
|
if( sigma_space <= 0 ) |
||||||
|
sigma_space = 1; |
||||||
|
|
||||||
|
double gauss_color_coeff = -0.5/(sigma_color*sigma_color); |
||||||
|
double gauss_space_coeff = -0.5/(sigma_space*sigma_space); |
||||||
|
|
||||||
|
if( d <= 0 ) |
||||||
|
radius = cvRound(sigma_space*1.5); |
||||||
|
else |
||||||
|
radius = d/2; |
||||||
|
radius = MAX(radius, 1); |
||||||
|
d = radius*2 + 1; |
||||||
|
// compute the min/max range for the input image (even if multichannel)
|
||||||
|
|
||||||
|
minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc ); |
||||||
|
if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON) |
||||||
|
{ |
||||||
|
src.copyTo(dst); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// temporary copy of the image with borders for easy processing
|
||||||
|
Mat temp; |
||||||
|
copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); |
||||||
|
minValSrc -= 5. * sigma_color; |
||||||
|
patchNaNs( temp, minValSrc ); // this replacement of NaNs makes the assumption that depth values are nonnegative
|
||||||
|
// TODO: make replacement parameter avalible in the outside function interface
|
||||||
|
// allocate lookup tables
|
||||||
|
std::vector<float> _space_weight(d*d); |
||||||
|
std::vector<int> _space_ofs(d*d); |
||||||
|
float* space_weight = &_space_weight[0]; |
||||||
|
int* space_ofs = &_space_ofs[0]; |
||||||
|
|
||||||
|
// assign a length which is slightly more than needed
|
||||||
|
len = (float)(maxValSrc - minValSrc) * cn; |
||||||
|
kExpNumBins = kExpNumBinsPerChannel * cn; |
||||||
|
std::vector<float> _expLUT(kExpNumBins+2); |
||||||
|
float* expLUT = &_expLUT[0]; |
||||||
|
|
||||||
|
scale_index = kExpNumBins/len; |
||||||
|
|
||||||
|
// initialize the exp LUT
|
||||||
|
for( i = 0; i < kExpNumBins+2; i++ ) |
||||||
|
{ |
||||||
|
if( lastExpVal > 0.f ) |
||||||
|
{ |
||||||
|
double val = i / scale_index; |
||||||
|
expLUT[i] = (float)std::exp(val * val * gauss_color_coeff); |
||||||
|
lastExpVal = expLUT[i]; |
||||||
|
} |
||||||
|
else |
||||||
|
expLUT[i] = 0.f; |
||||||
|
} |
||||||
|
|
||||||
|
// initialize space-related bilateral filter coefficients
|
||||||
|
for( i = -radius, maxk = 0; i <= radius; i++ ) |
||||||
|
for( j = -radius; j <= radius; j++ ) |
||||||
|
{ |
||||||
|
double r = std::sqrt((double)i*i + (double)j*j); |
||||||
|
if( r > radius ) |
||||||
|
continue; |
||||||
|
space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff); |
||||||
|
space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn); |
||||||
|
} |
||||||
|
|
||||||
|
// parallel_for usage
|
||||||
|
|
||||||
|
BilateralFilter_32f_Invoker body(cn, radius, maxk, space_ofs, temp, dst, scale_index, space_weight, expLUT); |
||||||
|
parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16)); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAVE_IPP |
||||||
|
#define IPP_BILATERAL_PARALLEL 1 |
||||||
|
|
||||||
|
#ifdef HAVE_IPP_IW |
||||||
|
class ipp_bilateralFilterParallel: public ParallelLoopBody |
||||||
|
{ |
||||||
|
public: |
||||||
|
ipp_bilateralFilterParallel(::ipp::IwiImage &_src, ::ipp::IwiImage &_dst, int _radius, Ipp32f _valSquareSigma, Ipp32f _posSquareSigma, ::ipp::IwiBorderType _borderType, bool *_ok): |
||||||
|
src(_src), dst(_dst) |
||||||
|
{ |
||||||
|
pOk = _ok; |
||||||
|
|
||||||
|
radius = _radius; |
||||||
|
valSquareSigma = _valSquareSigma; |
||||||
|
posSquareSigma = _posSquareSigma; |
||||||
|
borderType = _borderType; |
||||||
|
|
||||||
|
*pOk = true; |
||||||
|
} |
||||||
|
~ipp_bilateralFilterParallel() {} |
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
if(*pOk == false) |
||||||
|
return; |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start); |
||||||
|
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile); |
||||||
|
} |
||||||
|
catch(const ::ipp::IwException &) |
||||||
|
{ |
||||||
|
*pOk = false; |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
private: |
||||||
|
::ipp::IwiImage &src; |
||||||
|
::ipp::IwiImage &dst; |
||||||
|
|
||||||
|
int radius; |
||||||
|
Ipp32f valSquareSigma; |
||||||
|
Ipp32f posSquareSigma; |
||||||
|
::ipp::IwiBorderType borderType; |
||||||
|
|
||||||
|
bool *pOk; |
||||||
|
const ipp_bilateralFilterParallel& operator= (const ipp_bilateralFilterParallel&); |
||||||
|
}; |
||||||
|
#endif |
||||||
|
|
||||||
|
static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, double sigmaSpace, int borderType) |
||||||
|
{ |
||||||
|
#ifdef HAVE_IPP_IW |
||||||
|
CV_INSTRUMENT_REGION_IPP(); |
||||||
|
|
||||||
|
int radius = IPP_MAX(((d <= 0)?cvRound(sigmaSpace*1.5):d/2), 1); |
||||||
|
Ipp32f valSquareSigma = (Ipp32f)((sigmaColor <= 0)?1:sigmaColor*sigmaColor); |
||||||
|
Ipp32f posSquareSigma = (Ipp32f)((sigmaSpace <= 0)?1:sigmaSpace*sigmaSpace); |
||||||
|
|
||||||
|
// Acquire data and begin processing
|
||||||
|
try |
||||||
|
{ |
||||||
|
::ipp::IwiImage iwSrc = ippiGetImage(src); |
||||||
|
::ipp::IwiImage iwDst = ippiGetImage(dst); |
||||||
|
::ipp::IwiBorderSize borderSize(radius); |
||||||
|
::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize)); |
||||||
|
if(!ippBorder) |
||||||
|
return false; |
||||||
|
|
||||||
|
const int threads = ippiSuggestThreadsNum(iwDst, 2); |
||||||
|
if(IPP_BILATERAL_PARALLEL && threads > 1) { |
||||||
|
bool ok = true; |
||||||
|
Range range(0, (int)iwDst.m_size.height); |
||||||
|
ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok); |
||||||
|
if(!ok) |
||||||
|
return false; |
||||||
|
|
||||||
|
parallel_for_(range, invoker, threads*4); |
||||||
|
|
||||||
|
if(!ok) |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (const ::ipp::IwException &) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
#else |
||||||
|
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(d); CV_UNUSED(sigmaColor); CV_UNUSED(sigmaSpace); CV_UNUSED(borderType); |
||||||
|
return false; |
||||||
|
#endif |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, |
||||||
|
double sigmaColor, double sigmaSpace, |
||||||
|
int borderType ) |
||||||
|
{ |
||||||
|
CV_INSTRUMENT_REGION(); |
||||||
|
|
||||||
|
_dst.create( _src.size(), _src.type() ); |
||||||
|
|
||||||
|
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), |
||||||
|
ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType)) |
||||||
|
|
||||||
|
Mat src = _src.getMat(), dst = _dst.getMat(); |
||||||
|
|
||||||
|
CV_IPP_RUN_FAST(ipp_bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType)); |
||||||
|
|
||||||
|
if( src.depth() == CV_8U ) |
||||||
|
bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType ); |
||||||
|
else if( src.depth() == CV_32F ) |
||||||
|
bilateralFilter_32f( src, dst, d, sigmaColor, sigmaSpace, borderType ); |
||||||
|
else |
||||||
|
CV_Error( CV_StsUnsupportedFormat, |
||||||
|
"Bilateral filtering is only implemented for 8u and 32f images" ); |
||||||
|
} |
||||||
|
|
||||||
|
/* End of file. */ |
@ -0,0 +1,4 @@ |
|||||||
|
__pycache__ |
||||||
|
*.pyc |
||||||
|
*.egg-info |
||||||
|
*dist |
@ -0,0 +1,89 @@ |
|||||||
|
''' |
||||||
|
OpenCV Python binary extension loader |
||||||
|
''' |
||||||
|
import os |
||||||
|
import sys |
||||||
|
|
||||||
|
try: |
||||||
|
import numpy |
||||||
|
import numpy.core.multiarray |
||||||
|
except ImportError: |
||||||
|
print('OpenCV bindings requires "numpy" package.') |
||||||
|
print('Install it via command:') |
||||||
|
print(' pip install numpy') |
||||||
|
raise |
||||||
|
|
||||||
|
# TODO |
||||||
|
# is_x64 = sys.maxsize > 2**32 |
||||||
|
|
||||||
|
def bootstrap(): |
||||||
|
import sys |
||||||
|
if hasattr(sys, 'OpenCV_LOADER'): |
||||||
|
print(sys.path) |
||||||
|
raise ImportError('ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.') |
||||||
|
sys.OpenCV_LOADER = True |
||||||
|
|
||||||
|
DEBUG = False |
||||||
|
if hasattr(sys, 'OpenCV_LOADER_DEBUG'): |
||||||
|
DEBUG = True |
||||||
|
|
||||||
|
import platform |
||||||
|
if DEBUG: print('OpenCV loader: os.name="{}" platform.system()="{}"'.format(os.name, str(platform.system()))) |
||||||
|
|
||||||
|
LOADER_DIR=os.path.dirname(os.path.abspath(__file__)) |
||||||
|
|
||||||
|
PYTHON_EXTENSIONS_PATHS = [] |
||||||
|
BINARIES_PATHS = [] |
||||||
|
|
||||||
|
g_vars = globals() |
||||||
|
l_vars = locals() |
||||||
|
|
||||||
|
if sys.version_info[:2] < (3, 0): |
||||||
|
from cv2.load_config_py2 import exec_file_wrapper |
||||||
|
else: |
||||||
|
from . load_config_py3 import exec_file_wrapper |
||||||
|
|
||||||
|
def load_first_config(fnames, required=True): |
||||||
|
for fname in fnames: |
||||||
|
fpath = os.path.join(LOADER_DIR, fname) |
||||||
|
if not os.path.exists(fpath): |
||||||
|
if DEBUG: print('OpenCV loader: config not found, skip: {}'.format(fpath)) |
||||||
|
continue |
||||||
|
if DEBUG: print('OpenCV loader: loading config: {}'.format(fpath)) |
||||||
|
exec_file_wrapper(fpath, g_vars, l_vars) |
||||||
|
return True |
||||||
|
if required: |
||||||
|
raise ImportError('OpenCV loader: missing configuration file: {}. Check OpenCV installation.'.format(fnames)) |
||||||
|
|
||||||
|
load_first_config(['config.py'], True) |
||||||
|
load_first_config([ |
||||||
|
'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]), |
||||||
|
'config-{}.py'.format(sys.version_info[0]) |
||||||
|
], True) |
||||||
|
|
||||||
|
if DEBUG: print('OpenCV loader: PYTHON_EXTENSIONS_PATHS={}'.format(str(l_vars['PYTHON_EXTENSIONS_PATHS']))) |
||||||
|
if DEBUG: print('OpenCV loader: BINARIES_PATHS={}'.format(str(l_vars['BINARIES_PATHS']))) |
||||||
|
|
||||||
|
for p in reversed(l_vars['PYTHON_EXTENSIONS_PATHS']): |
||||||
|
sys.path.insert(0, p) |
||||||
|
|
||||||
|
if os.name == 'nt': |
||||||
|
os.environ['PATH'] = ';'.join(l_vars['BINARIES_PATHS']) + ';' + os.environ.get('PATH', '') |
||||||
|
if DEBUG: print('OpenCV loader: PATH={}'.format(str(os.environ['PATH']))) |
||||||
|
else: |
||||||
|
# amending of LD_LIBRARY_PATH works for sub-processes only |
||||||
|
os.environ['LD_LIBRARY_PATH'] = ':'.join(l_vars['BINARIES_PATHS']) + ':' + os.environ.get('LD_LIBRARY_PATH', '') |
||||||
|
|
||||||
|
if DEBUG: print('OpenCV loader: replacing cv2 module') |
||||||
|
del sys.modules['cv2'] |
||||||
|
import cv2 |
||||||
|
|
||||||
|
try: |
||||||
|
import sys |
||||||
|
del sys.OpenCV_LOADER |
||||||
|
except: |
||||||
|
pass |
||||||
|
|
||||||
|
if DEBUG: print('OpenCV loader: DONE') |
||||||
|
|
||||||
|
bootstrap() |
@ -0,0 +1,6 @@ |
|||||||
|
# flake8: noqa |
||||||
|
import sys |
||||||
|
|
||||||
|
if sys.version_info[:2] < (3, 0): |
||||||
|
def exec_file_wrapper(fpath, g_vars, l_vars): |
||||||
|
execfile(fpath, g_vars, l_vars) |
@ -0,0 +1,9 @@ |
|||||||
|
# flake8: noqa |
||||||
|
import os |
||||||
|
import sys |
||||||
|
|
||||||
|
if sys.version_info[:2] >= (3, 0): |
||||||
|
def exec_file_wrapper(fpath, g_vars, l_vars): |
||||||
|
with open(fpath) as f: |
||||||
|
code = compile(f.read(), os.path.basename(fpath), 'exec') |
||||||
|
exec(code, g_vars, l_vars) |
@ -0,0 +1,57 @@ |
|||||||
|
import os |
||||||
|
import sys |
||||||
|
import platform |
||||||
|
import setuptools |
||||||
|
|
||||||
|
SCRIPT_DIR=os.path.dirname(os.path.abspath(__file__)) |
||||||
|
|
||||||
|
def main(): |
||||||
|
os.chdir(SCRIPT_DIR) |
||||||
|
|
||||||
|
package_name = 'opencv' |
||||||
|
package_version = os.environ.get('OPENCV_VERSION', '4.0.0') # TODO |
||||||
|
|
||||||
|
long_description = 'Open Source Computer Vision Library Python bindings' # TODO |
||||||
|
|
||||||
|
setuptools.setup( |
||||||
|
name=package_name, |
||||||
|
version=package_version, |
||||||
|
url='https://github.com/opencv/opencv', |
||||||
|
license='BSD', |
||||||
|
description='OpenCV python bindings', |
||||||
|
long_description=long_description, |
||||||
|
long_description_content_type="text/markdown", |
||||||
|
packages=setuptools.find_packages(), |
||||||
|
maintainer="OpenCV Team", |
||||||
|
install_requires="numpy", |
||||||
|
classifiers=[ |
||||||
|
'Development Status :: 5 - Production/Stable', |
||||||
|
'Environment :: Console', |
||||||
|
'Intended Audience :: Developers', |
||||||
|
'Intended Audience :: Education', |
||||||
|
'Intended Audience :: Information Technology', |
||||||
|
'Intended Audience :: Science/Research', |
||||||
|
'License :: BSD License', |
||||||
|
'Operating System :: MacOS', |
||||||
|
'Operating System :: Microsoft :: Windows', |
||||||
|
'Operating System :: POSIX', |
||||||
|
'Operating System :: Unix', |
||||||
|
'Programming Language :: Python', |
||||||
|
'Programming Language :: Python :: 2', |
||||||
|
'Programming Language :: Python :: 2.7', |
||||||
|
'Programming Language :: Python :: 3', |
||||||
|
'Programming Language :: Python :: 3.4', |
||||||
|
'Programming Language :: Python :: 3.5', |
||||||
|
'Programming Language :: Python :: 3.6', |
||||||
|
'Programming Language :: Python :: 3.7', |
||||||
|
'Programming Language :: C++', |
||||||
|
'Programming Language :: Python :: Implementation :: CPython', |
||||||
|
'Topic :: Scientific/Engineering', |
||||||
|
'Topic :: Scientific/Engineering :: Image Recognition', |
||||||
|
'Topic :: Software Development', |
||||||
|
'Topic :: Software Development :: Libraries', |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
main() |
@ -0,0 +1,3 @@ |
|||||||
|
PYTHON_EXTENSIONS_PATHS = [ |
||||||
|
@CMAKE_PYTHON_EXTENSION_PATH@ |
||||||
|
] + PYTHON_EXTENSIONS_PATHS |
@ -0,0 +1,3 @@ |
|||||||
|
BINARIES_PATHS = [ |
||||||
|
@CMAKE_PYTHON_BINARIES_PATH@ |
||||||
|
] + BINARIES_PATHS |
@ -0,0 +1,54 @@ |
|||||||
|
ocv_assert(NOT OPENCV_SKIP_PYTHON_LOADER) |
||||||
|
|
||||||
|
set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}") |
||||||
|
|
||||||
|
ocv_assert(DEFINED OPENCV_PYTHON_INSTALL_PATH) |
||||||
|
if(OpenCV_FOUND) |
||||||
|
set(__loader_path "${OpenCV_BINARY_DIR}/python_loader") |
||||||
|
else() |
||||||
|
set(__loader_path "${CMAKE_BINARY_DIR}/python_loader") |
||||||
|
endif() |
||||||
|
|
||||||
|
set(__python_loader_install_tmp_path "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/python_loader/") |
||||||
|
if(IS_ABSOLUTE "${OPENCV_PYTHON_INSTALL_PATH}") |
||||||
|
set(OpenCV_PYTHON_INSTALL_PATH_RELATIVE_CONFIGCMAKE "${CMAKE_INSTALL_PREFIX}/") |
||||||
|
set(CMAKE_PYTHON_EXTENSION_INSTALL_PATH_BASE "'${CMAKE_INSTALL_PREFIX}'") |
||||||
|
else() |
||||||
|
file(RELATIVE_PATH OpenCV_PYTHON_INSTALL_PATH_RELATIVE_CONFIGCMAKE "${CMAKE_INSTALL_PREFIX}/${OPENCV_PYTHON_INSTALL_PATH}/cv2" ${CMAKE_INSTALL_PREFIX}) |
||||||
|
set(CMAKE_PYTHON_EXTENSION_INSTALL_PATH_BASE "os.path.join(LOADER_DIR, '${OpenCV_PYTHON_INSTALL_PATH_RELATIVE_CONFIGCMAKE}')") |
||||||
|
endif() |
||||||
|
|
||||||
|
set(PYTHON_LOADER_FILES |
||||||
|
"setup.py" "cv2/__init__.py" |
||||||
|
"cv2/load_config_py2.py" "cv2/load_config_py3.py" |
||||||
|
) |
||||||
|
foreach(fname ${PYTHON_LOADER_FILES}) |
||||||
|
get_filename_component(__dir "${fname}" DIRECTORY) |
||||||
|
file(COPY "${PYTHON_SOURCE_DIR}/package/${fname}" DESTINATION "${__loader_path}/${__dir}") |
||||||
|
install(FILES "${PYTHON_SOURCE_DIR}/package/${fname}" DESTINATION "${OPENCV_PYTHON_INSTALL_PATH}/${__dir}" COMPONENT python) |
||||||
|
endforeach() |
||||||
|
|
||||||
|
if(NOT OpenCV_FOUND) # Ignore "standalone" builds of Python bindings |
||||||
|
if(WIN32) |
||||||
|
if(CMAKE_GENERATOR MATCHES "Visual Studio") |
||||||
|
list(APPEND CMAKE_PYTHON_BINARIES_PATH "'${EXECUTABLE_OUTPUT_PATH}/Release'") # TODO: CMAKE_BUILD_TYPE is not defined |
||||||
|
else() |
||||||
|
list(APPEND CMAKE_PYTHON_BINARIES_PATH "'${EXECUTABLE_OUTPUT_PATH}'") |
||||||
|
endif() |
||||||
|
else() |
||||||
|
list(APPEND CMAKE_PYTHON_BINARIES_PATH "'${LIBRARY_OUTPUT_PATH}'") |
||||||
|
endif() |
||||||
|
string(REPLACE ";" ",\n " CMAKE_PYTHON_BINARIES_PATH "${CMAKE_PYTHON_BINARIES_PATH}") |
||||||
|
configure_file("${PYTHON_SOURCE_DIR}/package/template/config.py.in" "${__loader_path}/cv2/config.py" @ONLY) |
||||||
|
|
||||||
|
if(WIN32) |
||||||
|
list(APPEND CMAKE_PYTHON_BINARIES_INSTALL_PATH "os.path.join(${CMAKE_PYTHON_EXTENSION_INSTALL_PATH_BASE}, '${OPENCV_BIN_INSTALL_PATH}')") |
||||||
|
else() |
||||||
|
list(APPEND CMAKE_PYTHON_BINARIES_INSTALL_PATH "os.path.join(${CMAKE_PYTHON_EXTENSION_INSTALL_PATH_BASE}, '${OPENCV_LIB_INSTALL_PATH}')") |
||||||
|
endif() |
||||||
|
string(REPLACE ";" ",\n " CMAKE_PYTHON_BINARIES_PATH "${CMAKE_PYTHON_BINARIES_INSTALL_PATH}") |
||||||
|
configure_file("${PYTHON_SOURCE_DIR}/package/template/config.py.in" "${__python_loader_install_tmp_path}/cv2/config.py" @ONLY) |
||||||
|
install(FILES "${__python_loader_install_tmp_path}/cv2/config.py" DESTINATION "${OPENCV_PYTHON_INSTALL_PATH}/cv2/" COMPONENT python) |
||||||
|
|
||||||
|
message(STATUS "OpenCV Python: during development append to PYTHONPATH: ${__loader_path}") |
||||||
|
endif() |
@ -0,0 +1,124 @@ |
|||||||
|
@ECHO OFF |
||||||
|
SETLOCAL |
||||||
|
|
||||||
|
SET SCRIPT_DIR=%~dp0 |
||||||
|
IF NOT EXIST "%SCRIPT_DIR%\..\..\build\setup_vars_opencv4.cmd" ( |
||||||
|
ECHO ERROR: OpenCV Winpack installation is required |
||||||
|
pause |
||||||
|
exit |
||||||
|
) |
||||||
|
|
||||||
|
:: Detect Python binary |
||||||
|
python -V 2>nul |
||||||
|
IF %ERRORLEVEL% EQU 0 ( |
||||||
|
SET PYTHON=python |
||||||
|
GOTO :PYTHON_FOUND |
||||||
|
) |
||||||
|
|
||||||
|
CALL :QUERY_PYTHON 3.7 |
||||||
|
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND |
||||||
|
CALL :QUERY_PYTHON 3.6 |
||||||
|
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND |
||||||
|
CALL :QUERY_PYTHON 3.5 |
||||||
|
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND |
||||||
|
CALL :QUERY_PYTHON 3.4 |
||||||
|
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND |
||||||
|
CALL :QUERY_PYTHON 2.7 |
||||||
|
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND |
||||||
|
GOTO :PYTHON_NOT_FOUND |
||||||
|
|
||||||
|
:QUERY_PYTHON |
||||||
|
SETLOCAL |
||||||
|
SET PY_VERSION=%1 |
||||||
|
SET PYTHON_DIR= |
||||||
|
CALL :regquery "HKCU\SOFTWARE\Python\PythonCore\%PY_VERSION%\InstallPath" PYTHON_DIR |
||||||
|
IF EXIST "%PYTHON_DIR%\python.exe" ( |
||||||
|
SET "PYTHON=%PYTHON_DIR%\python.exe" |
||||||
|
GOTO :QUERY_PYTHON_FOUND |
||||||
|
) |
||||||
|
CALL :regquery "HKLM\SOFTWARE\Python\PythonCore\%PY_VERSION%\InstallPath" PYTHON_DIR |
||||||
|
IF EXIST "%PYTHON_DIR%\python.exe" ( |
||||||
|
SET "PYTHON=%PYTHON_DIR%\python.exe" |
||||||
|
GOTO :QUERY_PYTHON_FOUND |
||||||
|
) |
||||||
|
|
||||||
|
::echo Python %PY_VERSION% is not detected |
||||||
|
ENDLOCAL |
||||||
|
EXIT /B 1 |
||||||
|
|
||||||
|
:QUERY_PYTHON_FOUND |
||||||
|
ECHO Found Python %PY_VERSION% from Windows Registry: %PYTHON% |
||||||
|
ENDLOCAL & SET PYTHON=%PYTHON% |
||||||
|
EXIT /B 0 |
||||||
|
|
||||||
|
IF exist C:\Python27-x64\python.exe ( |
||||||
|
SET PYTHON=C:\Python27-x64\python.exe |
||||||
|
GOTO :PYTHON_FOUND |
||||||
|
) |
||||||
|
IF exist C:\Python27\python.exe ( |
||||||
|
SET PYTHON=C:\Python27\python.exe |
||||||
|
GOTO :PYTHON_FOUND |
||||||
|
) |
||||||
|
|
||||||
|
:PYTHON_NOT_FOUND |
||||||
|
ECHO ERROR: Python not found |
||||||
|
IF NOT DEFINED OPENCV_BATCH_MODE ( pause ) |
||||||
|
EXIT /B |
||||||
|
|
||||||
|
:PYTHON_FOUND |
||||||
|
ECHO Using Python: %PYTHON% |
||||||
|
|
||||||
|
:: Don't generate unnecessary .pyc cache files |
||||||
|
SET PYTHONDONTWRITEBYTECODE=1 |
||||||
|
|
||||||
|
IF [%1]==[] goto rundemo |
||||||
|
|
||||||
|
set SRC_FILENAME=%~dpnx1 |
||||||
|
echo SRC_FILENAME=%SRC_FILENAME% |
||||||
|
call :dirname "%SRC_FILENAME%" SRC_DIR |
||||||
|
call :dirname "%PYTHON%" PYTHON_DIR |
||||||
|
PUSHD %SRC_DIR% |
||||||
|
CALL "%SCRIPT_DIR%\..\..\build\setup_vars_opencv4.cmd" |
||||||
|
ECHO Run: %* |
||||||
|
%PYTHON% %* |
||||||
|
SET result=%errorlevel% |
||||||
|
IF %result% NEQ 0 ( |
||||||
|
IF NOT DEFINED OPENCV_BATCH_MODE ( |
||||||
|
SET "PATH=%PYTHON_DIR%;%PATH%" |
||||||
|
echo ================================================================================ |
||||||
|
echo ** Type 'python sample_name.py' to run sample |
||||||
|
echo ** Type 'exit' to exit from interactive shell and open the build directory |
||||||
|
echo ================================================================================ |
||||||
|
cmd /k echo Current directory: %CD% |
||||||
|
) |
||||||
|
) |
||||||
|
POPD |
||||||
|
EXIT /B %result% |
||||||
|
|
||||||
|
:rundemo |
||||||
|
PUSHD "%SCRIPT_DIR%\python" |
||||||
|
CALL "%SCRIPT_DIR%\..\..\build\setup_vars_opencv4.cmd" |
||||||
|
%PYTHON% demo.py |
||||||
|
SET result=%errorlevel% |
||||||
|
IF %result% NEQ 0 ( |
||||||
|
IF NOT DEFINED OPENCV_BATCH_MODE ( pause ) |
||||||
|
) |
||||||
|
POPD |
||||||
|
EXIT /B %result% |
||||||
|
|
||||||
|
|
||||||
|
:dirname file resultVar |
||||||
|
setlocal |
||||||
|
set _dir=%~dp1 |
||||||
|
set _dir=%_dir:~0,-1% |
||||||
|
endlocal & set %2=%_dir% |
||||||
|
EXIT /B 0 |
||||||
|
|
||||||
|
:regquery name resultVar |
||||||
|
SETLOCAL |
||||||
|
FOR /F "tokens=*" %%A IN ('REG QUERY "%1" /reg:64 /ve 2^>NUL ^| FIND "REG_SZ"') DO SET _val=%%A |
||||||
|
IF "x%_val%x"=="xx" EXIT /B 1 |
||||||
|
SET _val=%_val:*REG_SZ=% |
||||||
|
FOR /F "tokens=*" %%A IN ("%_val%") DO SET _val=%%A |
||||||
|
ENDLOCAL & SET %2=%_val% |
||||||
|
EXIT /B 0 |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue