vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
@@ -0,0 +1,629 @@
|
||||
if(WINRT)
|
||||
ocv_module_disable(dnn)
|
||||
endif()
|
||||
|
||||
set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass")
|
||||
|
||||
ocv_add_dispatched_file_force_all("layers/layers_common" AVX AVX2 AVX512_SKX RVV LASX NEON SVE)
|
||||
ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX RVV LASX NEON)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
|
||||
ocv_add_dispatched_file("layers/cpu_kernels/conv_winograd_f63" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/fast_gemm_kernels" AVX AVX2 NEON LASX)
|
||||
ocv_add_dispatched_file("layers/cpu_kernels/conv2_depthwise" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file("layers/cpu_kernels/conv2_kernels" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file_force_all("int8layers/conv2_int8_kernels" AVX2)
|
||||
ocv_add_dispatched_file("layers/cpu_kernels/activation_kernels" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/reduce2_kernels" AVX AVX2 NEON RVV LASX)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/transpose_kernels" AVX AVX2 NEON RVV LASX)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/gridsample_kernels" AVX AVX2 NEON RVV LASX)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/nary_eltwise_kernels" AVX AVX2 NEON RVV LASX)
|
||||
|
||||
ocv_add_module(dnn opencv_core opencv_imgproc opencv_geometry WRAP python java objc js)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake)
|
||||
|
||||
ocv_option(OPENCV_DNN_OPENCL "Build with OpenCL support" HAVE_OPENCL AND NOT APPLE)
|
||||
|
||||
if(OPENCV_DNN_OPENCL AND HAVE_OPENCL)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "CV_OCL4DNN=1")
|
||||
endif()
|
||||
|
||||
if(WITH_WEBNN AND HAVE_WEBNN)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "HAVE_WEBNN=1")
|
||||
endif()
|
||||
|
||||
if(HAVE_TIMVX)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "HAVE_TIMVX=1")
|
||||
endif()
|
||||
|
||||
if(HAVE_CANN)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "HAVE_CANN=1")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
ocv_target_compile_options(${the_module} PRIVATE "/fp:fast")
|
||||
elseif(CV_GCC OR CV_CLANG)
|
||||
ocv_target_compile_options(${the_module} PRIVATE -ffast-math)
|
||||
ocv_target_compile_options(${the_module} PRIVATE -fno-finite-math-only)
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_DNN_CUDA "Build with CUDA support"
|
||||
HAVE_CUDA
|
||||
AND HAVE_CUBLAS
|
||||
AND HAVE_CUDNN
|
||||
)
|
||||
|
||||
if(OPENCV_DNN_CUDA)
|
||||
if(HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "CV_CUDA4DNN=1")
|
||||
else()
|
||||
if(NOT HAVE_CUDA)
|
||||
message(SEND_ERROR "DNN: CUDA backend requires CUDA Toolkit. Please resolve dependency or disable OPENCV_DNN_CUDA=OFF")
|
||||
elseif(NOT HAVE_CUBLAS)
|
||||
message(SEND_ERROR "DNN: CUDA backend requires cuBLAS. Please resolve dependency or disable OPENCV_DNN_CUDA=OFF")
|
||||
elseif(NOT HAVE_CUDNN)
|
||||
message(SEND_ERROR "DNN: CUDA backend requires cuDNN. Please resolve dependency or disable OPENCV_DNN_CUDA=OFF")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
ocv_cmake_hook_append(INIT_MODULE_SOURCES_opencv_dnn "${CMAKE_CURRENT_LIST_DIR}/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake")
|
||||
|
||||
|
||||
if(MSVC)
|
||||
add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 )
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146
|
||||
/wd4305 /wd4127 /wd4100 /wd4512 /wd4125 /wd4389 /wd4510 /wd4610
|
||||
/wd4702 /wd4456 /wd4457 /wd4065 /wd4310 /wd4661 /wd4506
|
||||
)
|
||||
if(MSVC_VERSION LESS 1920) # MSVS 2015/2017, .pb.cc generated files
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4309) # 'static_cast': truncation of constant value
|
||||
endif()
|
||||
if(MSVC_VERSION LESS 1920) # <MSVS2019, .pb.cc generated files
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4189) # local variable is initialized but not referenced
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4592) # symbol will be dynamically initialized (implementation limitation)
|
||||
endif()
|
||||
else()
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated -Wmissing-prototypes -Wmissing-declarations -Wshadow
|
||||
-Wunused-parameter -Wsign-compare
|
||||
)
|
||||
endif()
|
||||
if(HAVE_CUDA)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef)
|
||||
endif()
|
||||
if(NOT HAVE_CXX11)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-undef) # LANG_CXX11 from protobuf files
|
||||
endif()
|
||||
|
||||
if(APPLE_FRAMEWORK)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshorten-64-to-32)
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
add_definitions(-DDISABLE_POSIX_MEMALIGN -DTH_DISABLE_HEAP_TRACKING)
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_PROTOBUF)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "OPENCV_DNN_EXTERNAL_PROTOBUF=1")
|
||||
endif()
|
||||
|
||||
#suppress warnings in autogenerated caffe.pb.* files
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS
|
||||
/wd4125 /wd4267 /wd4127 /wd4244 /wd4512 /wd4702
|
||||
/wd4456 /wd4510 /wd4610 /wd4800
|
||||
/wd4701 /wd4703 # potentially uninitialized local/pointer variable 'value' used
|
||||
/wd4505 # unreferenced local function has been removed
|
||||
/wd4458 # declaration of 'x' hides class member. GCC still works, MSVC bug is here: https://developercommunity.visualstudio.com/content/problem/219311/c-c4458-declaration-hides-class-member-warning-iss.html
|
||||
-wd858 -wd2196
|
||||
-Winvalid-offsetof # Apple Clang (attr_value.pb.cc)
|
||||
)
|
||||
|
||||
set(include_dirs "")
|
||||
set(libs "")
|
||||
|
||||
# ONNX Runtime
|
||||
ocv_option(WITH_ONNXRUNTIME "Build with ONNX Runtime support" OFF)
|
||||
ocv_option(DOWNLOAD_ONNXRUNTIME "Download ONNX Runtime prebuilt binaries" OFF IF WITH_ONNXRUNTIME)
|
||||
ocv_option(DOWNLOAD_ONNXRUNTIME_GPU "Download GPU-enabled ONNX Runtime prebuilt binaries when available" OFF IF WITH_ONNXRUNTIME)
|
||||
|
||||
set(ONNXRUNTIME_VERSION "1.25.1" CACHE STRING "ONNX Runtime version to download (prebuilt binaries)")
|
||||
|
||||
if(WITH_ONNXRUNTIME)
|
||||
include("${OpenCV_SOURCE_DIR}/cmake/FindONNX.cmake")
|
||||
|
||||
set(_ort_download_requested OFF)
|
||||
set(_ort_download_forced OFF)
|
||||
if(DOWNLOAD_ONNXRUNTIME OR DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
set(_ort_download_requested ON)
|
||||
set(_ort_download_forced ON)
|
||||
elseif(NOT HAVE_ONNXRUNTIME)
|
||||
set(_ort_download_requested ON)
|
||||
message(STATUS "DNN: ONNX Runtime was not found in system paths, attempting to download prebuilt package")
|
||||
endif()
|
||||
|
||||
if(_ort_download_requested)
|
||||
set(_ort_filename "")
|
||||
set(_ort_package_kind "CPU")
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
set(_ort_package_kind "GPU")
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _ort_processor)
|
||||
set(_ort_is_x64 FALSE)
|
||||
set(_ort_is_arm64 FALSE)
|
||||
set(_ort_is_x86 FALSE)
|
||||
if(X86_64 OR _ort_processor MATCHES "^(x86_64|amd64)$")
|
||||
set(_ort_is_x64 TRUE)
|
||||
endif()
|
||||
if(ARM64 OR AARCH64 OR _ort_processor MATCHES "^(aarch64|arm64)$")
|
||||
set(_ort_is_arm64 TRUE)
|
||||
endif()
|
||||
if(X86 OR _ort_processor MATCHES "^(x86|i[3-6]86)$")
|
||||
set(_ort_is_x86 TRUE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(_ort_is_arm64)
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
message(FATAL_ERROR "DNN: ONNX Runtime GPU package is not available for Windows ARM64. "
|
||||
"Disable DOWNLOAD_ONNXRUNTIME_GPU or use a supported platform (Windows x64 or Linux x64).")
|
||||
endif()
|
||||
set(_ort_filename "onnxruntime-win-arm64-${ONNXRUNTIME_VERSION}.zip")
|
||||
elseif(_ort_is_x64)
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
set(_ort_filename "onnxruntime-win-x64-gpu-${ONNXRUNTIME_VERSION}.zip")
|
||||
else()
|
||||
set(_ort_filename "onnxruntime-win-x64-${ONNXRUNTIME_VERSION}.zip")
|
||||
endif()
|
||||
elseif(_ort_is_x86)
|
||||
message(FATAL_ERROR
|
||||
"DNN: No official ONNX Runtime prebuilt package detected for 32-bit Windows and "
|
||||
"ONNXRUNTIME_VERSION='${ONNXRUNTIME_VERSION}'. "
|
||||
"Disable DOWNLOAD_ONNXRUNTIME and provide ONNXRT_ROOT_DIR manually."
|
||||
)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
message(FATAL_ERROR "DNN: ONNX Runtime GPU package is not available for macOS. "
|
||||
"Disable DOWNLOAD_ONNXRUNTIME_GPU or use a supported platform (Windows x64 or Linux x64).")
|
||||
endif()
|
||||
if(_ort_is_arm64)
|
||||
set(_ort_filename "onnxruntime-osx-arm64-${ONNXRUNTIME_VERSION}.tgz")
|
||||
elseif(_ort_is_x64)
|
||||
set(_ort_filename "onnxruntime-osx-x86_64-${ONNXRUNTIME_VERSION}.tgz")
|
||||
else()
|
||||
set(_ort_filename "onnxruntime-osx-universal2-${ONNXRUNTIME_VERSION}.tgz")
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
if(_ort_is_x64)
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
set(_ort_filename "onnxruntime-linux-x64-gpu-${ONNXRUNTIME_VERSION}.tgz")
|
||||
else()
|
||||
set(_ort_filename "onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz")
|
||||
endif()
|
||||
elseif(_ort_is_arm64)
|
||||
if(DOWNLOAD_ONNXRUNTIME_GPU)
|
||||
message(FATAL_ERROR "DNN: ONNX Runtime GPU package is not available for Linux AArch64. "
|
||||
"Disable DOWNLOAD_ONNXRUNTIME_GPU or use a supported platform (Windows x64 or Linux x64).")
|
||||
endif()
|
||||
set(_ort_filename "onnxruntime-linux-aarch64-${ONNXRUNTIME_VERSION}.tgz")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT _ort_filename)
|
||||
if(_ort_download_forced)
|
||||
message(FATAL_ERROR
|
||||
"DNN: DOWNLOAD_ONNXRUNTIME=ON, but there is no official ONNX Runtime prebuilt package for "
|
||||
"CMAKE_SYSTEM_NAME='${CMAKE_SYSTEM_NAME}', CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}'. "
|
||||
"Disable DOWNLOAD_ONNXRUNTIME and provide an installed ORT via ONNXRT_ROOT_DIR, or use a supported platform."
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
set(_ort_url "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/${_ort_filename}")
|
||||
string(REGEX REPLACE "\\.(tgz|zip)$" "" _ort_unpack_dirname "${_ort_filename}")
|
||||
|
||||
set(_ort_download_dir "${OpenCV_BINARY_DIR}/3rdparty/onnxruntime")
|
||||
set(_ort_cache_dir "${OPENCV_DOWNLOAD_PATH}/onnxruntime")
|
||||
set(_ort_cache_archive "${_ort_cache_dir}/${_ort_filename}")
|
||||
set(_ort_extracted_dir "${_ort_download_dir}/${_ort_unpack_dirname}")
|
||||
|
||||
message(STATUS "DNN: ONNX Runtime download mode: ${_ort_package_kind}")
|
||||
message(STATUS "DNN: ONNX Runtime package: ${_ort_filename}")
|
||||
|
||||
# Download to persistent cache if not already present
|
||||
if(NOT EXISTS "${_ort_cache_archive}")
|
||||
file(MAKE_DIRECTORY "${_ort_cache_dir}")
|
||||
message(STATUS "DNN: Downloading ONNX Runtime package from ${_ort_url}")
|
||||
file(DOWNLOAD "${_ort_url}" "${_ort_cache_archive}"
|
||||
SHOW_PROGRESS
|
||||
STATUS _ort_download_status
|
||||
LOG _ort_download_log)
|
||||
list(GET _ort_download_status 0 _ort_download_status_code)
|
||||
if(NOT _ort_download_status_code EQUAL 0)
|
||||
file(REMOVE "${_ort_cache_archive}")
|
||||
if(_ort_download_forced)
|
||||
message(FATAL_ERROR "DNN: ONNX Runtime download failed. URL='${_ort_url}'. Log: ${_ort_download_log}")
|
||||
else()
|
||||
message(STATUS "DNN: ONNX Runtime download failed, skipping. Log: ${_ort_download_log}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "DNN: ONNX Runtime package found in cache: ${_ort_cache_archive}")
|
||||
endif()
|
||||
|
||||
# Extract to build dir if not already extracted
|
||||
if(EXISTS "${_ort_cache_archive}" AND NOT EXISTS "${_ort_extracted_dir}")
|
||||
file(MAKE_DIRECTORY "${_ort_download_dir}")
|
||||
message(STATUS "DNN: Extracting ONNX Runtime package to ${_ort_download_dir}")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
file(ARCHIVE_EXTRACT INPUT "${_ort_cache_archive}"
|
||||
DESTINATION "${_ort_download_dir}")
|
||||
else()
|
||||
if(_ort_filename MATCHES "\\.zip$")
|
||||
set(_ort_tar_flags xvf)
|
||||
else()
|
||||
set(_ort_tar_flags xzf)
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E tar ${_ort_tar_flags} "${_ort_cache_archive}"
|
||||
WORKING_DIRECTORY "${_ort_download_dir}"
|
||||
RESULT_VARIABLE _ort_extract_status
|
||||
)
|
||||
if(NOT _ort_extract_status EQUAL 0)
|
||||
message(FATAL_ERROR "DNN: ONNX Runtime extraction failed for '${_ort_cache_archive}'.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ONNXRT_ROOT_DIR "${_ort_extracted_dir}"
|
||||
CACHE PATH "ONNX Runtime install directory" FORCE)
|
||||
|
||||
if(NOT APPLE AND NOT WIN32)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath,'$ORIGIN/../3rdparty/onnxruntime/${_ort_unpack_dirname}/lib'")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,'$ORIGIN/../3rdparty/onnxruntime/${_ort_unpack_dirname}/lib'")
|
||||
endif()
|
||||
|
||||
include("${OpenCV_SOURCE_DIR}/cmake/FindONNX.cmake")
|
||||
endif()
|
||||
endif() # _ort_download_requested
|
||||
|
||||
if(HAVE_ONNX)
|
||||
set(HAVE_ONNXRUNTIME 1 CACHE INTERNAL "ONNX Runtime availability")
|
||||
# Suppress warnings from ONNX Runtime headers
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wsuggest-override -Wsign-promo)
|
||||
|
||||
if(ONNXRUNTIME_PREFER_STATIC)
|
||||
set(_ort_static_lib "")
|
||||
if(ONNXRT_ROOT_DIR)
|
||||
find_file(_ort_static_lib
|
||||
NAMES libonnxruntime.a
|
||||
HINTS "${ONNXRT_ROOT_DIR}"
|
||||
PATH_SUFFIXES lib lib64
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif()
|
||||
if(NOT _ort_static_lib AND ONNX_LIBRARIES)
|
||||
foreach(_ort_lib ${ONNX_LIBRARIES})
|
||||
get_filename_component(_ort_lib_dir "${_ort_lib}" DIRECTORY)
|
||||
find_file(_ort_static_candidate
|
||||
NAMES libonnxruntime.a
|
||||
HINTS "${_ort_lib_dir}"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(_ort_static_candidate AND _ort_static_candidate MATCHES "\\.a$")
|
||||
set(_ort_static_lib "${_ort_static_candidate}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
if(_ort_static_lib AND _ort_static_lib MATCHES "\\.a$")
|
||||
set(ONNX_LIBRARIES "${_ort_static_lib}" CACHE STRING "ONNX Runtime libraries" FORCE)
|
||||
message(STATUS "DNN: ONNX Runtime static library selected: ${_ort_static_lib}")
|
||||
endif()
|
||||
unset(_ort_static_candidate)
|
||||
unset(_ort_static_lib)
|
||||
endif()
|
||||
|
||||
if(ONNX_INCLUDE_DIR)
|
||||
list(APPEND include_dirs "${ONNX_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(ONNX_LIBRARIES)
|
||||
list(APPEND libs "${ONNX_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
add_definitions(-DHAVE_ONNXRUNTIME=1)
|
||||
message(STATUS "DNN: ONNX Runtime enabled")
|
||||
|
||||
# Ensure runtime ORT binaries are deployed into OpenCV install tree
|
||||
set(_ort_runtime_libs "")
|
||||
if(WIN32)
|
||||
if(ONNXRT_ROOT_DIR)
|
||||
file(GLOB _ort_runtime_libs "${ONNXRT_ROOT_DIR}/bin/onnxruntime*.dll")
|
||||
endif()
|
||||
if(_ort_runtime_libs)
|
||||
install(FILES ${_ort_runtime_libs} DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
if(ONNXRT_ROOT_DIR)
|
||||
file(GLOB _ort_runtime_libs "${ONNXRT_ROOT_DIR}/lib/libonnxruntime*.dylib")
|
||||
endif()
|
||||
if(NOT _ort_runtime_libs AND ONNX_LIBRARIES)
|
||||
foreach(_ort_lib ${ONNX_LIBRARIES})
|
||||
get_filename_component(_ort_lib_dir "${_ort_lib}" DIRECTORY)
|
||||
file(GLOB _ort_runtime_libs "${_ort_lib_dir}/libonnxruntime*.dylib")
|
||||
if(_ort_runtime_libs)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
if(_ort_runtime_libs)
|
||||
install(FILES ${_ort_runtime_libs} DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs)
|
||||
endif()
|
||||
else()
|
||||
if(ONNXRT_ROOT_DIR)
|
||||
file(GLOB _ort_runtime_libs "${ONNXRT_ROOT_DIR}/lib/libonnxruntime.so*")
|
||||
endif()
|
||||
if(NOT _ort_runtime_libs AND ONNX_LIBRARIES)
|
||||
foreach(_ort_lib ${ONNX_LIBRARIES})
|
||||
get_filename_component(_ort_lib_dir "${_ort_lib}" DIRECTORY)
|
||||
file(GLOB _ort_runtime_libs "${_ort_lib_dir}/libonnxruntime.so*")
|
||||
if(_ort_runtime_libs)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
if(_ort_runtime_libs)
|
||||
install(FILES ${_ort_runtime_libs} DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs)
|
||||
endif()
|
||||
endif()
|
||||
unset(_ort_runtime_libs)
|
||||
else()
|
||||
message(SEND_ERROR
|
||||
"DNN: ONNX Runtime support was requested (WITH_ONNXRUNTIME=ON), but it was not found. "
|
||||
"Set ONNXRT_ROOT_DIR to an existing installation or enable DOWNLOAD_ONNXRUNTIME=ON."
|
||||
)
|
||||
endif()
|
||||
|
||||
unset(_ort_download_requested)
|
||||
unset(_ort_download_forced)
|
||||
endif()
|
||||
|
||||
if(HAVE_PROTOBUF)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "HAVE_PROTOBUF=1")
|
||||
|
||||
if(PROTOBUF_UPDATE_FILES)
|
||||
file(GLOB proto_files "${CMAKE_CURRENT_LIST_DIR}/src/tensorflow/*.proto" "${CMAKE_CURRENT_LIST_DIR}/src/onnx/opencv-onnx.proto")
|
||||
if(CMAKE_VERSION VERSION_LESS "3.13.0")
|
||||
set(PROTOBUF_GENERATE_CPP_APPEND_PATH ON) # required for tensorflow
|
||||
protobuf_generate_cpp(fw_srcs fw_hdrs ${proto_files})
|
||||
else()
|
||||
protobuf_generate(
|
||||
APPEND_PATH # required for tensorflow
|
||||
LANGUAGE cpp
|
||||
IMPORT_DIRS ${Protobuf_IMPORT_DIRS}
|
||||
OUT_VAR fw_srcs
|
||||
PROTOC_EXE ${Protobuf_PROTOC_EXECUTABLE}
|
||||
PROTOS ${proto_files})
|
||||
set(fw_hdrs "${fw_srcs}")
|
||||
# separate the header files and source files
|
||||
list(FILTER fw_srcs EXCLUDE REGEX ".+\.h$")
|
||||
list(FILTER fw_hdrs INCLUDE REGEX ".+\.h$")
|
||||
endif()
|
||||
else()
|
||||
file(GLOB fw_srcs "${CMAKE_CURRENT_LIST_DIR}/misc/tensorflow/*.cc" "${CMAKE_CURRENT_LIST_DIR}/misc/caffe/opencv-caffe.pb.cc" "${CMAKE_CURRENT_LIST_DIR}/misc/onnx/opencv-onnx.pb.cc")
|
||||
file(GLOB fw_hdrs "${CMAKE_CURRENT_LIST_DIR}/misc/tensorflow/*.h" "${CMAKE_CURRENT_LIST_DIR}/misc/caffe/opencv-caffe.pb.h" "${CMAKE_CURRENT_LIST_DIR}/misc/onnx/opencv-onnx.pb.h")
|
||||
set(fw_inc "${CMAKE_CURRENT_LIST_DIR}/misc/caffe" "${CMAKE_CURRENT_LIST_DIR}/misc/tensorflow" "${CMAKE_CURRENT_LIST_DIR}/misc/onnx")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_DNN_TFLITE "Build with TFLite support" (TARGET ocv.3rdparty.flatbuffers))
|
||||
if(TARGET ocv.3rdparty.flatbuffers AND OPENCV_DNN_TFLITE)
|
||||
if(NOT HAVE_FLATBUFFERS)
|
||||
message(FATAL_ERROR "DNN: TFLite is not supported without enabled 'flatbuffers'. Check build configuration.")
|
||||
endif()
|
||||
list(APPEND libs ocv.3rdparty.flatbuffers)
|
||||
list(APPEND fw_hdrs "${CMAKE_CURRENT_LIST_DIR}/misc/tflite/schema_generated.h")
|
||||
list(APPEND fw_inc "${CMAKE_CURRENT_LIST_DIR}/misc/tflite")
|
||||
|
||||
# Schema is generated by this command:
|
||||
#add_custom_command(
|
||||
# OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/schema_generated.h"
|
||||
# COMMAND flatbuffers::flatc --cpp -o "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/src/tflite/schema.fbs")
|
||||
endif()
|
||||
|
||||
list(APPEND include_dirs ${fw_inc})
|
||||
list(APPEND libs ${Protobuf_LIBRARIES})
|
||||
if(NOT BUILD_PROTOBUF)
|
||||
list(APPEND include_dirs ${Protobuf_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
set(sources_options "")
|
||||
|
||||
list(APPEND libs ${LAPACK_LIBRARIES})
|
||||
if(OPENCV_DNN_OPENCL AND HAVE_OPENCL)
|
||||
list(APPEND include_dirs ${OPENCL_INCLUDE_DIRS})
|
||||
else()
|
||||
set(sources_options EXCLUDE_OPENCL)
|
||||
endif()
|
||||
|
||||
if(OPENCV_DNN_CUDA AND HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN)
|
||||
list(APPEND include_dirs ${CUDA_TOOLKIT_INCLUDE} ${CUDNN_INCLUDE_DIRS})
|
||||
set(CC_LIST ${CUDA_ARCH_BIN})
|
||||
separate_arguments(CC_LIST)
|
||||
foreach(cc ${CC_LIST})
|
||||
if(cc VERSION_LESS 3.0)
|
||||
message(FATAL_ERROR "CUDA backend for DNN module requires CC 3.0 or higher. Please remove unsupported architectures from CUDA_ARCH_BIN option or disable OPENCV_DNN_CUDA=OFF.")
|
||||
endif()
|
||||
endforeach()
|
||||
unset(CC_LIST)
|
||||
if(ENABLE_CUDA_FIRST_CLASS_LANGUAGE)
|
||||
list(APPEND libs CUDA::cudart${CUDA_LIB_EXT} ${CUDNN_LIBRARIES} CUDA::cublas${CUDA_LIB_EXT})
|
||||
if(NOT CUDA_VERSION VERSION_LESS 10.1)
|
||||
list(APPEND libs CUDA::cublasLt${CUDA_LIB_EXT})
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(sources_options ${sources_options} EXCLUDE_CUDA)
|
||||
endif()
|
||||
|
||||
if(HAVE_TIMVX)
|
||||
list(APPEND include_dirs ${TIMVX_INCLUDE_DIR})
|
||||
list(APPEND libs -Wl,--whole-archive ${TIMVX_LIBRARY} -Wl,--no-whole-archive)
|
||||
endif()
|
||||
|
||||
if(HAVE_CANN)
|
||||
list(APPEND include_dirs ${CANN_INCLUDE_DIRS})
|
||||
list(APPEND libs -Wl,--whole-archive ${CANN_LIBRARIES} -Wl,--no-whole-archive)
|
||||
endif()
|
||||
|
||||
set(webnn_srcs "")
|
||||
if(NOT EMSCRIPTEN)
|
||||
if(HAVE_WEBNN)
|
||||
list(APPEND include_dirs ${WEBNN_HEADER_DIRS})
|
||||
list(APPEND include_dirs ${WEBNN_INCLUDE_DIRS})
|
||||
list(APPEND libs -Wl,--whole-archive ${WEBNN_LIBRARIES} -Wl,--no-whole-archive)
|
||||
list(APPEND webnn_srcs $ENV{WEBNN_NATIVE_DIR}/gen/src/webnn/webnn_cpp.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Vendored MLAS (Microsoft Linear Algebra Subprograms) from ONNX Runtime.
|
||||
# Sources live in 3rdparty/mlas/. Builds to an OBJECT library whose objects
|
||||
# link directly into opencv_dnn. Skipped under Emscripten: MLAS is a native
|
||||
# CPU SGEMM accelerator (asm/intrinsic kernels) and the wasm scalar fallback
|
||||
# offers no benefit for the JS bindings build that produces opencv.js.
|
||||
set(HAVE_MLAS 0)
|
||||
# Reset status flags + arch booleans
|
||||
foreach(_v OPENCV_DNN_MLAS_ENABLED OPENCV_DNN_MLAS_SKIP_REASON
|
||||
MLAS_X86_64 MLAS_X86 MLAS_ARM MLAS_ARM64 MLAS_POWER
|
||||
MLAS_LOONGARCH64 MLAS_S390X MLAS_RISCV64 MLAS_WASM
|
||||
MLAS_HAS_ASM MLAS_HAS_POWER10 MLAS_HAS_RISCV64_RVV)
|
||||
unset(${_v} CACHE)
|
||||
endforeach()
|
||||
if(NOT EMSCRIPTEN)
|
||||
add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/mlas" "${CMAKE_BINARY_DIR}/3rdparty/mlas")
|
||||
endif()
|
||||
if(HAVE_MLAS)
|
||||
add_definitions(-DHAVE_MLAS=1)
|
||||
list(APPEND include_dirs ${MLAS_INCLUDE_DIRS})
|
||||
message(STATUS "DNN: MLAS (vendored) enabled.")
|
||||
else()
|
||||
message(STATUS "DNN: MLAS (vendored) disabled — host arch/OS not wired up.")
|
||||
endif()
|
||||
|
||||
ocv_module_include_directories(${include_dirs})
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
ocv_append_source_files_cxx_compiler_options(fw_srcs "-Wno-suggest-override") # GCC
|
||||
ocv_append_source_files_cxx_compiler_options(fw_srcs "-Wno-array-bounds") # GCC 9.3.0 (Ubuntu 20.04)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
ocv_append_source_files_cxx_compiler_options(fw_srcs "-Wno-inconsistent-missing-override") # Clang
|
||||
endif()
|
||||
|
||||
set(dnn_runtime_libs "")
|
||||
|
||||
file(GLOB_RECURSE dnn_srcs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/*.cpp"
|
||||
)
|
||||
file(GLOB_RECURSE dnn_int_hdrs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/*.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/*.h"
|
||||
)
|
||||
set(dnn_plugin_srcs ${dnn_srcs} ${dnn_int_hdrs})
|
||||
ocv_list_filterout_ex(dnn_plugin_srcs
|
||||
"/src/dnn.cpp$|/src/dnn_utils.cpp$|/src/dnn_read.cpp$|/src/registry.cpp$|/src/backend.cpp$"
|
||||
# importers
|
||||
"/src/(caffe|onnx|tensorflow)/"
|
||||
# executors
|
||||
"/src/(cuda|cuda4dnn|ocl4dnn|vkcom|webnn)/"
|
||||
)
|
||||
|
||||
ocv_option(OPENCV_DNN_OPENVINO "Build with OpenVINO support (2021.4+)" (TARGET ocv.3rdparty.openvino))
|
||||
if(TARGET ocv.3rdparty.openvino AND OPENCV_DNN_OPENVINO)
|
||||
if(NOT HAVE_OPENVINO AND NOT HAVE_NGRAPH)
|
||||
message(FATAL_ERROR "DNN: Inference Engine is not supported without enabled 'nGraph'. Check build configuration.")
|
||||
endif()
|
||||
if("openvino" IN_LIST DNN_PLUGIN_LIST OR DNN_PLUGIN_LIST STREQUAL "all")
|
||||
# plugin doesn't support PCH, separate directory scope is necessary
|
||||
# opencv_world requires absolute path
|
||||
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/misc/plugin/openvino" "${CMAKE_CURRENT_BINARY_DIR}/dnn_plugin_openvino")
|
||||
elseif(NOT OPENCV_DNN_BUILTIN_BACKEND)
|
||||
list(APPEND dnn_runtime_libs ocv.3rdparty.openvino)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(OPENCV_DNN_BACKEND_DEFAULT "" CACHE STRING "Default backend used by the DNN module (DNN_BACKEND_OPENCV if empty)")
|
||||
if(OPENCV_DNN_BACKEND_DEFAULT)
|
||||
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/dnn_params.cpp" "OPENCV_DNN_BACKEND_DEFAULT=${OPENCV_DNN_BACKEND_DEFAULT}")
|
||||
endif()
|
||||
|
||||
ocv_install_used_external_targets(${libs} ${dnn_runtime_libs})
|
||||
|
||||
ocv_glob_module_sources(${sources_options} SOURCES ${fw_srcs} ${webnn_srcs} ${MLAS_OBJECTS})
|
||||
ocv_create_module(${libs} ${dnn_runtime_libs})
|
||||
ocv_add_samples()
|
||||
ocv_add_accuracy_tests(${dnn_runtime_libs})
|
||||
|
||||
if(NOT BUILD_PROTOBUF)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_compile_definitions(opencv_test_dnn PRIVATE "OPENCV_DNN_EXTERNAL_PROTOBUF=1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Include Tokenizer
|
||||
file(GLOB extra_tokenizer_src
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/tokenizer/*.cpp"
|
||||
)
|
||||
list(APPEND include_dirs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/tokenizer"
|
||||
)
|
||||
ocv_glob_module_sources(${sources_options} SOURCES ${fw_srcs} ${webnn_srcs} ${extra_tokenizer_src})
|
||||
|
||||
set(perf_path "${CMAKE_CURRENT_LIST_DIR}/perf")
|
||||
file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp")
|
||||
file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h")
|
||||
ocv_add_perf_tests(${dnn_runtime_libs}
|
||||
FILES test_common "${CMAKE_CURRENT_LIST_DIR}/test/test_common.hpp" "${CMAKE_CURRENT_LIST_DIR}/test/test_common.impl.hpp"
|
||||
FILES Src ${perf_srcs}
|
||||
FILES Include ${perf_hdrs}
|
||||
)
|
||||
|
||||
if(DNN_ENABLE_PLUGINS)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_compile_definitions(opencv_test_dnn PRIVATE ENABLE_PLUGINS)
|
||||
endif()
|
||||
if(OPENCV_DEBUG_POSTFIX)
|
||||
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/backend.cpp" "DEBUG_POSTFIX=${OPENCV_DEBUG_POSTFIX}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_TEST_DNN_OPENVINO "Build test with OpenVINO code" (TARGET ocv.3rdparty.openvino))
|
||||
if(TARGET ocv.3rdparty.openvino AND OPENCV_TEST_DNN_OPENVINO)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_link_libraries(opencv_test_dnn ocv.3rdparty.openvino)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_TEST_DNN_CANN "Build test with CANN" (TARGET ocv.3rdparty.cann))
|
||||
if(TARGET ocv.3rdparty.cann AND OPENCV_TEST_DNN_CANN)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_link_libraries(opencv_test_dnn ocv.3rdparty.cann)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_TEST_DNN_TIMVX "Build test with TIM-VX" (HAVE_TIMVX))
|
||||
if(OPENCV_TEST_DNN_TIMVX)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_compile_definitions(opencv_test_dnn PRIVATE "HAVE_TIMVX=1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_option(OPENCV_TEST_DNN_TFLITE "Build test with TFLite" (OPENCV_DNN_TFLITE))
|
||||
if(OPENCV_TEST_DNN_TFLITE)
|
||||
if(TARGET opencv_test_dnn)
|
||||
ocv_target_compile_definitions(opencv_test_dnn PRIVATE "OPENCV_TEST_DNN_TFLITE=1")
|
||||
endif()
|
||||
if(TARGET opencv_perf_dnn)
|
||||
ocv_target_compile_definitions(opencv_perf_dnn PRIVATE "OPENCV_TEST_DNN_TFLITE=1")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,11 @@
|
||||
if(NOT (OPENCV_DNN_OPENCL AND HAVE_OPENCL))
|
||||
message(STATUS "opencv_dnn: filter out ocl4dnn source code")
|
||||
ocv_list_filterout(OPENCV_MODULE_${the_module}_SOURCES "/ocl4dnn/")
|
||||
ocv_list_filterout(OPENCV_MODULE_${the_module}_HEADERS "/ocl4dnn/")
|
||||
endif()
|
||||
|
||||
if(NOT (OPENCV_DNN_CUDA AND HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN))
|
||||
message(STATUS "opencv_dnn: filter out cuda4dnn source code")
|
||||
ocv_list_filterout(OPENCV_MODULE_${the_module}_SOURCES "/cuda4dnn/")
|
||||
ocv_list_filterout(OPENCV_MODULE_${the_module}_HEADERS "/cuda4dnn/")
|
||||
endif()
|
||||
@@ -0,0 +1,29 @@
|
||||
if(PROJECT_NAME STREQUAL "OpenCV")
|
||||
set(ENABLE_PLUGINS_DEFAULT ON)
|
||||
if(EMSCRIPTEN OR IOS OR WINRT)
|
||||
set(ENABLE_PLUGINS_DEFAULT OFF)
|
||||
endif()
|
||||
set(DNN_PLUGIN_LIST "" CACHE STRING "List of DNN backends to be compiled as plugins (openvino, etc or special value 'all')")
|
||||
set(DNN_ENABLE_PLUGINS "${ENABLE_PLUGINS_DEFAULT}" CACHE BOOL "Allow building and using of DNN plugins")
|
||||
mark_as_advanced(DNN_PLUGIN_LIST DNN_ENABLE_PLUGINS)
|
||||
|
||||
string(REPLACE "," ";" DNN_PLUGIN_LIST "${DNN_PLUGIN_LIST}") # support comma-separated list (,) too
|
||||
string(TOLOWER "${DNN_PLUGIN_LIST}" DNN_PLUGIN_LIST)
|
||||
if(NOT DNN_ENABLE_PLUGINS)
|
||||
if(DNN_PLUGIN_LIST)
|
||||
message(WARNING "DNN: plugins are disabled through DNN_ENABLE_PLUGINS, so DNN_PLUGIN_LIST='${DNN_PLUGIN_LIST}' is ignored")
|
||||
set(DNN_PLUGIN_LIST "")
|
||||
endif()
|
||||
else()
|
||||
# Make virtual plugins target
|
||||
if(NOT TARGET opencv_dnn_plugins)
|
||||
add_custom_target(opencv_dnn_plugins ALL)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# Detect available dependencies
|
||||
#
|
||||
|
||||
# OpenVINO - detected by main CMake scripts (shared with G-API)
|
||||
@@ -0,0 +1,81 @@
|
||||
function(ocv_create_builtin_dnn_plugin name target)
|
||||
|
||||
ocv_debug_message("ocv_create_builtin_dnn_plugin(${ARGV})")
|
||||
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "${target} does not exist!")
|
||||
endif()
|
||||
if(NOT OpenCV_SOURCE_DIR)
|
||||
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
|
||||
endif()
|
||||
|
||||
message(STATUS "DNN: add builtin plugin '${name}'")
|
||||
|
||||
set(ENABLE_PRECOMPILED_HEADERS OFF) # no support for PCH in plugins, conflicts with module's source files
|
||||
|
||||
# TODO: update CPU optimizations scripts to support plugins
|
||||
add_definitions(-D__OPENCV_BUILD=1)
|
||||
add_definitions(-DBUILD_PLUGIN=1)
|
||||
include_directories("${OPENCV_MODULE_opencv_dnn_BINARY_DIR}") # Cannot open include file: 'layers/layers_common.simd_declarations.hpp'
|
||||
|
||||
foreach(src ${ARGN})
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/src/${src}")
|
||||
list(APPEND sources "${CMAKE_CURRENT_LIST_DIR}/src/${src}")
|
||||
elseif(IS_ABSOLUTE "${src}")
|
||||
list(APPEND sources "${src}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown source: ${src}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(OPENCV_MODULE_${the_module}_SOURCES_DISPATCHED)
|
||||
list(APPEND sources ${OPENCV_MODULE_${the_module}_SOURCES_DISPATCHED})
|
||||
endif()
|
||||
|
||||
set(__${name}_DEPS_EXT "")
|
||||
ocv_compiler_optimization_process_sources(sources __${name}_DEPS_EXT ${name})
|
||||
|
||||
add_library(${name} MODULE ${sources})
|
||||
target_include_directories(${name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
target_link_libraries(${name} PRIVATE ${target} ${__${name}_DEPS_EXT})
|
||||
target_link_libraries(${name} PRIVATE ${__plugin_libs})
|
||||
|
||||
foreach(mod opencv_dnn
|
||||
opencv_core
|
||||
opencv_imgproc
|
||||
opencv_dnn
|
||||
)
|
||||
ocv_target_link_libraries(${name} LINK_PRIVATE ${mod})
|
||||
ocv_target_include_directories(${name} "${OPENCV_MODULE_${mod}_LOCATION}/include")
|
||||
endforeach()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_USE_MATH_DEFINES)
|
||||
set(OPENCV_PLUGIN_VERSION "${OPENCV_DLLVERSION}" CACHE STRING "")
|
||||
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
|
||||
set(OPENCV_PLUGIN_ARCH "_64" CACHE STRING "")
|
||||
else()
|
||||
set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
|
||||
endif()
|
||||
else()
|
||||
set(OPENCV_PLUGIN_VERSION "" CACHE STRING "")
|
||||
set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
|
||||
endif()
|
||||
|
||||
set_target_properties(${name} PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
OUTPUT_NAME "${name}${OPENCV_PLUGIN_VERSION}${OPENCV_PLUGIN_ARCH}"
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(${name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||
install(TARGETS ${name} OPTIONAL LIBRARY DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT plugins)
|
||||
else()
|
||||
install(TARGETS ${name} OPTIONAL LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT plugins)
|
||||
endif()
|
||||
|
||||
add_dependencies(opencv_dnn_plugins ${name})
|
||||
|
||||
endfunction()
|
||||
@@ -0,0 +1,78 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifndef OPENCV_DNN_HPP
|
||||
#define OPENCV_DNN_HPP
|
||||
|
||||
// This is an umbrella header to include into you project.
|
||||
// We are free to change headers layout in dnn subfolder, so please include
|
||||
// this header for future compatibility
|
||||
|
||||
|
||||
/** @defgroup dnn Deep Neural Network module
|
||||
@{
|
||||
This module contains:
|
||||
- API for new layers creation, layers are building bricks of neural networks;
|
||||
- set of built-in most-useful Layers;
|
||||
- API to construct and modify comprehensive neural networks from layers;
|
||||
- functionality for loading serialized networks models from different frameworks.
|
||||
|
||||
Functionality of this module is designed only for forward pass computations (i.e. network testing).
|
||||
A network training is in principle not supported.
|
||||
@}
|
||||
*/
|
||||
/** @example samples/dnn/classification.cpp
|
||||
Check @ref tutorial_dnn_googlenet "the corresponding tutorial" for more details
|
||||
*/
|
||||
/** @example samples/dnn/colorization.cpp
|
||||
*/
|
||||
/** @example samples/dnn/object_detection.cpp
|
||||
Check @ref tutorial_dnn_yolo "the corresponding tutorial" for more details
|
||||
*/
|
||||
/** @example samples/dnn/openpose.cpp
|
||||
*/
|
||||
/** @example samples/dnn/segmentation.cpp
|
||||
*/
|
||||
/** @example samples/dnn/text_detection.cpp
|
||||
*/
|
||||
#include <opencv2/dnn/dnn.hpp>
|
||||
|
||||
#endif /* OPENCV_DNN_HPP */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
/*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) 2013, OpenCV Foundation, 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 <opencv2/core.hpp>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
#include <opencv2/dnn/dnn.hpp>
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_DICT_HPP
|
||||
#define OPENCV_DNN_DNN_DICT_HPP
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
|
||||
/** @brief This struct stores the scalar value (or array) of one of the following type: double, cv::String or int64.
|
||||
* @todo Maybe int64 is useless because double type exactly stores at least 2^52 integers.
|
||||
*/
|
||||
struct CV_EXPORTS_W DictValue
|
||||
{
|
||||
DictValue(const DictValue &r);
|
||||
explicit DictValue(bool i) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i ? 1 : 0; } //!< Constructs integer scalar
|
||||
explicit DictValue(int64 i = 0) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
|
||||
CV_WRAP explicit DictValue(int i) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
|
||||
explicit DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; } //!< Constructs integer scalar
|
||||
CV_WRAP explicit DictValue(double p) : type(Param::REAL), pd(new AutoBuffer<double,1>) { (*pd)[0] = p; } //!< Constructs floating point scalar
|
||||
CV_WRAP explicit DictValue(const String &s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< Constructs string scalar
|
||||
explicit DictValue(const char *s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< @overload
|
||||
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayInt(TypeIter begin, int size); //!< Constructs integer array
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayReal(TypeIter begin, int size); //!< Constructs floating point array
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayString(TypeIter begin, int size); //!< Constructs array of strings
|
||||
|
||||
template<typename T>
|
||||
T get(int idx = -1) const; //!< Tries to convert array element with specified index to requested type and returns its.
|
||||
|
||||
int size() const;
|
||||
|
||||
CV_WRAP bool isInt() const;
|
||||
CV_WRAP bool isString() const;
|
||||
CV_WRAP bool isReal() const;
|
||||
|
||||
CV_WRAP int getIntValue(int idx = -1) const;
|
||||
CV_WRAP double getRealValue(int idx = -1) const;
|
||||
CV_WRAP String getStringValue(int idx = -1) const;
|
||||
|
||||
DictValue &operator=(const DictValue &r);
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const DictValue &dictv);
|
||||
|
||||
~DictValue();
|
||||
|
||||
private:
|
||||
|
||||
Param type;
|
||||
|
||||
union
|
||||
{
|
||||
AutoBuffer<int64, 1> *pi;
|
||||
AutoBuffer<double, 1> *pd;
|
||||
AutoBuffer<String, 1> *ps;
|
||||
void *pv;
|
||||
};
|
||||
|
||||
DictValue(Param _type, void *_p) : type(_type), pv(_p) {}
|
||||
void release();
|
||||
};
|
||||
|
||||
/** @brief This class implements name-value dictionary, values are instances of DictValue. */
|
||||
class CV_EXPORTS Dict
|
||||
{
|
||||
typedef std::map<String, DictValue> _Dict;
|
||||
_Dict dict;
|
||||
|
||||
public:
|
||||
|
||||
//! Checks a presence of the @p key in the dictionary.
|
||||
bool has(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns pointer to its value, else returns NULL.
|
||||
DictValue *ptr(const String &key);
|
||||
|
||||
/** @overload */
|
||||
const DictValue *ptr(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns its value, else an error will be generated.
|
||||
const DictValue &get(const String &key) const;
|
||||
|
||||
/** @overload */
|
||||
template <typename T>
|
||||
T get(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns its value, else returns @p defaultValue.
|
||||
template <typename T>
|
||||
T get(const String &key, const T &defaultValue) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns its value, else returns empty vector.
|
||||
template <typename T>
|
||||
std::vector<T> getVector(const String &key) const;
|
||||
|
||||
//! Sets new @p value for the @p key, or adds new key-value pair into the dictionary.
|
||||
template<typename T>
|
||||
const T &set(const String &key, const T &value);
|
||||
|
||||
//! Erase @p key from the dictionary.
|
||||
void erase(const String &key);
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Dict &dict);
|
||||
|
||||
std::map<String, DictValue>::const_iterator begin() const;
|
||||
|
||||
std::map<String, DictValue>::const_iterator end() const;
|
||||
};
|
||||
|
||||
//! @}
|
||||
CV__DNN_INLINE_NS_END
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,447 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_INL_HPP
|
||||
#define OPENCV_DNN_DNN_INL_HPP
|
||||
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayInt(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::INT, new AutoBuffer<int64, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.pi)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayReal(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::REAL, new AutoBuffer<double, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.pd)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayString(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::STRING, new AutoBuffer<String, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.ps)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline DictValue DictValue::get<DictValue>(int idx) const
|
||||
{
|
||||
CV_Assert(idx == -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int64 DictValue::get<int64>(int idx) const
|
||||
{
|
||||
CV_Assert((idx == -1 && size() == 1) || (idx >= 0 && idx < size()));
|
||||
idx = (idx == -1) ? 0 : idx;
|
||||
|
||||
if (type == Param::INT)
|
||||
{
|
||||
return (*pi)[idx];
|
||||
}
|
||||
else if (type == Param::REAL)
|
||||
{
|
||||
double doubleValue = (*pd)[idx];
|
||||
|
||||
double fracpart, intpart;
|
||||
fracpart = std::modf(doubleValue, &intpart);
|
||||
CV_Assert(fracpart == 0.0);
|
||||
|
||||
return (int64)doubleValue;
|
||||
}
|
||||
else if (type == Param::STRING)
|
||||
{
|
||||
return std::atoi((*ps)[idx].c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(isInt() || isReal() || isString());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int DictValue::get<int>(int idx) const
|
||||
{
|
||||
return saturate_cast<int>(get<int64>(idx));
|
||||
}
|
||||
|
||||
inline int DictValue::getIntValue(int idx) const
|
||||
{
|
||||
return saturate_cast<int>(get<int64>(idx));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::vector<int> DictValue::get<std::vector<int> >(int idx) const
|
||||
{
|
||||
CV_Assert(idx == -1);
|
||||
int size_ = size();
|
||||
std::vector<int> values(size_);
|
||||
|
||||
for (int i = 0; i < size_; i++)
|
||||
values[i] = get<int>(i);
|
||||
return values;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned DictValue::get<unsigned>(int idx) const
|
||||
{
|
||||
return (unsigned)get<int64>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool DictValue::get<bool>(int idx) const
|
||||
{
|
||||
return (get<int64>(idx) != 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double DictValue::get<double>(int idx) const
|
||||
{
|
||||
CV_Assert((idx == -1 && size() == 1) || (idx >= 0 && idx < size()));
|
||||
idx = (idx == -1) ? 0 : idx;
|
||||
|
||||
if (type == Param::REAL)
|
||||
{
|
||||
return (*pd)[idx];
|
||||
}
|
||||
else if (type == Param::INT)
|
||||
{
|
||||
return (double)(*pi)[idx];
|
||||
}
|
||||
else if (type == Param::STRING)
|
||||
{
|
||||
return std::atof((*ps)[idx].c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(isReal() || isInt() || isString());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline double DictValue::getRealValue(int idx) const
|
||||
{
|
||||
return get<double>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float DictValue::get<float>(int idx) const
|
||||
{
|
||||
return (float)get<double>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline String DictValue::get<String>(int idx) const
|
||||
{
|
||||
CV_Assert(isString());
|
||||
CV_Assert((idx == -1 && ps->size() == 1) || (idx >= 0 && idx < (int)ps->size()));
|
||||
return (*ps)[(idx == -1) ? 0 : idx];
|
||||
}
|
||||
|
||||
|
||||
inline String DictValue::getStringValue(int idx) const
|
||||
{
|
||||
return get<String>(idx);
|
||||
}
|
||||
|
||||
inline void DictValue::release()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Param::INT:
|
||||
delete pi;
|
||||
break;
|
||||
case Param::STRING:
|
||||
delete ps;
|
||||
break;
|
||||
case Param::REAL:
|
||||
delete pd;
|
||||
break;
|
||||
case Param::BOOLEAN:
|
||||
case Param::MAT:
|
||||
case Param::MAT_VECTOR:
|
||||
case Param::ALGORITHM:
|
||||
case Param::FLOAT:
|
||||
case Param::UNSIGNED_INT:
|
||||
case Param::UINT64:
|
||||
case Param::UCHAR:
|
||||
case Param::SCALAR:
|
||||
break; // unhandled
|
||||
}
|
||||
}
|
||||
|
||||
inline DictValue::~DictValue()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
inline DictValue & DictValue::operator=(const DictValue &r)
|
||||
{
|
||||
if (&r == this)
|
||||
return *this;
|
||||
|
||||
if (r.type == Param::INT)
|
||||
{
|
||||
AutoBuffer<int64, 1> *tmp = new AutoBuffer<int64, 1>(*r.pi);
|
||||
release();
|
||||
pi = tmp;
|
||||
}
|
||||
else if (r.type == Param::STRING)
|
||||
{
|
||||
AutoBuffer<String, 1> *tmp = new AutoBuffer<String, 1>(*r.ps);
|
||||
release();
|
||||
ps = tmp;
|
||||
}
|
||||
else if (r.type == Param::REAL)
|
||||
{
|
||||
AutoBuffer<double, 1> *tmp = new AutoBuffer<double, 1>(*r.pd);
|
||||
release();
|
||||
pd = tmp;
|
||||
}
|
||||
|
||||
type = r.type;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline DictValue::DictValue(const DictValue &r)
|
||||
: pv(NULL)
|
||||
{
|
||||
type = r.type;
|
||||
|
||||
if (r.type == Param::INT)
|
||||
pi = new AutoBuffer<int64, 1>(*r.pi);
|
||||
else if (r.type == Param::STRING)
|
||||
ps = new AutoBuffer<String, 1>(*r.ps);
|
||||
else if (r.type == Param::REAL)
|
||||
pd = new AutoBuffer<double, 1>(*r.pd);
|
||||
}
|
||||
|
||||
inline bool DictValue::isString() const
|
||||
{
|
||||
return (type == Param::STRING);
|
||||
}
|
||||
|
||||
inline bool DictValue::isInt() const
|
||||
{
|
||||
return (type == Param::INT);
|
||||
}
|
||||
|
||||
inline bool DictValue::isReal() const
|
||||
{
|
||||
return (type == Param::REAL || type == Param::INT);
|
||||
}
|
||||
|
||||
inline int DictValue::size() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Param::INT:
|
||||
return (int)pi->size();
|
||||
case Param::STRING:
|
||||
return (int)ps->size();
|
||||
case Param::REAL:
|
||||
return (int)pd->size();
|
||||
case Param::BOOLEAN:
|
||||
case Param::MAT:
|
||||
case Param::MAT_VECTOR:
|
||||
case Param::ALGORITHM:
|
||||
case Param::FLOAT:
|
||||
case Param::UNSIGNED_INT:
|
||||
case Param::UINT64:
|
||||
case Param::UCHAR:
|
||||
case Param::SCALAR:
|
||||
break; // unhandled
|
||||
}
|
||||
CV_Error_(Error::StsInternal, ("Unhandled type (%d)", static_cast<int>(type)));
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const DictValue &dictv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dictv.isInt())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << dictv.get<int64>(i) << ", ";
|
||||
stream << dictv.get<int64>(i);
|
||||
}
|
||||
else if (dictv.isReal())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << dictv.get<double>(i) << ", ";
|
||||
stream << dictv.get<double>(i);
|
||||
}
|
||||
else if (dictv.isString())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << "\"" << dictv.get<String>(i) << "\", ";
|
||||
stream << dictv.get<String>(i);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool Dict::has(const String &key) const
|
||||
{
|
||||
return dict.count(key) != 0;
|
||||
}
|
||||
|
||||
inline DictValue *Dict::ptr(const String &key)
|
||||
{
|
||||
_Dict::iterator i = dict.find(key);
|
||||
return (i == dict.end()) ? NULL : &i->second;
|
||||
}
|
||||
|
||||
inline const DictValue *Dict::ptr(const String &key) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
return (i == dict.end()) ? NULL : &i->second;
|
||||
}
|
||||
|
||||
inline const DictValue &Dict::get(const String &key) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
if (i == dict.end())
|
||||
CV_Error(Error::StsObjectNotFound, "Required argument \"" + key + "\" not found into dictionary");
|
||||
return i->second;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T Dict::get(const String &key) const
|
||||
{
|
||||
return this->get(key).get<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T Dict::get(const String &key, const T &defaultValue) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
|
||||
if (i != dict.end())
|
||||
return i->second.get<T>();
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> Dict::getVector(const String &key) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
|
||||
if (i != dict.end())
|
||||
return i->second.get<std::vector<T> >();
|
||||
else
|
||||
return std::vector<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T &Dict::set(const String &key, const T &value)
|
||||
{
|
||||
_Dict::iterator i = dict.find(key);
|
||||
|
||||
if (i != dict.end())
|
||||
i->second = DictValue(value);
|
||||
else
|
||||
dict.insert(std::make_pair(key, DictValue(value)));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void Dict::erase(const String &key)
|
||||
{
|
||||
dict.erase(key);
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const Dict &dict)
|
||||
{
|
||||
Dict::_Dict::const_iterator it;
|
||||
for (it = dict.dict.begin(); it != dict.dict.end(); it++)
|
||||
stream << it->first << " : " << it->second << "\n";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::map<String, DictValue>::const_iterator Dict::begin() const
|
||||
{
|
||||
return dict.begin();
|
||||
}
|
||||
|
||||
inline std::map<String, DictValue>::const_iterator Dict::end() const
|
||||
{
|
||||
return dict.end();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
inline Arg::Arg() : idx(0) {}
|
||||
|
||||
inline Arg::Arg(int idx_) : idx(idx_) {}
|
||||
|
||||
inline bool Arg::empty() const { return idx == 0; }
|
||||
|
||||
inline Arg::operator int() const { return idx; }
|
||||
|
||||
inline bool operator == (const Arg& a, const Arg& b) { return a.idx == b.idx; }
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
// 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.
|
||||
//
|
||||
#ifndef OPENCV_DNN_LAYER_DETAILS_HPP
|
||||
#define OPENCV_DNN_LAYER_DETAILS_HPP
|
||||
|
||||
#include <opencv2/dnn/layer.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
/** @brief Registers layer constructor in runtime.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param constructorFunc pointer to the function of type LayerRegister::Constructor, which creates the layer.
|
||||
* @details This macros must be placed inside the function code.
|
||||
*/
|
||||
#define CV_DNN_REGISTER_LAYER_FUNC(type, constructorFunc) \
|
||||
cv::dnn::LayerFactory::registerLayer(#type, constructorFunc);
|
||||
|
||||
/** @brief Registers layer class in runtime.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param class C++ class, derived from Layer.
|
||||
* @details This macros must be placed inside the function code.
|
||||
*/
|
||||
#define CV_DNN_REGISTER_LAYER_CLASS(type, class) \
|
||||
cv::dnn::LayerFactory::registerLayer(#type, cv::dnn::details::_layerDynamicRegisterer<class>);
|
||||
|
||||
/** @brief Registers layer constructor on module load time.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param constructorFunc pointer to the function of type LayerRegister::Constructor, which creates the layer.
|
||||
* @details This macros must be placed outside the function code.
|
||||
*/
|
||||
#define CV_DNN_REGISTER_LAYER_FUNC_STATIC(type, constructorFunc) \
|
||||
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constructorFunc);
|
||||
|
||||
/** @brief Registers layer class on module load time.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param class C++ class, derived from Layer.
|
||||
* @details This macros must be placed outside the function code.
|
||||
*/
|
||||
#define CV_DNN_REGISTER_LAYER_CLASS_STATIC(type, class) \
|
||||
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams ¶ms) \
|
||||
{ return Ptr<Layer>(new class(params)); } \
|
||||
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename LayerClass>
|
||||
Ptr<Layer> _layerDynamicRegisterer(LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<Layer>(LayerClass::create(params));
|
||||
}
|
||||
|
||||
//allows automatically register created layer on module load time
|
||||
class _LayerStaticRegisterer
|
||||
{
|
||||
String type;
|
||||
public:
|
||||
|
||||
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constructor layerConstructor)
|
||||
{
|
||||
this->type = layerType;
|
||||
LayerFactory::registerLayer(layerType, layerConstructor);
|
||||
}
|
||||
|
||||
~_LayerStaticRegisterer()
|
||||
{
|
||||
LayerFactory::unregisterLayer(type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifndef OPENCV_DNN_LAYER_HPP
|
||||
#define OPENCV_DNN_LAYER_HPP
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
//!
|
||||
//! @defgroup dnnLayerFactory Utilities for New Layers Registration
|
||||
//! @{
|
||||
|
||||
/** @brief %Layer factory allows to create instances of registered layers. */
|
||||
class CV_EXPORTS LayerFactory
|
||||
{
|
||||
public:
|
||||
|
||||
//! Each Layer class must provide this function to the factory
|
||||
typedef Ptr<Layer>(*Constructor)(LayerParams ¶ms);
|
||||
|
||||
//! Registers the layer class with typename @p type and specified @p constructor. Thread-safe.
|
||||
static void registerLayer(const String &type, Constructor constructor);
|
||||
|
||||
//! Unregisters registered layer with specified type name. Thread-safe.
|
||||
static void unregisterLayer(const String &type);
|
||||
|
||||
//! Check if layer is registered.
|
||||
static bool isLayerRegistered(const std::string& type);
|
||||
|
||||
/** @brief Creates instance of registered layer.
|
||||
* @param type type name of creating layer.
|
||||
* @param params parameters which will be used for layer initialization.
|
||||
* @note Thread-safe.
|
||||
*/
|
||||
static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params);
|
||||
|
||||
private:
|
||||
LayerFactory();
|
||||
};
|
||||
|
||||
//! @}
|
||||
//! @}
|
||||
CV__DNN_INLINE_NS_END
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_LAYER_REG_HPP
|
||||
#define OPENCV_DNN_LAYER_REG_HPP
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
|
||||
typedef std::map<std::string, std::vector<LayerFactory::Constructor> > LayerFactory_Impl;
|
||||
|
||||
//! Register layer types of DNN model.
|
||||
//!
|
||||
//! @note In order to thread-safely access the factory, see getLayerFactoryMutex() function.
|
||||
LayerFactory_Impl& getLayerFactoryImpl();
|
||||
|
||||
//! Get the mutex guarding @ref LayerFactory_Impl, see getLayerFactoryImpl() function.
|
||||
Mutex& getLayerFactoryMutex();
|
||||
|
||||
//! @}
|
||||
CV__DNN_INLINE_NS_END
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,293 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_SHAPE_UTILS_HPP
|
||||
#define OPENCV_DNN_DNN_SHAPE_UTILS_HPP
|
||||
|
||||
#include <opencv2/dnn/dnn.hpp>
|
||||
#include <opencv2/core/cvdef.h> // CV_MAX_DIM
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
//Slicing
|
||||
|
||||
struct _Range : public cv::Range
|
||||
{
|
||||
_Range(const Range &r) : cv::Range(r) {}
|
||||
_Range(int start_, int size_ = 1) : cv::Range(start_, start_ + size_) {}
|
||||
};
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0)
|
||||
{
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 1; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1)
|
||||
{
|
||||
CV_Assert(m.dims >= 2);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 2; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2)
|
||||
{
|
||||
CV_Assert(m.dims >= 3);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 3; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
ranges[2] = r2;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2, const _Range &r3)
|
||||
{
|
||||
CV_Assert(m.dims >= 4);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 4; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
ranges[2] = r2;
|
||||
ranges[3] = r3;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat getPlane(const Mat &m, int n, int cn)
|
||||
{
|
||||
CV_Assert(m.dims > 2);
|
||||
int sz[CV_MAX_DIM];
|
||||
for(int i = 2; i < m.dims; i++)
|
||||
{
|
||||
sz[i-2] = m.size.p[i];
|
||||
}
|
||||
return Mat(m.dims - 2, sz, m.type(), (void*)m.ptr<float>(n, cn));
|
||||
}
|
||||
|
||||
static inline MatShape shape(const int* dims, const int n)
|
||||
{
|
||||
MatShape shape;
|
||||
shape.assign(dims, dims + n);
|
||||
return shape;
|
||||
}
|
||||
|
||||
static inline MatShape shape(const Mat& mat)
|
||||
{
|
||||
return mat.shape();
|
||||
}
|
||||
|
||||
static inline MatShape shape(const UMat& mat)
|
||||
{
|
||||
return mat.shape();
|
||||
}
|
||||
|
||||
#if 0 // issues with MatExpr wrapped into InputArray
|
||||
static inline
|
||||
MatShape shape(InputArray input)
|
||||
{
|
||||
int sz[CV_MAX_DIM];
|
||||
int ndims = input.sizend(sz);
|
||||
return shape(sz, ndims);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace {inline bool is_neg(int i) { return i < 0; }}
|
||||
|
||||
static inline MatShape shape(int a0, int a1=-1, int a2=-1, int a3=-1)
|
||||
{
|
||||
int shape_[] = {a0, a1, a2, a3};
|
||||
int dims = 1 + (a1 >= 0) + (a1 >= 0 && a2 >= 0) + (a1 >= 0 && a2 >= 0 && a3 >= 0);
|
||||
return shape(shape_, dims);
|
||||
}
|
||||
|
||||
static inline size_t total(const MatShape& shape, int start = -1, int end = -1)
|
||||
{
|
||||
//if (shape.empty())
|
||||
// return 0;
|
||||
|
||||
int dims = (int)shape.size();
|
||||
|
||||
if (start == -1) start = 0;
|
||||
if (end == -1) end = dims;
|
||||
|
||||
CV_CheckLE(0, start, "");
|
||||
CV_CheckLE(start, end, "");
|
||||
CV_CheckLE(end, dims, "");
|
||||
|
||||
size_t elems = 1;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
elems *= (size_t)shape[i];
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
// TODO: rename to countDimsElements()
|
||||
static inline size_t total(const Mat& mat, int start = -1, int end = -1)
|
||||
{
|
||||
if (mat.empty())
|
||||
return 0;
|
||||
|
||||
int dims = mat.dims;
|
||||
|
||||
if (start == -1) start = 0;
|
||||
if (end == -1) end = dims;
|
||||
|
||||
CV_CheckLE(0, start, "");
|
||||
CV_CheckLE(start, end, "");
|
||||
CV_CheckLE(end, dims, "");
|
||||
|
||||
size_t elems = 1;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
elems *= (size_t)mat.size[i];
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
static inline MatShape concat(const MatShape& a, const MatShape& b)
|
||||
{
|
||||
MatShape c = a;
|
||||
size_t a_size = a.size(), b_size = b.size(), c_size = a_size + b_size;
|
||||
c.resize(c_size);
|
||||
for (size_t i = 0; i < b_size; i++) {
|
||||
c[i+a_size] = b[i];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline std::string toString(const MatShape& shape, const String& name = "")
|
||||
{
|
||||
std::ostringstream ss;
|
||||
if (!name.empty())
|
||||
ss << name << ' ';
|
||||
ss << shape;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
static inline std::string toString(const std::vector<_Tp>& shape, const String& name = "")
|
||||
{
|
||||
std::ostringstream ss;
|
||||
if (!name.empty())
|
||||
ss << name << ' ';
|
||||
ss << '[';
|
||||
for(size_t i = 0, n = shape.size(); i < n; ++i)
|
||||
ss << ' ' << shape[i];
|
||||
ss << " ]";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
static inline void print(const std::vector<_Tp>& shape, const String& name = "")
|
||||
{
|
||||
std::cout << toString(shape, name) << std::endl;
|
||||
}
|
||||
template<typename _Tp>
|
||||
static inline std::ostream& operator<<(std::ostream &out, const std::vector<_Tp>& shape)
|
||||
{
|
||||
out << toString(shape);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// @brief Converts axis from `[-dims; dims)` (similar to Python's slice notation) to `[0; dims)` range.
|
||||
static inline
|
||||
int normalize_axis(int axis, int dims)
|
||||
{
|
||||
CV_Assert(dims >= 0);
|
||||
CV_Check(axis, axis >= -dims && axis <= dims, "");
|
||||
axis = (unsigned)axis < (unsigned)dims ? axis : axis < 0 ? axis + dims : axis - dims;
|
||||
return axis;
|
||||
}
|
||||
|
||||
static inline
|
||||
int normalize_axis(int axis, const MatShape& shape)
|
||||
{
|
||||
return normalize_axis(axis, (int)shape.size());
|
||||
}
|
||||
|
||||
static inline
|
||||
Range normalize_axis_range(const Range& r, int axisSize)
|
||||
{
|
||||
if (r == Range::all() || r == Range(0, INT_MAX))
|
||||
return Range(0, axisSize);
|
||||
CV_CheckGE(r.start, 0, "");
|
||||
Range clamped(r.start,
|
||||
r.end > 0 ? std::min(r.end, axisSize) : axisSize + r.end + 1);
|
||||
CV_DbgCheckGE(clamped.start, 0, "");
|
||||
CV_CheckLT(clamped.start, clamped.end, "");
|
||||
CV_CheckLE(clamped.end, axisSize, "");
|
||||
return clamped;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool isAllOnes(const MatShape &inputShape, int startPos, int endPos)
|
||||
{
|
||||
CV_CheckGE(startPos, 0, "");
|
||||
CV_CheckLE(startPos, endPos, "");
|
||||
CV_CheckLE(endPos, inputShape.dims, "");
|
||||
|
||||
for (int i = startPos; i < endPos; i++)
|
||||
{
|
||||
if (inputShape[i] != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_UTILS_DEBUG_UTILS_HPP
|
||||
#define OPENCV_DNN_UTILS_DEBUG_UTILS_HPP
|
||||
|
||||
#include "../dnn.hpp"
|
||||
|
||||
namespace cv { namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
/**
|
||||
* @brief Skip model import after diagnostic run in readNet() functions.
|
||||
* @param[in] skip Indicates whether to skip the import.
|
||||
*
|
||||
* This is an internal OpenCV function not intended for users.
|
||||
*/
|
||||
CV_EXPORTS void skipModelImport(bool skip);
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace
|
||||
|
||||
#endif // OPENCV_DNN_UTILS_DEBUG_UTILS_HPP
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#ifndef OPENCV_DNN_UTILS_INF_ENGINE_HPP
|
||||
#define OPENCV_DNN_UTILS_INF_ENGINE_HPP
|
||||
|
||||
#include "../dnn.hpp"
|
||||
|
||||
namespace cv { namespace dnn {
|
||||
CV__DNN_INLINE_NS_BEGIN
|
||||
|
||||
|
||||
/* Values for 'OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE' parameter */
|
||||
/// @deprecated
|
||||
#define CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API "NN_BUILDER"
|
||||
/// @deprecated
|
||||
#define CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH "NGRAPH"
|
||||
|
||||
/** @brief Returns Inference Engine internal backend API.
|
||||
*
|
||||
* See values of `CV_DNN_BACKEND_INFERENCE_ENGINE_*` macros.
|
||||
*
|
||||
* `OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE` runtime parameter (environment variable) is ignored since 4.6.0.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
CV_EXPORTS_W cv::String getInferenceEngineBackendType();
|
||||
|
||||
/** @brief Specify Inference Engine internal backend API.
|
||||
*
|
||||
* See values of `CV_DNN_BACKEND_INFERENCE_ENGINE_*` macros.
|
||||
*
|
||||
* @returns previous value of internal backend API
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
CV_EXPORTS_W cv::String setInferenceEngineBackendType(const cv::String& newBackendType);
|
||||
|
||||
|
||||
/** @brief Release a Myriad device (binded by OpenCV).
|
||||
*
|
||||
* Single Myriad device cannot be shared across multiple processes which uses
|
||||
* Inference Engine's Myriad plugin.
|
||||
*/
|
||||
CV_EXPORTS_W void resetMyriadDevice();
|
||||
|
||||
|
||||
/* Values for 'OPENCV_DNN_IE_VPU_TYPE' parameter */
|
||||
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_UNSPECIFIED ""
|
||||
/// Intel(R) Movidius(TM) Neural Compute Stick, NCS (USB 03e7:2150), Myriad2 (https://software.intel.com/en-us/movidius-ncs)
|
||||
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 "Myriad2"
|
||||
/// Intel(R) Neural Compute Stick 2, NCS2 (USB 03e7:2485), MyriadX (https://software.intel.com/ru-ru/neural-compute-stick)
|
||||
#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X "MyriadX"
|
||||
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_ARM_COMPUTE "ARM_COMPUTE"
|
||||
#define CV_DNN_INFERENCE_ENGINE_CPU_TYPE_X86 "X86"
|
||||
|
||||
|
||||
/** @brief Returns Inference Engine VPU type.
|
||||
*
|
||||
* See values of `CV_DNN_INFERENCE_ENGINE_VPU_TYPE_*` macros.
|
||||
*/
|
||||
CV_EXPORTS_W cv::String getInferenceEngineVPUType();
|
||||
|
||||
/** @brief Returns Inference Engine CPU type.
|
||||
*
|
||||
* Specify OpenVINO plugin: CPU or ARM.
|
||||
*/
|
||||
CV_EXPORTS_W cv::String getInferenceEngineCPUType();
|
||||
|
||||
/** @brief Release a HDDL plugin.
|
||||
*/
|
||||
CV_EXPORTS_W void releaseHDDLPlugin();
|
||||
|
||||
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace
|
||||
|
||||
#endif // OPENCV_DNN_UTILS_INF_ENGINE_HPP
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_VERSION_HPP
|
||||
#define OPENCV_DNN_VERSION_HPP
|
||||
|
||||
/// Use with major OpenCV version only.
|
||||
#define OPENCV_DNN_API_VERSION 20260605
|
||||
|
||||
#if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS
|
||||
#define CV__DNN_INLINE_NS __CV_CAT(dnn5_v, OPENCV_DNN_API_VERSION)
|
||||
#define CV__DNN_INLINE_NS_BEGIN namespace CV__DNN_INLINE_NS {
|
||||
#define CV__DNN_INLINE_NS_END }
|
||||
namespace cv { namespace dnn { namespace CV__DNN_INLINE_NS { } using namespace CV__DNN_INLINE_NS; }}
|
||||
#else
|
||||
#define CV__DNN_INLINE_NS_BEGIN
|
||||
#define CV__DNN_INLINE_NS_END
|
||||
#endif
|
||||
|
||||
#endif // OPENCV_DNN_VERSION_HPP
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
||||
# This script is used to estimate an accuracy of different face detection models.
|
||||
# COCO evaluation tool is used to compute an accuracy metrics (Average Precision).
|
||||
# Script works with different face detection datasets.
|
||||
import os
|
||||
import json
|
||||
from fnmatch import fnmatch
|
||||
from math import pi
|
||||
import cv2 as cv
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pycocotools.coco import COCO
|
||||
from pycocotools.cocoeval import COCOeval
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Evaluate OpenCV face detection algorithms '
|
||||
'using COCO evaluation tool, http://cocodataset.org/#detections-eval')
|
||||
parser.add_argument('--proto', help='Path to .pbtxt of TensorFlow graph')
|
||||
parser.add_argument('--model', help='Path to .onnx of ONNX model or .pb from TensorFlow')
|
||||
parser.add_argument('--cascade', help='Optional path to trained Haar cascade as '
|
||||
'an additional model for evaluation')
|
||||
parser.add_argument('--ann', help='Path to text file with ground truth annotations')
|
||||
parser.add_argument('--pics', help='Path to images root directory')
|
||||
parser.add_argument('--fddb', help='Evaluate FDDB dataset, http://vis-www.cs.umass.edu/fddb/', action='store_true')
|
||||
parser.add_argument('--wider', help='Evaluate WIDER FACE dataset, http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
dataset = {}
|
||||
dataset['images'] = []
|
||||
dataset['categories'] = [{ 'id': 0, 'name': 'face' }]
|
||||
dataset['annotations'] = []
|
||||
|
||||
def ellipse2Rect(params):
|
||||
rad_x = params[0]
|
||||
rad_y = params[1]
|
||||
angle = params[2] * 180.0 / pi
|
||||
center_x = params[3]
|
||||
center_y = params[4]
|
||||
pts = cv.ellipse2Poly((int(center_x), int(center_y)), (int(rad_x), int(rad_y)),
|
||||
int(angle), 0, 360, 10)
|
||||
rect = cv.boundingRect(pts)
|
||||
left = rect[0]
|
||||
top = rect[1]
|
||||
right = rect[0] + rect[2]
|
||||
bottom = rect[1] + rect[3]
|
||||
return left, top, right, bottom
|
||||
|
||||
def addImage(imagePath):
|
||||
assert('images' in dataset)
|
||||
imageId = len(dataset['images'])
|
||||
dataset['images'].append({
|
||||
'id': int(imageId),
|
||||
'file_name': imagePath
|
||||
})
|
||||
return imageId
|
||||
|
||||
def addBBox(imageId, left, top, width, height):
|
||||
assert('annotations' in dataset)
|
||||
dataset['annotations'].append({
|
||||
'id': len(dataset['annotations']),
|
||||
'image_id': int(imageId),
|
||||
'category_id': 0, # Face
|
||||
'bbox': [int(left), int(top), int(width), int(height)],
|
||||
'iscrowd': 0,
|
||||
'area': float(width * height)
|
||||
})
|
||||
|
||||
def addDetection(detections, imageId, left, top, width, height, score):
|
||||
detections.append({
|
||||
'image_id': int(imageId),
|
||||
'category_id': 0, # Face
|
||||
'bbox': [int(left), int(top), int(width), int(height)],
|
||||
'score': float(score)
|
||||
})
|
||||
|
||||
|
||||
def fddb_dataset(annotations, images):
|
||||
for d in os.listdir(annotations):
|
||||
if fnmatch(d, 'FDDB-fold-*-ellipseList.txt'):
|
||||
with open(os.path.join(annotations, d), 'rt') as f:
|
||||
lines = [line.rstrip('\n') for line in f]
|
||||
lineId = 0
|
||||
while lineId < len(lines):
|
||||
# Image
|
||||
imgPath = lines[lineId]
|
||||
lineId += 1
|
||||
imageId = addImage(os.path.join(images, imgPath) + '.jpg')
|
||||
|
||||
img = cv.imread(os.path.join(images, imgPath) + '.jpg')
|
||||
|
||||
# Faces
|
||||
numFaces = int(lines[lineId])
|
||||
lineId += 1
|
||||
for i in range(numFaces):
|
||||
params = [float(v) for v in lines[lineId].split()]
|
||||
lineId += 1
|
||||
left, top, right, bottom = ellipse2Rect(params)
|
||||
addBBox(imageId, left, top, width=right - left + 1,
|
||||
height=bottom - top + 1)
|
||||
|
||||
|
||||
def wider_dataset(annotations, images):
|
||||
with open(annotations, 'rt') as f:
|
||||
lines = [line.rstrip('\n') for line in f]
|
||||
lineId = 0
|
||||
while lineId < len(lines):
|
||||
# Image
|
||||
imgPath = lines[lineId]
|
||||
lineId += 1
|
||||
imageId = addImage(os.path.join(images, imgPath))
|
||||
|
||||
# Faces
|
||||
numFaces = int(lines[lineId])
|
||||
lineId += 1
|
||||
for i in range(numFaces):
|
||||
params = [int(v) for v in lines[lineId].split()]
|
||||
lineId += 1
|
||||
left, top, width, height = params[0], params[1], params[2], params[3]
|
||||
addBBox(imageId, left, top, width, height)
|
||||
|
||||
def evaluate():
|
||||
cocoGt = COCO('annotations.json')
|
||||
cocoDt = cocoGt.loadRes('detections.json')
|
||||
cocoEval = COCOeval(cocoGt, cocoDt, 'bbox')
|
||||
cocoEval.evaluate()
|
||||
cocoEval.accumulate()
|
||||
cocoEval.summarize()
|
||||
|
||||
|
||||
### Convert to COCO annotations format #########################################
|
||||
assert(args.fddb or args.wider)
|
||||
if args.fddb:
|
||||
fddb_dataset(args.ann, args.pics)
|
||||
elif args.wider:
|
||||
wider_dataset(args.ann, args.pics)
|
||||
|
||||
with open('annotations.json', 'wt') as f:
|
||||
json.dump(dataset, f)
|
||||
|
||||
### Obtain detections ##########################################################
|
||||
detections = []
|
||||
if args.proto and args.model and args.model.endswith('.pb'):
|
||||
net = cv.dnn.readNet(args.proto, args.model)
|
||||
|
||||
def detect(img, imageId):
|
||||
imgWidth = img.shape[1]
|
||||
imgHeight = img.shape[0]
|
||||
net.setInput(cv.dnn.blobFromImage(img, 1.0, (300, 300), (104., 177., 123.), False, False))
|
||||
out = net.forward()
|
||||
|
||||
for i in range(out.shape[2]):
|
||||
confidence = out[0, 0, i, 2]
|
||||
left = int(out[0, 0, i, 3] * img.shape[1])
|
||||
top = int(out[0, 0, i, 4] * img.shape[0])
|
||||
right = int(out[0, 0, i, 5] * img.shape[1])
|
||||
bottom = int(out[0, 0, i, 6] * img.shape[0])
|
||||
|
||||
x = max(0, min(left, img.shape[1] - 1))
|
||||
y = max(0, min(top, img.shape[0] - 1))
|
||||
w = max(0, min(right - x + 1, img.shape[1] - x))
|
||||
h = max(0, min(bottom - y + 1, img.shape[0] - y))
|
||||
|
||||
addDetection(detections, imageId, x, y, w, h, score=confidence)
|
||||
|
||||
elif args.model and args.model.endswith('.onnx'):
|
||||
net = cv.FaceDetectorYN.create(args.model, "", (320, 320), 0.3, 0.45, 5000)
|
||||
|
||||
def detect(img, imageId):
|
||||
net.setInputSize((img.shape[1], img.shape[0]))
|
||||
faces = net.detect(img)
|
||||
|
||||
if faces[1] is not None:
|
||||
for idx, face in enumerate(faces[1]):
|
||||
left, top, width, height = face[0], face[1], face[2], face[3]
|
||||
addDetection(detections, imageId, left, top, width, height, score=face[-1])
|
||||
|
||||
elif args.cascade:
|
||||
cascade = cv.CascadeClassifier(args.cascade)
|
||||
|
||||
def detect(img, imageId):
|
||||
srcImgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
faces = cascade.detectMultiScale(srcImgGray)
|
||||
|
||||
for rect in faces:
|
||||
left, top, width, height = rect[0], rect[1], rect[2], rect[3]
|
||||
addDetection(detections, imageId, left, top, width, height, score=1.0)
|
||||
|
||||
for i in range(len(dataset['images'])):
|
||||
sys.stdout.write('\r%d / %d' % (i + 1, len(dataset['images'])))
|
||||
sys.stdout.flush()
|
||||
|
||||
img = cv.imread(dataset['images'][i]['file_name'])
|
||||
imageId = int(dataset['images'][i]['id'])
|
||||
|
||||
detect(img, imageId)
|
||||
|
||||
with open('detections.json', 'wt') as f:
|
||||
json.dump(detections, f)
|
||||
|
||||
evaluate()
|
||||
|
||||
|
||||
def rm(f):
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
|
||||
rm('annotations.json')
|
||||
rm('detections.json')
|
||||
@@ -0,0 +1 @@
|
||||
misc/java/src/cpp/dnn_converters.hpp
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"type_dict": {
|
||||
"MatShape": {
|
||||
"j_type": "MatOfInt",
|
||||
"jn_type": "long",
|
||||
"jni_type": "jlong",
|
||||
"jni_var": "MatShape %(n)s",
|
||||
"suffix": "J",
|
||||
"v_type": "Mat",
|
||||
"j_import": "org.opencv.core.MatOfInt"
|
||||
},
|
||||
"vector_MatShape": {
|
||||
"j_type": "List<MatOfInt>",
|
||||
"jn_type": "List<MatOfInt>",
|
||||
"jni_type": "jobject",
|
||||
"jni_var": "std::vector< MatShape > %(n)s",
|
||||
"suffix": "Ljava_util_List",
|
||||
"v_type": "vector_MatShape",
|
||||
"j_import": "org.opencv.core.MatOfInt"
|
||||
},
|
||||
"vector_size_t": {
|
||||
"j_type": "MatOfDouble",
|
||||
"jn_type": "long",
|
||||
"jni_type": "jlong",
|
||||
"jni_var": "std::vector<size_t> %(n)s",
|
||||
"suffix": "J",
|
||||
"v_type": "Mat",
|
||||
"j_import": "org.opencv.core.MatOfDouble"
|
||||
},
|
||||
"vector_Ptr_Layer": {
|
||||
"j_type": "List<Layer>",
|
||||
"jn_type": "List<Layer>",
|
||||
"jni_type": "jobject",
|
||||
"jni_var": "std::vector< Ptr<cv::dnn::Layer> > %(n)s",
|
||||
"suffix": "Ljava_util_List",
|
||||
"v_type": "vector_Layer",
|
||||
"j_import": "org.opencv.dnn.Layer"
|
||||
},
|
||||
"vector_Target": {
|
||||
"j_type": "List<Integer>",
|
||||
"jn_type": "List<Integer>",
|
||||
"jni_type": "jobject",
|
||||
"jni_var": "std::vector< cv::dnn::Target > %(n)s",
|
||||
"suffix": "Ljava_util_List",
|
||||
"v_type": "vector_Target"
|
||||
},
|
||||
"LayerId": {
|
||||
"j_type": "DictValue",
|
||||
"jn_type": "long",
|
||||
"jn_args": [
|
||||
[
|
||||
"__int64",
|
||||
".getNativeObjAddr()"
|
||||
]
|
||||
|
||||
],
|
||||
"jni_name": "(*(*(Ptr<cv::dnn::DictValue>*)%(n)s_nativeObj))",
|
||||
"jni_type": "jlong",
|
||||
"suffix": "J",
|
||||
"j_import": "org.opencv.dnn.DictValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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
|
||||
|
||||
// Author: abratchik
|
||||
|
||||
#include "dnn_converters.hpp"
|
||||
|
||||
#define LOG_TAG "org.opencv.dnn"
|
||||
|
||||
void Mat_to_MatShape(cv::Mat& mat, cv::MatShape& matshape)
|
||||
{
|
||||
matshape.clear();
|
||||
CHECK_MAT(mat.type()==CV_32SC1 && mat.cols==1);
|
||||
matshape = (cv::MatShape) mat;
|
||||
}
|
||||
|
||||
void MatShape_to_Mat(cv::MatShape& matshape, cv::Mat& mat)
|
||||
{
|
||||
mat = cv::Mat(matshape, true);
|
||||
}
|
||||
|
||||
std::vector<cv::MatShape> List_to_vector_MatShape(JNIEnv* env, jobject list)
|
||||
{
|
||||
static jclass juArrayList = ARRAYLIST(env);
|
||||
jmethodID m_size = LIST_SIZE(env, juArrayList);
|
||||
jmethodID m_get = LIST_GET(env, juArrayList);
|
||||
|
||||
static jclass jMatOfInt = MATOFINT(env);
|
||||
|
||||
jint len = env->CallIntMethod(list, m_size);
|
||||
std::vector<cv::MatShape> result;
|
||||
result.reserve(len);
|
||||
for (jint i=0; i<len; i++)
|
||||
{
|
||||
jobject element = static_cast<jobject>(env->CallObjectMethod(list, m_get, i));
|
||||
cv::Mat& mat = *((cv::Mat*) GETNATIVEOBJ(env, jMatOfInt, element) );
|
||||
cv::MatShape matshape = (cv::MatShape) mat;
|
||||
result.push_back(matshape);
|
||||
env->DeleteLocalRef(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
jobject vector_Ptr_Layer_to_List(JNIEnv* env, std::vector<cv::Ptr<cv::dnn::Layer> >& vs)
|
||||
{
|
||||
static jclass juArrayList = ARRAYLIST(env);
|
||||
static jmethodID m_create = CONSTRUCTOR(env, juArrayList);
|
||||
jmethodID m_add = LIST_ADD(env, juArrayList);
|
||||
|
||||
static jclass jLayerClass = LAYER(env);
|
||||
static jmethodID m_create_layer = LAYER_CONSTRUCTOR(env, jLayerClass);
|
||||
|
||||
jobject result = env->NewObject(juArrayList, m_create, vs.size());
|
||||
for (std::vector< cv::Ptr<cv::dnn::Layer> >::iterator it = vs.begin(); it != vs.end(); ++it) {
|
||||
jobject element = env->NewObject(jLayerClass, m_create_layer, (*it).get());
|
||||
env->CallBooleanMethod(result, m_add, element);
|
||||
env->DeleteLocalRef(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
jobject vector_Target_to_List(JNIEnv* env, std::vector<cv::dnn::Target>& vs)
|
||||
{
|
||||
static jclass juArrayList = ARRAYLIST(env);
|
||||
static jmethodID m_create = CONSTRUCTOR(env, juArrayList);
|
||||
jmethodID m_add = LIST_ADD(env, juArrayList);
|
||||
|
||||
static jclass jInteger = env->FindClass("java/lang/Integer");
|
||||
static jmethodID m_create_Integer = env->GetMethodID(jInteger, "<init>", "(I)V");
|
||||
|
||||
jobject result = env->NewObject(juArrayList, m_create, vs.size());
|
||||
for (size_t i = 0; i < vs.size(); ++i)
|
||||
{
|
||||
jobject element = env->NewObject(jInteger, m_create_Integer, vs[i]);
|
||||
env->CallBooleanMethod(result, m_add, element);
|
||||
env->DeleteLocalRef(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list)
|
||||
{
|
||||
static jclass juArrayList = ARRAYLIST(env);
|
||||
jmethodID m_size = LIST_SIZE(env, juArrayList);
|
||||
jmethodID m_get = LIST_GET(env, juArrayList);
|
||||
|
||||
static jclass jLayerClass = LAYER(env);
|
||||
|
||||
jint len = env->CallIntMethod(list, m_size);
|
||||
std::vector< cv::Ptr<cv::dnn::Layer> > result;
|
||||
result.reserve(len);
|
||||
for (jint i=0; i<len; i++)
|
||||
{
|
||||
jobject element = static_cast<jobject>(env->CallObjectMethod(list, m_get, i));
|
||||
cv::Ptr<cv::dnn::Layer>* layer_ptr = (cv::Ptr<cv::dnn::Layer>*) GETNATIVEOBJ(env, jLayerClass, element) ;
|
||||
cv::Ptr<cv::dnn::Layer> layer = *(layer_ptr);
|
||||
result.push_back(layer);
|
||||
env->DeleteLocalRef(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// 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
|
||||
|
||||
// Author: abratchik
|
||||
|
||||
#ifndef DNN_CONVERTERS_HPP
|
||||
#define DNN_CONVERTERS_HPP
|
||||
|
||||
#include <jni.h>
|
||||
#include "opencv_java.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/dnn/dnn.hpp"
|
||||
|
||||
#define LAYER(ENV) static_cast<jclass>(ENV->NewGlobalRef(ENV->FindClass("org/opencv/dnn/Layer")))
|
||||
#define LAYER_CONSTRUCTOR(ENV, CLS) ENV->GetMethodID(CLS, "<init>", "(J)V")
|
||||
|
||||
using namespace cv::dnn;
|
||||
|
||||
void Mat_to_MatShape(cv::Mat& mat, cv::MatShape& matshape);
|
||||
|
||||
void MatShape_to_Mat(cv::MatShape& matshape, cv::Mat& mat);
|
||||
|
||||
std::vector<cv::MatShape> List_to_vector_MatShape(JNIEnv* env, jobject list);
|
||||
|
||||
jobject vector_Ptr_Layer_to_List(JNIEnv* env, std::vector<cv::Ptr<cv::dnn::Layer> >& vs);
|
||||
|
||||
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list);
|
||||
|
||||
jobject vector_Target_to_List(JNIEnv* env, std::vector<cv::dnn::Target>& vs);
|
||||
|
||||
#endif /* DNN_CONVERTERS_HPP */
|
||||
@@ -0,0 +1,149 @@
|
||||
package org.opencv.test.dnn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.core.Range;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Image2BlobParams;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class DnnBlobFromImageWithParamsTest extends OpenCVTestCase {
|
||||
|
||||
// test for DATA_LAYOUT_* and DNN_LAYOUT_* access from Core
|
||||
public void testDataLayoutConstants()
|
||||
{
|
||||
assertEquals(0, Core.DATA_LAYOUT_UNKNOWN);
|
||||
assertEquals(1, Core.DATA_LAYOUT_ND);
|
||||
assertEquals(2, Core.DATA_LAYOUT_NCHW);
|
||||
assertEquals(3, Core.DATA_LAYOUT_NCDHW);
|
||||
assertEquals(4, Core.DATA_LAYOUT_NHWC);
|
||||
assertEquals(5, Core.DATA_LAYOUT_NDHWC);
|
||||
assertEquals(6, Core.DATA_LAYOUT_PLANAR);
|
||||
assertEquals(7, Core.DATA_LAYOUT_BLOCK);
|
||||
}
|
||||
|
||||
public void testBlobFromImageWithParamsNHWCScalarScale()
|
||||
{
|
||||
// https://github.com/opencv/opencv/issues/27264
|
||||
Mat img = new Mat(10, 10, CvType.CV_8UC4, new Scalar(0, 1, 2, 3));
|
||||
Scalar scalefactor = new Scalar(0.1, 0.2, 0.3, 0.4);
|
||||
|
||||
Image2BlobParams params = new Image2BlobParams();
|
||||
params.set_scalefactor(scalefactor);
|
||||
params.set_datalayout(Core.DATA_LAYOUT_NHWC);
|
||||
|
||||
Mat blob = Dnn.blobFromImageWithParams(img, params); // [1, 10, 10, 4]
|
||||
|
||||
float[] expectedValues = { (float)scalefactor.val[0] * 0, (float)scalefactor.val[1] * 1, (float)scalefactor.val[2] * 2, (float)scalefactor.val[3] * 3 }; // Target Value.
|
||||
for (int h = 0; h < 10; h++)
|
||||
{
|
||||
for (int w = 0; w < 10; w++)
|
||||
{
|
||||
float[] actualValues = new float[4];
|
||||
blob.get(new int[]{0, h, w, 0}, actualValues);
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
// Check equal
|
||||
assertEquals(expectedValues[c], actualValues[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testBlobFromImageWithParamsCustomPaddingLetterBox()
|
||||
{
|
||||
Mat img = new Mat(40, 20, CvType.CV_8UC4, new Scalar(0, 1, 2, 3));
|
||||
|
||||
// Custom padding value that you have added
|
||||
Scalar customPaddingValue = new Scalar(5, 6, 7, 8); // Example padding value
|
||||
Size targetSize = new Size(20, 20);
|
||||
|
||||
Mat targetImg = img.clone();
|
||||
Core.copyMakeBorder(targetImg, targetImg, 0, 0, (int)targetSize.width / 2, (int)targetSize.width / 2, Core.BORDER_CONSTANT, customPaddingValue);
|
||||
|
||||
// Set up Image2BlobParams with your new functionality
|
||||
Image2BlobParams params = new Image2BlobParams();
|
||||
params.set_size(targetSize);
|
||||
params.set_paddingmode(Dnn.DNN_PMODE_LETTERBOX);
|
||||
params.set_borderValue(customPaddingValue); // Use your new feature here
|
||||
|
||||
// Create blob with custom padding
|
||||
Mat blob = Dnn.blobFromImageWithParams(img, params);
|
||||
|
||||
// Create target blob for comparison
|
||||
Mat targetBlob = Dnn.blobFromImage(targetImg, 1.0, targetSize);
|
||||
|
||||
assertEquals(0, Core.norm(targetBlob, blob, Core.NORM_INF), EPS);
|
||||
}
|
||||
|
||||
public void testBlobFromImageWithParams4chLetterBox()
|
||||
{
|
||||
Mat img = new Mat(40, 20, CvType.CV_8UC4, new Scalar(0, 1, 2, 3));
|
||||
|
||||
// Construct target mat.
|
||||
Mat[] targetChannels = new Mat[4];
|
||||
|
||||
// The letterbox will add zero at the left and right of output blob.
|
||||
// After the letterbox, every row data would have same value showing as valVec.
|
||||
byte[] valVec = { 0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0};
|
||||
|
||||
Mat rowM = new Mat(1, 20, CvType.CV_8UC1);
|
||||
rowM.put(0, 0, valVec);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Core.multiply(rowM, new Scalar(i), targetChannels[i] = new Mat());
|
||||
}
|
||||
|
||||
Mat targetImg = new Mat();
|
||||
Core.merge(Arrays.asList(targetChannels), targetImg);
|
||||
Size targetSize = new Size(20, 20);
|
||||
|
||||
Image2BlobParams params = new Image2BlobParams();
|
||||
params.set_size(targetSize);
|
||||
params.set_paddingmode(Dnn.DNN_PMODE_LETTERBOX);
|
||||
Mat blob = Dnn.blobFromImageWithParams(img, params);
|
||||
Mat targetBlob = Dnn.blobFromImage(targetImg, 1.0, targetSize); // only convert data from uint8 to float32.
|
||||
|
||||
assertEquals(0, Core.norm(targetBlob, blob, Core.NORM_INF), EPS);
|
||||
}
|
||||
|
||||
// https://github.com/opencv/opencv/issues/27264
|
||||
public void testBlobFromImageWithParams4chMultiImage()
|
||||
{
|
||||
Mat img = new Mat(10, 10, CvType.CV_8UC4, new Scalar(0, 1, 2, 3));
|
||||
|
||||
Scalar scalefactor = new Scalar(0.1, 0.2, 0.3, 0.4);
|
||||
|
||||
Image2BlobParams param = new Image2BlobParams();
|
||||
param.set_scalefactor(scalefactor);
|
||||
param.set_datalayout(Core.DATA_LAYOUT_NHWC);
|
||||
|
||||
List<Mat> images = new ArrayList<>();
|
||||
images.add(img);
|
||||
Mat img2 = new Mat();
|
||||
Core.multiply(img, Scalar.all(2), img2);
|
||||
images.add(img2);
|
||||
|
||||
Mat blobs = Dnn.blobFromImagesWithParams(images, param);
|
||||
|
||||
Range[] ranges = new Range[4];
|
||||
ranges[0] = new Range(0, 1);
|
||||
ranges[1] = new Range(0, blobs.size(1));
|
||||
ranges[2] = new Range(0, blobs.size(2));
|
||||
ranges[3] = new Range(0, blobs.size(3));
|
||||
|
||||
Mat blob0 = blobs.submat(ranges).clone();
|
||||
|
||||
ranges[0] = new Range(1, 2);
|
||||
Mat blob1 = blobs.submat(ranges).clone();
|
||||
|
||||
Core.multiply(blob0, Scalar.all(2), blob0);
|
||||
|
||||
assertEquals(0, Core.norm(blob0, blob1, Core.NORM_INF), EPS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.opencv.test.dnn;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Net;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class DnnForwardAndRetrieve extends OpenCVTestCase {
|
||||
|
||||
private final static String ENV_OPENCV_DNN_TEST_DATA_PATH = "OPENCV_DNN_TEST_DATA_PATH";
|
||||
private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
|
||||
|
||||
private String modelFileName = "";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
String dnnTestDataPath = System.getenv(ENV_OPENCV_DNN_TEST_DATA_PATH);
|
||||
String generalTestDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
|
||||
|
||||
File model = null;
|
||||
|
||||
if (generalTestDataPath != null) {
|
||||
model = new File(generalTestDataPath, "dnn/onnx/models/split_0.onnx");
|
||||
}
|
||||
|
||||
if ((model == null || !model.isFile()) && dnnTestDataPath != null) {
|
||||
model = new File(dnnTestDataPath, "dnn/onnx/models/split_0.onnx");
|
||||
}
|
||||
|
||||
if (model == null || !model.isFile()) {
|
||||
isTestCaseEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
modelFileName = model.getAbsolutePath();
|
||||
}
|
||||
|
||||
public void testForwardAndRetrieve()
|
||||
{
|
||||
// Verifies forwardAndRetrieve nested list marshalling using a small ONNX model instead of the removed Caffe importer.
|
||||
Net net = Dnn.readNetFromONNX(modelFileName, Dnn.ENGINE_CLASSIC);
|
||||
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
||||
|
||||
// split_0.onnx declares a single 4D input named "image" of shape [1, 3, 2, 2].
|
||||
Mat inp = new Mat(new int[]{1, 3, 2, 2}, CvType.CV_32F);
|
||||
Core.randu(inp, -1, 1);
|
||||
net.setInput(inp);
|
||||
|
||||
List<String> outNames = net.getUnconnectedOutLayersNames();
|
||||
assertFalse("Model has no output layers", outNames.isEmpty());
|
||||
|
||||
// Forward and retrieve every output blob of the requested layers.
|
||||
List<List<Mat>> outBlobs = new ArrayList<>();
|
||||
net.forwardAndRetrieve(outBlobs, outNames);
|
||||
|
||||
// One entry per requested layer name, each holding at least one valid blob.
|
||||
assertEquals(outNames.size(), outBlobs.size());
|
||||
for (List<Mat> blobs : outBlobs) {
|
||||
assertFalse(blobs.isEmpty());
|
||||
for (Mat blob : blobs)
|
||||
assertFalse(blob.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.opencv.test.dnn;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfInt;
|
||||
import org.opencv.core.MatOfFloat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.dnn.DictValue;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Layer;
|
||||
import org.opencv.dnn.Net;
|
||||
import org.opencv.imgcodecs.Imgcodecs;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
/*
|
||||
* regression test for #12324,
|
||||
* testing various java.util.List invocations,
|
||||
* which use the LIST_GET macro
|
||||
*/
|
||||
|
||||
public class DnnListRegressionTest extends OpenCVTestCase {
|
||||
|
||||
private final static String ENV_OPENCV_DNN_TEST_DATA_PATH = "OPENCV_DNN_TEST_DATA_PATH";
|
||||
|
||||
private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
|
||||
|
||||
String modelFileName = "";
|
||||
String sourceImageFile = "";
|
||||
|
||||
Net net;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
String envDnnTestDataPath = System.getenv(ENV_OPENCV_DNN_TEST_DATA_PATH);
|
||||
|
||||
if(envDnnTestDataPath == null){
|
||||
isTestCaseEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
File dnnTestDataPath = new File(envDnnTestDataPath);
|
||||
modelFileName = new File(dnnTestDataPath, "dnn/tensorflow_inception_graph.pb").toString();
|
||||
|
||||
String envTestDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
|
||||
|
||||
if(envTestDataPath == null) throw new Exception(ENV_OPENCV_TEST_DATA_PATH + " has to be defined!");
|
||||
|
||||
File testDataPath = new File(envTestDataPath);
|
||||
|
||||
File f = new File(testDataPath, "dnn/grace_hopper_227.png");
|
||||
sourceImageFile = f.toString();
|
||||
if(!f.exists()) throw new Exception("Test image is missing: " + sourceImageFile);
|
||||
|
||||
net = Dnn.readNetFromTensorflow(modelFileName);
|
||||
|
||||
Mat image = Imgcodecs.imread(sourceImageFile);
|
||||
assertNotNull("Loading image from file failed!", image);
|
||||
|
||||
Mat inputBlob = Dnn.blobFromImage(image, 1.0, new Size(224, 224), new Scalar(0), true, true);
|
||||
assertNotNull("Converting image to blob failed!", inputBlob);
|
||||
|
||||
net.setInput(inputBlob, "");
|
||||
}
|
||||
|
||||
/*public void testSetInputsNames() {
|
||||
List<String> inputs = new ArrayList();
|
||||
inputs.add("input");
|
||||
try {
|
||||
net.setInputsNames(inputs);
|
||||
} catch(Exception e) {
|
||||
fail("Net setInputsNames failed: " + e.getMessage());
|
||||
}
|
||||
}*/
|
||||
|
||||
public void testForward() {
|
||||
Mat out;
|
||||
try {
|
||||
out = net.forward();
|
||||
} catch(Exception e) {
|
||||
fail("Net forward failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetMemoryConsumption() {
|
||||
List<MatOfInt> netInputShapes = new ArrayList();
|
||||
netInputShapes.add(new MatOfInt(1, 3, 224, 224));
|
||||
MatOfInt netInputTypes = new MatOfInt(5);
|
||||
long[] weights=null;
|
||||
long[] blobs=null;
|
||||
try {
|
||||
net.getMemoryConsumption(netInputShapes, netInputTypes, weights, blobs);
|
||||
} catch(Exception e) {
|
||||
fail("Net getMemoryConsumption failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetFLOPS() {
|
||||
List<MatOfInt> netInputShapes = new ArrayList();
|
||||
netInputShapes.add(new MatOfInt(1, 3, 224, 224));
|
||||
MatOfInt netInputTypes = new MatOfInt(5);
|
||||
try {
|
||||
net.getFLOPS(netInputShapes, netInputTypes);
|
||||
} catch(Exception e) {
|
||||
fail("Net getFLOPS failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package org.opencv.test.dnn;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfFloat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.dnn.DictValue;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Layer;
|
||||
import org.opencv.dnn.Net;
|
||||
import org.opencv.imgcodecs.Imgcodecs;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class DnnTensorFlowTest extends OpenCVTestCase {
|
||||
|
||||
private final static String ENV_OPENCV_DNN_TEST_DATA_PATH = "OPENCV_DNN_TEST_DATA_PATH";
|
||||
|
||||
private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
|
||||
|
||||
String modelFileName = "";
|
||||
String sourceImageFile = "";
|
||||
|
||||
Net net;
|
||||
|
||||
private static void normAssert(Mat ref, Mat test) {
|
||||
final double l1 = 1e-5;
|
||||
final double lInf = 1e-4;
|
||||
double normL1 = Core.norm(ref, test, Core.NORM_L1) / ref.total();
|
||||
double normLInf = Core.norm(ref, test, Core.NORM_INF) / ref.total();
|
||||
assertTrue(normL1 < l1);
|
||||
assertTrue(normLInf < lInf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
String envDnnTestDataPath = System.getenv(ENV_OPENCV_DNN_TEST_DATA_PATH);
|
||||
|
||||
if(envDnnTestDataPath == null){
|
||||
isTestCaseEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
File dnnTestDataPath = new File(envDnnTestDataPath);
|
||||
modelFileName = new File(dnnTestDataPath, "dnn/tensorflow_inception_graph.pb").toString();
|
||||
|
||||
String envTestDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
|
||||
|
||||
if(envTestDataPath == null) throw new Exception(ENV_OPENCV_TEST_DATA_PATH + " has to be defined!");
|
||||
|
||||
File testDataPath = new File(envTestDataPath);
|
||||
|
||||
File f = new File(testDataPath, "dnn/grace_hopper_227.png");
|
||||
sourceImageFile = f.toString();
|
||||
if(!f.exists()) throw new Exception("Test image is missing: " + sourceImageFile);
|
||||
|
||||
net = Dnn.readNetFromTensorflow(modelFileName);
|
||||
}
|
||||
|
||||
public void testGetLayerTypes() {
|
||||
List<String> layertypes = new ArrayList();
|
||||
net.getLayerTypes(layertypes);
|
||||
|
||||
assertFalse("No layer types returned!", layertypes.isEmpty());
|
||||
}
|
||||
|
||||
public void testGetLayer() {
|
||||
List<String> layerNames = net.getLayerNames();
|
||||
assertFalse("Test net returned no layers!", layerNames.isEmpty());
|
||||
|
||||
int layerId = 0;
|
||||
for (String layerName: layerNames) {
|
||||
Layer layer = net.getLayer(layerId);
|
||||
assertEquals("Layer name does not match the expected value!", layerName, layer.get_name());
|
||||
layerId++;
|
||||
}
|
||||
}
|
||||
|
||||
public void checkInceptionNet(Net net)
|
||||
{
|
||||
Mat image = Imgcodecs.imread(sourceImageFile);
|
||||
assertNotNull("Loading image from file failed!", image);
|
||||
|
||||
Mat inputBlob = Dnn.blobFromImage(image, 1.0, new Size(224, 224), new Scalar(0), true, true);
|
||||
assertNotNull("Converting image to blob failed!", inputBlob);
|
||||
|
||||
net.setInput(inputBlob, "");
|
||||
|
||||
Mat result = new Mat();
|
||||
try {
|
||||
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
||||
result = net.forward("");
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail("DNN forward failed: " + e.getMessage());
|
||||
}
|
||||
assertNotNull("Net returned no result!", result);
|
||||
|
||||
result = result.reshape(1, 1);
|
||||
Core.MinMaxLocResult minmax = Core.minMaxLoc(result);
|
||||
assertEquals("Wrong prediction", (int)minmax.maxLoc.x, 866);
|
||||
|
||||
Mat top5RefScores = new MatOfFloat(new float[] {
|
||||
0.63032645f, 0.2561979f, 0.032181446f, 0.015721032f, 0.014785315f
|
||||
}).reshape(1, 1);
|
||||
|
||||
Core.sort(result, result, Core.SORT_DESCENDING);
|
||||
|
||||
normAssert(result.colRange(0, 5), top5RefScores);
|
||||
}
|
||||
|
||||
public void testTestNetForward() {
|
||||
checkInceptionNet(net);
|
||||
}
|
||||
|
||||
public void testReadFromBuffer() {
|
||||
File modelFile = new File(modelFileName);
|
||||
byte[] modelBuffer = new byte[ (int)modelFile.length() ];
|
||||
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(modelFile);
|
||||
fis.read(modelBuffer);
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
fail("Failed to read a model: " + e.getMessage());
|
||||
}
|
||||
net = Dnn.readNetFromTensorflow(new MatOfByte(modelBuffer));
|
||||
checkInceptionNet(net);
|
||||
}
|
||||
|
||||
public void testGetAvailableTargets() {
|
||||
List<Integer> targets = Dnn.getAvailableTargets(Dnn.DNN_BACKEND_OPENCV);
|
||||
assertTrue(targets.contains(Dnn.DNN_TARGET_CPU));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"whitelist":
|
||||
{
|
||||
"dnn_Net": ["setInput", "forward", "setPreferableBackend","getUnconnectedOutLayersNames"],
|
||||
"": ["readNetFromTensorflow", "readNetFromTorch",
|
||||
"readNetFromONNX", "readNetFromTFLite", "readNet", "blobFromImage"]
|
||||
},
|
||||
"namespace_prefix_override":
|
||||
{
|
||||
"dnn": ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"func_arg_fix" : {
|
||||
"Dnn": {
|
||||
"(Net*)readNetFromONNX:(NSString*)onnxFile engine:(int)engine" : { "readNetFromONNX" : {"name" : "readNetFromONNXFile"} },
|
||||
"(Net*)readNetFromONNX:(ByteVector*)buffer engine:(int)engine" : { "readNetFromONNX" : {"name" : "readNetFromONNXBuffer"} },
|
||||
"(Net*)readNetFromTensorflow:(NSString*)model config:(NSString*)config engine:(int)engine extraOutputs:(NSArray<NSString*>*)extraOutputs" : { "readNetFromTensorflow" : {"name" : "readNetFromTensorflowFile"} },
|
||||
"(Net*)readNetFromTensorflow:(ByteVector*)bufferModel bufferConfig:(ByteVector*)bufferConfig engine:(int)engine extraOutputs:(NSArray<NSString*>*)extraOutputs" : { "readNetFromTensorflow" : {"name" : "readNetFromTensorflowBuffer"} },
|
||||
"(Net*)readNetFromTFLite:(NSString*)model engine:(int)engine" : { "readNetFromTFLite" : {"name" : "readNetFromTFLiteFile"} },
|
||||
"(Net*)readNetFromTFLite:(ByteVector*)buffer engine:(int)engine" : { "readNetFromTFLite" : {"name" : "readNetFromTFLiteBuffer"} }
|
||||
},
|
||||
"Net": {
|
||||
"(void)forward:(NSMutableArray<Mat*>*)outputBlobs outputName:(NSString*)outputName" : { "forward" : {"name" : "forwardOutputBlobs"} },
|
||||
"(void)forward:(NSMutableArray<Mat*>*)outputBlobs outBlobNames:(NSArray<NSString*>*)outBlobNames" : { "forward" : {"name" : "forwardOutputBlobs"} },
|
||||
"(void)forwardAndRetrieve:(NSMutableArray<NSMutableArray<Mat*>*>*)outputBlobs outBlobNames:(NSArray<NSString*>*)outBlobNames" : { "forward" : {"swift_name" : "forwardAndRetrieve"} },
|
||||
"(Layer*)getLayer:(NSString*)layerName" : { "getLayer" : {"name" : "getLayerByName"} },
|
||||
"(Layer*)getLayer:(DictValue*)layerId" : { "getLayer" : {"name" : "getLayerByDictValue"} },
|
||||
"(Mat*)getParam:(NSString*)layerName numParam:(int)numParam" : { "getParam" : {"name" : "getParamByName"} },
|
||||
"(void)setParam:(NSString*)layerName numParam:(int)numParam blob:(Mat*)blob" : { "setParam" : {"name" : "setParamByName"} }
|
||||
}
|
||||
},
|
||||
"type_dict": {
|
||||
"MatShape": {
|
||||
"objc_type": "IntVector*",
|
||||
"to_cpp": "cv::MatShape(%(n)s.nativeRef)",
|
||||
"from_cpp": "[IntVector fromNative:%(n)s.vec()]"
|
||||
},
|
||||
"vector_MatShape": {
|
||||
"objc_type": "IntVector*",
|
||||
"to_cpp": "cv::MatShape(%(n)s.nativeRef)",
|
||||
"from_cpp": "[IntVector fromNative:%(n)s.vec()]",
|
||||
"v_type": "MatShape"
|
||||
},
|
||||
"vector_vector_MatShape": {
|
||||
"objc_type": "IntVector*",
|
||||
"to_cpp": "cv::MatShape(%(n)s.nativeRef)",
|
||||
"from_cpp": "[IntVector fromNative:%(n)s.vec()]",
|
||||
"v_v_type": "MatShape"
|
||||
},
|
||||
"LayerId": {
|
||||
"objc_type": "DictValue*",
|
||||
"to_cpp": "*(cv::dnn::DictValue*)(%(n)s.nativePtr)",
|
||||
"from_cpp": "[DictValue fromNative:%(n)s]"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
#include_directories("${OPENCV_MODULE_opencv_dnn_BINARY_DIR}") # Cannot open include file: 'layers/layers_common.simd_declarations.hpp'
|
||||
ocv_create_builtin_dnn_plugin(opencv_dnn_openvino ocv.3rdparty.openvino ${dnn_plugin_srcs})
|
||||
@@ -0,0 +1,214 @@
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
typedef dnn::DictValue LayerId;
|
||||
typedef std::vector<MatShape> vector_MatShape;
|
||||
typedef std::vector<std::vector<MatShape> > vector_vector_MatShape;
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const ArgInfo& info)
|
||||
{
|
||||
CV_UNUSED(info);
|
||||
if (!o || o == Py_None)
|
||||
return true; //Current state will be used
|
||||
else if (PyLong_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue((int64)PyLong_AsLongLong(o));
|
||||
return true;
|
||||
}
|
||||
else if (PyInt_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue((int64)PyInt_AS_LONG(o));
|
||||
return true;
|
||||
}
|
||||
else if (PyFloat_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue(PyFloat_AsDouble(o));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string str;
|
||||
if (getUnicodeString(o, str))
|
||||
{
|
||||
dv = dnn::DictValue(str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
PyObject* pyopencv_from(const dnn::DictValue &dv)
|
||||
{
|
||||
if (dv.size() > 1)
|
||||
{
|
||||
std::vector<T> vec(dv.size());
|
||||
for (int i = 0; i < dv.size(); ++i)
|
||||
vec[i] = dv.get<T>(i);
|
||||
return pyopencv_from_generic_vec(vec);
|
||||
}
|
||||
else
|
||||
return pyopencv_from(dv.get<T>());
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const dnn::DictValue &dv)
|
||||
{
|
||||
if (dv.isInt()) return pyopencv_from<int>(dv);
|
||||
if (dv.isReal()) return pyopencv_from<float>(dv);
|
||||
if (dv.isString()) return pyopencv_from<String>(dv);
|
||||
CV_Error(Error::StsNotImplemented, "Unknown value type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const dnn::LayerParams& lp)
|
||||
{
|
||||
PyObject* dict = PyDict_New();
|
||||
for (std::map<String, dnn::DictValue>::const_iterator it = lp.begin(); it != lp.end(); ++it)
|
||||
{
|
||||
CV_Assert(!PyDict_SetItemString(dict, it->first.c_str(), pyopencv_from(it->second)));
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject *o, dnn::LayerParams &lp, const ArgInfo& info)
|
||||
{
|
||||
CV_Assert(PyDict_Check(o));
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
std::string keyName;
|
||||
while (PyDict_Next(o, &pos, &key, &value)) {
|
||||
getUnicodeString(key, keyName);
|
||||
dnn::DictValue dv;
|
||||
pyopencv_to(value, dv, info);
|
||||
lp.set(keyName, dv);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const std::vector<dnn::Target> &t)
|
||||
{
|
||||
return pyopencv_from(std::vector<int>(t.begin(), t.end()));
|
||||
}
|
||||
|
||||
class pycvLayer CV_FINAL : public dnn::Layer
|
||||
{
|
||||
public:
|
||||
pycvLayer(const dnn::LayerParams ¶ms, PyObject* pyLayer) : Layer(params)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
PyObject* args = PyTuple_New(2);
|
||||
CV_Assert(!PyTuple_SetItem(args, 0, pyopencv_from(params)));
|
||||
CV_Assert(!PyTuple_SetItem(args, 1, pyopencv_from(params.blobs)));
|
||||
o = PyObject_CallObject(pyLayer, args);
|
||||
|
||||
Py_DECREF(args);
|
||||
PyGILState_Release(gstate);
|
||||
if (!o)
|
||||
CV_Error(Error::StsError, "Failed to create an instance of custom layer");
|
||||
}
|
||||
|
||||
static void registerLayer(const std::string& type, PyObject* o)
|
||||
{
|
||||
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);
|
||||
if (it != pyLayers.end())
|
||||
it->second.push_back(o);
|
||||
else
|
||||
pyLayers[type] = std::vector<PyObject*>(1, o);
|
||||
}
|
||||
|
||||
static void unregisterLayer(const std::string& type)
|
||||
{
|
||||
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);
|
||||
if (it != pyLayers.end())
|
||||
{
|
||||
if (it->second.size() > 1)
|
||||
it->second.pop_back();
|
||||
else
|
||||
pyLayers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
static Ptr<dnn::Layer> create(dnn::LayerParams ¶ms)
|
||||
{
|
||||
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(params.type);
|
||||
if (it == pyLayers.end())
|
||||
CV_Error(Error::StsNotImplemented, "Layer with a type \"" + params.type +
|
||||
"\" is not implemented");
|
||||
CV_Assert(!it->second.empty());
|
||||
return Ptr<dnn::Layer>(new pycvLayer(params, it->second.back()));
|
||||
}
|
||||
|
||||
virtual void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
std::vector<Mat> ins, outs;
|
||||
inputs_arr.getMatVector(ins);
|
||||
outputs_arr.getMatVector(outs);
|
||||
|
||||
PyObject* args = pyopencv_from(ins);
|
||||
PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("forward"), args, NULL);
|
||||
Py_DECREF(args);
|
||||
if (!res)
|
||||
CV_Error(Error::StsNotImplemented, "Failed to call \"forward\" method");
|
||||
|
||||
std::vector<Mat> pyOutputs;
|
||||
CV_Assert(pyopencv_to(res, pyOutputs, ArgInfo("", 0)));
|
||||
Py_DECREF(res);
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
CV_Assert(pyOutputs.size() == outs.size());
|
||||
for (size_t i = 0; i < outs.size(); ++i)
|
||||
{
|
||||
CV_Assert(pyOutputs[i].size == outs[i].size);
|
||||
CV_Assert(pyOutputs[i].type() == outs[i].type());
|
||||
pyOutputs[i].copyTo(outs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Map layers types to python classes.
|
||||
static std::map<std::string, std::vector<PyObject*> > pyLayers;
|
||||
PyObject* o; // Instance of implemented python layer.
|
||||
};
|
||||
|
||||
std::map<std::string, std::vector<PyObject*> > pycvLayer::pyLayers;
|
||||
|
||||
static PyObject *pyopencv_cv_dnn_registerLayer(PyObject*, PyObject *args, PyObject *kw)
|
||||
{
|
||||
const char *keywords[] = { "type", "class", NULL };
|
||||
char* layerType;
|
||||
PyObject *classInstance;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO", (char**)keywords, &layerType, &classInstance))
|
||||
return NULL;
|
||||
if (!PyCallable_Check(classInstance)) {
|
||||
PyErr_SetString(PyExc_TypeError, "class must be callable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pycvLayer::registerLayer(layerType, classInstance);
|
||||
dnn::LayerFactory::registerLayer(layerType, pycvLayer::create);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *pyopencv_cv_dnn_unregisterLayer(PyObject*, PyObject *args, PyObject *kw)
|
||||
{
|
||||
const char *keywords[] = { "type", NULL };
|
||||
char* layerType;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s", (char**)keywords, &layerType))
|
||||
return NULL;
|
||||
|
||||
pycvLayer::unregisterLayer(layerType);
|
||||
dnn::LayerFactory::unregisterLayer(layerType);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif // HAVE_OPENCV_DNN
|
||||
Executable
+474
@@ -0,0 +1,474 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from tests_common import NewOpenCVTests, unittest
|
||||
|
||||
def normAssert(test, a, b, msg=None, lInf=1e-5):
|
||||
test.assertLess(np.max(np.abs(a - b)), lInf, msg)
|
||||
|
||||
def inter_area(box1, box2):
|
||||
x_min, x_max = max(box1[0], box2[0]), min(box1[2], box2[2])
|
||||
y_min, y_max = max(box1[1], box2[1]), min(box1[3], box2[3])
|
||||
return (x_max - x_min) * (y_max - y_min)
|
||||
|
||||
def area(box):
|
||||
return (box[2] - box[0]) * (box[3] - box[1])
|
||||
|
||||
def box2str(box):
|
||||
left, top = box[0], box[1]
|
||||
width, height = box[2] - left, box[3] - top
|
||||
return '[%f x %f from (%f, %f)]' % (width, height, left, top)
|
||||
|
||||
def normAssertDetections(test, refClassIds, refScores, refBoxes, testClassIds, testScores, testBoxes,
|
||||
confThreshold=0.0, scores_diff=1e-5, boxes_iou_diff=1e-4):
|
||||
matchedRefBoxes = [False] * len(refBoxes)
|
||||
errMsg = ''
|
||||
for i in range(len(testBoxes)):
|
||||
testScore = testScores[i]
|
||||
if testScore < confThreshold:
|
||||
continue
|
||||
|
||||
testClassId, testBox = testClassIds[i], testBoxes[i]
|
||||
matched = False
|
||||
for j in range(len(refBoxes)):
|
||||
if (not matchedRefBoxes[j]) and testClassId == refClassIds[j] and \
|
||||
abs(testScore - refScores[j]) < scores_diff:
|
||||
interArea = inter_area(testBox, refBoxes[j])
|
||||
iou = interArea / (area(testBox) + area(refBoxes[j]) - interArea)
|
||||
if abs(iou - 1.0) < boxes_iou_diff:
|
||||
matched = True
|
||||
matchedRefBoxes[j] = True
|
||||
if not matched:
|
||||
errMsg += '\nUnmatched prediction: class %d score %f box %s' % (testClassId, testScore, box2str(testBox))
|
||||
|
||||
for i in range(len(refBoxes)):
|
||||
if (not matchedRefBoxes[i]) and refScores[i] > confThreshold:
|
||||
errMsg += '\nUnmatched reference: class %d score %f box %s' % (refClassIds[i], refScores[i], box2str(refBoxes[i]))
|
||||
if errMsg:
|
||||
test.fail(errMsg)
|
||||
|
||||
def printParams(backend, target):
|
||||
backendNames = {
|
||||
cv.dnn.DNN_BACKEND_OPENCV: 'OCV',
|
||||
cv.dnn.DNN_BACKEND_INFERENCE_ENGINE: 'DLIE'
|
||||
}
|
||||
targetNames = {
|
||||
cv.dnn.DNN_TARGET_CPU: 'CPU',
|
||||
cv.dnn.DNN_TARGET_OPENCL: 'OCL',
|
||||
cv.dnn.DNN_TARGET_OPENCL_FP16: 'OCL_FP16',
|
||||
cv.dnn.DNN_TARGET_MYRIAD: 'MYRIAD'
|
||||
}
|
||||
print('%s/%s' % (backendNames[backend], targetNames[target]))
|
||||
|
||||
def getDefaultThreshold(target):
|
||||
if target == cv.dnn.DNN_TARGET_OPENCL_FP16 or target == cv.dnn.DNN_TARGET_MYRIAD:
|
||||
return 4e-3
|
||||
else:
|
||||
return 1e-5
|
||||
|
||||
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
|
||||
|
||||
g_dnnBackendsAndTargets = None
|
||||
|
||||
class dnn_test(NewOpenCVTests):
|
||||
|
||||
def setUp(self):
|
||||
super(dnn_test, self).setUp()
|
||||
|
||||
global g_dnnBackendsAndTargets
|
||||
if g_dnnBackendsAndTargets is None:
|
||||
g_dnnBackendsAndTargets = self.initBackendsAndTargets()
|
||||
self.dnnBackendsAndTargets = g_dnnBackendsAndTargets
|
||||
|
||||
def checkIETarget(self, backend, target):
|
||||
# OpenVINO is optional; a target is usable only if its backend lists it.
|
||||
try:
|
||||
return target in cv.dnn.getAvailableTargets(backend)
|
||||
except BaseException:
|
||||
return False
|
||||
|
||||
def initBackendsAndTargets(self):
|
||||
self.dnnBackendsAndTargets = [
|
||||
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
|
||||
]
|
||||
|
||||
if self.checkIETarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_CPU):
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_CPU])
|
||||
if self.checkIETarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_MYRIAD):
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_MYRIAD])
|
||||
|
||||
if cv.ocl.haveOpenCL() and cv.ocl.useOpenCL():
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_OPENCL])
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_OPENCL_FP16])
|
||||
if cv.ocl_Device.getDefault().isIntel():
|
||||
if self.checkIETarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL):
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL])
|
||||
if self.checkIETarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL_FP16):
|
||||
self.dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL_FP16])
|
||||
return self.dnnBackendsAndTargets
|
||||
|
||||
def find_dnn_file(self, filename, required=True):
|
||||
if not required:
|
||||
required = testdata_required
|
||||
return self.find_file(filename, [os.environ.get('OPENCV_DNN_TEST_DATA_PATH', os.getcwd()),
|
||||
os.environ['OPENCV_TEST_DATA_PATH']],
|
||||
required=required)
|
||||
|
||||
def test_getAvailableTargets(self):
|
||||
targets = cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_OPENCV)
|
||||
self.assertTrue(cv.dnn.DNN_TARGET_CPU in targets)
|
||||
|
||||
def test_blobRectsToImageRects(self):
|
||||
paramNet = cv.dnn.Image2BlobParams()
|
||||
paramNet.size = (226, 226)
|
||||
paramNet.ddepth = cv.CV_32F
|
||||
paramNet.mean = [0.485, 0.456, 0.406]
|
||||
paramNet.scalefactor = [0.229, 0.224, 0.225]
|
||||
paramNet.swapRB = False
|
||||
paramNet.datalayout = cv.DATA_LAYOUT_NCHW
|
||||
paramNet.paddingmode = cv.dnn.DNN_PMODE_LETTERBOX
|
||||
rBlob = np.zeros(shape=(20, 4), dtype=np.int32)
|
||||
rImg = paramNet.blobRectsToImageRects(rBlob, (356, 356))
|
||||
self.assertTrue(type(rImg[0, 0])==np.int32)
|
||||
self.assertTrue(rImg.shape==(20, 4))
|
||||
|
||||
def test_blobRectToImageRect(self):
|
||||
paramNet = cv.dnn.Image2BlobParams()
|
||||
paramNet.size = (226, 226)
|
||||
paramNet.ddepth = cv.CV_32F
|
||||
paramNet.mean = [0.485, 0.456, 0.406]
|
||||
paramNet.scalefactor = [0.229, 0.224, 0.225]
|
||||
paramNet.swapRB = False
|
||||
paramNet.datalayout = cv.DATA_LAYOUT_NCHW
|
||||
paramNet.paddingmode = cv.dnn.DNN_PMODE_LETTERBOX
|
||||
rBlob = np.zeros(shape=(20, 4), dtype=np.int32)
|
||||
rImg = paramNet.blobRectToImageRect((0, 0, 0, 0), (356, 356))
|
||||
self.assertTrue(type(rImg[0])==int)
|
||||
|
||||
|
||||
def test_blobFromImage(self):
|
||||
np.random.seed(324)
|
||||
|
||||
width = 6
|
||||
height = 7
|
||||
scale = 1.0/127.5
|
||||
mean = (10, 20, 30)
|
||||
|
||||
# Test arguments names.
|
||||
img = np.random.randint(0, 255, [4, 5, 3]).astype(np.uint8)
|
||||
blob = cv.dnn.blobFromImage(img, scale, (width, height), mean, True, False)
|
||||
blob_args = cv.dnn.blobFromImage(img, scalefactor=scale, size=(width, height),
|
||||
mean=mean, swapRB=True, crop=False)
|
||||
normAssert(self, blob, blob_args)
|
||||
|
||||
# Test values.
|
||||
target = cv.resize(img, (width, height), interpolation=cv.INTER_LINEAR)
|
||||
target = target.astype(np.float32)
|
||||
target = target[:,:,[2, 1, 0]] # BGR2RGB
|
||||
target[:,:,0] -= mean[0]
|
||||
target[:,:,1] -= mean[1]
|
||||
target[:,:,2] -= mean[2]
|
||||
target *= scale
|
||||
target = target.transpose(2, 0, 1).reshape(1, 3, height, width) # to NCHW
|
||||
normAssert(self, blob, target)
|
||||
|
||||
def test_blobFromImageWithParams(self):
|
||||
np.random.seed(324)
|
||||
|
||||
width = 6
|
||||
height = 7
|
||||
stddev = np.array([0.2, 0.3, 0.4])
|
||||
scalefactor = 1.0/127.5 * stddev
|
||||
mean = (10, 20, 30)
|
||||
|
||||
# Test arguments names.
|
||||
img = np.random.randint(0, 255, [4, 5, 3]).astype(np.uint8)
|
||||
|
||||
param = cv.dnn.Image2BlobParams()
|
||||
param.scalefactor = scalefactor
|
||||
param.size = (6, 7)
|
||||
param.mean = mean
|
||||
param.swapRB=True
|
||||
param.datalayout = cv.DATA_LAYOUT_NHWC
|
||||
|
||||
blob = cv.dnn.blobFromImageWithParams(img, param)
|
||||
blob_args = cv.dnn.blobFromImageWithParams(img, cv.dnn.Image2BlobParams(scalefactor=scalefactor, size=(6, 7), mean=mean,
|
||||
swapRB=True, datalayout=cv.DATA_LAYOUT_NHWC))
|
||||
normAssert(self, blob, blob_args)
|
||||
|
||||
target2 = cv.resize(img, (width, height), interpolation=cv.INTER_LINEAR).astype(np.float32)
|
||||
target2 = target2[:,:,[2, 1, 0]] # BGR2RGB
|
||||
target2[:,:,0] -= mean[0]
|
||||
target2[:,:,1] -= mean[1]
|
||||
target2[:,:,2] -= mean[2]
|
||||
|
||||
target2[:,:,0] *= scalefactor[0]
|
||||
target2[:,:,1] *= scalefactor[1]
|
||||
target2[:,:,2] *= scalefactor[2]
|
||||
target2 = target2.reshape(1, height, width, 3) # to NHWC
|
||||
normAssert(self, blob, target2)
|
||||
|
||||
def test_model(self):
|
||||
img_path = self.find_dnn_file("dnn/street.png")
|
||||
weights = self.find_dnn_file("dnn/onnx/models/ssd_vgg16.onnx", required=False)
|
||||
if weights is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/onnx/models/ssd_vgg16.onnx). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
frame = cv.imread(img_path)
|
||||
model = cv.dnn_DetectionModel(weights)
|
||||
model.setInputParams(size=(300, 300), mean=(0, 0, 0), scale=1.0, swapRB=False)
|
||||
|
||||
iouDiff = 0.05
|
||||
confThreshold = 0.3
|
||||
nmsThreshold = 0
|
||||
scoreDiff = 5e-3
|
||||
|
||||
classIds, confidences, boxes = model.detect(frame, confThreshold, nmsThreshold)
|
||||
|
||||
refClassIds = (37,)
|
||||
refConfidences = (0.8196,)
|
||||
refBoxes = ((331, 233, 85, 107),)
|
||||
|
||||
normAssertDetections(self, refClassIds, refConfidences, refBoxes,
|
||||
classIds, confidences, boxes,confThreshold, scoreDiff, iouDiff)
|
||||
|
||||
for box in boxes:
|
||||
cv.rectangle(frame, box, (0, 255, 0))
|
||||
cv.rectangle(frame, np.array(box), (0, 255, 0))
|
||||
cv.rectangle(frame, tuple(box), (0, 255, 0))
|
||||
cv.rectangle(frame, list(box), (0, 255, 0))
|
||||
|
||||
|
||||
def test_classification_model(self):
|
||||
img_path = self.find_dnn_file("dnn/googlenet_0.png")
|
||||
weights = self.find_dnn_file("dnn/squeezenet_v1.1.onnx", required=False)
|
||||
ref = np.load(self.find_dnn_file("dnn/squeezenet_v1.1_prob.npy"))
|
||||
if weights is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/squeezenet_v1.1.onnx). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
frame = cv.imread(img_path)
|
||||
model = cv.dnn_ClassificationModel(weights)
|
||||
model.setInputSize(227, 227)
|
||||
model.setInputCrop(True)
|
||||
|
||||
out = model.predict(frame)
|
||||
normAssert(self, out, ref)
|
||||
|
||||
|
||||
def test_textdetection_model(self):
|
||||
img_path = self.find_dnn_file("dnn/text_det_test1.png")
|
||||
weights = self.find_dnn_file("dnn/onnx/models/DB_TD500_resnet50.onnx", required=False)
|
||||
if weights is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (onnx/models/DB_TD500_resnet50.onnx). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
frame = cv.imread(img_path)
|
||||
scale = 1.0 / 255.0
|
||||
size = (736, 736)
|
||||
mean = (122.67891434, 116.66876762, 104.00698793)
|
||||
|
||||
model = cv.dnn_TextDetectionModel_DB(weights)
|
||||
model.setInputParams(scale, size, mean)
|
||||
out, _ = model.detect(frame)
|
||||
|
||||
self.assertTrue(type(out) == tuple, msg='actual type {}'.format(str(type(out))))
|
||||
self.assertTrue(np.array(out).shape == (2, 4, 2))
|
||||
|
||||
|
||||
def test_face_detection(self):
|
||||
model = self.find_dnn_file('dnn/onnx/models/yunet-202605.onnx', required=False)
|
||||
img = self.get_sample('gpu/lbpcascade/er.png')
|
||||
|
||||
ref = [[1, 339.62445, 35.32416, 30.754604, 40.202126, 0.9302596],
|
||||
[1, 140.63962, 255.55545, 32.832615, 41.767395, 0.916015],
|
||||
[1, 68.39314, 126.74046, 30.29324, 39.14823, 0.90639645],
|
||||
[1, 119.57139, 48.482178, 30.600697, 40.485996, 0.906021],
|
||||
[1, 259.0921, 229.30713, 31.088186, 39.74022, 0.90490955],
|
||||
[1, 405.69778, 87.28158, 33.393406, 42.96226, 0.8996978]]
|
||||
|
||||
print('\n')
|
||||
for backend, target in self.dnnBackendsAndTargets:
|
||||
printParams(backend, target)
|
||||
|
||||
net = cv.FaceDetectorYN.create(
|
||||
model=model,
|
||||
config="",
|
||||
input_size=img.shape[:2],
|
||||
score_threshold=0.3,
|
||||
nms_threshold=0.45,
|
||||
top_k=5000,
|
||||
backend_id=backend,
|
||||
target_id=target
|
||||
)
|
||||
|
||||
out = net.detect(img)
|
||||
out = out[1]
|
||||
out = out.reshape(-1, 15)
|
||||
|
||||
ref = np.array(ref, np.float32)
|
||||
refClassIds, testClassIds = ref[:, 0], np.ones(out.shape[0], np.float32)
|
||||
refScores, testScores = ref[:, -1], out[:, -1]
|
||||
refBoxes, testBoxes = ref[:, 1:5], out[:, 0:4]
|
||||
|
||||
normAssertDetections(self, refClassIds, refScores, refBoxes, testClassIds,
|
||||
testScores, testBoxes, 0.5)
|
||||
|
||||
def test_nms(self):
|
||||
confs = (1, 1)
|
||||
rects = ((0, 0, 0.4, 0.4), (0, 0, 0.2, 0.4)) # 0.5 overlap
|
||||
|
||||
self.assertTrue(all(cv.dnn.NMSBoxes(rects, confs, 0, 0.6).ravel() == (0, 1)))
|
||||
|
||||
# BUG: https://github.com/opencv/opencv/issues/26200
|
||||
@unittest.skip("custom layers are partially broken with transition to the new dnn engine")
|
||||
def test_custom_layer(self):
|
||||
class CropLayer(object):
|
||||
def __init__(self, params, blobs):
|
||||
self.xstart = 0
|
||||
self.xend = 0
|
||||
self.ystart = 0
|
||||
self.yend = 0
|
||||
# Our layer receives two inputs. We need to crop the first input blob
|
||||
# to match a shape of the second one (keeping batch size and number of channels)
|
||||
def getMemoryShapes(self, inputs):
|
||||
inputShape, targetShape = inputs[0], inputs[1]
|
||||
batchSize, numChannels = inputShape[0], inputShape[1]
|
||||
height, width = targetShape[2], targetShape[3]
|
||||
self.ystart = (inputShape[2] - targetShape[2]) // 2
|
||||
self.xstart = (inputShape[3] - targetShape[3]) // 2
|
||||
self.yend = self.ystart + height
|
||||
self.xend = self.xstart + width
|
||||
return [[batchSize, numChannels, height, width]]
|
||||
def forward(self, inputs):
|
||||
return [inputs[0][:,:,self.ystart:self.yend,self.xstart:self.xend]]
|
||||
|
||||
cv.dnn_registerLayer('CropCaffe', CropLayer)
|
||||
|
||||
# Skipped: Requires ONNX custom layer multi-input support and Python binding fixes for Net.connect (see #26200).
|
||||
cv.dnn_unregisterLayer('CropCaffe')
|
||||
|
||||
# check that dnn module can work with 3D tensor as input for network
|
||||
def test_input_3d(self):
|
||||
model = self.find_dnn_file('dnn/onnx/models/hidden_lstm.onnx')
|
||||
input_file = self.find_dnn_file('dnn/onnx/data/input_hidden_lstm.npy')
|
||||
output_file = self.find_dnn_file('dnn/onnx/data/output_hidden_lstm.npy')
|
||||
if model is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/onnx/models/hidden_lstm.onnx). "
|
||||
"Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
if input_file is None or output_file is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/onnx/data/{input/output}_hidden_lstm.npy). "
|
||||
"Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
input = np.load(input_file)
|
||||
gold_output = np.load(output_file)
|
||||
|
||||
for backend, target in self.dnnBackendsAndTargets:
|
||||
printParams(backend, target)
|
||||
|
||||
net = cv.dnn.readNet(model, engine=cv.dnn.ENGINE_CLASSIC)
|
||||
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
|
||||
# Check whether 3d shape is parsed correctly for setInput
|
||||
net.setInput(input)
|
||||
|
||||
# Case 0: test API `forward(const String& outputName = String()`
|
||||
real_output = net.forward() # Retval is a np.array of shape [2, 5, 3]
|
||||
normAssert(self, real_output, gold_output, "Case 1", getDefaultThreshold(target))
|
||||
|
||||
'''
|
||||
Pre-allocate output memory with correct shape.
|
||||
Normally Python users do not use in this way,
|
||||
but we have to test it since we design API in this way
|
||||
'''
|
||||
# Case 1: a np.array with a string of output name.
|
||||
# It tests API `forward(OutputArrayOfArrays outputBlobs, const String& outputName = String()`
|
||||
# when outputBlobs is a np.array and we expect it to be the only output.
|
||||
real_output = np.empty([2, 5, 3], dtype=np.float32)
|
||||
real_output = net.forward(real_output, "237") # Retval is a tuple with a np.array of shape [2, 5, 3]
|
||||
normAssert(self, real_output, gold_output, "Case 1", getDefaultThreshold(target))
|
||||
|
||||
# Case 2: a tuple of np.array with a string of output name.
|
||||
# It tests API `forward(OutputArrayOfArrays outputBlobs, const String& outputName = String()`
|
||||
# when outputBlobs is a container of several np.array and we expect to save all outputs accordingly.
|
||||
real_output = tuple(np.empty([2, 5, 3], dtype=np.float32))
|
||||
real_output = net.forward(real_output, "237") # Retval is a tuple with a np.array of shape [2, 5, 3]
|
||||
normAssert(self, real_output, gold_output, "Case 2", getDefaultThreshold(target))
|
||||
|
||||
# Case 3: a tuple of np.array with a string of output name.
|
||||
# It tests API `forward(OutputArrayOfArrays outputBlobs, const std::vector<String>& outBlobNames)`
|
||||
real_output = tuple(np.empty([2, 5, 3], dtype=np.float32))
|
||||
# Note that it does not support parsing a list , e.g. ["237"]
|
||||
real_output = net.forward(real_output, ("237")) # Retval is a tuple with a np.array of shape [2, 5, 3]
|
||||
normAssert(self, real_output, gold_output, "Case 3", getDefaultThreshold(target))
|
||||
|
||||
def test_set_param_3d(self):
|
||||
model_path = self.find_dnn_file('dnn/onnx/models/matmul_3d_init.onnx')
|
||||
input_file = self.find_dnn_file('dnn/onnx/data/input_matmul_3d_init.npy')
|
||||
output_file = self.find_dnn_file('dnn/onnx/data/output_matmul_3d_init.npy')
|
||||
|
||||
input = np.load(input_file)
|
||||
output = np.load(output_file)
|
||||
|
||||
for backend, target in self.dnnBackendsAndTargets:
|
||||
printParams(backend, target)
|
||||
|
||||
net = cv.dnn.readNet(model_path, "", "", engine=cv.dnn.ENGINE_CLASSIC)
|
||||
|
||||
node_name = net.getLayerNames()[0]
|
||||
w = net.getParam(node_name, 0) # returns the original tensor of three-dimensional shape
|
||||
net.setParam(node_name, 0, w) # set param once again to see whether tensor is converted with correct shape
|
||||
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
|
||||
net.setInput(input)
|
||||
res_output = net.forward()
|
||||
|
||||
normAssert(self, output, res_output, "", getDefaultThreshold(target))
|
||||
|
||||
def test_scalefactor_assign(self):
|
||||
params = cv.dnn.Image2BlobParams()
|
||||
self.assertEqual(params.scalefactor, (1.0, 1.0, 1.0, 1.0))
|
||||
params.scalefactor = 2.0
|
||||
self.assertEqual(params.scalefactor, (2.0, 0.0, 0.0, 0.0))
|
||||
|
||||
def test_net_builder(self):
|
||||
net = cv.dnn.Net()
|
||||
params = {
|
||||
"kernel_w": 3,
|
||||
"kernel_h": 3,
|
||||
"stride_w": 3,
|
||||
"stride_h": 3,
|
||||
"pool": "max",
|
||||
}
|
||||
net.addLayerToPrev("pool", "Pooling", cv.CV_32F, params)
|
||||
|
||||
inp = np.random.standard_normal([1, 2, 9, 12]).astype(np.float32)
|
||||
net.setInput(inp)
|
||||
out = net.forward()
|
||||
self.assertEqual(out.shape, (1, 2, 3, 4))
|
||||
|
||||
def test_bool_operator(self):
|
||||
n = self.find_dnn_file('dnn/onnx/models/and_op.onnx')
|
||||
|
||||
x = np.random.randint(0, 2, [5], dtype=np.bool_)
|
||||
y = np.random.randint(0, 2, [5], dtype=np.bool_)
|
||||
o = x & y
|
||||
|
||||
net = cv.dnn.readNet(n)
|
||||
|
||||
names = ["x", "y"]
|
||||
net.setInputsNames(names)
|
||||
net.setInput(x, names[0])
|
||||
net.setInput(y, names[1])
|
||||
|
||||
out = net.forward()
|
||||
|
||||
self.assertTrue(np.all(out == o))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -0,0 +1,366 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import argparse
|
||||
import cv2 as cv
|
||||
assert cv.__version__ < "5.0", "Caffe importer is deprecated and removed from OpenCV 5.0"
|
||||
import tensorflow as tf
|
||||
import numpy as np
|
||||
import struct
|
||||
|
||||
if sys.version_info > (3,):
|
||||
long = int
|
||||
|
||||
from tensorflow.python.tools import optimize_for_inference_lib
|
||||
from tensorflow.tools.graph_transforms import TransformGraph
|
||||
from tensorflow.core.framework.node_def_pb2 import NodeDef
|
||||
from google.protobuf import text_format
|
||||
|
||||
parser = argparse.ArgumentParser(description="Use this script to create TensorFlow graph "
|
||||
"with weights from OpenCV's face detection network. "
|
||||
"Only backbone part of SSD model is converted this way. "
|
||||
"Look for .pbtxt configuration file at "
|
||||
"https://github.com/opencv/opencv_extra/tree/5.x/testdata/dnn/opencv_face_detector.pbtxt")
|
||||
parser.add_argument('--model', help='Path to .caffemodel weights', required=True)
|
||||
parser.add_argument('--proto', help='Path to .prototxt Caffe model definition', required=True)
|
||||
parser.add_argument('--pb', help='Path to output .pb TensorFlow model', required=True)
|
||||
parser.add_argument('--pbtxt', help='Path to output .pbxt TensorFlow graph', required=True)
|
||||
parser.add_argument('--quantize', help='Quantize weights to uint8', action='store_true')
|
||||
parser.add_argument('--fp16', help='Convert weights to half precision floats', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
assert(not args.quantize or not args.fp16)
|
||||
|
||||
dtype = tf.float16 if args.fp16 else tf.float32
|
||||
|
||||
################################################################################
|
||||
cvNet = cv.dnn.readNet(args.proto, args.model)
|
||||
|
||||
def dnnLayer(name):
|
||||
return cvNet.getLayer(long(cvNet.getLayerId(name)))
|
||||
|
||||
def scale(x, name):
|
||||
with tf.variable_scope(name):
|
||||
layer = dnnLayer(name)
|
||||
w = tf.Variable(layer.blobs[0].flatten(), dtype=dtype, name='mul')
|
||||
if len(layer.blobs) > 1:
|
||||
b = tf.Variable(layer.blobs[1].flatten(), dtype=dtype, name='add')
|
||||
return tf.nn.bias_add(tf.multiply(x, w), b)
|
||||
else:
|
||||
return tf.multiply(x, w, name)
|
||||
|
||||
def conv(x, name, stride=1, pad='SAME', dilation=1, activ=None):
|
||||
with tf.variable_scope(name):
|
||||
layer = dnnLayer(name)
|
||||
w = tf.Variable(layer.blobs[0].transpose(2, 3, 1, 0), dtype=dtype, name='weights')
|
||||
if dilation == 1:
|
||||
conv = tf.nn.conv2d(x, filter=w, strides=(1, stride, stride, 1), padding=pad)
|
||||
else:
|
||||
assert(stride == 1)
|
||||
conv = tf.nn.atrous_conv2d(x, w, rate=dilation, padding=pad)
|
||||
|
||||
if len(layer.blobs) > 1:
|
||||
b = tf.Variable(layer.blobs[1].flatten(), dtype=dtype, name='bias')
|
||||
conv = tf.nn.bias_add(conv, b)
|
||||
return activ(conv) if activ else conv
|
||||
|
||||
def batch_norm(x, name):
|
||||
with tf.variable_scope(name):
|
||||
# Unfortunately, TensorFlow's batch normalization layer doesn't work with fp16 input.
|
||||
# Here we do a cast to fp32 but remove it in the frozen graph.
|
||||
if x.dtype != tf.float32:
|
||||
x = tf.cast(x, tf.float32)
|
||||
|
||||
layer = dnnLayer(name)
|
||||
assert(len(layer.blobs) >= 3)
|
||||
|
||||
mean = layer.blobs[0].flatten()
|
||||
std = layer.blobs[1].flatten()
|
||||
scale = layer.blobs[2].flatten()
|
||||
|
||||
eps = 1e-5
|
||||
hasBias = len(layer.blobs) > 3
|
||||
hasWeights = scale.shape != (1,)
|
||||
|
||||
if not hasWeights and not hasBias:
|
||||
mean /= scale[0]
|
||||
std /= scale[0]
|
||||
|
||||
mean = tf.Variable(mean, dtype=tf.float32, name='mean')
|
||||
std = tf.Variable(std, dtype=tf.float32, name='std')
|
||||
gamma = tf.Variable(scale if hasWeights else np.ones(mean.shape), dtype=tf.float32, name='gamma')
|
||||
beta = tf.Variable(layer.blobs[3].flatten() if hasBias else np.zeros(mean.shape), dtype=tf.float32, name='beta')
|
||||
bn = tf.nn.fused_batch_norm(x, gamma, beta, mean, std, eps,
|
||||
is_training=False)[0]
|
||||
if bn.dtype != dtype:
|
||||
bn = tf.cast(bn, dtype)
|
||||
return bn
|
||||
|
||||
def l2norm(x, name):
|
||||
with tf.variable_scope(name):
|
||||
layer = dnnLayer(name)
|
||||
w = tf.Variable(layer.blobs[0].flatten(), dtype=dtype, name='mul')
|
||||
return tf.nn.l2_normalize(x, 3, epsilon=1e-10) * w
|
||||
|
||||
### Graph definition ###########################################################
|
||||
inp = tf.placeholder(dtype, [1, 300, 300, 3], 'data')
|
||||
data_bn = batch_norm(inp, 'data_bn')
|
||||
data_scale = scale(data_bn, 'data_scale')
|
||||
|
||||
# Instead of tf.pad we use tf.space_to_batch_nd layers which override convolution's padding strategy to explicit numbers
|
||||
# data_scale = tf.pad(data_scale, [[0, 0], [3, 3], [3, 3], [0, 0]])
|
||||
data_scale = tf.space_to_batch_nd(data_scale, [1, 1], [[3, 3], [3, 3]], name='Pad')
|
||||
conv1_h = conv(data_scale, stride=2, pad='VALID', name='conv1_h')
|
||||
|
||||
conv1_bn_h = batch_norm(conv1_h, 'conv1_bn_h')
|
||||
conv1_scale_h = scale(conv1_bn_h, 'conv1_scale_h')
|
||||
conv1_relu = tf.nn.relu(conv1_scale_h)
|
||||
conv1_pool = tf.layers.max_pooling2d(conv1_relu, pool_size=(3, 3), strides=(2, 2),
|
||||
padding='SAME', name='conv1_pool')
|
||||
|
||||
layer_64_1_conv1_h = conv(conv1_pool, 'layer_64_1_conv1_h')
|
||||
layer_64_1_bn2_h = batch_norm(layer_64_1_conv1_h, 'layer_64_1_bn2_h')
|
||||
layer_64_1_scale2_h = scale(layer_64_1_bn2_h, 'layer_64_1_scale2_h')
|
||||
layer_64_1_relu2 = tf.nn.relu(layer_64_1_scale2_h)
|
||||
layer_64_1_conv2_h = conv(layer_64_1_relu2, 'layer_64_1_conv2_h')
|
||||
layer_64_1_sum = layer_64_1_conv2_h + conv1_pool
|
||||
|
||||
layer_128_1_bn1_h = batch_norm(layer_64_1_sum, 'layer_128_1_bn1_h')
|
||||
layer_128_1_scale1_h = scale(layer_128_1_bn1_h, 'layer_128_1_scale1_h')
|
||||
layer_128_1_relu1 = tf.nn.relu(layer_128_1_scale1_h)
|
||||
layer_128_1_conv1_h = conv(layer_128_1_relu1, stride=2, name='layer_128_1_conv1_h')
|
||||
layer_128_1_bn2 = batch_norm(layer_128_1_conv1_h, 'layer_128_1_bn2')
|
||||
layer_128_1_scale2 = scale(layer_128_1_bn2, 'layer_128_1_scale2')
|
||||
layer_128_1_relu2 = tf.nn.relu(layer_128_1_scale2)
|
||||
layer_128_1_conv2 = conv(layer_128_1_relu2, 'layer_128_1_conv2')
|
||||
layer_128_1_conv_expand_h = conv(layer_128_1_relu1, stride=2, name='layer_128_1_conv_expand_h')
|
||||
layer_128_1_sum = layer_128_1_conv2 + layer_128_1_conv_expand_h
|
||||
|
||||
layer_256_1_bn1 = batch_norm(layer_128_1_sum, 'layer_256_1_bn1')
|
||||
layer_256_1_scale1 = scale(layer_256_1_bn1, 'layer_256_1_scale1')
|
||||
layer_256_1_relu1 = tf.nn.relu(layer_256_1_scale1)
|
||||
|
||||
# layer_256_1_conv1 = tf.pad(layer_256_1_relu1, [[0, 0], [1, 1], [1, 1], [0, 0]])
|
||||
layer_256_1_conv1 = tf.space_to_batch_nd(layer_256_1_relu1, [1, 1], [[1, 1], [1, 1]], name='Pad_1')
|
||||
layer_256_1_conv1 = conv(layer_256_1_conv1, stride=2, pad='VALID', name='layer_256_1_conv1')
|
||||
|
||||
layer_256_1_bn2 = batch_norm(layer_256_1_conv1, 'layer_256_1_bn2')
|
||||
layer_256_1_scale2 = scale(layer_256_1_bn2, 'layer_256_1_scale2')
|
||||
layer_256_1_relu2 = tf.nn.relu(layer_256_1_scale2)
|
||||
layer_256_1_conv2 = conv(layer_256_1_relu2, 'layer_256_1_conv2')
|
||||
layer_256_1_conv_expand = conv(layer_256_1_relu1, stride=2, name='layer_256_1_conv_expand')
|
||||
layer_256_1_sum = layer_256_1_conv2 + layer_256_1_conv_expand
|
||||
|
||||
layer_512_1_bn1 = batch_norm(layer_256_1_sum, 'layer_512_1_bn1')
|
||||
layer_512_1_scale1 = scale(layer_512_1_bn1, 'layer_512_1_scale1')
|
||||
layer_512_1_relu1 = tf.nn.relu(layer_512_1_scale1)
|
||||
layer_512_1_conv1_h = conv(layer_512_1_relu1, 'layer_512_1_conv1_h')
|
||||
layer_512_1_bn2_h = batch_norm(layer_512_1_conv1_h, 'layer_512_1_bn2_h')
|
||||
layer_512_1_scale2_h = scale(layer_512_1_bn2_h, 'layer_512_1_scale2_h')
|
||||
layer_512_1_relu2 = tf.nn.relu(layer_512_1_scale2_h)
|
||||
layer_512_1_conv2_h = conv(layer_512_1_relu2, dilation=2, name='layer_512_1_conv2_h')
|
||||
layer_512_1_conv_expand_h = conv(layer_512_1_relu1, 'layer_512_1_conv_expand_h')
|
||||
layer_512_1_sum = layer_512_1_conv2_h + layer_512_1_conv_expand_h
|
||||
|
||||
last_bn_h = batch_norm(layer_512_1_sum, 'last_bn_h')
|
||||
last_scale_h = scale(last_bn_h, 'last_scale_h')
|
||||
fc7 = tf.nn.relu(last_scale_h, name='last_relu')
|
||||
|
||||
conv6_1_h = conv(fc7, 'conv6_1_h', activ=tf.nn.relu)
|
||||
conv6_2_h = conv(conv6_1_h, stride=2, name='conv6_2_h', activ=tf.nn.relu)
|
||||
conv7_1_h = conv(conv6_2_h, 'conv7_1_h', activ=tf.nn.relu)
|
||||
|
||||
# conv7_2_h = tf.pad(conv7_1_h, [[0, 0], [1, 1], [1, 1], [0, 0]])
|
||||
conv7_2_h = tf.space_to_batch_nd(conv7_1_h, [1, 1], [[1, 1], [1, 1]], name='Pad_2')
|
||||
conv7_2_h = conv(conv7_2_h, stride=2, pad='VALID', name='conv7_2_h', activ=tf.nn.relu)
|
||||
|
||||
conv8_1_h = conv(conv7_2_h, pad='SAME', name='conv8_1_h', activ=tf.nn.relu)
|
||||
conv8_2_h = conv(conv8_1_h, pad='VALID', name='conv8_2_h', activ=tf.nn.relu)
|
||||
conv9_1_h = conv(conv8_2_h, 'conv9_1_h', activ=tf.nn.relu)
|
||||
conv9_2_h = conv(conv9_1_h, pad='VALID', name='conv9_2_h', activ=tf.nn.relu)
|
||||
|
||||
conv4_3_norm = l2norm(layer_256_1_relu1, 'conv4_3_norm')
|
||||
|
||||
### Locations and confidences ##################################################
|
||||
locations = []
|
||||
confidences = []
|
||||
flattenLayersNames = [] # Collect all reshape layers names that should be replaced to flattens.
|
||||
for top, suffix in zip([locations, confidences], ['_mbox_loc', '_mbox_conf']):
|
||||
for bottom, name in zip([conv4_3_norm, fc7, conv6_2_h, conv7_2_h, conv8_2_h, conv9_2_h],
|
||||
['conv4_3_norm', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']):
|
||||
name += suffix
|
||||
flat = tf.layers.flatten(conv(bottom, name))
|
||||
flattenLayersNames.append(flat.name[:flat.name.find(':')])
|
||||
top.append(flat)
|
||||
|
||||
mbox_loc = tf.concat(locations, axis=-1, name='mbox_loc')
|
||||
mbox_conf = tf.concat(confidences, axis=-1, name='mbox_conf')
|
||||
|
||||
total = int(np.prod(mbox_conf.shape[1:]))
|
||||
mbox_conf_reshape = tf.reshape(mbox_conf, [-1, 2], name='mbox_conf_reshape')
|
||||
mbox_conf_softmax = tf.nn.softmax(mbox_conf_reshape, name='mbox_conf_softmax')
|
||||
mbox_conf_flatten = tf.reshape(mbox_conf_softmax, [-1, total], name='mbox_conf_flatten')
|
||||
flattenLayersNames.append('mbox_conf_flatten')
|
||||
|
||||
with tf.Session() as sess:
|
||||
sess.run(tf.global_variables_initializer())
|
||||
|
||||
### Check correctness ######################################################
|
||||
out_nodes = ['mbox_loc', 'mbox_conf_flatten']
|
||||
inp_nodes = [inp.name[:inp.name.find(':')]]
|
||||
|
||||
np.random.seed(2701)
|
||||
inputData = np.random.standard_normal([1, 3, 300, 300]).astype(np.float32)
|
||||
|
||||
cvNet.setInput(inputData)
|
||||
cvNet.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
|
||||
outDNN = cvNet.forward(out_nodes)
|
||||
|
||||
outTF = sess.run([mbox_loc, mbox_conf_flatten], feed_dict={inp: inputData.transpose(0, 2, 3, 1)})
|
||||
print('Max diff @ locations: %e' % np.max(np.abs(outDNN[0] - outTF[0])))
|
||||
print('Max diff @ confidence: %e' % np.max(np.abs(outDNN[1] - outTF[1])))
|
||||
|
||||
# Save a graph
|
||||
graph_def = sess.graph.as_graph_def()
|
||||
|
||||
# Freeze graph. Replaces variables to constants.
|
||||
graph_def = tf.graph_util.convert_variables_to_constants(sess, graph_def, out_nodes)
|
||||
# Optimize graph. Removes training-only ops, unused nodes.
|
||||
graph_def = optimize_for_inference_lib.optimize_for_inference(graph_def, inp_nodes, out_nodes, dtype.as_datatype_enum)
|
||||
# Fuse constant operations.
|
||||
transforms = ["fold_constants(ignore_errors=True)"]
|
||||
if args.quantize:
|
||||
transforms += ["quantize_weights(minimum_size=0)"]
|
||||
transforms += ["sort_by_execution_order"]
|
||||
graph_def = TransformGraph(graph_def, inp_nodes, out_nodes, transforms)
|
||||
|
||||
# By default, float16 weights are stored in repeated tensor's field called
|
||||
# `half_val`. It has type int32 with leading zeros for unused bytes.
|
||||
# This type is encoded by Variant that means only 7 bits are used for value
|
||||
# representation but the last one is indicated the end of encoding. This way
|
||||
# float16 might takes 1 or 2 or 3 bytes depends on value. To improve compression,
|
||||
# we replace all `half_val` values to `tensor_content` using only 2 bytes for everyone.
|
||||
for node in graph_def.node:
|
||||
if 'value' in node.attr:
|
||||
halfs = node.attr["value"].tensor.half_val
|
||||
if not node.attr["value"].tensor.tensor_content and halfs:
|
||||
node.attr["value"].tensor.tensor_content = struct.pack('H' * len(halfs), *halfs)
|
||||
node.attr["value"].tensor.ClearField('half_val')
|
||||
|
||||
# Serialize
|
||||
with tf.gfile.FastGFile(args.pb, 'wb') as f:
|
||||
f.write(graph_def.SerializeToString())
|
||||
|
||||
|
||||
################################################################################
|
||||
# Write a text graph representation
|
||||
################################################################################
|
||||
def tensorMsg(values):
|
||||
msg = 'tensor { dtype: DT_FLOAT tensor_shape { dim { size: %d } }' % len(values)
|
||||
for value in values:
|
||||
msg += 'float_val: %f ' % value
|
||||
return msg + '}'
|
||||
|
||||
# Remove Const nodes and unused attributes.
|
||||
for i in reversed(range(len(graph_def.node))):
|
||||
if graph_def.node[i].op in ['Const', 'Dequantize']:
|
||||
del graph_def.node[i]
|
||||
for attr in ['T', 'data_format', 'Tshape', 'N', 'Tidx', 'Tdim',
|
||||
'use_cudnn_on_gpu', 'Index', 'Tperm', 'is_training',
|
||||
'Tpaddings', 'Tblock_shape', 'Tcrops']:
|
||||
if attr in graph_def.node[i].attr:
|
||||
del graph_def.node[i].attr[attr]
|
||||
|
||||
# Append prior box generators
|
||||
min_sizes = [30, 60, 111, 162, 213, 264]
|
||||
max_sizes = [60, 111, 162, 213, 264, 315]
|
||||
steps = [8, 16, 32, 64, 100, 300]
|
||||
aspect_ratios = [[2], [2, 3], [2, 3], [2, 3], [2], [2]]
|
||||
layers = [conv4_3_norm, fc7, conv6_2_h, conv7_2_h, conv8_2_h, conv9_2_h]
|
||||
for i in range(6):
|
||||
priorBox = NodeDef()
|
||||
priorBox.name = 'PriorBox_%d' % i
|
||||
priorBox.op = 'PriorBox'
|
||||
priorBox.input.append(layers[i].name[:layers[i].name.find(':')])
|
||||
priorBox.input.append(inp_nodes[0]) # data
|
||||
|
||||
text_format.Merge('i: %d' % min_sizes[i], priorBox.attr["min_size"])
|
||||
text_format.Merge('i: %d' % max_sizes[i], priorBox.attr["max_size"])
|
||||
text_format.Merge('b: true', priorBox.attr["flip"])
|
||||
text_format.Merge('b: false', priorBox.attr["clip"])
|
||||
text_format.Merge(tensorMsg(aspect_ratios[i]), priorBox.attr["aspect_ratio"])
|
||||
text_format.Merge(tensorMsg([0.1, 0.1, 0.2, 0.2]), priorBox.attr["variance"])
|
||||
text_format.Merge('f: %f' % steps[i], priorBox.attr["step"])
|
||||
text_format.Merge('f: 0.5', priorBox.attr["offset"])
|
||||
graph_def.node.extend([priorBox])
|
||||
|
||||
# Concatenate prior boxes
|
||||
concat = NodeDef()
|
||||
concat.name = 'mbox_priorbox'
|
||||
concat.op = 'ConcatV2'
|
||||
for i in range(6):
|
||||
concat.input.append('PriorBox_%d' % i)
|
||||
concat.input.append('mbox_loc/axis')
|
||||
graph_def.node.extend([concat])
|
||||
|
||||
# DetectionOutput layer
|
||||
detectionOut = NodeDef()
|
||||
detectionOut.name = 'detection_out'
|
||||
detectionOut.op = 'DetectionOutput'
|
||||
|
||||
detectionOut.input.append('mbox_loc')
|
||||
detectionOut.input.append('mbox_conf_flatten')
|
||||
detectionOut.input.append('mbox_priorbox')
|
||||
|
||||
text_format.Merge('i: 2', detectionOut.attr['num_classes'])
|
||||
text_format.Merge('b: true', detectionOut.attr['share_location'])
|
||||
text_format.Merge('i: 0', detectionOut.attr['background_label_id'])
|
||||
text_format.Merge('f: 0.45', detectionOut.attr['nms_threshold'])
|
||||
text_format.Merge('i: 400', detectionOut.attr['top_k'])
|
||||
text_format.Merge('s: "CENTER_SIZE"', detectionOut.attr['code_type'])
|
||||
text_format.Merge('i: 200', detectionOut.attr['keep_top_k'])
|
||||
text_format.Merge('f: 0.01', detectionOut.attr['confidence_threshold'])
|
||||
|
||||
graph_def.node.extend([detectionOut])
|
||||
|
||||
# Replace L2Normalization subgraph onto a single node.
|
||||
for i in reversed(range(len(graph_def.node))):
|
||||
if graph_def.node[i].name in ['conv4_3_norm/l2_normalize/Square',
|
||||
'conv4_3_norm/l2_normalize/Sum',
|
||||
'conv4_3_norm/l2_normalize/Maximum',
|
||||
'conv4_3_norm/l2_normalize/Rsqrt']:
|
||||
del graph_def.node[i]
|
||||
for node in graph_def.node:
|
||||
if node.name == 'conv4_3_norm/l2_normalize':
|
||||
node.op = 'L2Normalize'
|
||||
node.input.pop()
|
||||
node.input.pop()
|
||||
node.input.append(layer_256_1_relu1.name)
|
||||
node.input.append('conv4_3_norm/l2_normalize/Sum/reduction_indices')
|
||||
break
|
||||
|
||||
softmaxShape = NodeDef()
|
||||
softmaxShape.name = 'reshape_before_softmax'
|
||||
softmaxShape.op = 'Const'
|
||||
text_format.Merge(
|
||||
'tensor {'
|
||||
' dtype: DT_INT32'
|
||||
' tensor_shape { dim { size: 3 } }'
|
||||
' int_val: 0'
|
||||
' int_val: -1'
|
||||
' int_val: 2'
|
||||
'}', softmaxShape.attr["value"])
|
||||
graph_def.node.extend([softmaxShape])
|
||||
|
||||
for node in graph_def.node:
|
||||
if node.name == 'mbox_conf_reshape':
|
||||
node.input[1] = softmaxShape.name
|
||||
elif node.name == 'mbox_conf_softmax':
|
||||
text_format.Merge('i: 2', node.attr['axis'])
|
||||
elif node.name in flattenLayersNames:
|
||||
node.op = 'Flatten'
|
||||
inpName = node.input[0]
|
||||
node.input.pop()
|
||||
node.input.pop()
|
||||
node.input.append(inpName)
|
||||
|
||||
tf.train.write_graph(graph_def, "", args.pbtxt, as_text=True)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,904 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: graph.proto
|
||||
|
||||
#include "graph.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
namespace opencv_tensorflow {
|
||||
constexpr GraphDef::GraphDef(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: node_()
|
||||
, library_(nullptr)
|
||||
, versions_(nullptr)
|
||||
, version_(0){}
|
||||
struct GraphDefDefaultTypeInternal {
|
||||
constexpr GraphDefDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~GraphDefDefaultTypeInternal() {}
|
||||
union {
|
||||
GraphDef _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT GraphDefDefaultTypeInternal _GraphDef_default_instance_;
|
||||
constexpr NodeDef_AttrEntry_DoNotUse::NodeDef_AttrEntry_DoNotUse(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
|
||||
struct NodeDef_AttrEntry_DoNotUseDefaultTypeInternal {
|
||||
constexpr NodeDef_AttrEntry_DoNotUseDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~NodeDef_AttrEntry_DoNotUseDefaultTypeInternal() {}
|
||||
union {
|
||||
NodeDef_AttrEntry_DoNotUse _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT NodeDef_AttrEntry_DoNotUseDefaultTypeInternal _NodeDef_AttrEntry_DoNotUse_default_instance_;
|
||||
constexpr NodeDef::NodeDef(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: input_()
|
||||
, attr_(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{})
|
||||
, name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
|
||||
, op_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
|
||||
, device_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
|
||||
struct NodeDefDefaultTypeInternal {
|
||||
constexpr NodeDefDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~NodeDefDefaultTypeInternal() {}
|
||||
union {
|
||||
NodeDef _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT NodeDefDefaultTypeInternal _NodeDef_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_graph_2eproto[3];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_graph_2eproto = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_graph_2eproto = nullptr;
|
||||
|
||||
const uint32_t TableStruct_graph_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::GraphDef, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::GraphDef, node_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::GraphDef, versions_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::GraphDef, version_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::GraphDef, library_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse, _has_bits_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse, key_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse, value_),
|
||||
0,
|
||||
1,
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, name_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, op_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, input_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, device_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::NodeDef, attr_),
|
||||
};
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, -1, sizeof(::opencv_tensorflow::GraphDef)},
|
||||
{ 10, 18, -1, sizeof(::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse)},
|
||||
{ 20, -1, -1, sizeof(::opencv_tensorflow::NodeDef)},
|
||||
};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_GraphDef_default_instance_),
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_NodeDef_AttrEntry_DoNotUse_default_instance_),
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_NodeDef_default_instance_),
|
||||
};
|
||||
|
||||
const char descriptor_table_protodef_graph_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\013graph.proto\022\021opencv_tensorflow\032\020attr_v"
|
||||
"alue.proto\032\016function.proto\032\016versions.pro"
|
||||
"to\"\262\001\n\010GraphDef\022(\n\004node\030\001 \003(\0132\032.opencv_t"
|
||||
"ensorflow.NodeDef\022/\n\010versions\030\004 \001(\0132\035.op"
|
||||
"encv_tensorflow.VersionDef\022\023\n\007version\030\003 "
|
||||
"\001(\005B\002\030\001\0226\n\007library\030\002 \001(\0132%.opencv_tensor"
|
||||
"flow.FunctionDefLibrary\"\301\001\n\007NodeDef\022\014\n\004n"
|
||||
"ame\030\001 \001(\t\022\n\n\002op\030\002 \001(\t\022\r\n\005input\030\003 \003(\t\022\016\n\006"
|
||||
"device\030\004 \001(\t\0222\n\004attr\030\005 \003(\0132$.opencv_tens"
|
||||
"orflow.NodeDef.AttrEntry\032I\n\tAttrEntry\022\013\n"
|
||||
"\003key\030\001 \001(\t\022+\n\005value\030\002 \001(\0132\034.opencv_tenso"
|
||||
"rflow.AttrValue:\0028\001B,\n\030org.tensorflow.fr"
|
||||
"ameworkB\013GraphProtosP\001\370\001\001b\006proto3"
|
||||
;
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_graph_2eproto_deps[3] = {
|
||||
&::descriptor_table_attr_5fvalue_2eproto,
|
||||
&::descriptor_table_function_2eproto,
|
||||
&::descriptor_table_versions_2eproto,
|
||||
};
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_graph_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_graph_2eproto = {
|
||||
false, false, 513, descriptor_table_protodef_graph_2eproto, "graph.proto",
|
||||
&descriptor_table_graph_2eproto_once, descriptor_table_graph_2eproto_deps, 3, 3,
|
||||
schemas, file_default_instances, TableStruct_graph_2eproto::offsets,
|
||||
file_level_metadata_graph_2eproto, file_level_enum_descriptors_graph_2eproto, file_level_service_descriptors_graph_2eproto,
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_graph_2eproto_getter() {
|
||||
return &descriptor_table_graph_2eproto;
|
||||
}
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_graph_2eproto(&descriptor_table_graph_2eproto);
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class GraphDef::_Internal {
|
||||
public:
|
||||
static const ::opencv_tensorflow::VersionDef& versions(const GraphDef* msg);
|
||||
static const ::opencv_tensorflow::FunctionDefLibrary& library(const GraphDef* msg);
|
||||
};
|
||||
|
||||
const ::opencv_tensorflow::VersionDef&
|
||||
GraphDef::_Internal::versions(const GraphDef* msg) {
|
||||
return *msg->versions_;
|
||||
}
|
||||
const ::opencv_tensorflow::FunctionDefLibrary&
|
||||
GraphDef::_Internal::library(const GraphDef* msg) {
|
||||
return *msg->library_;
|
||||
}
|
||||
void GraphDef::clear_versions() {
|
||||
if (GetArenaForAllocation() == nullptr && versions_ != nullptr) {
|
||||
delete versions_;
|
||||
}
|
||||
versions_ = nullptr;
|
||||
}
|
||||
void GraphDef::clear_library() {
|
||||
if (GetArenaForAllocation() == nullptr && library_ != nullptr) {
|
||||
delete library_;
|
||||
}
|
||||
library_ = nullptr;
|
||||
}
|
||||
GraphDef::GraphDef(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
|
||||
node_(arena) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.GraphDef)
|
||||
}
|
||||
GraphDef::GraphDef(const GraphDef& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
node_(from.node_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
if (from._internal_has_library()) {
|
||||
library_ = new ::opencv_tensorflow::FunctionDefLibrary(*from.library_);
|
||||
} else {
|
||||
library_ = nullptr;
|
||||
}
|
||||
if (from._internal_has_versions()) {
|
||||
versions_ = new ::opencv_tensorflow::VersionDef(*from.versions_);
|
||||
} else {
|
||||
versions_ = nullptr;
|
||||
}
|
||||
version_ = from.version_;
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.GraphDef)
|
||||
}
|
||||
|
||||
inline void GraphDef::SharedCtor() {
|
||||
::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&library_) - reinterpret_cast<char*>(this)),
|
||||
0, static_cast<size_t>(reinterpret_cast<char*>(&version_) -
|
||||
reinterpret_cast<char*>(&library_)) + sizeof(version_));
|
||||
}
|
||||
|
||||
GraphDef::~GraphDef() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.GraphDef)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void GraphDef::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
if (this != internal_default_instance()) delete library_;
|
||||
if (this != internal_default_instance()) delete versions_;
|
||||
}
|
||||
|
||||
void GraphDef::ArenaDtor(void* object) {
|
||||
GraphDef* _this = reinterpret_cast< GraphDef* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void GraphDef::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void GraphDef::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void GraphDef::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.GraphDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
node_.Clear();
|
||||
if (GetArenaForAllocation() == nullptr && library_ != nullptr) {
|
||||
delete library_;
|
||||
}
|
||||
library_ = nullptr;
|
||||
if (GetArenaForAllocation() == nullptr && versions_ != nullptr) {
|
||||
delete versions_;
|
||||
}
|
||||
versions_ = nullptr;
|
||||
version_ = 0;
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* GraphDef::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// repeated .opencv_tensorflow.NodeDef node = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
|
||||
ptr -= 1;
|
||||
do {
|
||||
ptr += 1;
|
||||
ptr = ctx->ParseMessage(_internal_add_node(), ptr);
|
||||
CHK_(ptr);
|
||||
if (!ctx->DataAvailable(ptr)) break;
|
||||
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// .opencv_tensorflow.FunctionDefLibrary library = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
|
||||
ptr = ctx->ParseMessage(_internal_mutable_library(), ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// int32 version = 3 [deprecated = true];
|
||||
case 3:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
|
||||
version_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// .opencv_tensorflow.VersionDef versions = 4;
|
||||
case 4:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
|
||||
ptr = ctx->ParseMessage(_internal_mutable_versions(), ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* GraphDef::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.GraphDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .opencv_tensorflow.NodeDef node = 1;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->_internal_node_size()); i < n; i++) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
InternalWriteMessage(1, this->_internal_node(i), target, stream);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.FunctionDefLibrary library = 2;
|
||||
if (this->_internal_has_library()) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
InternalWriteMessage(
|
||||
2, _Internal::library(this), target, stream);
|
||||
}
|
||||
|
||||
// int32 version = 3 [deprecated = true];
|
||||
if (this->_internal_version() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_version(), target);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.VersionDef versions = 4;
|
||||
if (this->_internal_has_versions()) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
InternalWriteMessage(
|
||||
4, _Internal::versions(this), target, stream);
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.GraphDef)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t GraphDef::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.GraphDef)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .opencv_tensorflow.NodeDef node = 1;
|
||||
total_size += 1UL * this->_internal_node_size();
|
||||
for (const auto& msg : this->node_) {
|
||||
total_size +=
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.FunctionDefLibrary library = 2;
|
||||
if (this->_internal_has_library()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
|
||||
*library_);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.VersionDef versions = 4;
|
||||
if (this->_internal_has_versions()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
|
||||
*versions_);
|
||||
}
|
||||
|
||||
// int32 version = 3 [deprecated = true];
|
||||
if (this->_internal_version() != 0) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_version());
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData GraphDef::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
GraphDef::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GraphDef::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void GraphDef::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<GraphDef *>(to)->MergeFrom(
|
||||
static_cast<const GraphDef &>(from));
|
||||
}
|
||||
|
||||
|
||||
void GraphDef::MergeFrom(const GraphDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.GraphDef)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
node_.MergeFrom(from.node_);
|
||||
if (from._internal_has_library()) {
|
||||
_internal_mutable_library()->::opencv_tensorflow::FunctionDefLibrary::MergeFrom(from._internal_library());
|
||||
}
|
||||
if (from._internal_has_versions()) {
|
||||
_internal_mutable_versions()->::opencv_tensorflow::VersionDef::MergeFrom(from._internal_versions());
|
||||
}
|
||||
if (from._internal_version() != 0) {
|
||||
_internal_set_version(from._internal_version());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void GraphDef::CopyFrom(const GraphDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.GraphDef)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool GraphDef::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphDef::InternalSwap(GraphDef* other) {
|
||||
using std::swap;
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
node_.InternalSwap(&other->node_);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::memswap<
|
||||
PROTOBUF_FIELD_OFFSET(GraphDef, version_)
|
||||
+ sizeof(GraphDef::version_)
|
||||
- PROTOBUF_FIELD_OFFSET(GraphDef, library_)>(
|
||||
reinterpret_cast<char*>(&library_),
|
||||
reinterpret_cast<char*>(&other->library_));
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GraphDef::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_graph_2eproto_getter, &descriptor_table_graph_2eproto_once,
|
||||
file_level_metadata_graph_2eproto[0]);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
NodeDef_AttrEntry_DoNotUse::NodeDef_AttrEntry_DoNotUse() {}
|
||||
NodeDef_AttrEntry_DoNotUse::NodeDef_AttrEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena)
|
||||
: SuperType(arena) {}
|
||||
void NodeDef_AttrEntry_DoNotUse::MergeFrom(const NodeDef_AttrEntry_DoNotUse& other) {
|
||||
MergeFromInternal(other);
|
||||
}
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata NodeDef_AttrEntry_DoNotUse::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_graph_2eproto_getter, &descriptor_table_graph_2eproto_once,
|
||||
file_level_metadata_graph_2eproto[1]);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class NodeDef::_Internal {
|
||||
public:
|
||||
};
|
||||
|
||||
void NodeDef::clear_attr() {
|
||||
attr_.Clear();
|
||||
}
|
||||
NodeDef::NodeDef(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
|
||||
input_(arena),
|
||||
attr_(arena) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.NodeDef)
|
||||
}
|
||||
NodeDef::NodeDef(const NodeDef& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
input_(from.input_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
attr_.MergeFrom(from.attr_);
|
||||
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (!from._internal_name().empty()) {
|
||||
name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(),
|
||||
GetArenaForAllocation());
|
||||
}
|
||||
op_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
op_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (!from._internal_op().empty()) {
|
||||
op_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_op(),
|
||||
GetArenaForAllocation());
|
||||
}
|
||||
device_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
device_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (!from._internal_device().empty()) {
|
||||
device_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_device(),
|
||||
GetArenaForAllocation());
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.NodeDef)
|
||||
}
|
||||
|
||||
inline void NodeDef::SharedCtor() {
|
||||
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
op_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
op_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
device_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
device_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
}
|
||||
|
||||
NodeDef::~NodeDef() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.NodeDef)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void NodeDef::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
op_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
device_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void NodeDef::ArenaDtor(void* object) {
|
||||
NodeDef* _this = reinterpret_cast< NodeDef* >(object);
|
||||
(void)_this;
|
||||
_this->attr_. ~MapField();
|
||||
}
|
||||
inline void NodeDef::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena) {
|
||||
if (arena != nullptr) {
|
||||
arena->OwnCustomDestructor(this, &NodeDef::ArenaDtor);
|
||||
}
|
||||
}
|
||||
void NodeDef::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void NodeDef::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.NodeDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
input_.Clear();
|
||||
attr_.Clear();
|
||||
name_.ClearToEmpty();
|
||||
op_.ClearToEmpty();
|
||||
device_.ClearToEmpty();
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* NodeDef::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// string name = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
|
||||
auto str = _internal_mutable_name();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "opencv_tensorflow.NodeDef.name"));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// string op = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
|
||||
auto str = _internal_mutable_op();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "opencv_tensorflow.NodeDef.op"));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated string input = 3;
|
||||
case 3:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
|
||||
ptr -= 1;
|
||||
do {
|
||||
ptr += 1;
|
||||
auto str = _internal_add_input();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "opencv_tensorflow.NodeDef.input"));
|
||||
CHK_(ptr);
|
||||
if (!ctx->DataAvailable(ptr)) break;
|
||||
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// string device = 4;
|
||||
case 4:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
|
||||
auto str = _internal_mutable_device();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "opencv_tensorflow.NodeDef.device"));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// map<string, .opencv_tensorflow.AttrValue> attr = 5;
|
||||
case 5:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
|
||||
ptr -= 1;
|
||||
do {
|
||||
ptr += 1;
|
||||
ptr = ctx->ParseMessage(&attr_, ptr);
|
||||
CHK_(ptr);
|
||||
if (!ctx->DataAvailable(ptr)) break;
|
||||
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* NodeDef::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.NodeDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string name = 1;
|
||||
if (!this->_internal_name().empty()) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.NodeDef.name");
|
||||
target = stream->WriteStringMaybeAliased(
|
||||
1, this->_internal_name(), target);
|
||||
}
|
||||
|
||||
// string op = 2;
|
||||
if (!this->_internal_op().empty()) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->_internal_op().data(), static_cast<int>(this->_internal_op().length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.NodeDef.op");
|
||||
target = stream->WriteStringMaybeAliased(
|
||||
2, this->_internal_op(), target);
|
||||
}
|
||||
|
||||
// repeated string input = 3;
|
||||
for (int i = 0, n = this->_internal_input_size(); i < n; i++) {
|
||||
const auto& s = this->_internal_input(i);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
s.data(), static_cast<int>(s.length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.NodeDef.input");
|
||||
target = stream->WriteString(3, s, target);
|
||||
}
|
||||
|
||||
// string device = 4;
|
||||
if (!this->_internal_device().empty()) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->_internal_device().data(), static_cast<int>(this->_internal_device().length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.NodeDef.device");
|
||||
target = stream->WriteStringMaybeAliased(
|
||||
4, this->_internal_device(), target);
|
||||
}
|
||||
|
||||
// map<string, .opencv_tensorflow.AttrValue> attr = 5;
|
||||
if (!this->_internal_attr().empty()) {
|
||||
typedef ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::opencv_tensorflow::AttrValue >::const_pointer
|
||||
ConstPtr;
|
||||
typedef ConstPtr SortItem;
|
||||
typedef ::PROTOBUF_NAMESPACE_ID::internal::CompareByDerefFirst<SortItem> Less;
|
||||
struct Utf8Check {
|
||||
static void Check(ConstPtr p) {
|
||||
(void)p;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
p->first.data(), static_cast<int>(p->first.length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.NodeDef.AttrEntry.key");
|
||||
}
|
||||
};
|
||||
|
||||
if (stream->IsSerializationDeterministic() &&
|
||||
this->_internal_attr().size() > 1) {
|
||||
::std::unique_ptr<SortItem[]> items(
|
||||
new SortItem[this->_internal_attr().size()]);
|
||||
typedef ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::opencv_tensorflow::AttrValue >::size_type size_type;
|
||||
size_type n = 0;
|
||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, ::opencv_tensorflow::AttrValue >::const_iterator
|
||||
it = this->_internal_attr().begin();
|
||||
it != this->_internal_attr().end(); ++it, ++n) {
|
||||
items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);
|
||||
}
|
||||
::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
|
||||
for (size_type i = 0; i < n; i++) {
|
||||
target = NodeDef_AttrEntry_DoNotUse::Funcs::InternalSerialize(5, items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second, target, stream);
|
||||
Utf8Check::Check(&(*items[static_cast<ptrdiff_t>(i)]));
|
||||
}
|
||||
} else {
|
||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, ::opencv_tensorflow::AttrValue >::const_iterator
|
||||
it = this->_internal_attr().begin();
|
||||
it != this->_internal_attr().end(); ++it) {
|
||||
target = NodeDef_AttrEntry_DoNotUse::Funcs::InternalSerialize(5, it->first, it->second, target, stream);
|
||||
Utf8Check::Check(&(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.NodeDef)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t NodeDef::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.NodeDef)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated string input = 3;
|
||||
total_size += 1 *
|
||||
::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(input_.size());
|
||||
for (int i = 0, n = input_.size(); i < n; i++) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
input_.Get(i));
|
||||
}
|
||||
|
||||
// map<string, .opencv_tensorflow.AttrValue> attr = 5;
|
||||
total_size += 1 *
|
||||
::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_attr_size());
|
||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, ::opencv_tensorflow::AttrValue >::const_iterator
|
||||
it = this->_internal_attr().begin();
|
||||
it != this->_internal_attr().end(); ++it) {
|
||||
total_size += NodeDef_AttrEntry_DoNotUse::Funcs::ByteSizeLong(it->first, it->second);
|
||||
}
|
||||
|
||||
// string name = 1;
|
||||
if (!this->_internal_name().empty()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
this->_internal_name());
|
||||
}
|
||||
|
||||
// string op = 2;
|
||||
if (!this->_internal_op().empty()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
this->_internal_op());
|
||||
}
|
||||
|
||||
// string device = 4;
|
||||
if (!this->_internal_device().empty()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
this->_internal_device());
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData NodeDef::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
NodeDef::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*NodeDef::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void NodeDef::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<NodeDef *>(to)->MergeFrom(
|
||||
static_cast<const NodeDef &>(from));
|
||||
}
|
||||
|
||||
|
||||
void NodeDef::MergeFrom(const NodeDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.NodeDef)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
input_.MergeFrom(from.input_);
|
||||
attr_.MergeFrom(from.attr_);
|
||||
if (!from._internal_name().empty()) {
|
||||
_internal_set_name(from._internal_name());
|
||||
}
|
||||
if (!from._internal_op().empty()) {
|
||||
_internal_set_op(from._internal_op());
|
||||
}
|
||||
if (!from._internal_device().empty()) {
|
||||
_internal_set_device(from._internal_device());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void NodeDef::CopyFrom(const NodeDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.NodeDef)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool NodeDef::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void NodeDef::InternalSwap(NodeDef* other) {
|
||||
using std::swap;
|
||||
auto* lhs_arena = GetArenaForAllocation();
|
||||
auto* rhs_arena = other->GetArenaForAllocation();
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
input_.InternalSwap(&other->input_);
|
||||
attr_.InternalSwap(&other->attr_);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
|
||||
&name_, lhs_arena,
|
||||
&other->name_, rhs_arena
|
||||
);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
|
||||
&op_, lhs_arena,
|
||||
&other->op_, rhs_arena
|
||||
);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
|
||||
&device_, lhs_arena,
|
||||
&other->device_, rhs_arena
|
||||
);
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata NodeDef::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_graph_2eproto_getter, &descriptor_table_graph_2eproto_once,
|
||||
file_level_metadata_graph_2eproto[2]);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::GraphDef* Arena::CreateMaybeMessage< ::opencv_tensorflow::GraphDef >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::GraphDef >(arena);
|
||||
}
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse* Arena::CreateMaybeMessage< ::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::NodeDef_AttrEntry_DoNotUse >(arena);
|
||||
}
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::NodeDef* Arena::CreateMaybeMessage< ::opencv_tensorflow::NodeDef >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::NodeDef >(arena);
|
||||
}
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,751 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor.proto
|
||||
|
||||
#include "tensor.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
namespace opencv_tensorflow {
|
||||
constexpr TensorProto::TensorProto(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: float_val_()
|
||||
, double_val_()
|
||||
, int_val_()
|
||||
, _int_val_cached_byte_size_(0)
|
||||
, string_val_()
|
||||
, scomplex_val_()
|
||||
, int64_val_()
|
||||
, _int64_val_cached_byte_size_(0)
|
||||
, bool_val_()
|
||||
, dcomplex_val_()
|
||||
, half_val_()
|
||||
, _half_val_cached_byte_size_(0)
|
||||
, tensor_content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
|
||||
, tensor_shape_(nullptr)
|
||||
, dtype_(0)
|
||||
|
||||
, version_number_(0){}
|
||||
struct TensorProtoDefaultTypeInternal {
|
||||
constexpr TensorProtoDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~TensorProtoDefaultTypeInternal() {}
|
||||
union {
|
||||
TensorProto _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TensorProtoDefaultTypeInternal _TensorProto_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_tensor_2eproto[1];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_tensor_2eproto = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_tensor_2eproto = nullptr;
|
||||
|
||||
const uint32_t TableStruct_tensor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, dtype_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, tensor_shape_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, version_number_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, tensor_content_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, half_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, float_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, double_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, int_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, string_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, scomplex_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, int64_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, bool_val_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorProto, dcomplex_val_),
|
||||
};
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, -1, sizeof(::opencv_tensorflow::TensorProto)},
|
||||
};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_TensorProto_default_instance_),
|
||||
};
|
||||
|
||||
const char descriptor_table_protodef_tensor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\014tensor.proto\022\021opencv_tensorflow\032\022tenso"
|
||||
"r_shape.proto\032\013types.proto\"\363\002\n\013TensorPro"
|
||||
"to\022*\n\005dtype\030\001 \001(\0162\033.opencv_tensorflow.Da"
|
||||
"taType\0229\n\014tensor_shape\030\002 \001(\0132#.opencv_te"
|
||||
"nsorflow.TensorShapeProto\022\026\n\016version_num"
|
||||
"ber\030\003 \001(\005\022\026\n\016tensor_content\030\004 \001(\014\022\024\n\010hal"
|
||||
"f_val\030\r \003(\005B\002\020\001\022\025\n\tfloat_val\030\005 \003(\002B\002\020\001\022\026"
|
||||
"\n\ndouble_val\030\006 \003(\001B\002\020\001\022\023\n\007int_val\030\007 \003(\005B"
|
||||
"\002\020\001\022\022\n\nstring_val\030\010 \003(\014\022\030\n\014scomplex_val\030"
|
||||
"\t \003(\002B\002\020\001\022\025\n\tint64_val\030\n \003(\003B\002\020\001\022\024\n\010bool"
|
||||
"_val\030\013 \003(\010B\002\020\001\022\030\n\014dcomplex_val\030\014 \003(\001B\002\020\001"
|
||||
"B-\n\030org.tensorflow.frameworkB\014TensorProt"
|
||||
"osP\001\370\001\001b\006proto3"
|
||||
;
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_tensor_2eproto_deps[2] = {
|
||||
&::descriptor_table_tensor_5fshape_2eproto,
|
||||
&::descriptor_table_types_2eproto,
|
||||
};
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_tensor_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_tensor_2eproto = {
|
||||
false, false, 495, descriptor_table_protodef_tensor_2eproto, "tensor.proto",
|
||||
&descriptor_table_tensor_2eproto_once, descriptor_table_tensor_2eproto_deps, 2, 1,
|
||||
schemas, file_default_instances, TableStruct_tensor_2eproto::offsets,
|
||||
file_level_metadata_tensor_2eproto, file_level_enum_descriptors_tensor_2eproto, file_level_service_descriptors_tensor_2eproto,
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_tensor_2eproto_getter() {
|
||||
return &descriptor_table_tensor_2eproto;
|
||||
}
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_tensor_2eproto(&descriptor_table_tensor_2eproto);
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorProto::_Internal {
|
||||
public:
|
||||
static const ::opencv_tensorflow::TensorShapeProto& tensor_shape(const TensorProto* msg);
|
||||
};
|
||||
|
||||
const ::opencv_tensorflow::TensorShapeProto&
|
||||
TensorProto::_Internal::tensor_shape(const TensorProto* msg) {
|
||||
return *msg->tensor_shape_;
|
||||
}
|
||||
void TensorProto::clear_tensor_shape() {
|
||||
if (GetArenaForAllocation() == nullptr && tensor_shape_ != nullptr) {
|
||||
delete tensor_shape_;
|
||||
}
|
||||
tensor_shape_ = nullptr;
|
||||
}
|
||||
TensorProto::TensorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
|
||||
float_val_(arena),
|
||||
double_val_(arena),
|
||||
int_val_(arena),
|
||||
string_val_(arena),
|
||||
scomplex_val_(arena),
|
||||
int64_val_(arena),
|
||||
bool_val_(arena),
|
||||
dcomplex_val_(arena),
|
||||
half_val_(arena) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.TensorProto)
|
||||
}
|
||||
TensorProto::TensorProto(const TensorProto& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
float_val_(from.float_val_),
|
||||
double_val_(from.double_val_),
|
||||
int_val_(from.int_val_),
|
||||
string_val_(from.string_val_),
|
||||
scomplex_val_(from.scomplex_val_),
|
||||
int64_val_(from.int64_val_),
|
||||
bool_val_(from.bool_val_),
|
||||
dcomplex_val_(from.dcomplex_val_),
|
||||
half_val_(from.half_val_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
tensor_content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
tensor_content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (!from._internal_tensor_content().empty()) {
|
||||
tensor_content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_tensor_content(),
|
||||
GetArenaForAllocation());
|
||||
}
|
||||
if (from._internal_has_tensor_shape()) {
|
||||
tensor_shape_ = new ::opencv_tensorflow::TensorShapeProto(*from.tensor_shape_);
|
||||
} else {
|
||||
tensor_shape_ = nullptr;
|
||||
}
|
||||
::memcpy(&dtype_, &from.dtype_,
|
||||
static_cast<size_t>(reinterpret_cast<char*>(&version_number_) -
|
||||
reinterpret_cast<char*>(&dtype_)) + sizeof(version_number_));
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.TensorProto)
|
||||
}
|
||||
|
||||
inline void TensorProto::SharedCtor() {
|
||||
tensor_content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
tensor_content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&tensor_shape_) - reinterpret_cast<char*>(this)),
|
||||
0, static_cast<size_t>(reinterpret_cast<char*>(&version_number_) -
|
||||
reinterpret_cast<char*>(&tensor_shape_)) + sizeof(version_number_));
|
||||
}
|
||||
|
||||
TensorProto::~TensorProto() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.TensorProto)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void TensorProto::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
tensor_content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
if (this != internal_default_instance()) delete tensor_shape_;
|
||||
}
|
||||
|
||||
void TensorProto::ArenaDtor(void* object) {
|
||||
TensorProto* _this = reinterpret_cast< TensorProto* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void TensorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void TensorProto::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void TensorProto::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.TensorProto)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
float_val_.Clear();
|
||||
double_val_.Clear();
|
||||
int_val_.Clear();
|
||||
string_val_.Clear();
|
||||
scomplex_val_.Clear();
|
||||
int64_val_.Clear();
|
||||
bool_val_.Clear();
|
||||
dcomplex_val_.Clear();
|
||||
half_val_.Clear();
|
||||
tensor_content_.ClearToEmpty();
|
||||
if (GetArenaForAllocation() == nullptr && tensor_shape_ != nullptr) {
|
||||
delete tensor_shape_;
|
||||
}
|
||||
tensor_shape_ = nullptr;
|
||||
::memset(&dtype_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&version_number_) -
|
||||
reinterpret_cast<char*>(&dtype_)) + sizeof(version_number_));
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* TensorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// .opencv_tensorflow.DataType dtype = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
|
||||
uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
|
||||
CHK_(ptr);
|
||||
_internal_set_dtype(static_cast<::opencv_tensorflow::DataType>(val));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// .opencv_tensorflow.TensorShapeProto tensor_shape = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
|
||||
ptr = ctx->ParseMessage(_internal_mutable_tensor_shape(), ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// int32 version_number = 3;
|
||||
case 3:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
|
||||
version_number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// bytes tensor_content = 4;
|
||||
case 4:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
|
||||
auto str = _internal_mutable_tensor_content();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated float float_val = 5 [packed = true];
|
||||
case 5:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedFloatParser(_internal_mutable_float_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 45) {
|
||||
_internal_add_float_val(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr));
|
||||
ptr += sizeof(float);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated double double_val = 6 [packed = true];
|
||||
case 6:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedDoubleParser(_internal_mutable_double_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 49) {
|
||||
_internal_add_double_val(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr));
|
||||
ptr += sizeof(double);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated int32 int_val = 7 [packed = true];
|
||||
case 7:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_int_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 56) {
|
||||
_internal_add_int_val(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated bytes string_val = 8;
|
||||
case 8:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
|
||||
ptr -= 1;
|
||||
do {
|
||||
ptr += 1;
|
||||
auto str = _internal_add_string_val();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(ptr);
|
||||
if (!ctx->DataAvailable(ptr)) break;
|
||||
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<66>(ptr));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated float scomplex_val = 9 [packed = true];
|
||||
case 9:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedFloatParser(_internal_mutable_scomplex_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 77) {
|
||||
_internal_add_scomplex_val(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr));
|
||||
ptr += sizeof(float);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated int64 int64_val = 10 [packed = true];
|
||||
case 10:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt64Parser(_internal_mutable_int64_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 80) {
|
||||
_internal_add_int64_val(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated bool bool_val = 11 [packed = true];
|
||||
case 11:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 90)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedBoolParser(_internal_mutable_bool_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 88) {
|
||||
_internal_add_bool_val(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated double dcomplex_val = 12 [packed = true];
|
||||
case 12:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 98)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedDoubleParser(_internal_mutable_dcomplex_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 97) {
|
||||
_internal_add_dcomplex_val(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr));
|
||||
ptr += sizeof(double);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated int32 half_val = 13 [packed = true];
|
||||
case 13:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 106)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_half_val(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 104) {
|
||||
_internal_add_half_val(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* TensorProto::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.TensorProto)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// .opencv_tensorflow.DataType dtype = 1;
|
||||
if (this->_internal_dtype() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
|
||||
1, this->_internal_dtype(), target);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.TensorShapeProto tensor_shape = 2;
|
||||
if (this->_internal_has_tensor_shape()) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
InternalWriteMessage(
|
||||
2, _Internal::tensor_shape(this), target, stream);
|
||||
}
|
||||
|
||||
// int32 version_number = 3;
|
||||
if (this->_internal_version_number() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_version_number(), target);
|
||||
}
|
||||
|
||||
// bytes tensor_content = 4;
|
||||
if (!this->_internal_tensor_content().empty()) {
|
||||
target = stream->WriteBytesMaybeAliased(
|
||||
4, this->_internal_tensor_content(), target);
|
||||
}
|
||||
|
||||
// repeated float float_val = 5 [packed = true];
|
||||
if (this->_internal_float_val_size() > 0) {
|
||||
target = stream->WriteFixedPacked(5, _internal_float_val(), target);
|
||||
}
|
||||
|
||||
// repeated double double_val = 6 [packed = true];
|
||||
if (this->_internal_double_val_size() > 0) {
|
||||
target = stream->WriteFixedPacked(6, _internal_double_val(), target);
|
||||
}
|
||||
|
||||
// repeated int32 int_val = 7 [packed = true];
|
||||
{
|
||||
int byte_size = _int_val_cached_byte_size_.load(std::memory_order_relaxed);
|
||||
if (byte_size > 0) {
|
||||
target = stream->WriteInt32Packed(
|
||||
7, _internal_int_val(), byte_size, target);
|
||||
}
|
||||
}
|
||||
|
||||
// repeated bytes string_val = 8;
|
||||
for (int i = 0, n = this->_internal_string_val_size(); i < n; i++) {
|
||||
const auto& s = this->_internal_string_val(i);
|
||||
target = stream->WriteBytes(8, s, target);
|
||||
}
|
||||
|
||||
// repeated float scomplex_val = 9 [packed = true];
|
||||
if (this->_internal_scomplex_val_size() > 0) {
|
||||
target = stream->WriteFixedPacked(9, _internal_scomplex_val(), target);
|
||||
}
|
||||
|
||||
// repeated int64 int64_val = 10 [packed = true];
|
||||
{
|
||||
int byte_size = _int64_val_cached_byte_size_.load(std::memory_order_relaxed);
|
||||
if (byte_size > 0) {
|
||||
target = stream->WriteInt64Packed(
|
||||
10, _internal_int64_val(), byte_size, target);
|
||||
}
|
||||
}
|
||||
|
||||
// repeated bool bool_val = 11 [packed = true];
|
||||
if (this->_internal_bool_val_size() > 0) {
|
||||
target = stream->WriteFixedPacked(11, _internal_bool_val(), target);
|
||||
}
|
||||
|
||||
// repeated double dcomplex_val = 12 [packed = true];
|
||||
if (this->_internal_dcomplex_val_size() > 0) {
|
||||
target = stream->WriteFixedPacked(12, _internal_dcomplex_val(), target);
|
||||
}
|
||||
|
||||
// repeated int32 half_val = 13 [packed = true];
|
||||
{
|
||||
int byte_size = _half_val_cached_byte_size_.load(std::memory_order_relaxed);
|
||||
if (byte_size > 0) {
|
||||
target = stream->WriteInt32Packed(
|
||||
13, _internal_half_val(), byte_size, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.TensorProto)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t TensorProto::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.TensorProto)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated float float_val = 5 [packed = true];
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->_internal_float_val_size());
|
||||
size_t data_size = 4UL * count;
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated double double_val = 6 [packed = true];
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->_internal_double_val_size());
|
||||
size_t data_size = 8UL * count;
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated int32 int_val = 7 [packed = true];
|
||||
{
|
||||
size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
Int32Size(this->int_val_);
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size);
|
||||
_int_val_cached_byte_size_.store(cached_size,
|
||||
std::memory_order_relaxed);
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated bytes string_val = 8;
|
||||
total_size += 1 *
|
||||
::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(string_val_.size());
|
||||
for (int i = 0, n = string_val_.size(); i < n; i++) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
|
||||
string_val_.Get(i));
|
||||
}
|
||||
|
||||
// repeated float scomplex_val = 9 [packed = true];
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->_internal_scomplex_val_size());
|
||||
size_t data_size = 4UL * count;
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated int64 int64_val = 10 [packed = true];
|
||||
{
|
||||
size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
Int64Size(this->int64_val_);
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size);
|
||||
_int64_val_cached_byte_size_.store(cached_size,
|
||||
std::memory_order_relaxed);
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated bool bool_val = 11 [packed = true];
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->_internal_bool_val_size());
|
||||
size_t data_size = 1UL * count;
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated double dcomplex_val = 12 [packed = true];
|
||||
{
|
||||
unsigned int count = static_cast<unsigned int>(this->_internal_dcomplex_val_size());
|
||||
size_t data_size = 8UL * count;
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// repeated int32 half_val = 13 [packed = true];
|
||||
{
|
||||
size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
Int32Size(this->half_val_);
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size);
|
||||
_half_val_cached_byte_size_.store(cached_size,
|
||||
std::memory_order_relaxed);
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// bytes tensor_content = 4;
|
||||
if (!this->_internal_tensor_content().empty()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
|
||||
this->_internal_tensor_content());
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.TensorShapeProto tensor_shape = 2;
|
||||
if (this->_internal_has_tensor_shape()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
|
||||
*tensor_shape_);
|
||||
}
|
||||
|
||||
// .opencv_tensorflow.DataType dtype = 1;
|
||||
if (this->_internal_dtype() != 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_dtype());
|
||||
}
|
||||
|
||||
// int32 version_number = 3;
|
||||
if (this->_internal_version_number() != 0) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_version_number());
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData TensorProto::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
TensorProto::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*TensorProto::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void TensorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<TensorProto *>(to)->MergeFrom(
|
||||
static_cast<const TensorProto &>(from));
|
||||
}
|
||||
|
||||
|
||||
void TensorProto::MergeFrom(const TensorProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.TensorProto)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
float_val_.MergeFrom(from.float_val_);
|
||||
double_val_.MergeFrom(from.double_val_);
|
||||
int_val_.MergeFrom(from.int_val_);
|
||||
string_val_.MergeFrom(from.string_val_);
|
||||
scomplex_val_.MergeFrom(from.scomplex_val_);
|
||||
int64_val_.MergeFrom(from.int64_val_);
|
||||
bool_val_.MergeFrom(from.bool_val_);
|
||||
dcomplex_val_.MergeFrom(from.dcomplex_val_);
|
||||
half_val_.MergeFrom(from.half_val_);
|
||||
if (!from._internal_tensor_content().empty()) {
|
||||
_internal_set_tensor_content(from._internal_tensor_content());
|
||||
}
|
||||
if (from._internal_has_tensor_shape()) {
|
||||
_internal_mutable_tensor_shape()->::opencv_tensorflow::TensorShapeProto::MergeFrom(from._internal_tensor_shape());
|
||||
}
|
||||
if (from._internal_dtype() != 0) {
|
||||
_internal_set_dtype(from._internal_dtype());
|
||||
}
|
||||
if (from._internal_version_number() != 0) {
|
||||
_internal_set_version_number(from._internal_version_number());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void TensorProto::CopyFrom(const TensorProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.TensorProto)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool TensorProto::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TensorProto::InternalSwap(TensorProto* other) {
|
||||
using std::swap;
|
||||
auto* lhs_arena = GetArenaForAllocation();
|
||||
auto* rhs_arena = other->GetArenaForAllocation();
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
float_val_.InternalSwap(&other->float_val_);
|
||||
double_val_.InternalSwap(&other->double_val_);
|
||||
int_val_.InternalSwap(&other->int_val_);
|
||||
string_val_.InternalSwap(&other->string_val_);
|
||||
scomplex_val_.InternalSwap(&other->scomplex_val_);
|
||||
int64_val_.InternalSwap(&other->int64_val_);
|
||||
bool_val_.InternalSwap(&other->bool_val_);
|
||||
dcomplex_val_.InternalSwap(&other->dcomplex_val_);
|
||||
half_val_.InternalSwap(&other->half_val_);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
|
||||
&tensor_content_, lhs_arena,
|
||||
&other->tensor_content_, rhs_arena
|
||||
);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::memswap<
|
||||
PROTOBUF_FIELD_OFFSET(TensorProto, version_number_)
|
||||
+ sizeof(TensorProto::version_number_)
|
||||
- PROTOBUF_FIELD_OFFSET(TensorProto, tensor_shape_)>(
|
||||
reinterpret_cast<char*>(&tensor_shape_),
|
||||
reinterpret_cast<char*>(&other->tensor_shape_));
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata TensorProto::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_tensor_2eproto_getter, &descriptor_table_tensor_2eproto_once,
|
||||
file_level_metadata_tensor_2eproto[0]);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::TensorProto* Arena::CreateMaybeMessage< ::opencv_tensorflow::TensorProto >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::TensorProto >(arena);
|
||||
}
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,554 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor_shape.proto
|
||||
|
||||
#include "tensor_shape.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
namespace opencv_tensorflow {
|
||||
constexpr TensorShapeProto_Dim::TensorShapeProto_Dim(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
|
||||
, size_(int64_t{0}){}
|
||||
struct TensorShapeProto_DimDefaultTypeInternal {
|
||||
constexpr TensorShapeProto_DimDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~TensorShapeProto_DimDefaultTypeInternal() {}
|
||||
union {
|
||||
TensorShapeProto_Dim _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TensorShapeProto_DimDefaultTypeInternal _TensorShapeProto_Dim_default_instance_;
|
||||
constexpr TensorShapeProto::TensorShapeProto(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: dim_()
|
||||
, unknown_rank_(false){}
|
||||
struct TensorShapeProtoDefaultTypeInternal {
|
||||
constexpr TensorShapeProtoDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~TensorShapeProtoDefaultTypeInternal() {}
|
||||
union {
|
||||
TensorShapeProto _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TensorShapeProtoDefaultTypeInternal _TensorShapeProto_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_tensor_5fshape_2eproto[2];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_tensor_5fshape_2eproto = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_tensor_5fshape_2eproto = nullptr;
|
||||
|
||||
const uint32_t TableStruct_tensor_5fshape_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto_Dim, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto_Dim, size_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto_Dim, name_),
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto, dim_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::TensorShapeProto, unknown_rank_),
|
||||
};
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, -1, sizeof(::opencv_tensorflow::TensorShapeProto_Dim)},
|
||||
{ 8, -1, -1, sizeof(::opencv_tensorflow::TensorShapeProto)},
|
||||
};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_TensorShapeProto_Dim_default_instance_),
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_TensorShapeProto_default_instance_),
|
||||
};
|
||||
|
||||
const char descriptor_table_protodef_tensor_5fshape_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\022tensor_shape.proto\022\021opencv_tensorflow\""
|
||||
"\201\001\n\020TensorShapeProto\0224\n\003dim\030\002 \003(\0132\'.open"
|
||||
"cv_tensorflow.TensorShapeProto.Dim\022\024\n\014un"
|
||||
"known_rank\030\003 \001(\010\032!\n\003Dim\022\014\n\004size\030\001 \001(\003\022\014\n"
|
||||
"\004name\030\002 \001(\tB2\n\030org.tensorflow.frameworkB"
|
||||
"\021TensorShapeProtosP\001\370\001\001b\006proto3"
|
||||
;
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_tensor_5fshape_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_tensor_5fshape_2eproto = {
|
||||
false, false, 231, descriptor_table_protodef_tensor_5fshape_2eproto, "tensor_shape.proto",
|
||||
&descriptor_table_tensor_5fshape_2eproto_once, nullptr, 0, 2,
|
||||
schemas, file_default_instances, TableStruct_tensor_5fshape_2eproto::offsets,
|
||||
file_level_metadata_tensor_5fshape_2eproto, file_level_enum_descriptors_tensor_5fshape_2eproto, file_level_service_descriptors_tensor_5fshape_2eproto,
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_tensor_5fshape_2eproto_getter() {
|
||||
return &descriptor_table_tensor_5fshape_2eproto;
|
||||
}
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_tensor_5fshape_2eproto(&descriptor_table_tensor_5fshape_2eproto);
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorShapeProto_Dim::_Internal {
|
||||
public:
|
||||
};
|
||||
|
||||
TensorShapeProto_Dim::TensorShapeProto_Dim(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
TensorShapeProto_Dim::TensorShapeProto_Dim(const TensorShapeProto_Dim& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message() {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (!from._internal_name().empty()) {
|
||||
name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(),
|
||||
GetArenaForAllocation());
|
||||
}
|
||||
size_ = from.size_;
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
|
||||
inline void TensorShapeProto_Dim::SharedCtor() {
|
||||
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
size_ = int64_t{0};
|
||||
}
|
||||
|
||||
TensorShapeProto_Dim::~TensorShapeProto_Dim() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void TensorShapeProto_Dim::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::ArenaDtor(void* object) {
|
||||
TensorShapeProto_Dim* _this = reinterpret_cast< TensorShapeProto_Dim* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void TensorShapeProto_Dim::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void TensorShapeProto_Dim::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
name_.ClearToEmpty();
|
||||
size_ = int64_t{0};
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* TensorShapeProto_Dim::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// int64 size = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
|
||||
size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// string name = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
|
||||
auto str = _internal_mutable_name();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "opencv_tensorflow.TensorShapeProto.Dim.name"));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* TensorShapeProto_Dim::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// int64 size = 1;
|
||||
if (this->_internal_size() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_size(), target);
|
||||
}
|
||||
|
||||
// string name = 2;
|
||||
if (!this->_internal_name().empty()) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"opencv_tensorflow.TensorShapeProto.Dim.name");
|
||||
target = stream->WriteStringMaybeAliased(
|
||||
2, this->_internal_name(), target);
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t TensorShapeProto_Dim::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string name = 2;
|
||||
if (!this->_internal_name().empty()) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
this->_internal_name());
|
||||
}
|
||||
|
||||
// int64 size = 1;
|
||||
if (this->_internal_size() != 0) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64SizePlusOne(this->_internal_size());
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData TensorShapeProto_Dim::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
TensorShapeProto_Dim::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*TensorShapeProto_Dim::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void TensorShapeProto_Dim::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<TensorShapeProto_Dim *>(to)->MergeFrom(
|
||||
static_cast<const TensorShapeProto_Dim &>(from));
|
||||
}
|
||||
|
||||
|
||||
void TensorShapeProto_Dim::MergeFrom(const TensorShapeProto_Dim& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (!from._internal_name().empty()) {
|
||||
_internal_set_name(from._internal_name());
|
||||
}
|
||||
if (from._internal_size() != 0) {
|
||||
_internal_set_size(from._internal_size());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::CopyFrom(const TensorShapeProto_Dim& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool TensorShapeProto_Dim::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::InternalSwap(TensorShapeProto_Dim* other) {
|
||||
using std::swap;
|
||||
auto* lhs_arena = GetArenaForAllocation();
|
||||
auto* rhs_arena = other->GetArenaForAllocation();
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
|
||||
&name_, lhs_arena,
|
||||
&other->name_, rhs_arena
|
||||
);
|
||||
swap(size_, other->size_);
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata TensorShapeProto_Dim::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_tensor_5fshape_2eproto_getter, &descriptor_table_tensor_5fshape_2eproto_once,
|
||||
file_level_metadata_tensor_5fshape_2eproto[0]);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorShapeProto::_Internal {
|
||||
public:
|
||||
};
|
||||
|
||||
TensorShapeProto::TensorShapeProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
|
||||
dim_(arena) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.TensorShapeProto)
|
||||
}
|
||||
TensorShapeProto::TensorShapeProto(const TensorShapeProto& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
dim_(from.dim_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
unknown_rank_ = from.unknown_rank_;
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.TensorShapeProto)
|
||||
}
|
||||
|
||||
inline void TensorShapeProto::SharedCtor() {
|
||||
unknown_rank_ = false;
|
||||
}
|
||||
|
||||
TensorShapeProto::~TensorShapeProto() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.TensorShapeProto)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void TensorShapeProto::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
}
|
||||
|
||||
void TensorShapeProto::ArenaDtor(void* object) {
|
||||
TensorShapeProto* _this = reinterpret_cast< TensorShapeProto* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void TensorShapeProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void TensorShapeProto::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void TensorShapeProto::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.TensorShapeProto)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
dim_.Clear();
|
||||
unknown_rank_ = false;
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* TensorShapeProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// repeated .opencv_tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
|
||||
ptr -= 1;
|
||||
do {
|
||||
ptr += 1;
|
||||
ptr = ctx->ParseMessage(_internal_add_dim(), ptr);
|
||||
CHK_(ptr);
|
||||
if (!ctx->DataAvailable(ptr)) break;
|
||||
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// bool unknown_rank = 3;
|
||||
case 3:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
|
||||
unknown_rank_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* TensorShapeProto::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.TensorShapeProto)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .opencv_tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->_internal_dim_size()); i < n; i++) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
InternalWriteMessage(2, this->_internal_dim(i), target, stream);
|
||||
}
|
||||
|
||||
// bool unknown_rank = 3;
|
||||
if (this->_internal_unknown_rank() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_unknown_rank(), target);
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.TensorShapeProto)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t TensorShapeProto::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.TensorShapeProto)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated .opencv_tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
total_size += 1UL * this->_internal_dim_size();
|
||||
for (const auto& msg : this->dim_) {
|
||||
total_size +=
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
|
||||
}
|
||||
|
||||
// bool unknown_rank = 3;
|
||||
if (this->_internal_unknown_rank() != 0) {
|
||||
total_size += 1 + 1;
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData TensorShapeProto::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
TensorShapeProto::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*TensorShapeProto::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void TensorShapeProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<TensorShapeProto *>(to)->MergeFrom(
|
||||
static_cast<const TensorShapeProto &>(from));
|
||||
}
|
||||
|
||||
|
||||
void TensorShapeProto::MergeFrom(const TensorShapeProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.TensorShapeProto)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
dim_.MergeFrom(from.dim_);
|
||||
if (from._internal_unknown_rank() != 0) {
|
||||
_internal_set_unknown_rank(from._internal_unknown_rank());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void TensorShapeProto::CopyFrom(const TensorShapeProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.TensorShapeProto)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool TensorShapeProto::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TensorShapeProto::InternalSwap(TensorShapeProto* other) {
|
||||
using std::swap;
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
dim_.InternalSwap(&other->dim_);
|
||||
swap(unknown_rank_, other->unknown_rank_);
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata TensorShapeProto::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_tensor_5fshape_2eproto_getter, &descriptor_table_tensor_5fshape_2eproto_once,
|
||||
file_level_metadata_tensor_5fshape_2eproto[1]);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::TensorShapeProto_Dim* Arena::CreateMaybeMessage< ::opencv_tensorflow::TensorShapeProto_Dim >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::TensorShapeProto_Dim >(arena);
|
||||
}
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::TensorShapeProto* Arena::CreateMaybeMessage< ::opencv_tensorflow::TensorShapeProto >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::TensorShapeProto >(arena);
|
||||
}
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
@@ -0,0 +1,559 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor_shape.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_tensor_5fshape_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_tensor_5fshape_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3019000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_tensor_5fshape_2eproto
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct TableStruct_tensor_5fshape_2eproto {
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_tensor_5fshape_2eproto;
|
||||
namespace opencv_tensorflow {
|
||||
class TensorShapeProto;
|
||||
struct TensorShapeProtoDefaultTypeInternal;
|
||||
extern TensorShapeProtoDefaultTypeInternal _TensorShapeProto_default_instance_;
|
||||
class TensorShapeProto_Dim;
|
||||
struct TensorShapeProto_DimDefaultTypeInternal;
|
||||
extern TensorShapeProto_DimDefaultTypeInternal _TensorShapeProto_Dim_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> ::opencv_tensorflow::TensorShapeProto* Arena::CreateMaybeMessage<::opencv_tensorflow::TensorShapeProto>(Arena*);
|
||||
template<> ::opencv_tensorflow::TensorShapeProto_Dim* Arena::CreateMaybeMessage<::opencv_tensorflow::TensorShapeProto_Dim>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorShapeProto_Dim final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:opencv_tensorflow.TensorShapeProto.Dim) */ {
|
||||
public:
|
||||
inline TensorShapeProto_Dim() : TensorShapeProto_Dim(nullptr) {}
|
||||
~TensorShapeProto_Dim() override;
|
||||
explicit constexpr TensorShapeProto_Dim(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
TensorShapeProto_Dim(const TensorShapeProto_Dim& from);
|
||||
TensorShapeProto_Dim(TensorShapeProto_Dim&& from) noexcept
|
||||
: TensorShapeProto_Dim() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline TensorShapeProto_Dim& operator=(const TensorShapeProto_Dim& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline TensorShapeProto_Dim& operator=(TensorShapeProto_Dim&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const TensorShapeProto_Dim& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const TensorShapeProto_Dim* internal_default_instance() {
|
||||
return reinterpret_cast<const TensorShapeProto_Dim*>(
|
||||
&_TensorShapeProto_Dim_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(TensorShapeProto_Dim& a, TensorShapeProto_Dim& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(TensorShapeProto_Dim* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(TensorShapeProto_Dim* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
TensorShapeProto_Dim* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<TensorShapeProto_Dim>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const TensorShapeProto_Dim& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom(const TensorShapeProto_Dim& from);
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(TensorShapeProto_Dim* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "opencv_tensorflow.TensorShapeProto.Dim";
|
||||
}
|
||||
protected:
|
||||
explicit TensorShapeProto_Dim(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kNameFieldNumber = 2,
|
||||
kSizeFieldNumber = 1,
|
||||
};
|
||||
// string name = 2;
|
||||
void clear_name();
|
||||
const std::string& name() const;
|
||||
template <typename ArgT0 = const std::string&, typename... ArgT>
|
||||
void set_name(ArgT0&& arg0, ArgT... args);
|
||||
std::string* mutable_name();
|
||||
PROTOBUF_NODISCARD std::string* release_name();
|
||||
void set_allocated_name(std::string* name);
|
||||
private:
|
||||
const std::string& _internal_name() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
|
||||
std::string* _internal_mutable_name();
|
||||
public:
|
||||
|
||||
// int64 size = 1;
|
||||
void clear_size();
|
||||
int64_t size() const;
|
||||
void set_size(int64_t value);
|
||||
private:
|
||||
int64_t _internal_size() const;
|
||||
void _internal_set_size(int64_t value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:opencv_tensorflow.TensorShapeProto.Dim)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
|
||||
int64_t size_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
friend struct ::TableStruct_tensor_5fshape_2eproto;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class TensorShapeProto final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:opencv_tensorflow.TensorShapeProto) */ {
|
||||
public:
|
||||
inline TensorShapeProto() : TensorShapeProto(nullptr) {}
|
||||
~TensorShapeProto() override;
|
||||
explicit constexpr TensorShapeProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
TensorShapeProto(const TensorShapeProto& from);
|
||||
TensorShapeProto(TensorShapeProto&& from) noexcept
|
||||
: TensorShapeProto() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline TensorShapeProto& operator=(const TensorShapeProto& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline TensorShapeProto& operator=(TensorShapeProto&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const TensorShapeProto& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const TensorShapeProto* internal_default_instance() {
|
||||
return reinterpret_cast<const TensorShapeProto*>(
|
||||
&_TensorShapeProto_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
1;
|
||||
|
||||
friend void swap(TensorShapeProto& a, TensorShapeProto& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(TensorShapeProto* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(TensorShapeProto* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
TensorShapeProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<TensorShapeProto>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const TensorShapeProto& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom(const TensorShapeProto& from);
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(TensorShapeProto* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "opencv_tensorflow.TensorShapeProto";
|
||||
}
|
||||
protected:
|
||||
explicit TensorShapeProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef TensorShapeProto_Dim Dim;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kDimFieldNumber = 2,
|
||||
kUnknownRankFieldNumber = 3,
|
||||
};
|
||||
// repeated .opencv_tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
int dim_size() const;
|
||||
private:
|
||||
int _internal_dim_size() const;
|
||||
public:
|
||||
void clear_dim();
|
||||
::opencv_tensorflow::TensorShapeProto_Dim* mutable_dim(int index);
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::opencv_tensorflow::TensorShapeProto_Dim >*
|
||||
mutable_dim();
|
||||
private:
|
||||
const ::opencv_tensorflow::TensorShapeProto_Dim& _internal_dim(int index) const;
|
||||
::opencv_tensorflow::TensorShapeProto_Dim* _internal_add_dim();
|
||||
public:
|
||||
const ::opencv_tensorflow::TensorShapeProto_Dim& dim(int index) const;
|
||||
::opencv_tensorflow::TensorShapeProto_Dim* add_dim();
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::opencv_tensorflow::TensorShapeProto_Dim >&
|
||||
dim() const;
|
||||
|
||||
// bool unknown_rank = 3;
|
||||
void clear_unknown_rank();
|
||||
bool unknown_rank() const;
|
||||
void set_unknown_rank(bool value);
|
||||
private:
|
||||
bool _internal_unknown_rank() const;
|
||||
void _internal_set_unknown_rank(bool value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:opencv_tensorflow.TensorShapeProto)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::opencv_tensorflow::TensorShapeProto_Dim > dim_;
|
||||
bool unknown_rank_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
friend struct ::TableStruct_tensor_5fshape_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// TensorShapeProto_Dim
|
||||
|
||||
// int64 size = 1;
|
||||
inline void TensorShapeProto_Dim::clear_size() {
|
||||
size_ = int64_t{0};
|
||||
}
|
||||
inline int64_t TensorShapeProto_Dim::_internal_size() const {
|
||||
return size_;
|
||||
}
|
||||
inline int64_t TensorShapeProto_Dim::size() const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.TensorShapeProto.Dim.size)
|
||||
return _internal_size();
|
||||
}
|
||||
inline void TensorShapeProto_Dim::_internal_set_size(int64_t value) {
|
||||
|
||||
size_ = value;
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_size(int64_t value) {
|
||||
_internal_set_size(value);
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.TensorShapeProto.Dim.size)
|
||||
}
|
||||
|
||||
// string name = 2;
|
||||
inline void TensorShapeProto_Dim::clear_name() {
|
||||
name_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& TensorShapeProto_Dim::name() const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.TensorShapeProto.Dim.name)
|
||||
return _internal_name();
|
||||
}
|
||||
template <typename ArgT0, typename... ArgT>
|
||||
inline PROTOBUF_ALWAYS_INLINE
|
||||
void TensorShapeProto_Dim::set_name(ArgT0&& arg0, ArgT... args) {
|
||||
|
||||
name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
inline std::string* TensorShapeProto_Dim::mutable_name() {
|
||||
std::string* _s = _internal_mutable_name();
|
||||
// @@protoc_insertion_point(field_mutable:opencv_tensorflow.TensorShapeProto.Dim.name)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& TensorShapeProto_Dim::_internal_name() const {
|
||||
return name_.Get();
|
||||
}
|
||||
inline void TensorShapeProto_Dim::_internal_set_name(const std::string& value) {
|
||||
|
||||
name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* TensorShapeProto_Dim::_internal_mutable_name() {
|
||||
|
||||
return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
|
||||
}
|
||||
inline std::string* TensorShapeProto_Dim::release_name() {
|
||||
// @@protoc_insertion_point(field_release:opencv_tensorflow.TensorShapeProto.Dim.name)
|
||||
return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_allocated_name(std::string* name) {
|
||||
if (name != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
|
||||
GetArenaForAllocation());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
|
||||
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:opencv_tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// TensorShapeProto
|
||||
|
||||
// repeated .opencv_tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
inline int TensorShapeProto::_internal_dim_size() const {
|
||||
return dim_.size();
|
||||
}
|
||||
inline int TensorShapeProto::dim_size() const {
|
||||
return _internal_dim_size();
|
||||
}
|
||||
inline void TensorShapeProto::clear_dim() {
|
||||
dim_.Clear();
|
||||
}
|
||||
inline ::opencv_tensorflow::TensorShapeProto_Dim* TensorShapeProto::mutable_dim(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:opencv_tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Mutable(index);
|
||||
}
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::opencv_tensorflow::TensorShapeProto_Dim >*
|
||||
TensorShapeProto::mutable_dim() {
|
||||
// @@protoc_insertion_point(field_mutable_list:opencv_tensorflow.TensorShapeProto.dim)
|
||||
return &dim_;
|
||||
}
|
||||
inline const ::opencv_tensorflow::TensorShapeProto_Dim& TensorShapeProto::_internal_dim(int index) const {
|
||||
return dim_.Get(index);
|
||||
}
|
||||
inline const ::opencv_tensorflow::TensorShapeProto_Dim& TensorShapeProto::dim(int index) const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.TensorShapeProto.dim)
|
||||
return _internal_dim(index);
|
||||
}
|
||||
inline ::opencv_tensorflow::TensorShapeProto_Dim* TensorShapeProto::_internal_add_dim() {
|
||||
return dim_.Add();
|
||||
}
|
||||
inline ::opencv_tensorflow::TensorShapeProto_Dim* TensorShapeProto::add_dim() {
|
||||
::opencv_tensorflow::TensorShapeProto_Dim* _add = _internal_add_dim();
|
||||
// @@protoc_insertion_point(field_add:opencv_tensorflow.TensorShapeProto.dim)
|
||||
return _add;
|
||||
}
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::opencv_tensorflow::TensorShapeProto_Dim >&
|
||||
TensorShapeProto::dim() const {
|
||||
// @@protoc_insertion_point(field_list:opencv_tensorflow.TensorShapeProto.dim)
|
||||
return dim_;
|
||||
}
|
||||
|
||||
// bool unknown_rank = 3;
|
||||
inline void TensorShapeProto::clear_unknown_rank() {
|
||||
unknown_rank_ = false;
|
||||
}
|
||||
inline bool TensorShapeProto::_internal_unknown_rank() const {
|
||||
return unknown_rank_;
|
||||
}
|
||||
inline bool TensorShapeProto::unknown_rank() const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.TensorShapeProto.unknown_rank)
|
||||
return _internal_unknown_rank();
|
||||
}
|
||||
inline void TensorShapeProto::_internal_set_unknown_rank(bool value) {
|
||||
|
||||
unknown_rank_ = value;
|
||||
}
|
||||
inline void TensorShapeProto::set_unknown_rank(bool value) {
|
||||
_internal_set_unknown_rank(value);
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.TensorShapeProto.unknown_rank)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace opencv_tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_tensor_5fshape_2eproto
|
||||
@@ -0,0 +1,120 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: types.proto
|
||||
|
||||
#include "types.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
namespace opencv_tensorflow {
|
||||
} // namespace opencv_tensorflow
|
||||
static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_types_2eproto[1];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_types_2eproto = nullptr;
|
||||
const uint32_t TableStruct_types_2eproto::offsets[1] = {};
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema* schemas = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::Message* const* file_default_instances = nullptr;
|
||||
|
||||
const char descriptor_table_protodef_types_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\013types.proto\022\021opencv_tensorflow*\234\005\n\010Dat"
|
||||
"aType\022\016\n\nDT_INVALID\020\000\022\014\n\010DT_FLOAT\020\001\022\r\n\tD"
|
||||
"T_DOUBLE\020\002\022\014\n\010DT_INT32\020\003\022\014\n\010DT_UINT8\020\004\022\014"
|
||||
"\n\010DT_INT16\020\005\022\013\n\007DT_INT8\020\006\022\r\n\tDT_STRING\020\007"
|
||||
"\022\020\n\014DT_COMPLEX64\020\010\022\014\n\010DT_INT64\020\t\022\013\n\007DT_B"
|
||||
"OOL\020\n\022\014\n\010DT_QINT8\020\013\022\r\n\tDT_QUINT8\020\014\022\r\n\tDT"
|
||||
"_QINT32\020\r\022\017\n\013DT_BFLOAT16\020\016\022\r\n\tDT_QINT16\020"
|
||||
"\017\022\016\n\nDT_QUINT16\020\020\022\r\n\tDT_UINT16\020\021\022\021\n\rDT_C"
|
||||
"OMPLEX128\020\022\022\013\n\007DT_HALF\020\023\022\020\n\014DT_FLOAT_REF"
|
||||
"\020e\022\021\n\rDT_DOUBLE_REF\020f\022\020\n\014DT_INT32_REF\020g\022"
|
||||
"\020\n\014DT_UINT8_REF\020h\022\020\n\014DT_INT16_REF\020i\022\017\n\013D"
|
||||
"T_INT8_REF\020j\022\021\n\rDT_STRING_REF\020k\022\024\n\020DT_CO"
|
||||
"MPLEX64_REF\020l\022\020\n\014DT_INT64_REF\020m\022\017\n\013DT_BO"
|
||||
"OL_REF\020n\022\020\n\014DT_QINT8_REF\020o\022\021\n\rDT_QUINT8_"
|
||||
"REF\020p\022\021\n\rDT_QINT32_REF\020q\022\023\n\017DT_BFLOAT16_"
|
||||
"REF\020r\022\021\n\rDT_QINT16_REF\020s\022\022\n\016DT_QUINT16_R"
|
||||
"EF\020t\022\021\n\rDT_UINT16_REF\020u\022\025\n\021DT_COMPLEX128"
|
||||
"_REF\020v\022\017\n\013DT_HALF_REF\020wB,\n\030org.tensorflo"
|
||||
"w.frameworkB\013TypesProtosP\001\370\001\001b\006proto3"
|
||||
;
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_types_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_types_2eproto = {
|
||||
false, false, 757, descriptor_table_protodef_types_2eproto, "types.proto",
|
||||
&descriptor_table_types_2eproto_once, nullptr, 0, 0,
|
||||
schemas, file_default_instances, TableStruct_types_2eproto::offsets,
|
||||
nullptr, file_level_enum_descriptors_types_2eproto, file_level_service_descriptors_types_2eproto,
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_types_2eproto_getter() {
|
||||
return &descriptor_table_types_2eproto;
|
||||
}
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_types_2eproto(&descriptor_table_types_2eproto);
|
||||
namespace opencv_tensorflow {
|
||||
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* DataType_descriptor() {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_types_2eproto);
|
||||
return file_level_enum_descriptors_types_2eproto[0];
|
||||
}
|
||||
bool DataType_IsValid(int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
case 111:
|
||||
case 112:
|
||||
case 113:
|
||||
case 114:
|
||||
case 115:
|
||||
case 116:
|
||||
case 117:
|
||||
case 118:
|
||||
case 119:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
@@ -0,0 +1,154 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: types.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_types_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_types_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3019000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_types_2eproto
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct TableStruct_types_2eproto {
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_types_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
enum DataType : int {
|
||||
DT_INVALID = 0,
|
||||
DT_FLOAT = 1,
|
||||
DT_DOUBLE = 2,
|
||||
DT_INT32 = 3,
|
||||
DT_UINT8 = 4,
|
||||
DT_INT16 = 5,
|
||||
DT_INT8 = 6,
|
||||
DT_STRING = 7,
|
||||
DT_COMPLEX64 = 8,
|
||||
DT_INT64 = 9,
|
||||
DT_BOOL = 10,
|
||||
DT_QINT8 = 11,
|
||||
DT_QUINT8 = 12,
|
||||
DT_QINT32 = 13,
|
||||
DT_BFLOAT16 = 14,
|
||||
DT_QINT16 = 15,
|
||||
DT_QUINT16 = 16,
|
||||
DT_UINT16 = 17,
|
||||
DT_COMPLEX128 = 18,
|
||||
DT_HALF = 19,
|
||||
DT_FLOAT_REF = 101,
|
||||
DT_DOUBLE_REF = 102,
|
||||
DT_INT32_REF = 103,
|
||||
DT_UINT8_REF = 104,
|
||||
DT_INT16_REF = 105,
|
||||
DT_INT8_REF = 106,
|
||||
DT_STRING_REF = 107,
|
||||
DT_COMPLEX64_REF = 108,
|
||||
DT_INT64_REF = 109,
|
||||
DT_BOOL_REF = 110,
|
||||
DT_QINT8_REF = 111,
|
||||
DT_QUINT8_REF = 112,
|
||||
DT_QINT32_REF = 113,
|
||||
DT_BFLOAT16_REF = 114,
|
||||
DT_QINT16_REF = 115,
|
||||
DT_QUINT16_REF = 116,
|
||||
DT_UINT16_REF = 117,
|
||||
DT_COMPLEX128_REF = 118,
|
||||
DT_HALF_REF = 119,
|
||||
DataType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
|
||||
DataType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
|
||||
};
|
||||
bool DataType_IsValid(int value);
|
||||
constexpr DataType DataType_MIN = DT_INVALID;
|
||||
constexpr DataType DataType_MAX = DT_HALF_REF;
|
||||
constexpr int DataType_ARRAYSIZE = DataType_MAX + 1;
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* DataType_descriptor();
|
||||
template<typename T>
|
||||
inline const std::string& DataType_Name(T enum_t_value) {
|
||||
static_assert(::std::is_same<T, DataType>::value ||
|
||||
::std::is_integral<T>::value,
|
||||
"Incorrect type passed to function DataType_Name.");
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
|
||||
DataType_descriptor(), enum_t_value);
|
||||
}
|
||||
inline bool DataType_Parse(
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam name, DataType* value) {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<DataType>(
|
||||
DataType_descriptor(), name, value);
|
||||
}
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace opencv_tensorflow
|
||||
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
template <> struct is_proto_enum< ::opencv_tensorflow::DataType> : ::std::true_type {};
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::opencv_tensorflow::DataType>() {
|
||||
return ::opencv_tensorflow::DataType_descriptor();
|
||||
}
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_types_2eproto
|
||||
@@ -0,0 +1,342 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: versions.proto
|
||||
|
||||
#include "versions.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
PROTOBUF_PRAGMA_INIT_SEG
|
||||
namespace opencv_tensorflow {
|
||||
constexpr VersionDef::VersionDef(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
|
||||
: bad_consumers_()
|
||||
, _bad_consumers_cached_byte_size_(0)
|
||||
, producer_(0)
|
||||
, min_consumer_(0){}
|
||||
struct VersionDefDefaultTypeInternal {
|
||||
constexpr VersionDefDefaultTypeInternal()
|
||||
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
|
||||
~VersionDefDefaultTypeInternal() {}
|
||||
union {
|
||||
VersionDef _instance;
|
||||
};
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT VersionDefDefaultTypeInternal _VersionDef_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_versions_2eproto[1];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_versions_2eproto = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_versions_2eproto = nullptr;
|
||||
|
||||
const uint32_t TableStruct_versions_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::VersionDef, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
~0u, // no _inlined_string_donated_
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::VersionDef, producer_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::VersionDef, min_consumer_),
|
||||
PROTOBUF_FIELD_OFFSET(::opencv_tensorflow::VersionDef, bad_consumers_),
|
||||
};
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, -1, sizeof(::opencv_tensorflow::VersionDef)},
|
||||
};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::opencv_tensorflow::_VersionDef_default_instance_),
|
||||
};
|
||||
|
||||
const char descriptor_table_protodef_versions_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\016versions.proto\022\021opencv_tensorflow\"K\n\nV"
|
||||
"ersionDef\022\020\n\010producer\030\001 \001(\005\022\024\n\014min_consu"
|
||||
"mer\030\002 \001(\005\022\025\n\rbad_consumers\030\003 \003(\005B/\n\030org."
|
||||
"tensorflow.frameworkB\016VersionsProtosP\001\370\001"
|
||||
"\001b\006proto3"
|
||||
;
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_versions_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_versions_2eproto = {
|
||||
false, false, 169, descriptor_table_protodef_versions_2eproto, "versions.proto",
|
||||
&descriptor_table_versions_2eproto_once, nullptr, 0, 1,
|
||||
schemas, file_default_instances, TableStruct_versions_2eproto::offsets,
|
||||
file_level_metadata_versions_2eproto, file_level_enum_descriptors_versions_2eproto, file_level_service_descriptors_versions_2eproto,
|
||||
};
|
||||
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_versions_2eproto_getter() {
|
||||
return &descriptor_table_versions_2eproto;
|
||||
}
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_versions_2eproto(&descriptor_table_versions_2eproto);
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class VersionDef::_Internal {
|
||||
public:
|
||||
};
|
||||
|
||||
VersionDef::VersionDef(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
|
||||
bad_consumers_(arena) {
|
||||
SharedCtor();
|
||||
if (!is_message_owned) {
|
||||
RegisterArenaDtor(arena);
|
||||
}
|
||||
// @@protoc_insertion_point(arena_constructor:opencv_tensorflow.VersionDef)
|
||||
}
|
||||
VersionDef::VersionDef(const VersionDef& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
bad_consumers_(from.bad_consumers_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
::memcpy(&producer_, &from.producer_,
|
||||
static_cast<size_t>(reinterpret_cast<char*>(&min_consumer_) -
|
||||
reinterpret_cast<char*>(&producer_)) + sizeof(min_consumer_));
|
||||
// @@protoc_insertion_point(copy_constructor:opencv_tensorflow.VersionDef)
|
||||
}
|
||||
|
||||
inline void VersionDef::SharedCtor() {
|
||||
::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&producer_) - reinterpret_cast<char*>(this)),
|
||||
0, static_cast<size_t>(reinterpret_cast<char*>(&min_consumer_) -
|
||||
reinterpret_cast<char*>(&producer_)) + sizeof(min_consumer_));
|
||||
}
|
||||
|
||||
VersionDef::~VersionDef() {
|
||||
// @@protoc_insertion_point(destructor:opencv_tensorflow.VersionDef)
|
||||
if (GetArenaForAllocation() != nullptr) return;
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
inline void VersionDef::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
|
||||
}
|
||||
|
||||
void VersionDef::ArenaDtor(void* object) {
|
||||
VersionDef* _this = reinterpret_cast< VersionDef* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void VersionDef::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void VersionDef::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
|
||||
void VersionDef::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:opencv_tensorflow.VersionDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
bad_consumers_.Clear();
|
||||
::memset(&producer_, 0, static_cast<size_t>(
|
||||
reinterpret_cast<char*>(&min_consumer_) -
|
||||
reinterpret_cast<char*>(&producer_)) + sizeof(min_consumer_));
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* VersionDef::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
uint32_t tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
switch (tag >> 3) {
|
||||
// int32 producer = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
|
||||
producer_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// int32 min_consumer = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
|
||||
min_consumer_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
// repeated int32 bad_consumers = 3;
|
||||
case 3:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_bad_consumers(), ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else if (static_cast<uint8_t>(tag) == 24) {
|
||||
_internal_add_bad_consumers(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
|
||||
CHK_(ptr);
|
||||
} else
|
||||
goto handle_unusual;
|
||||
continue;
|
||||
default:
|
||||
goto handle_unusual;
|
||||
} // switch
|
||||
handle_unusual:
|
||||
if ((tag == 0) || ((tag & 7) == 4)) {
|
||||
CHK_(ptr);
|
||||
ctx->SetLastTag(tag);
|
||||
goto message_done;
|
||||
}
|
||||
ptr = UnknownFieldParse(
|
||||
tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
} // while
|
||||
message_done:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto message_done;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
uint8_t* VersionDef::_InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:opencv_tensorflow.VersionDef)
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// int32 producer = 1;
|
||||
if (this->_internal_producer() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_producer(), target);
|
||||
}
|
||||
|
||||
// int32 min_consumer = 2;
|
||||
if (this->_internal_min_consumer() != 0) {
|
||||
target = stream->EnsureSpace(target);
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_min_consumer(), target);
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
{
|
||||
int byte_size = _bad_consumers_cached_byte_size_.load(std::memory_order_relaxed);
|
||||
if (byte_size > 0) {
|
||||
target = stream->WriteInt32Packed(
|
||||
3, _internal_bad_consumers(), byte_size, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:opencv_tensorflow.VersionDef)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t VersionDef::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:opencv_tensorflow.VersionDef)
|
||||
size_t total_size = 0;
|
||||
|
||||
uint32_t cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
{
|
||||
size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
||||
Int32Size(this->bad_consumers_);
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
|
||||
static_cast<int32_t>(data_size));
|
||||
}
|
||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size);
|
||||
_bad_consumers_cached_byte_size_.store(cached_size,
|
||||
std::memory_order_relaxed);
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
// int32 producer = 1;
|
||||
if (this->_internal_producer() != 0) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_producer());
|
||||
}
|
||||
|
||||
// int32 min_consumer = 2;
|
||||
if (this->_internal_min_consumer() != 0) {
|
||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_min_consumer());
|
||||
}
|
||||
|
||||
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
|
||||
}
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData VersionDef::_class_data_ = {
|
||||
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
|
||||
VersionDef::MergeImpl
|
||||
};
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*VersionDef::GetClassData() const { return &_class_data_; }
|
||||
|
||||
void VersionDef::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
static_cast<VersionDef *>(to)->MergeFrom(
|
||||
static_cast<const VersionDef &>(from));
|
||||
}
|
||||
|
||||
|
||||
void VersionDef::MergeFrom(const VersionDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:opencv_tensorflow.VersionDef)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
uint32_t cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
bad_consumers_.MergeFrom(from.bad_consumers_);
|
||||
if (from._internal_producer() != 0) {
|
||||
_internal_set_producer(from._internal_producer());
|
||||
}
|
||||
if (from._internal_min_consumer() != 0) {
|
||||
_internal_set_min_consumer(from._internal_min_consumer());
|
||||
}
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
}
|
||||
|
||||
void VersionDef::CopyFrom(const VersionDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:opencv_tensorflow.VersionDef)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool VersionDef::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void VersionDef::InternalSwap(VersionDef* other) {
|
||||
using std::swap;
|
||||
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
|
||||
bad_consumers_.InternalSwap(&other->bad_consumers_);
|
||||
::PROTOBUF_NAMESPACE_ID::internal::memswap<
|
||||
PROTOBUF_FIELD_OFFSET(VersionDef, min_consumer_)
|
||||
+ sizeof(VersionDef::min_consumer_)
|
||||
- PROTOBUF_FIELD_OFFSET(VersionDef, producer_)>(
|
||||
reinterpret_cast<char*>(&producer_),
|
||||
reinterpret_cast<char*>(&other->producer_));
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata VersionDef::GetMetadata() const {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
|
||||
&descriptor_table_versions_2eproto_getter, &descriptor_table_versions_2eproto_once,
|
||||
file_level_metadata_versions_2eproto[0]);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_NOINLINE ::opencv_tensorflow::VersionDef* Arena::CreateMaybeMessage< ::opencv_tensorflow::VersionDef >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::opencv_tensorflow::VersionDef >(arena);
|
||||
}
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
@@ -0,0 +1,357 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: versions.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_versions_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_versions_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3019000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_versions_2eproto
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct TableStruct_versions_2eproto {
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
|
||||
static const uint32_t offsets[];
|
||||
};
|
||||
extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_versions_2eproto;
|
||||
namespace opencv_tensorflow {
|
||||
class VersionDef;
|
||||
struct VersionDefDefaultTypeInternal;
|
||||
extern VersionDefDefaultTypeInternal _VersionDef_default_instance_;
|
||||
} // namespace opencv_tensorflow
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> ::opencv_tensorflow::VersionDef* Arena::CreateMaybeMessage<::opencv_tensorflow::VersionDef>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
namespace opencv_tensorflow {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class VersionDef final :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:opencv_tensorflow.VersionDef) */ {
|
||||
public:
|
||||
inline VersionDef() : VersionDef(nullptr) {}
|
||||
~VersionDef() override;
|
||||
explicit constexpr VersionDef(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
|
||||
|
||||
VersionDef(const VersionDef& from);
|
||||
VersionDef(VersionDef&& from) noexcept
|
||||
: VersionDef() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline VersionDef& operator=(const VersionDef& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline VersionDef& operator=(VersionDef&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetOwningArena() == from.GetOwningArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetOwningArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const VersionDef& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const VersionDef* internal_default_instance() {
|
||||
return reinterpret_cast<const VersionDef*>(
|
||||
&_VersionDef_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
friend void swap(VersionDef& a, VersionDef& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(VersionDef* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() != nullptr &&
|
||||
GetOwningArena() == other->GetOwningArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetOwningArena() == other->GetOwningArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(VersionDef* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
VersionDef* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
|
||||
return CreateMaybeMessage<VersionDef>(arena);
|
||||
}
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
|
||||
void CopyFrom(const VersionDef& from);
|
||||
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
|
||||
void MergeFrom(const VersionDef& from);
|
||||
private:
|
||||
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
|
||||
public:
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
uint8_t* _InternalSerialize(
|
||||
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(VersionDef* other);
|
||||
|
||||
private:
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "opencv_tensorflow.VersionDef";
|
||||
}
|
||||
protected:
|
||||
explicit VersionDef(::PROTOBUF_NAMESPACE_ID::Arena* arena,
|
||||
bool is_message_owned = false);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
public:
|
||||
|
||||
static const ClassData _class_data_;
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kBadConsumersFieldNumber = 3,
|
||||
kProducerFieldNumber = 1,
|
||||
kMinConsumerFieldNumber = 2,
|
||||
};
|
||||
// repeated int32 bad_consumers = 3;
|
||||
int bad_consumers_size() const;
|
||||
private:
|
||||
int _internal_bad_consumers_size() const;
|
||||
public:
|
||||
void clear_bad_consumers();
|
||||
private:
|
||||
int32_t _internal_bad_consumers(int index) const;
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
|
||||
_internal_bad_consumers() const;
|
||||
void _internal_add_bad_consumers(int32_t value);
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
|
||||
_internal_mutable_bad_consumers();
|
||||
public:
|
||||
int32_t bad_consumers(int index) const;
|
||||
void set_bad_consumers(int index, int32_t value);
|
||||
void add_bad_consumers(int32_t value);
|
||||
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
|
||||
bad_consumers() const;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
|
||||
mutable_bad_consumers();
|
||||
|
||||
// int32 producer = 1;
|
||||
void clear_producer();
|
||||
int32_t producer() const;
|
||||
void set_producer(int32_t value);
|
||||
private:
|
||||
int32_t _internal_producer() const;
|
||||
void _internal_set_producer(int32_t value);
|
||||
public:
|
||||
|
||||
// int32 min_consumer = 2;
|
||||
void clear_min_consumer();
|
||||
int32_t min_consumer() const;
|
||||
void set_min_consumer(int32_t value);
|
||||
private:
|
||||
int32_t _internal_min_consumer() const;
|
||||
void _internal_set_min_consumer(int32_t value);
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:opencv_tensorflow.VersionDef)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > bad_consumers_;
|
||||
mutable std::atomic<int> _bad_consumers_cached_byte_size_;
|
||||
int32_t producer_;
|
||||
int32_t min_consumer_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
friend struct ::TableStruct_versions_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// VersionDef
|
||||
|
||||
// int32 producer = 1;
|
||||
inline void VersionDef::clear_producer() {
|
||||
producer_ = 0;
|
||||
}
|
||||
inline int32_t VersionDef::_internal_producer() const {
|
||||
return producer_;
|
||||
}
|
||||
inline int32_t VersionDef::producer() const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.VersionDef.producer)
|
||||
return _internal_producer();
|
||||
}
|
||||
inline void VersionDef::_internal_set_producer(int32_t value) {
|
||||
|
||||
producer_ = value;
|
||||
}
|
||||
inline void VersionDef::set_producer(int32_t value) {
|
||||
_internal_set_producer(value);
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.VersionDef.producer)
|
||||
}
|
||||
|
||||
// int32 min_consumer = 2;
|
||||
inline void VersionDef::clear_min_consumer() {
|
||||
min_consumer_ = 0;
|
||||
}
|
||||
inline int32_t VersionDef::_internal_min_consumer() const {
|
||||
return min_consumer_;
|
||||
}
|
||||
inline int32_t VersionDef::min_consumer() const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.VersionDef.min_consumer)
|
||||
return _internal_min_consumer();
|
||||
}
|
||||
inline void VersionDef::_internal_set_min_consumer(int32_t value) {
|
||||
|
||||
min_consumer_ = value;
|
||||
}
|
||||
inline void VersionDef::set_min_consumer(int32_t value) {
|
||||
_internal_set_min_consumer(value);
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.VersionDef.min_consumer)
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
inline int VersionDef::_internal_bad_consumers_size() const {
|
||||
return bad_consumers_.size();
|
||||
}
|
||||
inline int VersionDef::bad_consumers_size() const {
|
||||
return _internal_bad_consumers_size();
|
||||
}
|
||||
inline void VersionDef::clear_bad_consumers() {
|
||||
bad_consumers_.Clear();
|
||||
}
|
||||
inline int32_t VersionDef::_internal_bad_consumers(int index) const {
|
||||
return bad_consumers_.Get(index);
|
||||
}
|
||||
inline int32_t VersionDef::bad_consumers(int index) const {
|
||||
// @@protoc_insertion_point(field_get:opencv_tensorflow.VersionDef.bad_consumers)
|
||||
return _internal_bad_consumers(index);
|
||||
}
|
||||
inline void VersionDef::set_bad_consumers(int index, int32_t value) {
|
||||
bad_consumers_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:opencv_tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
inline void VersionDef::_internal_add_bad_consumers(int32_t value) {
|
||||
bad_consumers_.Add(value);
|
||||
}
|
||||
inline void VersionDef::add_bad_consumers(int32_t value) {
|
||||
_internal_add_bad_consumers(value);
|
||||
// @@protoc_insertion_point(field_add:opencv_tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
|
||||
VersionDef::_internal_bad_consumers() const {
|
||||
return bad_consumers_;
|
||||
}
|
||||
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
|
||||
VersionDef::bad_consumers() const {
|
||||
// @@protoc_insertion_point(field_list:opencv_tensorflow.VersionDef.bad_consumers)
|
||||
return _internal_bad_consumers();
|
||||
}
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
|
||||
VersionDef::_internal_mutable_bad_consumers() {
|
||||
return &bad_consumers_;
|
||||
}
|
||||
inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
|
||||
VersionDef::mutable_bad_consumers() {
|
||||
// @@protoc_insertion_point(field_mutable_list:opencv_tensorflow.VersionDef.bad_consumers)
|
||||
return _internal_mutable_bad_consumers();
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace opencv_tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_versions_2eproto
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
#include "../test/test_common.impl.hpp" // shared with accuracy tests
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct Conv1DParam_t {
|
||||
int kernel;
|
||||
struct BlobShape { int dims[3]; } shapeIn;
|
||||
int outCN;
|
||||
int groups;
|
||||
int stride;
|
||||
int dilation;
|
||||
int pad[2];
|
||||
const char* padMode;
|
||||
bool hasBias;
|
||||
double declared_flops;
|
||||
};
|
||||
// Details: #12142
|
||||
static const Conv1DParam_t testConvolution1DConfigs[] = {
|
||||
{3, {{1, 6, 10}}, 6, 1, 1, 1, {0, 0}, "VALID", true, 1776.},
|
||||
{3, {{1, 2, 19}}, 2, 2, 2, 1, {1, 1}, "", true, 260.},
|
||||
{3, {{1, 2, 25}}, 2, 2, 1, 1, {2, 2}, "SAME", false, 650.},
|
||||
};
|
||||
|
||||
struct Conv1DParamID
|
||||
{
|
||||
enum {
|
||||
CONV_0 = 0,
|
||||
CONV_LAST = sizeof(testConvolution1DConfigs) / sizeof(testConvolution1DConfigs[0])
|
||||
};
|
||||
int val_;
|
||||
Conv1DParamID(int val = 0) : val_(val) {}
|
||||
operator int() const { return val_; }
|
||||
static ::testing::internal::ParamGenerator<Conv1DParamID> all()
|
||||
{
|
||||
enum { NUM = (int)CONV_LAST };
|
||||
Conv1DParamID v_[NUM]; for (int i = 0; i < NUM; ++i) { v_[i] = Conv1DParamID(i); } // reduce generated code size
|
||||
return ::testing::ValuesIn(v_, v_ + NUM);
|
||||
}
|
||||
};
|
||||
static inline void PrintTo(const Conv1DParamID& v, std::ostream* os)
|
||||
{
|
||||
CV_Assert((int)v >= 0); CV_Assert((int)v < Conv1DParamID::CONV_LAST);
|
||||
const Conv1DParam_t& p = testConvolution1DConfigs[(int)v];
|
||||
|
||||
*os << "GFLOPS=" << cv::format("%.3f", p.declared_flops * 1e-9)
|
||||
<< ", K=[" << p.kernel << "]"
|
||||
<< ", IN={" << p.shapeIn.dims[0] << ", " << p.shapeIn.dims[1] << ", " << p.shapeIn.dims[2] << "}"
|
||||
<< ", OCN=" << p.outCN;
|
||||
if (p.groups > 1)
|
||||
*os << ", G=" << p.groups;
|
||||
if (p.stride != 1)
|
||||
*os << ", S=" << p.stride;
|
||||
if (p.dilation != 1)
|
||||
*os << ", D=" << p.dilation;
|
||||
if (p.pad[0] != 0 && p.pad[1] != 0 )
|
||||
*os << ", P=(" << p.pad[0] << ", " << p.pad[1] << ")";
|
||||
if (!((std::string)p.padMode).empty())
|
||||
*os << ", PM=" << ((std::string)p.padMode);
|
||||
if (p.hasBias)
|
||||
*os << ", BIAS";
|
||||
}
|
||||
|
||||
|
||||
typedef tuple<Conv1DParamID, tuple<Backend, Target> > Conv1DTestParam_t;
|
||||
typedef TestBaseWithParam<Conv1DTestParam_t> Conv1D;
|
||||
|
||||
PERF_TEST_P_(Conv1D, conv1d)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, Conv1DParamID::CONV_LAST);
|
||||
const Conv1DParam_t& params = testConvolution1DConfigs[test_id];
|
||||
double declared_flops = params.declared_flops;
|
||||
|
||||
DictValue kernel = DictValue::arrayInt(¶ms.kernel, 1);
|
||||
DictValue stride = DictValue::arrayInt(¶ms.stride, 1);
|
||||
DictValue pad = DictValue::arrayInt(¶ms.pad[0], 2);
|
||||
DictValue dilation = DictValue::arrayInt(¶ms.dilation, 1);
|
||||
|
||||
MatShape inputShape = MatShape(params.shapeIn.dims, params.shapeIn.dims + 3);
|
||||
int outChannels = params.outCN;
|
||||
int groups = params.groups;
|
||||
std::string padMode(params.padMode);
|
||||
|
||||
bool hasBias = params.hasBias;
|
||||
Backend backendId = get<0>(get<1>(GetParam()));
|
||||
Target targetId = get<1>(get<1>(GetParam()));
|
||||
|
||||
if (targetId != DNN_TARGET_CPU)
|
||||
throw SkipTestException("Only CPU is supported");
|
||||
|
||||
int inChannels = inputShape[1];
|
||||
|
||||
int sz[] = {outChannels, inChannels / groups, params.kernel};
|
||||
Mat weights(3, &sz[0], CV_32F);
|
||||
randu(weights, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.set("kernel_size", kernel);
|
||||
lp.set("pad", pad);
|
||||
if (!padMode.empty())
|
||||
lp.set("pad_mode", padMode);
|
||||
|
||||
lp.set("stride", stride);
|
||||
lp.set("dilation", dilation);
|
||||
lp.set("num_output", outChannels);
|
||||
lp.set("group", groups);
|
||||
lp.set("bias_term", hasBias);
|
||||
lp.type = "Convolution";
|
||||
lp.name = "testLayer";
|
||||
lp.blobs.push_back(weights);
|
||||
|
||||
if (hasBias)
|
||||
{
|
||||
Mat bias(1, outChannels, CV_32F);
|
||||
randu(bias, -1.0f, 1.0f);
|
||||
lp.blobs.push_back(bias);
|
||||
}
|
||||
|
||||
int inpSz[] = {1, inChannels, inputShape[2]};
|
||||
Mat input(3, &inpSz[0], CV_32F);
|
||||
randu(input, -1.0f, 1.0f);
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
|
||||
net.setInput(input);
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
// warmup
|
||||
Mat output = net.forward();
|
||||
|
||||
MatShape netInputShape = shape(input);
|
||||
cv::dnn::MatType netInputType = input.depth();
|
||||
|
||||
bool fp16 = false;
|
||||
#ifdef HAVE_OPENCL
|
||||
fp16 = ocl::Device::getDefault().isExtensionSupported("cl_khr_fp16");
|
||||
#endif
|
||||
if (netInputType == CV_32F && fp16 && targetId == DNN_TARGET_OPENCL_FP16)
|
||||
netInputType = CV_16F;
|
||||
size_t weightsMemory = 0, blobsMemory = 0;
|
||||
net.getMemoryConsumption(netInputShape, netInputType, weightsMemory, blobsMemory);
|
||||
int64 flops = net.getFLOPS(netInputShape, netInputType);
|
||||
CV_Assert(flops > 0);
|
||||
|
||||
std::cout
|
||||
<< "IN=" << divUp(input.total() * input.elemSize(), 1u<<10) << " Kb " << netInputShape
|
||||
<< " OUT=" << divUp(output.total() * output.elemSize(), 1u<<10) << " Kb " << shape(output)
|
||||
<< " Weights(parameters): " << divUp(weightsMemory, 1u<<10) << " Kb"
|
||||
<< " MFLOPS=" << flops * 1e-6 << std::endl;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
EXPECT_NEAR(flops, declared_flops, declared_flops * 1e-6);
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Conv1D, Combine(
|
||||
Conv1DParamID::all(),
|
||||
dnnBackendsAndTargets(/* withInferenceEngine = */false, /* obsolete_withHalide = */false) // defined in ../test/test_common.hpp
|
||||
));
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,190 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct Conv3DParam_t {
|
||||
int kernel[3];
|
||||
struct BlobShape { int dims[5]; } shapeIn;
|
||||
int outCN;
|
||||
int groups;
|
||||
int stride[3];
|
||||
int dilation[3];
|
||||
int pad[6];
|
||||
const char* padMode;
|
||||
bool hasBias;
|
||||
double declared_flops;
|
||||
};
|
||||
// Details: #12142
|
||||
static const Conv3DParam_t testConvolution3DConfigs[] = {
|
||||
{{3, 3, 3}, {{1, 6, 10, 38, 50}}, 6, 1, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "VALID", true, 26956800.},
|
||||
{{3, 3, 3}, {{1, 2, 19, 19, 19}}, 2, 2, {2, 2, 2}, {1, 1, 1}, {1, 1, 1, 1, 1, 1}, "", true, 218000.},
|
||||
{{3, 3, 3}, {{1, 2, 25, 19, 19}}, 2, 2, {1, 2, 2}, {1, 1, 1}, {2, 2, 2, 2, 2, 2}, "SAME", false, 545000.},
|
||||
{{3, 3, 3}, {{1, 11, 9, 150, 200}}, 11, 1, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "VALID", true, 1342562760.},
|
||||
{{3, 3, 3}, {{1, 10, 98, 10, 10}}, 10, 1, {1, 1, 1}, {1, 1, 1}, {1, 0, 1, 1, 0,1}, "SAME", false, 53018000.},
|
||||
{{5, 5, 5}, {{1, 6, 19, 19, 19}}, 6, 2, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "", false, 30395250.},
|
||||
{{5, 5, 5}, {{1, 4, 50, 19, 19}}, 4, 1, {2, 2, 2}, {1, 1, 1}, {1, 1, 1, 1, 1, 1}, "VALID", false, 5893888.},
|
||||
{{5, 5, 5}, {{1, 3, 75, 75, 100}}, 3, 1, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "SAME", true, 1267312500.},
|
||||
{{5, 5, 5}, {{1, 2, 21, 75, 100}}, 2, 1, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "", true, 116103744.},
|
||||
{{5, 5, 5}, {{1, 4, 40, 75, 75}}, 4, 1, {2, 2, 2}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "", false, 93405312.},
|
||||
{{7, 7, 7}, {{1, 6, 15, 19, 19}}, 6, 1, {2, 1, 1}, {1, 1, 1}, {3, 3, 3, 3, 3, 3}, "SAME", true, 71339376.},
|
||||
{{7, 7, 7}, {{1, 2, 38, 38, 38}}, 2, 1, {1, 2, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "", false, 44990464.},
|
||||
{{1, 1, 1}, {{1, 4, 9, 10, 10}}, 4, 1, {1, 1, 2}, {1, 1, 1}, {1, 1, 1, 1, 1, 1}, "VALID", false, 16200.},
|
||||
{{3, 1, 4}, {{1, 14, 5, 10, 10}}, 14, 1, {1, 1, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "SAME", false, 2359000.},
|
||||
{{1, 1, 1}, {{1, 8, 1, 10, 10}}, 8, 8, {1, 1, 1}, {1, 1, 1}, {1, 1, 1, 1, 1, 1}, "", true, 58752.},
|
||||
{{3, 4, 2}, {{1, 4, 8, 10, 10}}, 4, 4, {1, 2, 1}, {1, 1, 1}, {0, 0, 0, 0, 0, 0}, "", true, 166752.}
|
||||
};
|
||||
|
||||
struct Conv3DParamID
|
||||
{
|
||||
enum {
|
||||
CONV_0 = 0,
|
||||
CONV_100 = 16,
|
||||
CONV_LAST = sizeof(testConvolution3DConfigs) / sizeof(testConvolution3DConfigs[0])
|
||||
};
|
||||
int val_;
|
||||
Conv3DParamID(int val = 0) : val_(val) {}
|
||||
operator int() const { return val_; }
|
||||
static ::testing::internal::ParamGenerator<Conv3DParamID> all()
|
||||
{
|
||||
#if 0
|
||||
enum { NUM = (int)CONV_LAST };
|
||||
#else
|
||||
enum { NUM = (int)CONV_100 };
|
||||
#endif
|
||||
Conv3DParamID v_[NUM]; for (int i = 0; i < NUM; ++i) { v_[i] = Conv3DParamID(i); } // reduce generated code size
|
||||
return ::testing::ValuesIn(v_, v_ + NUM);
|
||||
}
|
||||
};
|
||||
static inline void PrintTo(const Conv3DParamID& v, std::ostream* os)
|
||||
{
|
||||
CV_Assert((int)v >= 0); CV_Assert((int)v < Conv3DParamID::CONV_LAST);
|
||||
const Conv3DParam_t& p = testConvolution3DConfigs[(int)v];
|
||||
|
||||
*os << "GFLOPS=" << cv::format("%.3f", p.declared_flops * 1e-9)
|
||||
<< ", K=[" << p.kernel[0] << " x " << p.kernel[1] << " x " << p.kernel[2] << "]"
|
||||
<< ", IN={" << p.shapeIn.dims[0] << ", " << p.shapeIn.dims[1] << ", " << p.shapeIn.dims[2] << ", " << p.shapeIn.dims[3] << ", " << p.shapeIn.dims[4] << "}"
|
||||
<< ", OCN=" << p.outCN;
|
||||
if (p.groups > 1)
|
||||
*os << ", G=" << p.groups;
|
||||
if (p.stride[0] * p.stride[1] * p.stride[2] != 1)
|
||||
*os << ", S=[" << p.stride[0] << " x " << p.stride[1] << " x " << p.stride[2] << "]";
|
||||
if (p.dilation[0] * p.dilation[1] * p.dilation[2] != 1)
|
||||
*os << ", D=[" << p.dilation[0] << " x " << p.dilation[1] << " x " << p.dilation[2] << "]";
|
||||
if (p.pad[0] != 0 && p.pad[1] != 0 && p.pad[2] != 0 &&
|
||||
p.pad[3] != 0 && p.pad[4] != 0 && p.pad[5] != 0)
|
||||
*os << ", P=(" << p.pad[0] << ", " << p.pad[3] << ") x ("
|
||||
<< p.pad[1] << ", " << p.pad[4] << ") x ("
|
||||
<< p.pad[2] << ", " << p.pad[5] << ")";
|
||||
if (!((std::string)p.padMode).empty())
|
||||
*os << ", PM=" << ((std::string)p.padMode);
|
||||
if (p.hasBias)
|
||||
*os << ", BIAS";
|
||||
}
|
||||
|
||||
|
||||
typedef tuple<Conv3DParamID, tuple<Backend, Target> > Conv3DTestParam_t;
|
||||
typedef TestBaseWithParam<Conv3DTestParam_t> Conv3D;
|
||||
|
||||
PERF_TEST_P_(Conv3D, conv3d)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, Conv3DParamID::CONV_LAST);
|
||||
const Conv3DParam_t& params = testConvolution3DConfigs[test_id];
|
||||
double declared_flops = params.declared_flops;
|
||||
|
||||
DictValue kernel = DictValue::arrayInt(¶ms.kernel[0], 3);
|
||||
DictValue stride = DictValue::arrayInt(¶ms.stride[0], 3);
|
||||
DictValue pad = DictValue::arrayInt(¶ms.pad[0], 6);
|
||||
DictValue dilation = DictValue::arrayInt(¶ms.dilation[0], 3);
|
||||
|
||||
MatShape inputShape = MatShape(params.shapeIn.dims, params.shapeIn.dims + 5);
|
||||
int outChannels = params.outCN;
|
||||
int groups = params.groups;
|
||||
std::string padMode(params.padMode);
|
||||
|
||||
bool hasBias = params.hasBias;
|
||||
Backend backendId = get<0>(get<1>(GetParam()));
|
||||
Target targetId = get<1>(get<1>(GetParam()));
|
||||
|
||||
if (targetId != DNN_TARGET_CPU && backendId != DNN_BACKEND_CUDA)
|
||||
throw SkipTestException("Only CPU and CUDA is supported");
|
||||
|
||||
int inChannels = inputShape[1];
|
||||
|
||||
int sz[] = {outChannels, inChannels / groups, params.kernel[0], params.kernel[1], params.kernel[2]};
|
||||
Mat weights(5, &sz[0], CV_32F);
|
||||
randu(weights, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.set("kernel_size", kernel);
|
||||
lp.set("pad", pad);
|
||||
if (!padMode.empty())
|
||||
lp.set("pad_mode", padMode);
|
||||
|
||||
lp.set("stride", stride);
|
||||
lp.set("dilation", dilation);
|
||||
lp.set("num_output", outChannels);
|
||||
lp.set("group", groups);
|
||||
lp.set("bias_term", hasBias);
|
||||
lp.type = "Convolution";
|
||||
lp.name = "testLayer";
|
||||
lp.blobs.push_back(weights);
|
||||
|
||||
if (hasBias)
|
||||
{
|
||||
Mat bias(1, outChannels, CV_32F);
|
||||
randu(bias, -1.0f, 1.0f);
|
||||
lp.blobs.push_back(bias);
|
||||
}
|
||||
int inpSz[] = {1, inChannels, inputShape[2], inputShape[3], inputShape[4]};
|
||||
Mat input(5, &inpSz[0], CV_32F);
|
||||
randu(input, -1.0f, 1.0f);
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
|
||||
net.setInput(input);
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
|
||||
Mat output = net.forward();
|
||||
|
||||
MatShape netInputShape = shape(input);
|
||||
cv::dnn::MatType netInputType = input.depth();
|
||||
|
||||
bool fp16 = false;
|
||||
#ifdef HAVE_OPENCL
|
||||
fp16 = ocl::Device::getDefault().isExtensionSupported("cl_khr_fp16");
|
||||
#endif
|
||||
if (netInputType == CV_32F && fp16 && targetId == DNN_TARGET_OPENCL_FP16)
|
||||
netInputType = CV_16F;
|
||||
size_t weightsMemory = 0, blobsMemory = 0;
|
||||
net.getMemoryConsumption(netInputShape, netInputType, weightsMemory, blobsMemory);
|
||||
int64 flops = net.getFLOPS(netInputShape, netInputType);
|
||||
CV_Assert(flops > 0);
|
||||
|
||||
std::cout
|
||||
<< "IN=" << divUp(input.total() * input.elemSize(), 1u<<10) << " Kb " << netInputShape
|
||||
<< " OUT=" << divUp(output.total() * output.elemSize(), 1u<<10) << " Kb " << shape(output)
|
||||
<< " Weights(parameters): " << divUp(weightsMemory, 1u<<10) << " Kb"
|
||||
<< " MFLOPS=" << flops * 1e-6 << std::endl;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
EXPECT_NEAR(flops, declared_flops, declared_flops * 1e-6);
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Conv3D, Combine(
|
||||
Conv3DParamID::all(),
|
||||
dnnBackendsAndTargets(/* withInferenceEngine = */false, /* obsolete_withHalide = */false) // defined in ../test/test_common.hpp
|
||||
));
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct EinsumParams {
|
||||
int inputSize;
|
||||
int outputSize;
|
||||
std::string equation;
|
||||
std::vector<std::vector<int> > einsumInpShapes;
|
||||
EinsumParams(std::string equation_, std::vector<std::vector<int> > einsumInpShapes_ = std::vector<std::vector<int> >())
|
||||
{
|
||||
inputSize = einsumInpShapes_.size();
|
||||
equation = equation_;
|
||||
einsumInpShapes = einsumInpShapes_;
|
||||
}
|
||||
};
|
||||
|
||||
static inline void PrintTo(const EinsumParams& params, ::std::ostream* os) {
|
||||
(*os) << "Equation=" << params.equation << " ";
|
||||
|
||||
(*os) << "InputShape={";
|
||||
for(int i = 0; i < params.einsumInpShapes.size(); i++)
|
||||
{
|
||||
(*os) << "{";
|
||||
for(int j = 0; j < params.einsumInpShapes[i].size(); j++)
|
||||
{
|
||||
(*os) << params.einsumInpShapes[i][j] << ((j < params.einsumInpShapes[i].size() - 1) ? ", " : "");
|
||||
}
|
||||
(*os) << ((i < params.einsumInpShapes.size() - 1) ? "}, " : "}");
|
||||
}
|
||||
(*os) << "}";
|
||||
}
|
||||
|
||||
// test cases
|
||||
static const EinsumParams testEinsumConfigs[] = {
|
||||
// TODO: Add tests with one input after ellips merge
|
||||
{"ij, jk -> ik", {{2, 3}, {3, 2}}},
|
||||
{"ij, jk -> ik", {{20, 30}, {30, 20}}},
|
||||
{"ij, jk -> ik", {{113, 127}, {127, 113}}},
|
||||
|
||||
{"imkj, injs -> imnks", {{1, 4, 7, 9}, {1, 5, 9, 8}}},
|
||||
{"imkj, injs -> imnks", {{1, 4, 70, 90}, {1, 5, 90, 80}}},
|
||||
{"imkj, injs -> imnks", {{1, 4, 73, 91}, {1, 5, 91, 57}}},
|
||||
|
||||
{"ij -> i", {{30, 40}}},
|
||||
{"ij -> i", {{113, 374}}},
|
||||
|
||||
{"...ij -> ...i", {{30, 40}}},
|
||||
{"...ij -> ...i", {{113, 374}}},
|
||||
|
||||
{"...ij, ...jk -> ...ik", {{40, 50}, {50, 80}}},
|
||||
{"...ij, ...jk -> ...ik", {{47, 51}, {51, 83}}},
|
||||
};
|
||||
|
||||
class Layer_Einsum: public TestBaseWithParam<EinsumParams> {};
|
||||
|
||||
PERF_TEST_P_(Layer_Einsum, einsum) {
|
||||
const EinsumParams& params = GetParam();
|
||||
LayerParams lp;
|
||||
lp.type = "Einsum";
|
||||
lp.name = "testEinsum";
|
||||
lp.set("equation", params.equation);
|
||||
lp.set("inputSize", params.inputSize);
|
||||
lp.set("outputSize", 1);
|
||||
|
||||
CV_CheckFalse(params.einsumInpShapes.empty(), "ERROR no inputs shapes provided");
|
||||
|
||||
for (int i = 0; i < params.einsumInpShapes.size(); i++) {
|
||||
lp.set("inputShapes" + cv::format("%d", i), DictValue::arrayInt(params.einsumInpShapes[i].begin(), params.einsumInpShapes[i].size()));
|
||||
}
|
||||
|
||||
Net net;
|
||||
std::vector<Mat> inputs;
|
||||
std::vector<std::string> input_names;
|
||||
int id = net.addLayer(lp.name, lp.type, lp);
|
||||
|
||||
for (int i = 0; i < params.inputSize; ++i) {
|
||||
// create inputs
|
||||
inputs.emplace_back(Mat(params.einsumInpShapes[i], CV_32FC1));
|
||||
|
||||
// connect each input to the layer
|
||||
net.connect(0, i, id, i);
|
||||
|
||||
// create input names dynamically, assuming input naming follows a consistent pattern
|
||||
input_names.emplace_back("input" + std::to_string(i + 1));
|
||||
}
|
||||
|
||||
//warm up
|
||||
std::vector<Mat> outputs;
|
||||
net.setInputsNames(input_names);
|
||||
for (int i = 0; i < input_names.size(); i++){
|
||||
net.setInput(inputs[i], input_names[i]);
|
||||
}
|
||||
net.forward(outputs, "testEinsum");
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
net.forward(outputs, "testEinsum");
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Layer_Einsum, testing::ValuesIn(testEinsumConfigs));
|
||||
|
||||
}; //namespace
|
||||
@@ -0,0 +1,415 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct GemmParam_t {
|
||||
std::vector<int> a_shape;
|
||||
std::vector<int> b_shape;
|
||||
std::vector<int> c_shape;
|
||||
bool trans_a;
|
||||
bool trans_b;
|
||||
|
||||
GemmParam_t(std::vector<int> a_shape_, std::vector<int> b_shape_, std::vector<int> c_shape_ = {}, bool trans_a_ = false, bool trans_b_ = false)
|
||||
: a_shape(a_shape_), b_shape(b_shape_), c_shape(c_shape_), trans_a(trans_a_), trans_b(trans_b_) {}
|
||||
};
|
||||
|
||||
// TODO: Dsiable most of the test cases except vision transformers to save time
|
||||
static const GemmParam_t test_gemm_configs[] = {
|
||||
// vision transformers cases
|
||||
{ { 768, 768 }, { 768, 768 }, { 768 } },
|
||||
{ { 1024, 1024 }, { 1024, 1024 }, { 1024 } },
|
||||
{ { 50, 768 }, { 768, 2304 } },
|
||||
{ { 197, 768 }, { 768, 2304 } },
|
||||
{ { 50, 1024 }, { 1024, 3072 } },
|
||||
{ { 197, 1024 }, { 1024, 3072 } },
|
||||
|
||||
// these cases are commented to save testing time
|
||||
/*
|
||||
// square mat
|
||||
{ { 64, 64 }, { 64, 64 } },
|
||||
{ { 128, 128 }, { 128, 128 } },
|
||||
{ { 256, 256 }, { 256, 256 } },
|
||||
{ { 512, 512 }, { 512, 512 } },
|
||||
{ { 1024, 1024 }, { 1024, 1024 } },
|
||||
{ { 4096, 4096 }, { 4096, 4096 } },
|
||||
|
||||
// retangular mat
|
||||
{ { 256, 256 }, { 256, 1024 } },
|
||||
{ { 256, 1024 }, { 1024, 256 } },
|
||||
{ { 256, 1024 }, { 1024, 1024 } },
|
||||
{ { 1024, 1024 }, { 1024, 256 } },
|
||||
{ { 1024, 256 }, { 256, 1024 } },
|
||||
{ { 1024, 256 }, { 256, 256 } },
|
||||
|
||||
// with C
|
||||
{ { 256, 256 }, { 256, 256 }, { 256 } },
|
||||
{ { 256, 256 }, { 256, 1024 }, { 1024 } },
|
||||
{ { 256, 1024 }, { 1024, 256 }, { 256 } },
|
||||
{ { 256, 1024 }, { 1024, 1024 }, { 1024 } },
|
||||
{ { 1024, 1024 }, { 1024, 256 }, { 256 } },
|
||||
{ { 1024, 256 }, { 256, 1024 }, { 1024 } },
|
||||
{ { 1024, 256 }, { 256, 256 }, { 256 } },
|
||||
|
||||
// with C and trans_b
|
||||
{ { 256, 256 }, { 256, 256 }, { 256 } , false, true},
|
||||
{ { 256, 1024 }, { 256, 1024 }, { 256 } , false, true},
|
||||
{ { 256, 1024 }, { 1024, 1024 }, { 1024 } , false, true},
|
||||
{ { 1024, 1024 }, { 1024, 1024 }, { 1024 } , false, true},
|
||||
{ { 1024, 256 }, { 1024, 256 }, { 1024 } , false, true},
|
||||
{ { 1024, 256 }, { 256, 256 }, { 256 } , false, true},
|
||||
|
||||
// with C and trans_b and trans_a
|
||||
{ { 256, 256 }, { 256, 256 }, { 256 } , true, true},
|
||||
{ { 1024, 256 }, { 256, 1024 }, { 256 } , true, true},
|
||||
{ { 256, 1024 }, { 1024, 256 }, { 1024 } , true, true},
|
||||
{ { 1024, 1024 }, { 1024, 1024 }, { 1024 } , true, true},
|
||||
*/
|
||||
};
|
||||
|
||||
static const GemmParam_t test_matmul_configs[] = {
|
||||
// vision transformer cases
|
||||
{ {12, 197, 197}, {12, 197, 64} },
|
||||
{ {12, 197, 64 }, {12, 64, 197} },
|
||||
{ {12, 50, 64}, {12, 64, 50} },
|
||||
{ {12, 50, 50}, {12, 50, 64} },
|
||||
{ {16, 197, 197}, {16, 197, 64} },
|
||||
{ {16, 197, 64 }, {16, 64, 197} },
|
||||
{ {16, 50, 64}, {16, 64, 50} },
|
||||
{ {16, 50, 50}, {16, 50, 64} },
|
||||
};
|
||||
|
||||
struct GemmParamId
|
||||
{
|
||||
enum {
|
||||
GEMM_0 = 0,
|
||||
GEMM_LAST = sizeof(test_gemm_configs) / sizeof(test_gemm_configs[0])
|
||||
};
|
||||
int val_;
|
||||
GemmParamId(int val = 0) : val_(val) {}
|
||||
operator int() const { return val_; }
|
||||
static ::testing::internal::ParamGenerator<GemmParamId> all()
|
||||
{
|
||||
enum { NUM = (int)GEMM_LAST };
|
||||
GemmParamId v_[NUM]; for (int i = 0; i < NUM; ++i) { v_[i] = GemmParamId(i); } // reduce generated code size
|
||||
return ::testing::ValuesIn(v_, v_ + NUM);
|
||||
}
|
||||
};
|
||||
|
||||
struct MatMulParamId {
|
||||
enum {
|
||||
MATMUL_0 = 0,
|
||||
MATMUL_LAST = sizeof(test_matmul_configs) / sizeof(test_matmul_configs[0])
|
||||
};
|
||||
int val_;
|
||||
MatMulParamId(int val = 0) : val_(val) {}
|
||||
operator int() const { return val_; }
|
||||
static ::testing::internal::ParamGenerator<MatMulParamId> all() {
|
||||
enum { NUM = (int)MATMUL_LAST };
|
||||
MatMulParamId v_[NUM]; for (int i = 0; i < NUM; i++) { v_[i] = MatMulParamId(i); }
|
||||
return ::testing::ValuesIn(v_, v_ + NUM);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void PrintTo(const GemmParamId& v, std::ostream* os)
|
||||
{
|
||||
CV_Assert((int)v >= 0); CV_Assert((int)v < GemmParamId::GEMM_LAST);
|
||||
const GemmParam_t& p = test_gemm_configs[(int)v];
|
||||
|
||||
auto print_shape = [os](const std::vector<int>& shape, const std::string tag) {
|
||||
if (shape.empty()) {
|
||||
return ;
|
||||
}
|
||||
|
||||
*os << tag << "=[";
|
||||
for (size_t i = 0; i < shape.size(); ++i) {
|
||||
if (i == shape.size() - 1) {
|
||||
*os << shape[i] << "]";
|
||||
break;
|
||||
}
|
||||
*os << shape[i] << ", ";
|
||||
}
|
||||
};
|
||||
|
||||
print_shape(p.a_shape, "A");
|
||||
print_shape(p.b_shape, ", B");
|
||||
print_shape(p.c_shape, ", C");
|
||||
*os << ", trans_a=" << p.trans_a << ", trans_b=" << p.trans_b;
|
||||
}
|
||||
|
||||
typedef tuple<GemmParamId, tuple<Backend, Target> > GemmTestParam_t;
|
||||
typedef TestBaseWithParam<GemmTestParam_t> Gemm;
|
||||
|
||||
PERF_TEST_P_(Gemm, gemm)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, GemmParamId::GEMM_LAST);
|
||||
const GemmParam_t& params = test_gemm_configs[test_id];
|
||||
auto a_shape = params.a_shape;
|
||||
auto b_shape = params.b_shape;
|
||||
auto c_shape = params.c_shape;
|
||||
auto trans_a = params.trans_a;
|
||||
auto trans_b = params.trans_b;
|
||||
float alpha = 1.f;
|
||||
float beta = 1.f;
|
||||
|
||||
Backend backend_id = get<0>(get<1>(GetParam()));
|
||||
Target target_id = get<1>(get<1>(GetParam()));
|
||||
|
||||
bool have_bias = c_shape.empty() ? false : true;
|
||||
|
||||
Mat A(static_cast<int>(a_shape.size()), a_shape.data(), CV_32F);
|
||||
randu(A, -1.0f, 1.0f);
|
||||
Mat B(static_cast<int>(b_shape.size()), b_shape.data(), CV_32F);
|
||||
randu(B, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.type = "Gemm";
|
||||
lp.name = "testLayer";
|
||||
lp.set("transA", trans_a);
|
||||
lp.set("transB", trans_b);
|
||||
lp.set("alpha", alpha);
|
||||
lp.set("beta", beta);
|
||||
lp.set("real_ndims_C", static_cast<int>(c_shape.size()));
|
||||
|
||||
lp.set("constB", true);
|
||||
lp.blobs.push_back(B);
|
||||
if (have_bias) {
|
||||
Mat C(static_cast<int>(c_shape.size()), c_shape.data(), CV_32F);
|
||||
randu(C, -1.0f, 1.0f);
|
||||
lp.set("have_bias", true);
|
||||
lp.set("constC", true);
|
||||
lp.blobs.push_back(C);
|
||||
}
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
|
||||
// warmup
|
||||
{
|
||||
net.setInput(A);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Gemm, innerproduct)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, GemmParamId::GEMM_LAST);
|
||||
const GemmParam_t& params = test_gemm_configs[test_id];
|
||||
auto a_shape = params.a_shape;
|
||||
auto b_shape = params.b_shape;
|
||||
auto c_shape = params.c_shape;
|
||||
auto trans_a = params.trans_a;
|
||||
auto trans_b = params.trans_b;
|
||||
|
||||
Backend backend_id = get<0>(get<1>(GetParam()));
|
||||
Target target_id = get<1>(get<1>(GetParam()));
|
||||
|
||||
bool have_bias = c_shape.empty() ? false : true;
|
||||
|
||||
Mat A(static_cast<int>(a_shape.size()), a_shape.data(), CV_32F);
|
||||
randu(A, -1.0f, 1.0f);
|
||||
Mat B(static_cast<int>(b_shape.size()), b_shape.data(), CV_32F);
|
||||
randu(B, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.type = "InnerProduct";
|
||||
lp.name = "testLayer";
|
||||
if (trans_a) {
|
||||
cv::transpose(A, A);
|
||||
}
|
||||
if (!trans_b) {
|
||||
cv::transpose(B, B);
|
||||
}
|
||||
lp.blobs.push_back(B);
|
||||
lp.set("num_output", B.size[0]);
|
||||
if (have_bias) {
|
||||
Mat C(static_cast<int>(c_shape.size()), c_shape.data(), CV_32F);
|
||||
randu(C, -1.0f, 1.0f);
|
||||
lp.blobs.push_back(C);
|
||||
lp.set("bias_term", true);
|
||||
} else {
|
||||
lp.set("bias_term", false);
|
||||
}
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
|
||||
// warmup
|
||||
{
|
||||
std::vector<std::string> input_names(1);
|
||||
input_names[0] = "A";
|
||||
net.setInputsNames(input_names);
|
||||
net.setInput(A, input_names[0]);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
static inline void PrintTo(const MatMulParamId& v, std::ostream* os)
|
||||
{
|
||||
CV_Assert((int)v >= 0); CV_Assert((int)v < MatMulParamId::MATMUL_LAST);
|
||||
const GemmParam_t& p = test_matmul_configs[(int)v];
|
||||
|
||||
auto print_shape = [os](const std::vector<int>& shape, const std::string tag) {
|
||||
if (shape.empty()) {
|
||||
return ;
|
||||
}
|
||||
|
||||
*os << tag << "=[";
|
||||
for (size_t i = 0; i < shape.size(); ++i) {
|
||||
if (i == shape.size() - 1) {
|
||||
*os << shape[i] << "]";
|
||||
break;
|
||||
}
|
||||
*os << shape[i] << ", ";
|
||||
}
|
||||
};
|
||||
|
||||
print_shape(p.a_shape, "A");
|
||||
print_shape(p.b_shape, ", B");
|
||||
print_shape(p.c_shape, ", C");
|
||||
*os << ", trans_a=" << p.trans_a << ", trans_b=" << p.trans_b;
|
||||
}
|
||||
|
||||
using MatMulTestParam_t = tuple<MatMulParamId, tuple<Backend, Target>>;
|
||||
using MatMul = TestBaseWithParam<MatMulTestParam_t>;
|
||||
|
||||
PERF_TEST_P_(MatMul, matmul)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, MatMulParamId::MATMUL_LAST);
|
||||
const GemmParam_t& params = test_matmul_configs[test_id];
|
||||
auto a_shape = params.a_shape;
|
||||
auto b_shape = params.b_shape;
|
||||
auto trans_a = params.trans_a;
|
||||
auto trans_b = params.trans_b;
|
||||
float alpha = 1.f;
|
||||
float beta = 1.f;
|
||||
|
||||
Backend backend_id = get<0>(get<1>(GetParam()));
|
||||
Target target_id = get<1>(get<1>(GetParam()));
|
||||
|
||||
Mat A(a_shape, CV_32F);
|
||||
randu(A, -1.0f, 1.0f);
|
||||
Mat B(b_shape, CV_32F);
|
||||
randu(B, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.type = "MatMul";
|
||||
lp.name = "testLayer";
|
||||
lp.set("transA", trans_a);
|
||||
lp.set("transB", trans_b);
|
||||
lp.set("alpha", alpha);
|
||||
lp.set("beta", beta);
|
||||
lp.blobs.push_back(B);
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
|
||||
// warmup
|
||||
{
|
||||
std::vector<std::string> input_names{"A"};
|
||||
net.setInputsNames(input_names);
|
||||
net.setInput(A, input_names[0]);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(MatMul, innerproduct)
|
||||
{
|
||||
int test_id = (int)get<0>(GetParam());
|
||||
ASSERT_GE(test_id, 0); ASSERT_LT(test_id, MatMulParamId::MATMUL_LAST);
|
||||
const GemmParam_t& params = test_matmul_configs[test_id];
|
||||
auto a_shape = params.a_shape;
|
||||
auto b_shape = params.b_shape;
|
||||
|
||||
Backend backend_id = get<0>(get<1>(GetParam()));
|
||||
Target target_id = get<1>(get<1>(GetParam()));
|
||||
|
||||
Mat A(a_shape, CV_32F);
|
||||
randu(A, -1.0f, 1.0f);
|
||||
Mat B(b_shape, CV_32F);
|
||||
randu(B, -1.0f, 1.0f);
|
||||
|
||||
LayerParams lp;
|
||||
lp.type = "InnerProduct";
|
||||
lp.name = "testLayer";
|
||||
lp.set("axis", (int)(a_shape.size() - 1));
|
||||
lp.set("bias_term", false);
|
||||
|
||||
// pre-transpose
|
||||
std::vector<int> order(b_shape.size());
|
||||
std::iota(order.begin(), order.end(), 0);
|
||||
std::swap(order.back(), order[b_shape.size() - 2]);
|
||||
Mat B_transposed;
|
||||
transposeND(B, order, B_transposed);
|
||||
lp.blobs.push_back(B_transposed);
|
||||
lp.set("num_output", int(B_transposed.total(0, b_shape.size() - 1)));
|
||||
lp.set("is_matmul", true);
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.setPreferableBackend(backend_id);
|
||||
net.setPreferableTarget(target_id);
|
||||
|
||||
// warmup
|
||||
{
|
||||
std::vector<std::string> input_names{"A"};
|
||||
net.setInputsNames(input_names);
|
||||
net.setInput(A, input_names[0]);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Gemm, Combine(
|
||||
GemmParamId::all(),
|
||||
dnnBackendsAndTargets(false, false) // defined in ../test/test_common.hpp
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, MatMul, Combine(
|
||||
MatMulParamId::all(),
|
||||
dnnBackendsAndTargets(false, false) // defined in ../test/test_common.hpp
|
||||
));
|
||||
|
||||
} // namespace
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
CV_PERF_TEST_MAIN(dnn, cvtest::addDataSearchEnv("OPENCV_DNN_TEST_DATA_PATH"))
|
||||
@@ -0,0 +1,770 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
|
||||
#include "opencv2/dnn/shape_utils.hpp"
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
|
||||
#include "../test/test_common.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
class DNNTestNetwork : public ::perf::TestBaseWithParam< tuple<Backend, Target> >
|
||||
{
|
||||
public:
|
||||
dnn::Backend backend;
|
||||
dnn::Target target;
|
||||
|
||||
dnn::Net net;
|
||||
|
||||
DNNTestNetwork()
|
||||
{
|
||||
backend = (dnn::Backend)(int)get<0>(GetParam());
|
||||
target = (dnn::Target)(int)get<1>(GetParam());
|
||||
}
|
||||
|
||||
void processNet(std::string weights, std::string proto,
|
||||
const std::vector<std::tuple<Mat, std::string>>& inputs, const std::string& outputLayer = ""){
|
||||
weights = findDataFile(weights, false);
|
||||
if (!proto.empty())
|
||||
proto = findDataFile(proto);
|
||||
net = readNet(weights, proto);
|
||||
// Set multiple inputs
|
||||
for(auto &inp: inputs){
|
||||
net.setInput(std::get<0>(inp), std::get<1>(inp));
|
||||
}
|
||||
|
||||
net.setPreferableBackend(backend);
|
||||
net.setPreferableTarget(target);
|
||||
|
||||
// Calculate multiple inputs memory consumption
|
||||
std::vector<MatShape> netMatShapes;
|
||||
for(auto &inp: inputs){
|
||||
netMatShapes.push_back(shape(std::get<0>(inp)));
|
||||
}
|
||||
|
||||
bool fp16 = false;
|
||||
#ifdef HAVE_OPENCL
|
||||
fp16 = ocl::Device::getDefault().isExtensionSupported("cl_khr_fp16");
|
||||
#endif
|
||||
std::vector<cv::dnn::MatType> netMatTypes;
|
||||
for (auto& inp : inputs) {
|
||||
cv::dnn::MatType t = std::get<0>(inp).depth();
|
||||
if (t == CV_32F && fp16 && target == DNN_TARGET_OPENCL_FP16)
|
||||
t = CV_16F;
|
||||
netMatTypes.push_back(t);
|
||||
}
|
||||
|
||||
net.forward(outputLayer); // warmup
|
||||
|
||||
size_t weightsMemory = 0, blobsMemory = 0;
|
||||
net.getMemoryConsumption(netMatShapes, netMatTypes, weightsMemory, blobsMemory);
|
||||
int64 flops = net.getFLOPS(netMatShapes, netMatTypes);
|
||||
CV_Assert(flops > 0);
|
||||
std::cout << "Memory consumption:" << std::endl;
|
||||
std::cout << " Weights(parameters): " << divUp(weightsMemory, 1u<<20) << " Mb" << std::endl;
|
||||
std::cout << " Blobs: " << divUp(blobsMemory, 1u<<20) << " Mb" << std::endl;
|
||||
std::cout << "Calculation complexity: " << flops * 1e-9 << " GFlops" << std::endl;
|
||||
|
||||
PERF_SAMPLE_BEGIN()
|
||||
net.forward();
|
||||
PERF_SAMPLE_END()
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
void processNet(std::string weights, std::string proto,
|
||||
Mat &input, const std::string& outputLayer = "")
|
||||
{
|
||||
processNet(weights, proto, {std::make_tuple(input, "")}, outputLayer);
|
||||
}
|
||||
|
||||
void processNet(std::string weights, std::string proto,
|
||||
Size inpSize, const std::string& outputLayer = "")
|
||||
{
|
||||
Mat input_data(inpSize, CV_32FC3);
|
||||
randu(input_data, 0.0f, 1.0f);
|
||||
Mat input = blobFromImage(input_data, 1.0, Size(), Scalar(), false);
|
||||
processNet(weights, proto, input, outputLayer);
|
||||
}
|
||||
};
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, AlexNet)
|
||||
{
|
||||
processNet("dnn/onnx/models/alexnet.onnx", "", cv::Size(227, 227));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, GoogLeNet)
|
||||
{
|
||||
processNet("dnn/onnx/models/googlenet.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet_50)
|
||||
{
|
||||
processNet("dnn/onnx/models/resnet50v1.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet_18_v1_ONNX)
|
||||
{
|
||||
processNet("dnn/onnx/models/resnet18v1.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet_50_v1_ONNX)
|
||||
{
|
||||
processNet("dnn/onnx/models/resnet50v1.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNetv2_ONNX)
|
||||
{
|
||||
processNet("dnn/onnx/models/mobilenetv2.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, ResNet50_QDQ_ONNX)
|
||||
{
|
||||
processNet("dnn/onnx/models/resnet50-v1-12-qdq.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, SqueezeNet_v1_1)
|
||||
{
|
||||
processNet("dnn/onnx/models/squeezenet.onnx", "", cv::Size(227, 227));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, Inception_5h)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) throw SkipTestException("");
|
||||
processNet("dnn/tensorflow_inception_graph.pb", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, SSD)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
// SSD_VGG16's specialized preprocessing is handled by the new engine importer only.
|
||||
auto engine_forced = static_cast<dnn::EngineType>(
|
||||
utils::getConfigurationParameterSizeT("OPENCV_FORCE_DNN_ENGINE", dnn::ENGINE_AUTO));
|
||||
if (engine_forced == dnn::ENGINE_CLASSIC)
|
||||
throw SkipTestException("SSD_VGG16 is supported on the new DNN engine only");
|
||||
|
||||
processNet("dnn/onnx/models/ssd_vgg16.onnx", "", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v1_ONNX)
|
||||
{
|
||||
// Dynamic-shape preprocessing in this model needs the new engine; OpenVINO uses the classic one.
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
// This model expects a uint8 NHWC image as input.
|
||||
Mat image(cv::Size(300, 300), CV_8UC3);
|
||||
randu(image, 0, 255);
|
||||
int imsize[] = {1, image.rows, image.cols, 3};
|
||||
Mat input(4, imsize, CV_8U, image.data);
|
||||
processNet("dnn/onnx/models/ssd_mobilenet_v1_12.onnx", "", input);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow)
|
||||
{
|
||||
processNet("dnn/ssd_mobilenet_v1_coco_2017_11_17.pb", "ssd_mobilenet_v1_coco_2017_11_17.pbtxt", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_v2_TensorFlow)
|
||||
{
|
||||
processNet("dnn/ssd_mobilenet_v2_coco_2018_03_29.pb", "ssd_mobilenet_v2_coco_2018_03_29.pbtxt", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
|
||||
{
|
||||
processNet("dnn/onnx/models/densenet121.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_HDDL))
|
||||
throw SkipTestException("");
|
||||
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
|
||||
processNet("dnn/onnx/models/openpose_pose_mpi.onnx", "", cv::Size(368, 368));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "ssd_inception_v2_coco_2017_11_17.pbtxt", cv::Size(300, 300));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOv3)
|
||||
{
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020040000) // nGraph compilation failure
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2020.4");
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2020.4");
|
||||
#endif
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2021010000) // nGraph compilation failure
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
throw SkipTestException("");
|
||||
#endif
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
cv::resize(sample, sample, Size(640, 640));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(), Scalar(), true);
|
||||
processNet("dnn/yolov3.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOv4)
|
||||
{
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_MEMORY_2GB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
if (target == DNN_TARGET_MYRIAD) // not enough resources
|
||||
throw SkipTestException("");
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020040000) // nGraph compilation failure
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2020.4");
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2020.4");
|
||||
#endif
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
cv::resize(sample, sample, Size(608, 608));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(), Scalar(), true);
|
||||
processNet("dnn/yolov4.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOv4_tiny)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2021010000) // nGraph compilation failure
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
throw SkipTestException("");
|
||||
#endif
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(), Scalar(), true);
|
||||
processNet("dnn/yolov4-tiny.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOv5) {
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/yolov5n.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOv8)
|
||||
{
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_MEMORY_512MB,
|
||||
CV_TEST_TAG_DEBUG_LONG
|
||||
);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/yolov8n.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLOX) {
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_MEMORY_512MB,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG
|
||||
);
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/yolox_s.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, EAST_text_detection)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
processNet("dnn/frozen_east_text_detection.pb", "", cv::Size(320, 320));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, FastNeuralStyle_eccv16)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
processNet("dnn/mosaic-9.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, Inception_v2_Faster_RCNN)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019010000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2019R1");
|
||||
#endif
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2019R2");
|
||||
#endif
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2021010000)
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
throw SkipTestException("Test is disabled in OpenVINO 2021.1+ / MYRIAD");
|
||||
#endif
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) ||
|
||||
(backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16))
|
||||
throw SkipTestException("");
|
||||
processNet("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pb",
|
||||
"dnn/faster_rcnn_inception_v2_coco_2018_01_28.pbtxt",
|
||||
cv::Size(800, 600));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, EfficientDet)
|
||||
{
|
||||
if (target != DNN_TARGET_CPU)
|
||||
throw SkipTestException("");
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(512, 512), Scalar(), true);
|
||||
processNet("dnn/efficientdet-d0.pb", "dnn/efficientdet-d0.pbtxt", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, EfficientNet)
|
||||
{
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(224, 224), Scalar(), true);
|
||||
transposeND(inp, {0, 2, 3, 1}, inp);
|
||||
processNet("dnn/efficientnet-lite4.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YuNet_320) {
|
||||
processNet("dnn/onnx/models/yunet-202605.onnx", "", cv::Size(320, 320));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YuNet_640) {
|
||||
processNet("dnn/onnx/models/yunet-202605.onnx", "", cv::Size(640, 640));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, YuNet_1280) {
|
||||
processNet("dnn/onnx/models/yunet-202605.onnx", "", cv::Size(1280, 736));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, SFace) {
|
||||
processNet("dnn/face_recognition_sface_2021dec.onnx", "", cv::Size(112, 112));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MPPalm) {
|
||||
Mat inp(cv::Size(192, 192), CV_32FC3);
|
||||
randu(inp, 0.0f, 1.0f);
|
||||
inp = blobFromImage(inp, 1.0, Size(), Scalar(), false);
|
||||
transposeND(inp, {0, 2, 3, 1}, inp);
|
||||
processNet("dnn/palm_detection_mediapipe_2023feb.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MPHand) {
|
||||
Mat inp(cv::Size(224, 224), CV_32FC3);
|
||||
randu(inp, 0.0f, 1.0f);
|
||||
inp = blobFromImage(inp, 1.0, Size(), Scalar(), false);
|
||||
transposeND(inp, {0, 2, 3, 1}, inp);
|
||||
processNet("dnn/handpose_estimation_mediapipe_2023feb.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MPPose) {
|
||||
Mat inp(cv::Size(256, 256), CV_32FC3);
|
||||
randu(inp, 0.0f, 1.0f);
|
||||
inp = blobFromImage(inp, 1.0, Size(), Scalar(), false);
|
||||
transposeND(inp, {0, 2, 3, 1}, inp);
|
||||
processNet("dnn/pose_estimation_mediapipe_2023mar.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, PPOCRv3) {
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
processNet("dnn/onnx/models/PP_OCRv3_DB_text_det.onnx", "", cv::Size(736, 736));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, PPHumanSeg) {
|
||||
processNet("dnn/human_segmentation_pphumanseg_2023mar.onnx", "", cv::Size(192, 192));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, CRNN) {
|
||||
Mat inp(cv::Size(100, 32), CV_32FC1);
|
||||
randu(inp, 0.0f, 1.0f);
|
||||
inp = blobFromImage(inp, 1.0, Size(), Scalar(), false);
|
||||
processNet("dnn/text_recognition_CRNN_EN_2021sep.onnx", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, VitTrack) {
|
||||
Mat inp1(cv::Size(128, 128), CV_32FC3);
|
||||
Mat inp2(cv::Size(256, 256), CV_32FC3);
|
||||
randu(inp1, 0.0f, 1.0f);
|
||||
randu(inp2, 0.0f, 1.0f);
|
||||
inp1 = blobFromImage(inp1, 1.0, Size(), Scalar(), false);
|
||||
inp2 = blobFromImage(inp2, 1.0, Size(), Scalar(), false);
|
||||
processNet("dnn/onnx/models/object_tracking_vittrack_2023sep.onnx", "", {std::make_tuple(inp1, "template"), std::make_tuple(inp2, "search")});
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, EfficientDet_int8)
|
||||
{
|
||||
if (target != DNN_TARGET_CPU || (backend != DNN_BACKEND_OPENCV &&
|
||||
backend != DNN_BACKEND_TIMVX && backend != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) {
|
||||
throw SkipTestException("");
|
||||
}
|
||||
Mat inp = imread(findDataFile("dnn/dog416.png"));
|
||||
inp = blobFromImage(inp, 1.0 / 255.0, Size(320, 320), Scalar(), true);
|
||||
processNet("dnn/tflite/coco_efficientdet_lite0_v1_1.0_quant_2021_09_06.tflite", "", inp);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, VIT_B_32)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_DEBUG_VERYLONG);
|
||||
|
||||
processNet("dnn/onnx/models/vit_b_32.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, BERT)
|
||||
{
|
||||
const int seq_len = 9;
|
||||
int64_t input_ids_data[seq_len] = {101, 1996, 103, 2938, 2006, 1996, 13523, 1012, 102};
|
||||
int64_t attention_mask_data[seq_len] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
int64_t token_type_ids_data[seq_len] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int shp[2] = {1, seq_len};
|
||||
Mat input_ids(2, shp, CV_64S, input_ids_data);
|
||||
Mat attention_mask(2, shp, CV_64S, attention_mask_data);
|
||||
Mat token_type_ids(2, shp, CV_64S, token_type_ids_data);
|
||||
processNet("dnn/onnx/models/bert.onnx", "",
|
||||
{std::make_tuple(input_ids, "input_ids"),
|
||||
std::make_tuple(attention_mask, "attention_mask"),
|
||||
std::make_tuple(token_type_ids, "token_type_ids")});
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, VIT_Base_Patch16_224)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
processNet("dnn/vit_base_patch16_224_Opset16.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, DeiT_Tiny_Patch16_224)
|
||||
{
|
||||
processNet("dnn/deit_tiny_patch16_224_Opset16.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileViT_XS)
|
||||
{
|
||||
processNet("dnn/mobilevit_xs_Opset16.onnx", "", cv::Size(256, 256));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, MobileViTv2_100_ONNX)
|
||||
{
|
||||
processNet("dnn/mobilevitv2_100_Opset16.onnx", "", cv::Size(256, 256));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, BEiT_Base_Patch16_224)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
processNet("dnn/beit_base_patch16_224_Opset16.onnx", "", cv::Size(224, 224));
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, BlazeFace)
|
||||
{
|
||||
Mat input(cv::Size(128, 128), CV_32FC3);
|
||||
randu(input, 0.0f, 1.0f);
|
||||
input = blobFromImage(input, 1.0 / 255.0, Size(128, 128));
|
||||
|
||||
const int oneDim[] = {1};
|
||||
Mat conf(1, oneDim, CV_32F); conf.ptr<float>()[0] = 0.20f;
|
||||
Mat iou(1, oneDim, CV_32F); iou.ptr<float>()[0] = 0.30f;
|
||||
Mat maxDet(1, oneDim, CV_64S); maxDet.ptr<int64_t>()[0] = 25;
|
||||
|
||||
processNet("dnn/onnx/models/blazeface.onnx", "",
|
||||
{std::make_tuple(input, "image"),
|
||||
std::make_tuple(conf, "conf_threshold"),
|
||||
std::make_tuple(iou, "iou_threshold"),
|
||||
std::make_tuple(maxDet, "max_detections")});
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DNNTestNetwork, FacePaint)
|
||||
{
|
||||
processNet("dnn/onnx/models/face_paint_512_v2_0.onnx", "", cv::Size(512, 512));
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/vietanhdev/segment-anything-2-onnx-models/blob/main/sam2_hiera_large.encoder.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, SAM2_Encoder)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(1024, 1024), Scalar(), true);
|
||||
processNet("dnn/onnx/models/sam2_hiera_large.encoder.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/vietanhdev/segment-anything-2-onnx-models/blob/main/sam2_hiera_large.decoder.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, SAM2_Decoder)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_1GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
// Synthetic encoder outputs used as decoder inputs
|
||||
int shp_embed[4] = {1, 256, 64, 64};
|
||||
int shp_feat0[4] = {1, 32, 256, 256};
|
||||
int shp_feat1[4] = {1, 64, 128, 128};
|
||||
|
||||
Mat image_embed(4, shp_embed, CV_32F);
|
||||
Mat high_res_feats_0(4, shp_feat0, CV_32F);
|
||||
Mat high_res_feats_1(4, shp_feat1, CV_32F);
|
||||
randu(image_embed, 0.0f, 1.0f);
|
||||
randu(high_res_feats_0, 0.0f, 1.0f);
|
||||
randu(high_res_feats_1, 0.0f, 1.0f);
|
||||
|
||||
// Single point prompt at center of image, label=1 (foreground)
|
||||
int shp_pts[3] = {1, 1, 2};
|
||||
int shp_lbl[2] = {1, 1};
|
||||
int shp_mask[4] = {1, 1, 256, 256};
|
||||
int shp_hasmask[1] = {1};
|
||||
float point_coords_data[2] = {512.0f, 512.0f};
|
||||
float point_labels_data[1] = {1.0f};
|
||||
float has_mask_input_data[1]= {0.0f};
|
||||
Mat point_coords(3, shp_pts, CV_32F, point_coords_data);
|
||||
Mat point_labels(2, shp_lbl, CV_32F, point_labels_data);
|
||||
Mat mask_input(4, shp_mask, CV_32F, Scalar(0));
|
||||
Mat has_mask_input(1, shp_hasmask, CV_32F, has_mask_input_data);
|
||||
|
||||
processNet("dnn/onnx/models/sam2_hiera_large.decoder.onnx", "",
|
||||
{std::make_tuple(image_embed, "image_embed"),
|
||||
std::make_tuple(high_res_feats_0, "high_res_feats_0"),
|
||||
std::make_tuple(high_res_feats_1, "high_res_feats_1"),
|
||||
std::make_tuple(point_coords, "point_coords"),
|
||||
std::make_tuple(point_labels, "point_labels"),
|
||||
std::make_tuple(mask_input, "mask_input"),
|
||||
std::make_tuple(has_mask_input, "has_mask_input")});
|
||||
}
|
||||
|
||||
// Model: https://github.com/opencv/opencv_zoo/tree/main/models/optical_flow_estimation_raft
|
||||
PERF_TEST_P_(DNNTestNetwork, RAFT)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
// RAFT takes two consecutive frames to estimate optical flow between them
|
||||
Mat frame0 = imread(findDataFile("gpu/opticalflow/frame0.png"));
|
||||
Mat frame1 = imread(findDataFile("gpu/opticalflow/frame1.png"));
|
||||
Mat blob0 = blobFromImage(frame0, 1.0, Size(480, 360), Scalar(), true);
|
||||
Mat blob1 = blobFromImage(frame1, 1.0, Size(480, 360), Scalar(), true);
|
||||
|
||||
processNet("dnn/onnx/models/optical_flow_estimation_raft_2023aug.onnx", "",
|
||||
{std::make_tuple(blob0, "0"),
|
||||
std::make_tuple(blob1, "1")});
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/onnx-community/owlv2-base-patch16-finetuned-ONNX
|
||||
PERF_TEST_P_(DNNTestNetwork, OWLv2)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_1GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
// Image input: [1, 3, 960, 960] (60x60 patches x 16 = 960)
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat pixel_values = blobFromImage(sample, 1.0 / 255.0, Size(960, 960), Scalar(), true);
|
||||
|
||||
// Text query tokens: "a dog" with CLIP tokenizer, seq_len=16
|
||||
// [BOS=49406, "a"=320, "dog"=1929, EOS=49407, pad=0, ...]
|
||||
const int seq_len = 16;
|
||||
int shp[2] = {1, seq_len};
|
||||
int64_t input_ids_data[seq_len] = {49406, 320, 1929, 49407, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int64_t attention_mask_data[seq_len]= {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
Mat input_ids(2, shp, CV_64S, input_ids_data);
|
||||
Mat attention_mask(2, shp, CV_64S, attention_mask_data);
|
||||
|
||||
processNet("dnn/onnx/models/owlv2_base_patch_16.onnx", "",
|
||||
{std::make_tuple(input_ids, "input_ids"),
|
||||
std::make_tuple(pixel_values, "pixel_values"),
|
||||
std::make_tuple(attention_mask, "attention_mask")});
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/1IU7iktOUbvNPFnDJb_ivl3LxYIdpEp3f/view?usp=drive_link
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLO26m_Seg)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/onnx/models/yolo26m-seg.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/17OWMXSiefFMmj46CT42Fd2q5kl_jHRBC/view?usp=drive_link
|
||||
PERF_TEST_P_(DNNTestNetwork, YOLO26n)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/onnx/models/yolo26n.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/Xenova/segformer_b2_clothes/blob/main/onnx/model.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, SegFormer_B2_Clothes)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(512, 512), Scalar(), true);
|
||||
processNet("dnn/onnx/models/segformer_b2_clothes.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/Xenova/siglip-base-patch16-224/blob/main/onnx/model.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, SigLIP)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
// Image input: [1, 3, 224, 224] normalized to [-1, 1]
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat pixel_values = blobFromImage(sample, 1.0 / 255.0, Size(224, 224), Scalar(0.5, 0.5, 0.5), true);
|
||||
pixel_values = (pixel_values - 0.5f) / 0.5f;
|
||||
|
||||
// Text input: dummy token IDs for "a photo of a dog", seq_len=64
|
||||
const int seq_len = 64;
|
||||
int shp[2] = {1, seq_len};
|
||||
Mat input_ids(2, shp, CV_64S, Scalar(0));
|
||||
// BOS=1, "a photo of a dog"=some tokens, EOS=2
|
||||
int64_t* ids = input_ids.ptr<int64_t>();
|
||||
ids[0] = 1; ids[1] = 263; ids[2] = 2514; ids[3] = 275; ids[4] = 262; ids[5] = 3914; ids[6] = 2;
|
||||
|
||||
processNet("dnn/onnx/models/siglip_base_patch16_224.onnx", "",
|
||||
{std::make_tuple(input_ids, "input_ids"),
|
||||
std::make_tuple(pixel_values, "pixel_values")});
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/onnx-community/depth-anything-v2-small/blob/main/onnx/model.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, Depth_Anything_V2)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/street.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(518, 518), Scalar(), true);
|
||||
processNet("dnn/onnx/models/depth_anything_v2_small.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/1G2begS7rrEmWnI-xj2K5UL3PQ7H_0svc/view?usp=drive_link
|
||||
PERF_TEST_P_(DNNTestNetwork, RetinaFace)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
|
||||
|
||||
processNet("dnn/onnx/models/retinaface_10g.onnx", "", cv::Size(640, 640));
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/onnx-community/grounding-dino-tiny-ONNX
|
||||
PERF_TEST_P_(DNNTestNetwork, Grounding_DINO)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
// Image input: [1, 3, 800, 800]
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat pixel_values = blobFromImage(sample, 1.0 / 255.0, Size(800, 800), Scalar(), true);
|
||||
|
||||
// Text token inputs (dummy tokens for "dog ." as query text, seq_len=7)
|
||||
const int seq_len = 7;
|
||||
int64_t input_ids_data[seq_len] = {101, 3899, 1012, 102, 0, 0, 0};
|
||||
int64_t attention_mask_data[seq_len] = {1, 1, 1, 1, 0, 0, 0};
|
||||
int64_t token_type_ids_data[seq_len] = {0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
int shp[2] = {1, seq_len};
|
||||
Mat input_ids(2, shp, CV_64S, input_ids_data);
|
||||
Mat attention_mask(2, shp, CV_64S, attention_mask_data);
|
||||
Mat token_type_ids(2, shp, CV_64S, token_type_ids_data);
|
||||
|
||||
// Image attention mask: [1, 800, 800] all ones (valid pixels)
|
||||
int shp_mask[3] = {1, 800, 800};
|
||||
Mat pixel_mask(3, shp_mask, CV_64S, Scalar(1));
|
||||
|
||||
processNet("dnn/onnx/models/grounding_dino_tiny.onnx", "",
|
||||
{std::make_tuple(pixel_values, "pixel_values"),
|
||||
std::make_tuple(input_ids, "input_ids"),
|
||||
std::make_tuple(token_type_ids,"token_type_ids"),
|
||||
std::make_tuple(attention_mask,"attention_mask"),
|
||||
std::make_tuple(pixel_mask, "pixel_mask")});
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/1P6a7oS_dV5y09FsCA4XDZK1-WcdZbWFh/view?usp=drive_link
|
||||
PERF_TEST_P_(DNNTestNetwork, RF_DETR)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_1GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(560, 560), Scalar(), true);
|
||||
processNet("dnn/onnx/models/rfdetr.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/1OrSmlXURayVQgW8nrrxjggzPMN7xPRGJ/view?usp=sharing
|
||||
PERF_TEST_P_(DNNTestNetwork, RT_DETR_L)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_1GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(640, 640), Scalar(), true);
|
||||
processNet("dnn/onnx/models/rtdetr-l.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://drive.google.com/file/d/1HuR5jeGtgX6TKFlWR5JjwZ7be-JDwz57/view?usp=drive_link
|
||||
PERF_TEST_P_(DNNTestNetwork, RTMPose_M)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(192, 256), Scalar(), true);
|
||||
processNet("dnn/onnx/models/rtmpose_m.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/tomjackson2023/rembg/resolve/main/u2net.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, U2Net)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(320, 320), Scalar(), true);
|
||||
processNet("dnn/onnx/models/u2net.onnx", "",
|
||||
{std::make_tuple(inp, "input.1")});
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/qualcomm/Real-ESRGAN-x4plus/resolve/01179a4da7bf5ac91faca650e6afbf282ac93933/Real-ESRGAN-x4plus.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, RealESRGAN_x4plus)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(128, 128), Scalar(), true);
|
||||
processNet("dnn/onnx/models/realesrgan_x4plus.onnx", "",
|
||||
{std::make_tuple(inp, "image")});
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/rocca/swin-ir-onnx/resolve/main/003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x4_GAN.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, SwinIR_x4)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(128, 128), Scalar(), true);
|
||||
processNet("dnn/onnx/models/swinir_x4_gan.onnx", "", inp);
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/onnx-community/BiRefNet-ONNX/resolve/main/onnx/model.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, BiRefNet)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_2GB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(1024, 1024), Scalar(), true);
|
||||
processNet("dnn/onnx/models/birefnet.onnx", "",
|
||||
{std::make_tuple(inp, "input_image")});
|
||||
}
|
||||
|
||||
// Model: https://huggingface.co/onnx-community/dinov2-small/resolve/main/onnx/model.onnx
|
||||
PERF_TEST_P_(DNNTestNetwork, DINOv2_Small)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_MEMORY_512MB, CV_TEST_TAG_VERYLONG);
|
||||
|
||||
Mat sample = imread(findDataFile("dnn/dog416.png"));
|
||||
Mat inp = blobFromImage(sample, 1.0 / 255.0, Size(224, 224), Scalar(), true);
|
||||
processNet("dnn/onnx/models/dinov2_small.onnx", "",
|
||||
{std::make_tuple(inp, "pixel_values")});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, DNNTestNetwork, dnnBackendsAndTargets());
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
#include <opencv2/ts.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
#include "../test/test_common.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
using namespace perf;
|
||||
using namespace cv::dnn;
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct LstmParams {
|
||||
// Batch size
|
||||
int nrSamples;
|
||||
|
||||
// Size of the input vector
|
||||
int inputSize;
|
||||
|
||||
// Size of the internal state vector
|
||||
int hiddenSize;
|
||||
|
||||
// Number of timesteps for the LSTM
|
||||
int nrSteps;
|
||||
};
|
||||
|
||||
static inline void PrintTo(const LstmParams& params, ::std::ostream* os) {
|
||||
(*os) << "BATCH=" << params.nrSamples
|
||||
<< ", IN=" << params.inputSize
|
||||
<< ", HIDDEN=" << params.hiddenSize
|
||||
<< ", TS=" << params.nrSteps;
|
||||
}
|
||||
|
||||
static const LstmParams testLstmConfigs[] = {
|
||||
{1, 192, 192, 100},
|
||||
{1, 1024, 192, 100},
|
||||
{1, 64, 192, 100},
|
||||
{1, 192, 512, 100},
|
||||
{64, 192, 192, 2},
|
||||
{64, 1024, 192, 2},
|
||||
{64, 64, 192, 2},
|
||||
{64, 192, 512, 2},
|
||||
{128, 192, 192, 2},
|
||||
{128, 1024, 192, 2},
|
||||
{128, 64, 192, 2},
|
||||
{128, 192, 512, 2}
|
||||
};
|
||||
|
||||
class Layer_LSTM : public TestBaseWithParam<LstmParams> {};
|
||||
|
||||
PERF_TEST_P_(Layer_LSTM, lstm) {
|
||||
const LstmParams& params = GetParam();
|
||||
LayerParams lp;
|
||||
lp.type = "LSTM";
|
||||
lp.name = "testLstm";
|
||||
lp.set("produce_cell_output", false);
|
||||
lp.set("use_timestamp_dim", true);
|
||||
|
||||
Mat weightH(params.hiddenSize * 4, params.hiddenSize, CV_32FC1, cv::Scalar(0));
|
||||
Mat weightX(params.hiddenSize * 4, params.inputSize, CV_32FC1, cv::Scalar(0));
|
||||
Mat bias(params.hiddenSize * 4, 1, CV_32FC1, cv::Scalar(0));
|
||||
Mat hInternal(params.nrSteps, params.hiddenSize, CV_32FC1, cv::Scalar(0));
|
||||
Mat cInternal(params.nrSteps, params.hiddenSize, CV_32FC1, cv::Scalar(0));
|
||||
lp.blobs.push_back(weightH);
|
||||
lp.blobs.push_back(weightX);
|
||||
lp.blobs.push_back(bias);
|
||||
lp.blobs.push_back(hInternal);
|
||||
lp.blobs.push_back(cInternal);
|
||||
|
||||
std::vector<int> inputDims;
|
||||
inputDims.push_back(params.nrSamples);
|
||||
inputDims.push_back(params.nrSteps);
|
||||
inputDims.push_back(params.inputSize);
|
||||
Mat input(inputDims.size(), inputDims.data(), CV_32FC1);
|
||||
input = cv::Scalar(0);
|
||||
|
||||
Net net;
|
||||
net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.setInput(input);
|
||||
|
||||
// Warm up
|
||||
std::vector<Mat> outputs(2);
|
||||
net.forward(outputs, "testLstm");
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
net.forward(outputs, "testLstm");
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Layer_LSTM, testing::ValuesIn(testLstmConfigs));
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct Layer_Resize : public TestBaseWithParam<tuple<Backend, Target>>
|
||||
{
|
||||
void test_layer(const std::vector<int>& inpShape, int outH, int outW, const String& interp)
|
||||
{
|
||||
int backendId = get<0>(GetParam());
|
||||
int targetId = get<1>(GetParam());
|
||||
|
||||
Mat input(inpShape, CV_32FC1);
|
||||
randu(input, 0.f, 1.f);
|
||||
|
||||
Net net;
|
||||
LayerParams lp;
|
||||
lp.type = "Resize";
|
||||
lp.name = "testLayer";
|
||||
lp.set("interpolation", interp);
|
||||
lp.set("width", outW);
|
||||
lp.set("height", outH);
|
||||
|
||||
|
||||
|
||||
int id = net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.connect(0, 0, id, 0);
|
||||
|
||||
// warmup
|
||||
{
|
||||
net.setInputsNames({"data"});
|
||||
net.setInput(input, "data");
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
};
|
||||
|
||||
PERF_TEST_P_(Layer_Resize, Resize_Upsample_Linear)
|
||||
{
|
||||
// N=4, C=64, H=64, W=64 -> 128x128 (x2 upsample)
|
||||
// Common in segmentation/detection heads
|
||||
test_layer({4, 64, 64, 64}, 128, 128, "opencv_linear");
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Layer_Resize, Resize_Downsample_Nearest)
|
||||
{
|
||||
// N=4, C=128, H=128, W=128 -> 64x64 (x0.5 downsample)
|
||||
test_layer({4, 128, 128, 128}, 64, 64, "nearest");
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Layer_Resize, dnnBackendsAndTargets());
|
||||
|
||||
} // namespace opencv_test
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
struct Layer_Slice : public TestBaseWithParam<tuple<Backend, Target>>
|
||||
{
|
||||
void test_slice(const std::vector<int>& input_shape, int axis, int begin, int end, int step = 1)
|
||||
{
|
||||
int backendId = get<0>(GetParam());
|
||||
int targetId = get<1>(GetParam());
|
||||
|
||||
Mat data(input_shape, CV_32FC1);
|
||||
randu(data, 0.f, 1.f);
|
||||
|
||||
Net net;
|
||||
LayerParams lp;
|
||||
lp.type = "Slice";
|
||||
lp.name = "testLayer";
|
||||
lp.set("axis", axis);
|
||||
|
||||
std::vector<int> begins(input_shape.size(), 0);
|
||||
std::vector<int> ends = input_shape;
|
||||
std::vector<int> steps(input_shape.size(), 1);
|
||||
|
||||
begins[axis] = begin;
|
||||
ends[axis] = end;
|
||||
steps[axis] = step;
|
||||
|
||||
lp.set("begin", DictValue::arrayInt(&begins[0], begins.size()));
|
||||
lp.set("end", DictValue::arrayInt(&ends[0], ends.size()));
|
||||
if (step != 1) {
|
||||
lp.set("steps", DictValue::arrayInt(&steps[0], steps.size()));
|
||||
}
|
||||
|
||||
int id = net.addLayerToPrev(lp.name, lp.type, lp);
|
||||
net.connect(0, 0, id, 0);
|
||||
|
||||
net.setInputsNames({"data"});
|
||||
|
||||
// warmup
|
||||
{
|
||||
net.setInput(data, "data");
|
||||
net.setPreferableBackend(backendId);
|
||||
net.setPreferableTarget(targetId);
|
||||
Mat out = net.forward();
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Mat res = net.forward();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
};
|
||||
|
||||
PERF_TEST_P_(Layer_Slice, Slice_Contiguous_Axis0)
|
||||
{
|
||||
test_slice({64, 128, 128}, 0, 10, 54);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Layer_Slice, Slice_Contiguous_Axis2)
|
||||
{
|
||||
test_slice({64, 128, 128}, 2, 10, 118);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Layer_Slice, Slice_Small_Middle)
|
||||
{
|
||||
test_slice({32, 64, 32}, 1, 20, 40);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Layer_Slice, Slice_Strided_Axis0_Step2)
|
||||
{
|
||||
// Strided slice on outer axis.
|
||||
// [64, 128, 128] -> [0:64:2, ...]
|
||||
test_slice({64, 128, 128}, 0, 0, 64, 2);
|
||||
}
|
||||
|
||||
PERF_TEST_P_(Layer_Slice, Slice_Strided_Axis2_Step2)
|
||||
{
|
||||
// Strided slice on inner axis.
|
||||
// [64, 128, 128] -> [..., 0:128:2]
|
||||
test_slice({64, 128, 128}, 2, 0, 128, 2);
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Layer_Slice, dnnBackendsAndTargets(false, false, true, false, false, false, false, false));
|
||||
|
||||
} // namespace opencv_test
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
using Utils_blobFromImage = TestBaseWithParam<std::vector<int>>;
|
||||
PERF_TEST_P_(Utils_blobFromImage, HWC_TO_NCHW) {
|
||||
std::vector<int> input_shape = GetParam();
|
||||
|
||||
Mat input(input_shape, CV_32FC3);
|
||||
randu(input, -10.0f, 10.f);
|
||||
|
||||
TEST_CYCLE() {
|
||||
Mat blob = blobFromImage(input);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Utils_blobFromImage,
|
||||
Values(std::vector<int>{ 32, 32},
|
||||
std::vector<int>{ 64, 64},
|
||||
std::vector<int>{ 128, 128},
|
||||
std::vector<int>{ 256, 256},
|
||||
std::vector<int>{ 512, 512},
|
||||
std::vector<int>{1024, 1024},
|
||||
std::vector<int>{2048, 2048})
|
||||
);
|
||||
|
||||
using Utils_blobFromImages = TestBaseWithParam<std::vector<int>>;
|
||||
PERF_TEST_P_(Utils_blobFromImages, HWC_TO_NCHW) {
|
||||
std::vector<int> input_shape = GetParam();
|
||||
|
||||
int batch = input_shape.front();
|
||||
std::vector<int> input_shape_no_batch(input_shape.begin()+1, input_shape.end());
|
||||
|
||||
if (input_shape_no_batch[0]*input_shape_no_batch[1] >= 2048*2048)
|
||||
{
|
||||
applyTestTag( CV_TEST_TAG_MEMORY_2GB);
|
||||
}
|
||||
|
||||
std::vector<Mat> inputs;
|
||||
for (int i = 0; i < batch; i++) {
|
||||
Mat input(input_shape_no_batch, CV_32FC3);
|
||||
randu(input, -10.0f, 10.f);
|
||||
inputs.push_back(input);
|
||||
}
|
||||
|
||||
TEST_CYCLE() {
|
||||
Mat blobs = blobFromImages(inputs);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Utils_blobFromImages,
|
||||
Values(std::vector<int>{16, 32, 32},
|
||||
std::vector<int>{16, 64, 64},
|
||||
std::vector<int>{16, 128, 128},
|
||||
std::vector<int>{16, 256, 256},
|
||||
std::vector<int>{16, 512, 512},
|
||||
std::vector<int>{16, 1024, 1024},
|
||||
std::vector<int>{16, 2048, 2048})
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 "backend.hpp"
|
||||
|
||||
#include <opencv2/core/private.hpp>
|
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <opencv2/core/utils/logger.defines.hpp>
|
||||
#ifdef NDEBUG
|
||||
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||
#else
|
||||
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
|
||||
#endif
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#include "factory.hpp"
|
||||
|
||||
#include "plugin_api.hpp"
|
||||
#include "plugin_wrapper.impl.hpp"
|
||||
|
||||
|
||||
namespace cv { namespace dnn_backend {
|
||||
|
||||
NetworkBackend::~NetworkBackend()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
}} // namespace cv::dnn_backend
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
#ifndef OPENCV_DNN_BACKEND_HPP
|
||||
#define OPENCV_DNN_BACKEND_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace cv { namespace dnn_backend {
|
||||
|
||||
using namespace cv::dnn;
|
||||
|
||||
class CV_EXPORTS NetworkBackend
|
||||
{
|
||||
public:
|
||||
virtual ~NetworkBackend();
|
||||
|
||||
virtual void switchBackend(Net& net) = 0;
|
||||
|
||||
/**
|
||||
@param loaderID use empty "" for auto
|
||||
@param model see cv::dnn::readNetwork
|
||||
@param config see cv::dnn::readNetwork
|
||||
*/
|
||||
virtual Net readNetwork(const std::string& loaderID, const std::string& model, const std::string& config) = 0;
|
||||
|
||||
/** @overload */
|
||||
virtual Net readNetwork(
|
||||
const std::string& loaderID,
|
||||
const uchar* bufferModelConfigPtr, size_t bufferModelConfigSize,
|
||||
const uchar* bufferWeightsPtr, size_t bufferWeightsSize
|
||||
) = 0;
|
||||
|
||||
// TODO: target as string + configuration
|
||||
virtual bool checkTarget(Target target) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace dnn_backend
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_DNN_BACKEND_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,131 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//COPYRIGHT
|
||||
//
|
||||
//All contributions by the University of California:
|
||||
//Copyright (c) 2014, The Regents of the University of California (Regents)
|
||||
//All rights reserved.
|
||||
//
|
||||
//All other contributions:
|
||||
//Copyright (c) 2014, the respective contributors
|
||||
//All rights reserved.
|
||||
//
|
||||
//Caffe uses a shared copyright model: each contributor holds copyright over
|
||||
//their contributions to Caffe. The project versioning records all such
|
||||
//contribution and copyright details. If a contributor wants to further mark
|
||||
//their specific copyright on a particular contribution, they should indicate
|
||||
//their copyright solely in the commit message of the change when it is
|
||||
//committed.
|
||||
//
|
||||
//LICENSE
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//2. Redistributions 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.
|
||||
//
|
||||
//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 COPYRIGHT OWNER 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.
|
||||
//
|
||||
//CONTRIBUTION AGREEMENT
|
||||
//
|
||||
//By contributing to the BVLC/caffe repository through pull-request, comment,
|
||||
//or otherwise, the contributor releases their content to the
|
||||
//license and copyright terms herein.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_DNN_CAFFE_IO_HPP__
|
||||
#define __OPENCV_DNN_CAFFE_IO_HPP__
|
||||
#ifdef HAVE_PROTOBUF
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
#endif
|
||||
#include "opencv-caffe.pb.h"
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace caffe { using namespace opencv_caffe; } // avoid massive renames from caffe proto package
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
// Read parameters from a file into a NetParameter proto message.
|
||||
void ReadNetParamsFromTextFileOrDie(const char* param_file,
|
||||
caffe::NetParameter* param);
|
||||
void ReadNetParamsFromBinaryFileOrDie(const char* param_file,
|
||||
caffe::NetParameter* param);
|
||||
|
||||
// Read parameters from a memory buffer into a NetParammeter proto message.
|
||||
void ReadNetParamsFromBinaryBufferOrDie(const char* data, size_t len,
|
||||
caffe::NetParameter* param);
|
||||
void ReadNetParamsFromTextBufferOrDie(const char* data, size_t len,
|
||||
caffe::NetParameter* param);
|
||||
|
||||
// Utility functions used internally by Caffe and TensorFlow loaders
|
||||
bool ReadProtoFromTextFile(const char* filename, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromTextFile(const char* filename, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromBinaryFile(const char* filename, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromTextBuffer(const char* data, size_t len, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromTextBuffer(const char* data, size_t len, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromBinaryBuffer(const char* data, size_t len, ::google::protobuf::MessageLite* proto);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
/*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) 2013, OpenCV Foundation, 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*/
|
||||
|
||||
#ifndef __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__
|
||||
#define __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#define CHECK(cond) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, "CHECK", #cond, cond); _logger.exit(); _logger.check()) _logger.stream()
|
||||
#define CHECK_EQ(a, b) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, "CHECK", #a"="#b, ((a) == (b))); _logger.exit(); _logger.check()) _logger.stream()
|
||||
#define LOG(TYPE) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, #TYPE); _logger.exit(); _logger.check()) _logger.stream()
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class GLogWrapper
|
||||
{
|
||||
const char *file, *func, *type, *cond_str;
|
||||
int line;
|
||||
bool cond_status, exit_loop;
|
||||
std::stringstream sstream;
|
||||
|
||||
public:
|
||||
|
||||
GLogWrapper(const char *_file, const char *_func, int _line,
|
||||
const char *_type,
|
||||
const char *_cond_str = NULL, bool _cond_status = true
|
||||
) :
|
||||
file(_file), func(_func), type(_type), cond_str(_cond_str),
|
||||
line(_line), cond_status(_cond_status), exit_loop(true) {}
|
||||
|
||||
std::iostream &stream()
|
||||
{
|
||||
return sstream;
|
||||
}
|
||||
|
||||
bool exit()
|
||||
{
|
||||
return exit_loop;
|
||||
}
|
||||
|
||||
void check()
|
||||
{
|
||||
exit_loop = false;
|
||||
|
||||
if (cond_str && !cond_status)
|
||||
{
|
||||
cv::error(cv::Error::StsError, "FAILED: " + String(cond_str) + ". " + sstream.str(), func, file, line);
|
||||
}
|
||||
else if (!cond_str && strcmp(type, "CHECK"))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (!std::strcmp(type, "INFO"))
|
||||
std::cout << sstream.str() << std::endl;
|
||||
else
|
||||
std::cerr << sstream.str() << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp, std::size_t N>
|
||||
__global__ void generic_op_eltwise_op_inplace_vec(Span<T> inplace_output, View<T> eltwise, const typename ActivationOp::Params act_params, const typename EltwiseOp::Params eltwise_params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto inplace_output_vPtr = vector_type::get_pointer(inplace_output.data());
|
||||
auto eltwise_vPtr = vector_type::get_pointer(eltwise.data());
|
||||
|
||||
ActivationOp activation_op(act_params);
|
||||
EltwiseOp eltwise_op(eltwise_params);
|
||||
|
||||
for (auto i : grid_stride_range(inplace_output.size() / vector_type::size())) {
|
||||
vector_type output_vec, eltwise_vec;
|
||||
v_load(output_vec, inplace_output_vPtr[i]);
|
||||
v_load(eltwise_vec, eltwise_vPtr[i]);
|
||||
for(int j = 0; j < output_vec.size(); j++)
|
||||
output_vec.data[j] = eltwise_op(activation_op(output_vec.data[j]), eltwise_vec.data[j]);
|
||||
v_store(inplace_output_vPtr[i], output_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp, std::size_t N> static
|
||||
void launch_vectorized_generic_op_eltwise_op_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise, const typename ActivationOp::Params& act_params, const typename EltwiseOp::Params& eltwise_params) {
|
||||
CV_Assert(is_fully_aligned<T>(inplace_output, N));
|
||||
CV_Assert(is_fully_aligned<T>(eltwise, N));
|
||||
|
||||
auto kernel = raw::generic_op_eltwise_op_inplace_vec<T, ActivationOp, EltwiseOp, N>;
|
||||
auto policy = make_policy(kernel, inplace_output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, inplace_output, eltwise, act_params, eltwise_params);
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp> static
|
||||
void generic_op_eltwise_op_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise, const typename ActivationOp::Params& act_params = {}, const typename EltwiseOp::Params& eltwise_params = {}) {
|
||||
CV_Assert(inplace_output.size() == eltwise.size());
|
||||
|
||||
if (is_fully_aligned<T>(inplace_output, 4) && is_fully_aligned<T>(eltwise, 4)) {
|
||||
launch_vectorized_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 4>(stream, inplace_output, eltwise, act_params, eltwise_params);
|
||||
} else if (is_fully_aligned<T>(inplace_output, 2) && is_fully_aligned<T>(eltwise, 2)) {
|
||||
launch_vectorized_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 2>(stream, inplace_output, eltwise, act_params, eltwise_params);
|
||||
} else {
|
||||
launch_vectorized_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 1>(stream, inplace_output, eltwise, act_params, eltwise_params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void relu_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise, T slope) {
|
||||
generic_op_eltwise_op_inplace<T, ReLUFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void clipped_relu_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise, T floor, T ceiling) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceiling));
|
||||
generic_op_eltwise_op_inplace<T, ClippedReLUFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise, {floor, ceiling});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void tanh_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise) {
|
||||
generic_op_eltwise_op_inplace<T, TanHFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void swish_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise) {
|
||||
generic_op_eltwise_op_inplace<T, SwishFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void mish_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise) {
|
||||
generic_op_eltwise_op_inplace<T, MishFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sigmoid_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise) {
|
||||
generic_op_eltwise_op_inplace<T, SigmoidFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void power_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, View<T> eltwise, T exp, T scale, T shift) {
|
||||
generic_op_eltwise_op_inplace<T, PowerFunctor<T>, SumFunctor<T>>(stream, inplace_output, eltwise, {exp, scale, shift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void relu_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>, __half);
|
||||
template void clipped_relu_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void tanh_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void swish_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void mish_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void sigmoid_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void power_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, View<__half>, __half, __half, __half);
|
||||
#endif
|
||||
|
||||
template void relu_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>, float);
|
||||
template void clipped_relu_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void tanh_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>);
|
||||
template void swish_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>);
|
||||
template void mish_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>);
|
||||
template void sigmoid_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>);
|
||||
template void power_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, View<float>, float, float, float);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,412 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include "../cuda4dnn/kernels/scale_shift.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, class ActivationOp, std::size_t N>
|
||||
__global__ void generic_op_vec(Span<T> output, View<T> input, const typename ActivationOp::Params params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
auto input_vPtr = vector_type::get_pointer(input.data());
|
||||
|
||||
ActivationOp activation_op(params);
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
vector_type vec;
|
||||
v_load(vec, input_vPtr[i]);
|
||||
for (int j = 0; j < vector_type::size(); j++)
|
||||
vec.data[j] = activation_op(vec.data[j]);
|
||||
v_store(output_vPtr[i], vec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
__global__ void axiswise_relu_vec(Span<T> output, View<T> input, size_type inner_size, View<T> slope) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
auto input_vPtr = vector_type::get_pointer(input.data());
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
const index_type c = (i / inner_size) % slope.size();
|
||||
|
||||
vector_type vec;
|
||||
v_load(vec, input_vPtr[i]);
|
||||
for (int j = 0; j < vector_type::size(); j++)
|
||||
vec.data[j] = vec.data[j] > T(0) ? vec.data[j] : vec.data[j] * slope[c];
|
||||
v_store(output_vPtr[i], vec);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace raw */
|
||||
|
||||
template <class T, class ActivationOp, std::size_t N> static
|
||||
void launch_vectorized_generic_op(const Stream& stream, Span<T> output, View<T> input, const typename ActivationOp::Params& params) {
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(input, N));
|
||||
|
||||
auto kernel = raw::generic_op_vec<T, ActivationOp, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, params);
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp> static
|
||||
void generic_op(const Stream& stream, Span<T> output, View<T> input, const typename ActivationOp::Params& params = {}) {
|
||||
CV_Assert(input.size() == output.size());
|
||||
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(input, 4)) {
|
||||
launch_vectorized_generic_op<T, ActivationOp, 4>(stream, output, input, params);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(input, 2)) {
|
||||
launch_vectorized_generic_op<T, ActivationOp, 2>(stream, output, input, params);
|
||||
} else {
|
||||
launch_vectorized_generic_op<T, ActivationOp, 1>(stream, output, input, params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void relu(const Stream& stream, Span<T> output, View<T> input, T slope) {
|
||||
generic_op<T, ReLUFunctor<T>>(stream, output, input, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void clipped_relu(const Stream& stream, Span<T> output, View<T> input, T floor, T ceiling) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceiling));
|
||||
generic_op<T, ClippedReLUFunctor<T>>(stream, output, input, {floor, ceiling});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void tanh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, TanHFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void swish(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SwishFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void mish(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, MishFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sigmoid(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SigmoidFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void elu(const Stream& stream, Span<T> output, View<T> input, T alpha) {
|
||||
generic_op<T, ELUFunctor<T>>(stream, output, input, {alpha});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void bnll(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, BNLLFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ceil(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, CeilFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void floor(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, FloorFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void log(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, LogFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void rint(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, RintFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sqrt(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SqrtFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void not_k(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, NotFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void acos(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AcosFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void acosh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AcoshFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void asin(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AsinFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void asinh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AsinhFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void atan(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AtanFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void atanh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AtanhFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void cos(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, CosFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void cosh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, CoshFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void erf(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, ErfFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hardswish(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, HardSwishFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sin(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SinFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sinh(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SinhFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void softplus(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SoftplusFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void softsign(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SoftsignFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void tan(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, TanFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void celu(const Stream& stream, Span<T> output, View<T> input, T alpha) {
|
||||
generic_op<T, CeluFunctor<T>>(stream, output, input, {alpha});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hardsigmoid(const Stream& stream, Span<T> output, View<T> input, T alpha, T beta) {
|
||||
generic_op<T, HardSigmoidFunctor<T>>(stream, output, input, {alpha, beta});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void selu(const Stream& stream, Span<T> output, View<T> input, T alpha, T gamma) {
|
||||
generic_op<T, SeluFunctor<T>>(stream, output, input, {alpha, gamma});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void gelu(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, GeluFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sign(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, SignFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void shrink(const Stream& stream, Span<T> output, View<T> input, T bias, T lambd) {
|
||||
generic_op<T, ShrinkFunctor<T>>(stream, output, input, {bias, lambd});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void reciprocal(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, ReciprocalFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void thresholdedrelu(const Stream& stream, Span<T> output, View<T> input, T alpha) {
|
||||
generic_op<T, ThresholdedReluFunctor<T>>(stream, output, input, {alpha});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void abs(const Stream& stream, Span<T> output, View<T> input) {
|
||||
generic_op<T, AbsFunctor<T>>(stream, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void power(const Stream& stream, Span<T> output, View<T> input, T exp, T scale, T shift) {
|
||||
CV_Assert(input.size() == output.size());
|
||||
|
||||
if (static_cast<float>(exp) == 1.0f) {
|
||||
scale1_with_bias1(stream, output, input, scale, shift);
|
||||
return;
|
||||
}
|
||||
|
||||
generic_op<T, PowerFunctor<T>>(stream, output, input, {exp, scale, shift});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void exp(const Stream& stream, Span<T> output, View<T> input, T normScale, T normShift) {
|
||||
generic_op<T, ExpFunctor<T>>(stream, output, input, {normScale, normShift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void relu<__half>(const Stream&, Span<__half>, View<__half>, __half);
|
||||
template void clipped_relu<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void tanh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void swish<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void mish<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void sigmoid<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void elu<__half>(const Stream&, Span<__half>, View<__half>, __half);
|
||||
template void abs<__half>(const Stream& stream, Span<__half> output, View<__half> input);
|
||||
template void bnll<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void ceil<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void floor<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void log<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void rint<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void sqrt<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void not_k<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void acos<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void acosh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void asin<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void asinh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void atan<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void atanh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void cos<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void cosh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void erf<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void hardswish<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void sin<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void sinh<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void softplus<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void softsign<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void tan<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void celu<__half>(const Stream&, Span<__half>, View<__half>, __half);
|
||||
template void hardsigmoid<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void selu<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void gelu<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void thresholdedrelu<__half>(const Stream&, Span<__half>, View<__half>, __half);
|
||||
template void power<__half>(const Stream&, Span<__half>, View<__half>, __half, __half, __half);
|
||||
template void exp<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void sign<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
template void shrink<__half>(const Stream&, Span<__half>, View<__half>, __half, __half);
|
||||
template void reciprocal<__half>(const Stream&, Span<__half>, View<__half>);
|
||||
#endif
|
||||
|
||||
|
||||
template void relu<float>(const Stream&, Span<float>, View<float>, float);
|
||||
template void clipped_relu<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void tanh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void swish<float>(const Stream&, Span<float>, View<float>);
|
||||
template void mish<float>(const Stream&, Span<float>, View<float>);
|
||||
template void sigmoid<float>(const Stream&, Span<float>, View<float>);
|
||||
template void elu<float>(const Stream&, Span<float>, View<float>, float);
|
||||
template void abs<float>(const Stream& stream, Span<float> output, View<float> input);
|
||||
template void bnll<float>(const Stream&, Span<float>, View<float>);
|
||||
template void ceil<float>(const Stream&, Span<float>, View<float>);
|
||||
template void floor<float>(const Stream&, Span<float>, View<float>);
|
||||
template void log<float>(const Stream&, Span<float>, View<float>);
|
||||
template void rint<float>(const Stream&, Span<float>, View<float>);
|
||||
template void sqrt<float>(const Stream&, Span<float>, View<float>);
|
||||
template void not_k<float>(const Stream&, Span<float>, View<float>);
|
||||
template void acos<float>(const Stream&, Span<float>, View<float>);
|
||||
template void acosh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void asin<float>(const Stream&, Span<float>, View<float>);
|
||||
template void asinh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void atan<float>(const Stream&, Span<float>, View<float>);
|
||||
template void atanh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void cos<float>(const Stream&, Span<float>, View<float>);
|
||||
template void cosh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void erf<float>(const Stream&, Span<float>, View<float>);
|
||||
template void hardswish<float>(const Stream&, Span<float>, View<float>);
|
||||
template void sin<float>(const Stream&, Span<float>, View<float>);
|
||||
template void sinh<float>(const Stream&, Span<float>, View<float>);
|
||||
template void softplus<float>(const Stream&, Span<float>, View<float>);
|
||||
template void softsign<float>(const Stream&, Span<float>, View<float>);
|
||||
template void tan<float>(const Stream&, Span<float>, View<float>);
|
||||
template void celu<float>(const Stream&, Span<float>, View<float>, float);
|
||||
template void hardsigmoid<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void selu<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void gelu<float>(const Stream&, Span<float>, View<float>);
|
||||
template void thresholdedrelu<float>(const Stream&, Span<float>, View<float>, float);
|
||||
template void power<float>(const Stream&, Span<float>, View<float>, float, float, float);
|
||||
template void exp<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void sign<float>(const Stream&, Span<float>, View<float>);
|
||||
template void shrink<float>(const Stream&, Span<float>, View<float>, float, float);
|
||||
template void reciprocal<float>(const Stream&, Span<float>, View<float>);
|
||||
|
||||
template <class T, std::size_t N> static
|
||||
void launch_vectorized_axiswise_relu(const Stream& stream, Span<T> output, View<T> input, std::size_t inner_size, View<T> slope) {
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(input, N));
|
||||
CV_Assert(inner_size % N == 0);
|
||||
|
||||
auto kernel = raw::axiswise_relu_vec<T, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, inner_size / N, slope);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void axiswise_relu(const Stream& stream, Span<T> output, View<T> input, std::size_t inner_size, View<T> slope) {
|
||||
CV_Assert(input.size() == output.size());
|
||||
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(input, 4) && inner_size % 4 == 0) {
|
||||
launch_vectorized_axiswise_relu<T, 4>(stream, output, input, inner_size, slope);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(input, 2) && inner_size % 2 == 0) {
|
||||
launch_vectorized_axiswise_relu<T, 2>(stream, output, input, inner_size, slope);
|
||||
} else {
|
||||
launch_vectorized_axiswise_relu<T, 1>(stream, output, input, inner_size, slope);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void axiswise_relu<__half>(const Stream&, Span<__half>, View<__half>, std::size_t, View<__half>);
|
||||
#endif
|
||||
template void axiswise_relu<float>(const Stream&, Span<float>, View<float>, std::size_t, View<float>);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_ARRAY_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_ARRAY_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <iterator>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct array {
|
||||
using value_type = T;
|
||||
using size_type = device::size_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = typename std::add_lvalue_reference<value_type>::type;
|
||||
using const_reference = typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type;
|
||||
using pointer = typename std::add_pointer<value_type>::type;
|
||||
using const_pointer = typename std::add_pointer<typename std::add_const<value_type>::type>::type;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
__host__ __device__ bool empty() const noexcept { return N == 0; }
|
||||
__host__ __device__ size_type size() const noexcept { return N; }
|
||||
|
||||
__host__ __device__ iterator begin() noexcept { return ptr; }
|
||||
__host__ __device__ iterator end() noexcept { return ptr + N; }
|
||||
__host__ __device__ const_iterator begin() const noexcept { return ptr; }
|
||||
__host__ __device__ const_iterator end() const noexcept { return ptr + N; }
|
||||
|
||||
__host__ __device__ const_iterator cbegin() const noexcept { return ptr; }
|
||||
__host__ __device__ const_iterator cend() const noexcept { return ptr + N; }
|
||||
|
||||
__host__ __device__ reverse_iterator rbegin() noexcept { return ptr + N; }
|
||||
__host__ __device__ reverse_iterator rend() noexcept { return ptr; }
|
||||
__host__ __device__ const_reverse_iterator rbegin() const noexcept { return ptr + N; }
|
||||
__host__ __device__ const_reverse_iterator rend() const noexcept { return ptr; }
|
||||
|
||||
__host__ __device__ const_reverse_iterator crbegin() const noexcept { return ptr + N; }
|
||||
__host__ __device__ const_reverse_iterator crend() const noexcept { return ptr; }
|
||||
|
||||
template <class InputItr>
|
||||
__host__ void assign(InputItr first, InputItr last) {
|
||||
std::copy(first, last, std::begin(ptr));
|
||||
}
|
||||
|
||||
__host__ __device__ reference operator[](int idx) { return ptr[idx]; }
|
||||
__host__ __device__ const_reference operator[](int idx) const { return ptr[idx]; }
|
||||
|
||||
__host__ __device__ reference front() { return ptr[0]; }
|
||||
__host__ __device__ const_reference front() const { return ptr[0]; }
|
||||
|
||||
__host__ __device__ reference back() { return ptr[N - 1]; }
|
||||
__host__ __device__ const_reference back() const { return ptr[N - 1]; }
|
||||
|
||||
__host__ __device__ pointer data() noexcept { return ptr; }
|
||||
__host__ __device__ const_pointer data() const noexcept { return ptr; }
|
||||
|
||||
T ptr[N];
|
||||
};
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_ARRAY_HPP */
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_ATOMICS_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_ATOMICS_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
// The 16-bit __half floating-point version of atomicAdd() is only supported by devices of compute capability 7.x and higher.
|
||||
// This function was introduced in CUDA 10.
|
||||
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#atomicadd
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 700 && CUDART_VERSION >= 10000)
|
||||
// And half-precision floating-point operations are not supported by devices of compute capability strictly lower than 5.3
|
||||
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications
|
||||
#elif __CUDA_ARCH__ < 530
|
||||
#else
|
||||
inline __device__ void atomicAdd(__half* address, __half val) {
|
||||
unsigned int* address_as_ui = (unsigned int *)((char *)address - ((size_t)address & 2));
|
||||
unsigned int old = *address_as_ui;
|
||||
unsigned int assumed;
|
||||
|
||||
do {
|
||||
assumed = old;
|
||||
|
||||
__half_raw hsum;
|
||||
hsum.x = (size_t)address & 2 ? (old >> 16) : (old & 0xffff);
|
||||
__half tmpres = hsum + val;
|
||||
hsum = __half_raw(tmpres);
|
||||
|
||||
old = (size_t)address & 2 ? (old & 0xffff) | (hsum.x << 16) : (old & 0xffff0000) | hsum.x;
|
||||
old = atomicCAS(address_as_ui, assumed, old);
|
||||
} while (assumed != old);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_ATOMICS_HPP */
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_BBOX_UTILS_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_BBOX_UTILS_HPP
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
struct BoundingBox
|
||||
{
|
||||
float xmin, ymin, xmax, ymax;
|
||||
};
|
||||
|
||||
template <bool NORMALIZED_BBOX>
|
||||
__device__ __forceinline__ float compute_bbox_size(BoundingBox bbox)
|
||||
{
|
||||
float width = bbox.xmax - bbox.xmin;
|
||||
float height = bbox.ymax - bbox.ymin;
|
||||
if (width < 0 || height < 0)
|
||||
return 0.0;
|
||||
|
||||
if (!NORMALIZED_BBOX)
|
||||
{
|
||||
width += 1;
|
||||
height += 1;
|
||||
}
|
||||
|
||||
using csl::device::mul_ftz;
|
||||
return mul_ftz(width, height);
|
||||
}
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_BBOX_UTILS_HPP */
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, class ActivationOp, std::size_t N>
|
||||
__global__ void biasN_generic_op_inplace_vec(Span<T> inplace_output, size_type inner_size, View<T> bias, const typename ActivationOp::Params params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto inplace_output_vPtr = vector_type::get_pointer(inplace_output.data());
|
||||
|
||||
ActivationOp activation_op(params);
|
||||
|
||||
for (auto i : grid_stride_range(inplace_output.size() / vector_type::size())) {
|
||||
const index_type bias_idx = (i / inner_size) % bias.size();
|
||||
|
||||
vector_type vec;
|
||||
v_load(vec, inplace_output_vPtr[i]);
|
||||
for(int j = 0; j < vec.size(); j++)
|
||||
vec.data[j] = activation_op(vec.data[j] + bias[bias_idx]);
|
||||
v_store(inplace_output_vPtr[i], vec);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace raw */
|
||||
|
||||
template <class T, class ActivationOp, std::size_t N> static
|
||||
void launch_vectorized_biasN_generic_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, const typename ActivationOp::Params& params) {
|
||||
CV_Assert(inplace_output.size() % inner_size == 0);
|
||||
CV_Assert(is_fully_aligned<T>(inplace_output, N));
|
||||
CV_Assert(inner_size % N == 0);
|
||||
|
||||
auto kernel = raw::biasN_generic_op_inplace_vec<T, ActivationOp, N>;
|
||||
auto policy = make_policy(kernel, inplace_output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, inplace_output, inner_size / N, bias, params);
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp> static
|
||||
void biasN_generic_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, const typename ActivationOp::Params& params = {}) {
|
||||
if (is_fully_aligned<T>(inplace_output, 4) && inner_size % 4 == 0) {
|
||||
launch_vectorized_biasN_generic_op_inplace<T, ActivationOp, 4>(stream, inplace_output, inner_size, bias, params);
|
||||
} else if (is_fully_aligned<T>(inplace_output, 2) && inner_size % 2 == 0) {
|
||||
launch_vectorized_biasN_generic_op_inplace<T, ActivationOp, 2>(stream, inplace_output, inner_size, bias, params);
|
||||
} else {
|
||||
launch_vectorized_biasN_generic_op_inplace<T, ActivationOp, 1>(stream, inplace_output, inner_size, bias, params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_relu_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, T slope) {
|
||||
biasN_generic_op_inplace<T, ReLUFunctor<T>>(stream, inplace_output, inner_size, bias, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_clipped_relu_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, T floor, T ceil) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceil));
|
||||
biasN_generic_op_inplace<T, ClippedReLUFunctor<T>>(stream, inplace_output, inner_size, bias, {floor, ceil});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_tanh_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias) {
|
||||
biasN_generic_op_inplace<T, TanHFunctor<T>>(stream, inplace_output, inner_size, bias);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_swish_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias) {
|
||||
biasN_generic_op_inplace<T, SwishFunctor<T>>(stream, inplace_output, inner_size, bias);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_mish_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias) {
|
||||
biasN_generic_op_inplace<T, MishFunctor<T>>(stream, inplace_output, inner_size, bias);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_sigmoid_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias) {
|
||||
biasN_generic_op_inplace<T, SigmoidFunctor<T>>(stream, inplace_output, inner_size, bias);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_power_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, T power, T scale, T shift) {
|
||||
biasN_generic_op_inplace<T, PowerFunctor<T>>(stream, inplace_output, inner_size, bias, {power, scale, shift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void biasN_relu_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, __half);
|
||||
template void biasN_clipped_relu_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, __half, __half);
|
||||
template void biasN_tanh_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>);
|
||||
template void biasN_swish_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>);
|
||||
template void biasN_mish_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>);
|
||||
template void biasN_sigmoid_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>);
|
||||
template void biasN_power_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, __half, __half, __half);
|
||||
#endif
|
||||
|
||||
template void biasN_relu_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, float);
|
||||
template void biasN_clipped_relu_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, float, float);
|
||||
template void biasN_tanh_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>);
|
||||
template void biasN_swish_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>);
|
||||
template void biasN_mish_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>);
|
||||
template void biasN_sigmoid_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>);
|
||||
template void biasN_power_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, float, float, float);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,125 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp, std::size_t N>
|
||||
__global__ void biasN_generic_op_eltwise_op_inplace_vec(Span<T> inplace_output, size_type inner_size, View<T> bias, View<T> eltwise, const typename ActivationOp::Params act_params, const typename EltwiseOp::Params eltwise_params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto inplace_output_vPtr = vector_type::get_pointer(inplace_output.data());
|
||||
auto eltwise_vPtr = vector_type::get_pointer(eltwise.data());
|
||||
|
||||
ActivationOp activation_op(act_params);
|
||||
EltwiseOp eltwise_op(eltwise_params);
|
||||
|
||||
for (auto i : grid_stride_range(inplace_output.size() / vector_type::size())) {
|
||||
const index_type bias_idx = (i / inner_size) % bias.size();
|
||||
|
||||
vector_type output_vec, eltwise_vec;
|
||||
v_load(output_vec, inplace_output_vPtr[i]);
|
||||
v_load(eltwise_vec, eltwise_vPtr[i]);
|
||||
for(int j = 0; j < output_vec.size(); j++)
|
||||
output_vec.data[j] = eltwise_op(activation_op(output_vec.data[j] + bias[bias_idx]), eltwise_vec.data[j]);
|
||||
v_store(inplace_output_vPtr[i], output_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp, std::size_t N> static
|
||||
void launch_vectorized_biasN_generic_op_eltwise_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, const typename ActivationOp::Params& act_params, const typename EltwiseOp::Params& eltwise_params) {
|
||||
CV_Assert(is_fully_aligned<T>(inplace_output, N));
|
||||
CV_Assert(is_fully_aligned<T>(eltwise, N));
|
||||
CV_Assert(inner_size % N == 0);
|
||||
|
||||
auto kernel = raw::biasN_generic_op_eltwise_op_inplace_vec<T, ActivationOp, EltwiseOp, N>;
|
||||
auto policy = make_policy(kernel, inplace_output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, inplace_output, inner_size / N, bias, eltwise, act_params, eltwise_params);
|
||||
}
|
||||
|
||||
template <class T, class ActivationOp, class EltwiseOp> static
|
||||
void biasN_generic_op_eltwise_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, const typename ActivationOp::Params& act_params = {}, const typename EltwiseOp::Params& eltwise_params = {}) {
|
||||
CV_Assert(inplace_output.size() == eltwise.size());
|
||||
|
||||
if (is_fully_aligned<T>(inplace_output, 4) && is_fully_aligned<T>(eltwise, 4) && inner_size % 4 == 0) {
|
||||
launch_vectorized_biasN_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 4>(stream, inplace_output, inner_size, bias, eltwise, act_params, eltwise_params);
|
||||
} else if (is_fully_aligned<T>(inplace_output, 2) && is_fully_aligned<T>(eltwise, 2) && inner_size % 2 == 0) {
|
||||
launch_vectorized_biasN_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 2>(stream, inplace_output, inner_size, bias, eltwise, act_params, eltwise_params);
|
||||
} else {
|
||||
launch_vectorized_biasN_generic_op_eltwise_op_inplace<T, ActivationOp, EltwiseOp, 1>(stream, inplace_output, inner_size, bias, eltwise, act_params, eltwise_params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_relu_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T slope) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, ReLUFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_clipped_relu_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T floor, T ceiling) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceiling));
|
||||
biasN_generic_op_eltwise_op_inplace<T, ClippedReLUFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {floor, ceiling});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_tanh_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, TanHFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_swish_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, SwishFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_mish_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, MishFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_sigmoid_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, SigmoidFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_power_eltwise_sum_2_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T exp, T scale, T shift) {
|
||||
biasN_generic_op_eltwise_op_inplace<T, PowerFunctor<T>, SumFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {exp, scale, shift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void biasN_relu_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half);
|
||||
template void biasN_clipped_relu_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half, __half);
|
||||
template void biasN_tanh_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_swish_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_mish_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_sigmoid_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_power_eltwise_sum_2_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half, __half, __half);
|
||||
#endif
|
||||
|
||||
template void biasN_relu_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float);
|
||||
template void biasN_clipped_relu_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float, float);
|
||||
template void biasN_tanh_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_swish_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_mish_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_sigmoid_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_power_eltwise_sum_2_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float, float, float);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,132 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, class EltwiseOp, class ActivationOp, std::size_t N>
|
||||
__global__ void biasN_eltwise_op_generic_op_inplace_vec(Span<T> inplace_output, size_type inner_size, View<T> bias, View<T> eltwise, const typename EltwiseOp::Params eltwise_params, const typename ActivationOp::Params act_params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto inplace_output_vPtr = vector_type::get_pointer(inplace_output.data());
|
||||
auto eltwise_vPtr = vector_type::get_pointer(eltwise.data());
|
||||
|
||||
EltwiseOp eltwise_op(eltwise_params);
|
||||
ActivationOp activation_op(act_params);
|
||||
|
||||
for (auto i : grid_stride_range(inplace_output.size() / vector_type::size())) {
|
||||
const index_type bias_idx = (i / inner_size) % bias.size();
|
||||
|
||||
vector_type output_vec, eltwise_vec;
|
||||
v_load(output_vec, inplace_output_vPtr[i]);
|
||||
v_load(eltwise_vec, eltwise_vPtr[i]);
|
||||
for(int j = 0; j < output_vec.size(); j++)
|
||||
output_vec.data[j] = activation_op(eltwise_op(output_vec.data[j] + bias[bias_idx], eltwise_vec.data[j]));
|
||||
v_store(inplace_output_vPtr[i], output_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, class ActivationOp, std::size_t N> static
|
||||
void launch_vectorized_biasN_eltwise_op_generic_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, const typename EltwiseOp::Params& eltwise_params, const typename ActivationOp::Params& act_params) {
|
||||
CV_Assert(is_fully_aligned<T>(inplace_output, N));
|
||||
CV_Assert(inplace_output.size() % bias.size() == 0);
|
||||
CV_Assert(is_fully_aligned<T>(eltwise, N));
|
||||
CV_Assert(inner_size % N == 0);
|
||||
|
||||
auto kernel = raw::biasN_eltwise_op_generic_op_inplace_vec<T, EltwiseOp, ActivationOp, N>;
|
||||
auto policy = make_policy(kernel, inplace_output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, inplace_output, inner_size / N, bias, eltwise, eltwise_params, act_params);
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, class ActivationOp> static
|
||||
void biasN_eltwise_op_generic_op_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, const typename EltwiseOp::Params& eltwise_params = {}, const typename ActivationOp::Params& act_params = {}) {
|
||||
CV_Assert(inplace_output.size() == eltwise.size());
|
||||
|
||||
if (is_fully_aligned<T>(inplace_output, 4) && is_fully_aligned<T>(eltwise, 4) && inner_size % 4 == 0) {
|
||||
launch_vectorized_biasN_eltwise_op_generic_op_inplace<T, EltwiseOp, ActivationOp, 4>(stream, inplace_output, inner_size, bias, eltwise, eltwise_params, act_params);
|
||||
} else if (is_fully_aligned<T>(inplace_output, 2) && is_fully_aligned<T>(eltwise, 2) && inner_size % 2 == 0) {
|
||||
launch_vectorized_biasN_eltwise_op_generic_op_inplace<T, EltwiseOp, ActivationOp, 2>(stream, inplace_output, inner_size, bias, eltwise, eltwise_params, act_params);
|
||||
} else {
|
||||
launch_vectorized_biasN_eltwise_op_generic_op_inplace<T, EltwiseOp, ActivationOp, 1>(stream, inplace_output, inner_size, bias, eltwise, eltwise_params, act_params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_identity_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, IdentityFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_relu_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T slope) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, ReLUFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {}, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_clipped_relu_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T floor, T ceiling) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceiling));
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, ClippedReLUFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {}, {floor, ceiling});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_tanh_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, TanHFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_swish_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, SwishFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_mish_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, MishFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_sigmoid_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, SigmoidFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void biasN_eltwise_sum_2_power_inplace(const Stream& stream, Span<T> inplace_output, std::size_t inner_size, View<T> bias, View<T> eltwise, T exp, T scale, T shift) {
|
||||
biasN_eltwise_op_generic_op_inplace<T, SumFunctor<T>, PowerFunctor<T>>(stream, inplace_output, inner_size, bias, eltwise, {}, {exp, scale, shift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void biasN_eltwise_sum_2_identity_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_eltwise_sum_2_relu_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half);
|
||||
template void biasN_eltwise_sum_2_clipped_relu_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half, __half);
|
||||
template void biasN_eltwise_sum_2_tanh_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_eltwise_sum_2_swish_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_eltwise_sum_2_mish_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_eltwise_sum_2_sigmoid_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>);
|
||||
template void biasN_eltwise_sum_2_power_inplace<__half>(const Stream&, Span<__half>, std::size_t, View<__half>, View<__half>, __half, __half, __half);
|
||||
#endif
|
||||
|
||||
template void biasN_eltwise_sum_2_identity_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_eltwise_sum_2_relu_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float);
|
||||
template void biasN_eltwise_sum_2_clipped_relu_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float, float);
|
||||
template void biasN_eltwise_sum_2_tanh_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_eltwise_sum_2_swish_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_eltwise_sum_2_mish_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_eltwise_sum_2_sigmoid_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>);
|
||||
template void biasN_eltwise_sum_2_power_inplace<float>(const Stream&, Span<float>, std::size_t, View<float>, View<float>, float, float, float);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_BLOCK_STRIDE_RANGE_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_BLOCK_STRIDE_RANGE_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
#include "index_helpers.hpp"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <int dim, int BLOCK_SIZE = 0, class index_type = device::index_type, class size_type = device::size_type>
|
||||
class block_stride_range_generic {
|
||||
public:
|
||||
__device__ block_stride_range_generic(index_type to_) : from(0), to(to_) { }
|
||||
__device__ block_stride_range_generic(index_type from_, index_type to_) : from(from_), to(to_) { }
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
__device__ iterator(index_type pos_) : pos(pos_) {}
|
||||
|
||||
/* these iterators return the index when dereferenced; this allows us to loop
|
||||
* through the indices using a range based for loop
|
||||
*/
|
||||
__device__ index_type operator*() const { return pos; }
|
||||
|
||||
__device__ iterator& operator++() {
|
||||
const index_type block_size = BLOCK_SIZE == 0 ? getBlockDim<dim>() : BLOCK_SIZE;
|
||||
pos += block_size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__device__ bool operator!=(const iterator& other) const {
|
||||
/* NOTE HACK
|
||||
* 'pos' can move in large steps (see operator++)
|
||||
* expansion of range for loop uses != as the loop conditioion
|
||||
* => operator!= must return false if 'pos' crosses the end
|
||||
*/
|
||||
return pos < other.pos;
|
||||
}
|
||||
|
||||
private:
|
||||
index_type pos;
|
||||
};
|
||||
|
||||
__device__ iterator begin() const {
|
||||
return iterator(from + getThreadIdx<dim>());
|
||||
}
|
||||
|
||||
__device__ iterator end() const {
|
||||
return iterator(to);
|
||||
}
|
||||
|
||||
private:
|
||||
index_type from, to;
|
||||
};
|
||||
|
||||
using block_stride_range_x = block_stride_range_generic<0>;
|
||||
using block_stride_range_y = block_stride_range_generic<1>;
|
||||
using block_stride_range_z = block_stride_range_generic<2>;
|
||||
|
||||
template <size_type BLOCK_SIZE = 0>
|
||||
using block_stride_range = block_stride_range_generic<0, BLOCK_SIZE>;
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_BLOCK_STRIDE_RANGE_HPP */
|
||||
@@ -0,0 +1,289 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "kernel_dispatcher.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include "../cuda4dnn/kernels/fill_copy.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, std::size_t N>
|
||||
__global__ void concat_vec(
|
||||
Span<T> output, size_type output_axis_size, index_type output_axis_offset,
|
||||
View<T> input, size_type input_axis_size, size_type concat_size)
|
||||
{
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
auto input_vPtr = vector_type::get_pointer(input.data());
|
||||
|
||||
/* we need to copy all the elements of input to some location in the output
|
||||
* we copy blocks of size `total_concat_size` to some location in the output
|
||||
*/
|
||||
const auto total_concat_size = concat_size * input_axis_size;
|
||||
|
||||
for (auto in_idx : grid_stride_range(input.size() / vector_type::size())) {
|
||||
const index_type idx = in_idx * vector_type::size();
|
||||
const index_type concat_num = idx / total_concat_size;
|
||||
const index_type concat_index = idx % total_concat_size;
|
||||
const index_type top_index = concat_index +
|
||||
(concat_num * output_axis_size + output_axis_offset) * concat_size;
|
||||
|
||||
const auto out_idx = top_index / vector_type::size();
|
||||
|
||||
vector_type vec;
|
||||
v_load(vec, input_vPtr[in_idx]);
|
||||
v_store(output_vPtr[out_idx], vec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t Rank>
|
||||
__global__ void concat_with_offsets(
|
||||
Span<T> output, array<size_type, Rank> out_strides, array<index_type, Rank> out_offset,
|
||||
View<T> input, array<size_type, Rank> in_strides)
|
||||
{
|
||||
for (auto i : grid_stride_range(input.size())) {
|
||||
index_type in_index = i / in_strides[0];
|
||||
index_type out_index = out_offset[0] + in_index;
|
||||
index_type oidx = out_index * out_strides[0];
|
||||
for (int j = 1; j < Rank; j++) {
|
||||
in_index = (i % in_strides[j - 1]) / in_strides[j];
|
||||
out_index = out_offset[j] + in_index;
|
||||
oidx += out_index * out_strides[j];
|
||||
}
|
||||
|
||||
output[oidx] = input[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t N> static
|
||||
void launch_vectorized_concat(const Stream& stream,
|
||||
Span<T> output, size_type output_axis_size, index_type output_axis_offset,
|
||||
View<T> input, size_type input_axis_size, size_type concat_size)
|
||||
{
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(input, N));
|
||||
/* more assertions are required to fully check for vectorization possibility; check concat() */
|
||||
|
||||
auto kernel = raw::concat_vec<T, N>;
|
||||
auto policy = make_policy(kernel, input.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, output_axis_size, output_axis_offset, input, input_axis_size, concat_size);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void concat(
|
||||
const Stream& stream,
|
||||
TensorSpan<T> output, std::size_t output_axis_offset,
|
||||
TensorView<T> input, std::size_t axis)
|
||||
{
|
||||
CV_Assert(output.rank() == input.rank());
|
||||
CV_Assert(output_axis_offset < output.get_axis_size(axis));
|
||||
|
||||
/* if axes preceding the concat axis are all singleton, the concat blocks are contiguous
|
||||
* in the output and we can copy each block directly
|
||||
*/
|
||||
if (output.size_range(0, axis) == 1)
|
||||
{
|
||||
auto stride = output.size_range(axis + 1, output.rank());
|
||||
auto sliced_output = Span<T>(output.get() + output_axis_offset * stride, input.size());
|
||||
kernels::copy<T>(stream, sliced_output, input);
|
||||
return;
|
||||
}
|
||||
|
||||
/* let's call the axis of interest as the channel axis for the purpose of the following discussion
|
||||
* even though it can be any axis
|
||||
*
|
||||
* for each batch item:
|
||||
* we move all the channels from the input (which together, for a single batch item, is contiguous)
|
||||
* of a batch item to its corresponding contiguous place in the output
|
||||
*
|
||||
* for a valid vector operation:
|
||||
* - the size of each copy block must be aligned
|
||||
* - input must be aligned
|
||||
* - all the destination locations in the output must be aligned
|
||||
*/
|
||||
std::size_t concat_size = output.size_range(axis + 1, output.rank());
|
||||
|
||||
std::size_t input_axis_size = input.get_axis_size(axis);
|
||||
std::size_t output_axis_size = output.get_axis_size(axis);
|
||||
|
||||
std::size_t copy_block_size = concat_size * input_axis_size;
|
||||
std::size_t copy_block_stride = concat_size * output_axis_size;
|
||||
std::size_t starting_offset = output_axis_offset * concat_size;
|
||||
|
||||
/* in a nutshell, all this concat operation does is copy several blocks of size `copy_block_size`
|
||||
* to the output starting from `starting_offset` with blocks in the output strided by `copy_block_stride`
|
||||
*/
|
||||
|
||||
bool is_aligned_4 = copy_block_size % 4 == 0 && copy_block_stride % 4 == 0 && starting_offset % 4 == 0;
|
||||
bool is_aligned_2 = copy_block_size % 2 == 0 && copy_block_stride % 2 == 0 && starting_offset % 2 == 0;
|
||||
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(input, 4) && is_aligned_4) {
|
||||
launch_vectorized_concat<T, 4>(stream, output, output_axis_size, output_axis_offset, input, input_axis_size, concat_size);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(input, 2) && is_aligned_2) {
|
||||
launch_vectorized_concat<T, 2>(stream, output, output_axis_size, output_axis_offset, input, input_axis_size, concat_size);
|
||||
} else {
|
||||
launch_vectorized_concat<T, 1>(stream, output, output_axis_size, output_axis_offset, input, input_axis_size, concat_size);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void concat<__half>(const Stream&, TensorSpan<__half>, std::size_t, TensorView<__half>, std::size_t);
|
||||
#endif
|
||||
template void concat<float>(const Stream&, TensorSpan<float>, std::size_t, TensorView<float>, std::size_t);
|
||||
template void concat<int8_t>(const Stream&, TensorSpan<int8_t>, std::size_t, TensorView<int8_t>, std::size_t);
|
||||
template void concat<uint8_t>(const Stream&, TensorSpan<uint8_t>, std::size_t, TensorView<uint8_t>, std::size_t);
|
||||
template void concat<int32_t>(const Stream&, TensorSpan<int32_t>, std::size_t, TensorView<int32_t>, std::size_t);
|
||||
template void concat<int64_t>(const Stream&, TensorSpan<int64_t>, std::size_t, TensorView<int64_t>, std::size_t);
|
||||
template void concat<bool>(const Stream&, TensorSpan<bool>, std::size_t, TensorView<bool>, std::size_t);
|
||||
|
||||
template <class T, std::size_t Rank> static
|
||||
void launch_concat_with_offsets(
|
||||
const Stream& stream,
|
||||
Span<T> output, const std::vector<std::size_t>& outStride, const std::vector<std::size_t>& outOffset,
|
||||
View<T> input, const std::vector<std::size_t>& inStride)
|
||||
{
|
||||
CV_Assert(outStride.size() == Rank);
|
||||
CV_Assert(outOffset.size() == Rank);
|
||||
CV_Assert(inStride.size() == Rank);
|
||||
|
||||
array<size_type, Rank> outStride_k, inStride_k;
|
||||
outStride_k.assign(std::begin(outStride), std::end(outStride));
|
||||
inStride_k.assign(std::begin(inStride), std::end(inStride));
|
||||
|
||||
array<index_type, Rank> outOffset_k;
|
||||
outOffset_k.assign(std::begin(outOffset), std::end(outOffset));
|
||||
|
||||
auto kernel = raw::concat_with_offsets<T, Rank>;
|
||||
auto policy = make_policy(kernel, input.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, outStride_k, outOffset_k, input, inStride_k);
|
||||
}
|
||||
|
||||
GENERATE_KERNEL_DISPATCHER(concat_with_offsets_dispatcher, launch_concat_with_offsets);
|
||||
|
||||
template <class T>
|
||||
void concat_with_offsets(
|
||||
const Stream& stream,
|
||||
TensorSpan<T> output, TensorView<T> input,
|
||||
std::vector<std::size_t> offsets)
|
||||
{
|
||||
CV_Assert(output.rank() == input.rank());
|
||||
CV_Assert(output.rank() == offsets.size());
|
||||
|
||||
/* squeezable axes at the beginning of both tensors can be eliminated
|
||||
*
|
||||
* Reasoning:
|
||||
* ----------
|
||||
* Suppose an item's indices in the input tensor is [i1, i2, ...]. The indices in the output
|
||||
* tensor will be [i1 + off1, i2 + off2, ...]. The concat operation essentially copies items
|
||||
* from the input tensor to new locations in the output tensor.
|
||||
*
|
||||
* If the size of the first axis of the input and output tensor is unity, the input and output
|
||||
* indices for all the elements will be of the form be [0, i2, ...] and [0, i2 + off2, ...]
|
||||
* respectively. The first index does not contribute to the element's address calculation and
|
||||
* hence does nothing apart from eating up few cycles.
|
||||
*/
|
||||
while (input.get_axis_size(0) == 1 && output.get_axis_size(0) == 1) {
|
||||
CV_Assert(offsets[0] == 0);
|
||||
|
||||
input.squeeze(0);
|
||||
output.squeeze(0);
|
||||
offsets.erase(std::begin(offsets));
|
||||
|
||||
CV_Assert(output.rank() == input.rank());
|
||||
CV_Assert(output.rank() == offsets.size());
|
||||
}
|
||||
|
||||
auto inShape = input.shape_as_vector();
|
||||
auto outShape = output.shape_as_vector();
|
||||
|
||||
/* contiguous axes that undergo full copy can be combined into one axis
|
||||
*
|
||||
* Reasoning:
|
||||
* ----------
|
||||
* Suppose an item's indices in the input tensor is [i1, i2, i3, ...]. Let the first two axes not undergo any
|
||||
* concatenation. The indices in the output tensor will be [i1, i2, i3 + off3, ...].
|
||||
*
|
||||
* Each axis in the contiguous axes sequence will add an offset of iN * strideN. In the above example,
|
||||
* the two axes add a total offset of `i1 * stride1 + i2 * stride2`. We can merge the two axes into one axis with
|
||||
* a size of `size1 * size2`. The new offset added will be i12 * stride2` as the kernel iterates through `i12`.
|
||||
* Note that `i12` is actually `(i1 * size2 + i2)` in the original tensor.
|
||||
*/
|
||||
for (int i = 0; i < inShape.size(); i++) {
|
||||
/* check if axis `i` requires any slicing */
|
||||
if (offsets[i] == 0 && inShape[i] == outShape[i]) {
|
||||
/* loop invariant: `i` is the first axis in the contiguous unsliced axis sequence */
|
||||
|
||||
int j = i + 1; /* `j` is the axis which we will attempt to merge */
|
||||
while (j < inShape.size() && offsets[j] == 0 && inShape[j] == outShape[j]) {
|
||||
/* `j` axis is also copied fully; merge `i` and `j` */
|
||||
auto new_size = inShape[i] * inShape[j];
|
||||
inShape[i] = new_size;
|
||||
outShape[i] = new_size;
|
||||
offsets[i] = 0; /* redundant */
|
||||
|
||||
/* delete axis `j` */
|
||||
inShape.erase(std::begin(inShape) + j);
|
||||
outShape.erase(std::begin(outShape) + j);
|
||||
offsets.erase(std::begin(offsets) + j);
|
||||
|
||||
/* optimizations should not break the invariants */
|
||||
CV_Assert(inShape.size() == outShape.size());
|
||||
CV_Assert(inShape.size() == offsets.size());
|
||||
CV_Assert(inShape[i] == outShape[i]);
|
||||
CV_Assert(offsets[i] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto rank = inShape.size();
|
||||
|
||||
std::vector<std::size_t> inStride(rank), outStride(rank);
|
||||
inStride.back() = 1;
|
||||
outStride.back() = 1;
|
||||
/* garbage, ..., garbage, 1 */
|
||||
|
||||
std::copy(std::begin(inShape) + 1, std::end(inShape), std::begin(inStride));
|
||||
std::copy(std::begin(outShape) + 1, std::end(outShape), std::begin(outStride));
|
||||
/* dim[0], dim[1], ..., dim[-1], 1 */
|
||||
|
||||
std::partial_sum(inStride.rbegin(), inStride.rend(), inStride.rbegin(), std::multiplies<int>());
|
||||
std::partial_sum(outStride.rbegin(), outStride.rend(), outStride.rbegin(), std::multiplies<int>());
|
||||
/* stride[0], stride[1], ..., stride[-2], 1 */
|
||||
|
||||
CV_Assert(1 <= rank && rank <= CSL_MAX_TENSOR_RANK);
|
||||
concat_with_offsets_dispatcher<T, 1, CSL_MAX_TENSOR_RANK>(rank, stream, output, outStride, offsets, input, inStride);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<__half>, TensorView<__half>, std::vector<std::size_t>);
|
||||
#endif
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<float>, TensorView<float>, std::vector<std::size_t>);
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<int8_t>, TensorView<int8_t>, std::vector<std::size_t>);
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<uint8_t>, TensorView<uint8_t>, std::vector<std::size_t>);
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<int32_t>, TensorView<int32_t>, std::vector<std::size_t>);
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<int64_t>, TensorView<int64_t>, std::vector<std::size_t>);
|
||||
template void concat_with_offsets(const Stream&, TensorSpan<bool>, TensorView<bool>, std::vector<std::size_t>);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,171 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "types.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, std::size_t CHANNELS_PER_ITER>
|
||||
__global__ void crop_and_resize(
|
||||
Span<T> output, size_type out_height, size_type out_width,
|
||||
View<T> input, size_type in_height, size_type in_width,
|
||||
View<T> boxes,
|
||||
size_type num_channels)
|
||||
{
|
||||
// input [1, num_channels, in_height, in_width]
|
||||
// output [boxes, num_channels, out_height, out_width]
|
||||
|
||||
const auto in_image_size = in_height * in_width;
|
||||
const auto out_image_size = out_height * out_width;
|
||||
const auto out_box_size = num_channels * out_image_size;
|
||||
|
||||
/* we have to compute the output value for every combination of (box, c, y, x) in the output
|
||||
*
|
||||
* the computation involving (y, x) are identical for all non-spatial dimensions
|
||||
* the computation and memory requests involving the box are identical for remaining three axes
|
||||
*
|
||||
* we process multiple channels every iteration to reuse the identical computation
|
||||
* and memory requests involved with the box and spatial dimensions
|
||||
*/
|
||||
|
||||
/*
|
||||
* if we are processing `CHANNELS_PER_ITER` channels per iteration, we will need
|
||||
* (num_channels / CHANNELS_PER_ITER) iterations per (box, x, y)
|
||||
*/
|
||||
auto num_channel_iters_per_box_xy = num_channels / CHANNELS_PER_ITER;
|
||||
|
||||
/* we need `num_channel_iters_per_box_xy` iterations per (box, x, y) and there are
|
||||
* `num_boxes` boxes and `out_image_size` combinations of (x, y)
|
||||
*/
|
||||
auto num_boxes = boxes.size() / 7; /* 7 values per box */
|
||||
auto iters_per_box = num_channel_iters_per_box_xy * out_image_size;
|
||||
auto iters_required = num_boxes * iters_per_box;
|
||||
|
||||
for (auto iter : grid_stride_range(iters_required)) {
|
||||
const index_type box_no = iter / iters_per_box;
|
||||
const index_type c_start = ((iter % iters_per_box) / out_image_size) * CHANNELS_PER_ITER;
|
||||
|
||||
/* note here that consecutive `iter` values will often have consecutive `x` values
|
||||
* => stores into output will be coalesced across threads
|
||||
*/
|
||||
const index_type y = (iter % out_image_size) / out_width;
|
||||
const index_type x = iter % out_width;
|
||||
|
||||
const index_type box_offset = box_no * 7;
|
||||
const auto left = boxes[box_offset + 3],
|
||||
top = boxes[box_offset + 4],
|
||||
right = boxes[box_offset + 5],
|
||||
bottom = boxes[box_offset + 6];
|
||||
|
||||
const auto box_width = right - left;
|
||||
const auto box_height = bottom - top;
|
||||
|
||||
const auto o2i_fy = static_cast<T>(in_height - 1) / static_cast<T>(out_height - 1);
|
||||
const auto o2i_fx = static_cast<T>(in_width - 1) / static_cast<T>(out_width - 1);
|
||||
|
||||
const auto height_scale = box_height * o2i_fy;
|
||||
const auto width_scale = box_width * o2i_fx;
|
||||
|
||||
const auto in_y = top * static_cast<T>(in_height - 1) + static_cast<T>(y) * height_scale;
|
||||
const auto in_x = left * static_cast<T>(in_width - 1) + static_cast<T>(x) * width_scale;
|
||||
|
||||
const auto in_y0 = static_cast<index_type>(in_y);
|
||||
const auto in_x0 = static_cast<index_type>(in_x);
|
||||
|
||||
using device::min;
|
||||
const auto in_x1 = min<index_type>(in_x0 + 1, in_width - 1);
|
||||
const auto in_y1 = min<index_type>(in_y0 + 1, in_height - 1);
|
||||
|
||||
index_type in_offset_r0 = c_start * in_image_size + in_y0 * in_width;
|
||||
index_type in_offset_r1 = c_start * in_image_size + in_y1 * in_width;
|
||||
index_type out_idx = box_no * out_box_size + c_start * out_image_size + y * out_width + x;
|
||||
|
||||
#pragma unroll 1 /* disable unrolling */
|
||||
for (int i = 0; i < CHANNELS_PER_ITER; i++) {
|
||||
auto v_00 = load_ldg(input[in_offset_r0 + in_x0]),
|
||||
v_01 = load_ldg(input[in_offset_r0 + in_x1]),
|
||||
v_10 = load_ldg(input[in_offset_r1 + in_x0]),
|
||||
v_11 = load_ldg(input[in_offset_r1 + in_x1]);
|
||||
|
||||
output[out_idx] =
|
||||
v_00 +
|
||||
T(in_y - T(in_y0)) * T(v_10 - v_00) +
|
||||
T(in_x - T(in_x0)) * T(v_01 - v_00) +
|
||||
T(in_y - T(in_y0)) * T(in_x - T(in_x0)) * T(v_11 - v_01 - v_10 + v_00);
|
||||
|
||||
in_offset_r0 += in_image_size;
|
||||
in_offset_r1 += in_image_size;
|
||||
out_idx += out_image_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t CHANNELS_PER_ITER> static
|
||||
void launch_multichannel_crop_and_resize(const Stream& stream,
|
||||
Span<T> output, size_type out_height, size_type out_width,
|
||||
View<T> input, size_type in_height, size_type in_width,
|
||||
View<T> boxes, size_type num_channels)
|
||||
{
|
||||
auto kernel = raw::crop_and_resize<T, CHANNELS_PER_ITER>;
|
||||
auto policy = make_policy(kernel, output.size() / CHANNELS_PER_ITER, 0, stream);
|
||||
launch_kernel(kernel, policy, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void crop_and_resize(const Stream& stream, TensorSpan<T> output, TensorView<T> input, View<T> boxes) {
|
||||
CV_Assert(input.get_axis_size(0) == 1); /* batch not supported */
|
||||
CV_Assert(input.get_axis_size(1) == output.get_axis_size(1));
|
||||
|
||||
auto out_height = output.get_axis_size(-2);
|
||||
auto out_width = output.get_axis_size(-1);
|
||||
|
||||
auto in_height = input.get_axis_size(-2);
|
||||
auto in_width = input.get_axis_size(-1);
|
||||
|
||||
auto num_channels = input.get_axis_size(1);
|
||||
|
||||
if (num_channels % 64 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 64>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else if (num_channels % 32 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 32>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else if (num_channels % 16 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 16>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else if (num_channels % 8 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 8>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else if (num_channels % 4 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 4>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else if (num_channels % 2 == 0) {
|
||||
launch_multichannel_crop_and_resize<T, 2>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
} else {
|
||||
launch_multichannel_crop_and_resize<T, 1>(stream, output, out_height, out_width, input, in_height, in_width, boxes, num_channels);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void crop_and_resize<__half>(const Stream&, TensorSpan<__half>, TensorView<__half>, View<__half> boxes);
|
||||
#endif
|
||||
template void crop_and_resize<float>(const Stream&, TensorSpan<float>, TensorView<float>, View<float> boxes);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,897 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "bbox_utils.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "block_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, bool SHARE_LOCATION, bool VARIANCE_ENCODED_IN_TARGET, bool CORNER_TRUE_CENTER_FALSE, bool CLIP_BBOX>
|
||||
__global__ void decode_bbox(Span<T> decoded_bboxes, View<T> locations, View<T> priors,
|
||||
bool transpose_location, bool normalized_bbox,
|
||||
size_type num_loc_classes, index_type background_class_id,
|
||||
float clip_width, float clip_height)
|
||||
{
|
||||
// decoded_bboxes: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// locations: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// priors: [1, C, num_priors, 4]
|
||||
// C = 2 if !VARIANCE_ENCODED_IN_TARGET; otherwise, 1
|
||||
|
||||
/* 4 bbox values + 4 variance values per prior */
|
||||
constexpr int PRIOR_BOX_SIZE = VARIANCE_ENCODED_IN_TARGET ? 4 : 8;
|
||||
const size_type num_priors = priors.size() / PRIOR_BOX_SIZE;
|
||||
|
||||
using vector_type = get_vector_type_t<T, 4>;
|
||||
auto locations_vPtr = vector_type::get_pointer(locations.data());
|
||||
auto priors_vPtr = vector_type::get_pointer(priors.data());
|
||||
auto decoded_bboxes_vPtr = vector_type::get_pointer(decoded_bboxes.data());
|
||||
|
||||
const auto boxes_per_batch = num_priors * num_loc_classes;
|
||||
for (auto idx : grid_stride_range(decoded_bboxes.size() / 4))
|
||||
{
|
||||
index_type p;
|
||||
index_type c;
|
||||
|
||||
if (SHARE_LOCATION)
|
||||
{
|
||||
// locations are shared across all classes => num_loc_classes = 1
|
||||
p = idx % boxes_per_batch;
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (idx % boxes_per_batch) / num_loc_classes;
|
||||
c = idx % num_loc_classes;
|
||||
}
|
||||
|
||||
if (!SHARE_LOCATION && c == background_class_id)
|
||||
continue;
|
||||
|
||||
BoundingBox bbox;
|
||||
{
|
||||
vector_type location;
|
||||
v_load(location, locations_vPtr[idx]);
|
||||
|
||||
if (transpose_location)
|
||||
{
|
||||
bbox.ymin = location.data[0];
|
||||
bbox.xmin = location.data[1];
|
||||
bbox.ymax = location.data[2];
|
||||
bbox.xmax = location.data[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox.xmin = location.data[0];
|
||||
bbox.ymin = location.data[1];
|
||||
bbox.xmax = location.data[2];
|
||||
bbox.ymax = location.data[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (!VARIANCE_ENCODED_IN_TARGET)
|
||||
{
|
||||
vector_type prior_variance;
|
||||
v_load_ldg(prior_variance, priors_vPtr[num_priors + p]);
|
||||
|
||||
bbox.xmin *= static_cast<float>(prior_variance.data[0]);
|
||||
bbox.ymin *= static_cast<float>(prior_variance.data[1]);
|
||||
bbox.xmax *= static_cast<float>(prior_variance.data[2]);
|
||||
bbox.ymax *= static_cast<float>(prior_variance.data[3]);
|
||||
}
|
||||
|
||||
BoundingBox prior;
|
||||
{
|
||||
vector_type prior_box;
|
||||
v_load_ldg(prior_box, priors_vPtr[p]);
|
||||
|
||||
prior.xmin = prior_box.data[0];
|
||||
prior.ymin = prior_box.data[1];
|
||||
prior.xmax = prior_box.data[2];
|
||||
prior.ymax = prior_box.data[3];
|
||||
}
|
||||
|
||||
BoundingBox decoded_bbox;
|
||||
if (CORNER_TRUE_CENTER_FALSE)
|
||||
{
|
||||
decoded_bbox.xmin = prior.xmin + bbox.xmin;
|
||||
decoded_bbox.ymin = prior.ymin + bbox.ymin;
|
||||
decoded_bbox.xmax = prior.xmax + bbox.xmax;
|
||||
decoded_bbox.ymax = prior.ymax + bbox.ymax;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto prior_width = prior.xmax - prior.xmin;
|
||||
auto prior_height = prior.ymax - prior.ymin;
|
||||
if (!normalized_bbox)
|
||||
{
|
||||
prior_width += 1;
|
||||
prior_height += 1;
|
||||
}
|
||||
|
||||
auto prior_center_x = prior.xmin + prior_width * 0.5f;
|
||||
auto prior_center_y = prior.ymin + prior_height * 0.5f;
|
||||
|
||||
auto decode_bbox_center_x = bbox.xmin * prior_width + prior_center_x;
|
||||
auto decode_bbox_center_y = bbox.ymin * prior_height + prior_center_y;
|
||||
|
||||
using device::exp;
|
||||
float decode_bbox_width = exp(bbox.xmax) * prior_width;
|
||||
float decode_bbox_height = exp(bbox.ymax) * prior_height;
|
||||
|
||||
decoded_bbox.xmin = decode_bbox_center_x - decode_bbox_width * 0.5f;
|
||||
decoded_bbox.ymin = decode_bbox_center_y - decode_bbox_height * 0.5f;
|
||||
decoded_bbox.xmax = decode_bbox_center_x + decode_bbox_width * 0.5f;
|
||||
decoded_bbox.ymax = decode_bbox_center_y + decode_bbox_height * 0.5f;
|
||||
}
|
||||
|
||||
vector_type decoded_bbox_vec;
|
||||
if (CLIP_BBOX)
|
||||
{
|
||||
decoded_bbox_vec.data[0] = clamp(decoded_bbox.xmin, 0.0f, clip_width);
|
||||
decoded_bbox_vec.data[1] = clamp(decoded_bbox.ymin, 0.0f, clip_height);
|
||||
decoded_bbox_vec.data[2] = clamp(decoded_bbox.xmax, 0.0f, clip_width);
|
||||
decoded_bbox_vec.data[3] = clamp(decoded_bbox.ymax, 0.0f, clip_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded_bbox_vec.data[0] = decoded_bbox.xmin;
|
||||
decoded_bbox_vec.data[1] = decoded_bbox.ymin;
|
||||
decoded_bbox_vec.data[2] = decoded_bbox.xmax;
|
||||
decoded_bbox_vec.data[3] = decoded_bbox.ymax;
|
||||
}
|
||||
|
||||
v_store(decoded_bboxes_vPtr[idx], decoded_bbox_vec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, int BINS, int BLOCK_SIZE>
|
||||
__launch_bounds__(BLOCK_SIZE)
|
||||
__global__ void findTopK(Span<int> indices_, Span<int> count_, View<T> scores_, float threshold, size_type classwise_topK, size_type num_classes, size_type num_priors, index_type background_class_id)
|
||||
{
|
||||
/* We need to sort boxes based on their confidence scores. The confidence scores fall in
|
||||
* the range [0.0, 1.0]. We break the range into bins and perform count sort. This is an
|
||||
* approximate algorithm.
|
||||
*
|
||||
* Each block handles a particular class of a particular batch item.
|
||||
*/
|
||||
const auto c = blockIdx.x;
|
||||
const auto b = blockIdx.y;
|
||||
|
||||
if (c == background_class_id)
|
||||
return;
|
||||
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
auto count = count_.data() + b * num_classes + c;
|
||||
auto scores = scores_.data() + (b * num_classes + c) * num_priors;
|
||||
auto indices = indices_.data() + (b * num_classes + c) * classwise_topK;
|
||||
|
||||
/* We do not require a large number of bins to find the top K confidence scores. We will use
|
||||
* a reasonable number of bins which will fit in the shared memory.
|
||||
*
|
||||
* Note that smaller scores will have a smaller index, i.e. the `bins` are ordered in
|
||||
* ascending order.
|
||||
*/
|
||||
|
||||
__shared__ int bins[BINS];
|
||||
|
||||
#pragma unroll
|
||||
for (int unroll = 0; unroll < BINS / BLOCK_SIZE; unroll++)
|
||||
bins[unroll * BLOCK_SIZE + threadIdx.x] = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (auto i : block_stride_range<BLOCK_SIZE>(num_priors))
|
||||
{
|
||||
const float confidence = load_ldg(scores[i]);
|
||||
if (confidence > threshold)
|
||||
{
|
||||
using device::fast_divide_ftz;
|
||||
auto conf_scaled = fast_divide_ftz(confidence - threshold, 1 - threshold);
|
||||
|
||||
using device::clamp;
|
||||
int bin_index = conf_scaled * BINS;
|
||||
|
||||
/* We store counts of confidence scores in the bins. Our ultimate goal is to store the indices
|
||||
* of the `classwise_topK` confidence values in the `indices` array.
|
||||
*
|
||||
* We use a little trick to parallelize the process of filling up the `indices` array.
|
||||
* We want every thread in the block to participate in the process. To do so, we want the
|
||||
* bins array to be shifted by one place to the left. We will be computing the suffix sum
|
||||
* of the bins array later. Details and reasons for doing so will be explained later.
|
||||
*/
|
||||
bin_index = clamp<int>(bin_index, 0, BINS - 1) - 1; // shift left by one
|
||||
|
||||
if (bin_index >= 0)
|
||||
atomicAdd(&bins[bin_index], 1);
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
constexpr int WARP_SIZE = 32; /* must be equal to warpSize */
|
||||
// FORWARD_COMPATIBILITY_TAG: WARP_SIZE_DEPENDENT_CODE
|
||||
|
||||
if (threadIdx.x < WARP_SIZE)
|
||||
{
|
||||
/* We can compute suffix sum of an array in groups of N numbers.
|
||||
* Let N be 4 for this example.
|
||||
*
|
||||
* 1) Last 4 numbers
|
||||
* 1 2 3 4 | 5 6 7 8 | 9 10 11 12
|
||||
* group suffix sum: 42 33 23 12
|
||||
*
|
||||
* 2) Middle 4 numbers
|
||||
* 1 2 3 4 | 5 6 7 8 | 9 10 11 12
|
||||
* group suffix sum: | 26 21 15 8 |
|
||||
*
|
||||
* We add `42` (first element in the previous group) to each element to get:
|
||||
*
|
||||
* 1 2 3 4 | 5 6 7 8 | 9 10 11 12
|
||||
* | 68 63 57 50 | 42 33 23 12
|
||||
* 3) First 4 numbers
|
||||
*
|
||||
* 1 2 3 4 | 5 6 7 8 | 9 10 11 12
|
||||
* group suffix sum: 10 9 7 4 |
|
||||
*
|
||||
* We add `68` (first element in the previous group) to each element to get:
|
||||
*
|
||||
* 1 2 3 4 | 5 6 7 8 | 9 10 11 12
|
||||
* group suffix sum: 78 77 75 72 | 68 63 57 50 | 42 33 23 12
|
||||
*
|
||||
* What we are left with now is the suffix sum of the entire array.
|
||||
*
|
||||
* We use the aforementioned logic in the code below but work in groups of `warpSize`.
|
||||
*/
|
||||
|
||||
/* We calculate suffix sums WARP_SIZE elements at a time starting from the right end.
|
||||
* Hence, we will need BINS / WARP_SIZE number of iterations.
|
||||
*
|
||||
* Each iteration uses shuffle instructions to exchange data between threads. Shuffle
|
||||
* instructions cannot be used in warp-divergent code. If the bins are a multiple of
|
||||
* the warpSize, all the threads in the warp will participate.
|
||||
*/
|
||||
static_assert(BINS % WARP_SIZE == 0, "number of bins must be a multiple of warp size");
|
||||
|
||||
const int thread_id = threadIdx.x;
|
||||
const int inverse_lane_id = WARP_SIZE - thread_id - 1;
|
||||
|
||||
int previous_group_first_element = 0;
|
||||
for (int iter = BINS / WARP_SIZE - 1; iter >= 0; iter--)
|
||||
{
|
||||
const index_type idx = iter * WARP_SIZE + thread_id;
|
||||
auto value = bins[idx];
|
||||
|
||||
for (int i = 1; i < WARP_SIZE; i *= 2)
|
||||
{
|
||||
auto n = __shfl_down_sync(0xFFFFFFFF, value, i);
|
||||
if (inverse_lane_id >= i)
|
||||
value += n;
|
||||
}
|
||||
|
||||
value += previous_group_first_element;
|
||||
bins[idx] = value;
|
||||
|
||||
previous_group_first_element = __shfl_sync(0xFFFFFFFF, value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
*count = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (auto i : block_stride_range<BLOCK_SIZE>(num_priors))
|
||||
{
|
||||
const float confidence = load_ldg(scores[i]);
|
||||
if (confidence > threshold)
|
||||
{
|
||||
using device::fast_divide_ftz;
|
||||
auto conf_scaled = fast_divide_ftz(confidence - threshold, 1 - threshold);
|
||||
|
||||
int bin_index = conf_scaled * BINS;
|
||||
bin_index = clamp<int>(bin_index, 0, BINS - 1);
|
||||
|
||||
/* This bounding box is eligible to be selected unless it does not fall in
|
||||
* the `classwise_topK`. If it did, we would have to compute the location where it needs
|
||||
* to be stored.
|
||||
*
|
||||
* Suppose we had just 4 bins and say the following were the counts:
|
||||
* BIN0 2
|
||||
* BIN1 1
|
||||
* BIN2 3
|
||||
* BIN3 0 (last bin is always zero as we shift left by one while populating the bins)
|
||||
*
|
||||
* We will try our best to store the boxes in a sorted order in the `indices` array.
|
||||
* This requires that the boxes in later bins (higher confidence scores) must be
|
||||
* stored earlier.
|
||||
*
|
||||
* We compute the suffix sum of the array. This gives us:
|
||||
* BIN0 6
|
||||
* BIN1 4
|
||||
* BIN2 3
|
||||
* BIN3 0
|
||||
*
|
||||
* The bins now give us the location in the `indices` array from which the indices of the
|
||||
* scores corresponding to that bin would be stored. We atomically increment the bin count
|
||||
* everytime we store a box corresponding to that bin. Therefore, the value in the bins
|
||||
* gives the index in the `indices` array where the next box corresponding to that bin must
|
||||
* be put.
|
||||
*/
|
||||
|
||||
const index_type idx = atomicAdd(&bins[bin_index], 1);
|
||||
if (idx < classwise_topK)
|
||||
{
|
||||
indices[idx] = i;
|
||||
atomicAdd(&count[0], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void box_collect(Span<T> collected_bboxes_, View<T> decoded_bboxes_, View<int> indices_, View<int> count_, bool share_location, size_type num_priors, size_type num_classes, size_type classwise_topK, index_type background_class_id)
|
||||
{
|
||||
const index_type c = blockIdx.x;
|
||||
if (c == background_class_id)
|
||||
return;
|
||||
|
||||
const index_type b = blockIdx.y;
|
||||
|
||||
// collected_bboxes: [batch_size, num_classes, classwise_topK, 4]
|
||||
// decoded_bboxes: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
|
||||
const auto num_loc_classes = share_location ? 1 : num_classes;
|
||||
|
||||
auto collected_bboxes = collected_bboxes_.data() + (b * num_classes + c) * classwise_topK * 4;
|
||||
auto decoded_bboxes = decoded_bboxes_.data() + b * num_priors * num_loc_classes * 4;
|
||||
auto indices = indices_.data() + (b * num_classes + c) * classwise_topK;
|
||||
auto count = count_.data() + b * num_classes + c;
|
||||
|
||||
const auto boxes = load_ldg(&count[0]);
|
||||
if (boxes == 0)
|
||||
return;
|
||||
|
||||
using vector_type = get_vector_type_t<T, 4>;
|
||||
auto decoded_bboxes_vPtr = vector_type::get_pointer(decoded_bboxes);
|
||||
auto collected_bboxes_vPtr = vector_type::get_pointer(collected_bboxes);
|
||||
|
||||
for (auto i : block_stride_range<>(boxes))
|
||||
{
|
||||
const auto prior_id = indices[i];
|
||||
const index_type idx = share_location ? prior_id : (prior_id * num_classes + c);
|
||||
|
||||
vector_type box;
|
||||
v_load(box, decoded_bboxes_vPtr[idx]);
|
||||
v_store(collected_bboxes_vPtr[i], box);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, bool NORMALIZED_BBOX>
|
||||
__global__ void blockwise_class_nms(Span<int> indices_, Span<int> count_, View<T> collected_bboxes_, size_type num_classes, size_type classwise_topK, index_type background_class_id, float nms_threshold)
|
||||
{
|
||||
const index_type b = blockIdx.x / num_classes;
|
||||
const index_type c = blockIdx.x % num_classes;
|
||||
if (c == background_class_id)
|
||||
return;
|
||||
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// collected_bboxes: [batch_size, num_classes, classwise_topK, 4]
|
||||
|
||||
auto indices = indices_.data() + (b * num_classes + c) * classwise_topK;
|
||||
auto count = count_.data() + b * num_classes + c;
|
||||
auto collected_bboxes = collected_bboxes_.data() + (b * num_classes + c) * classwise_topK * 4;
|
||||
|
||||
const auto boxes = count[0];
|
||||
if (boxes == 0)
|
||||
return;
|
||||
|
||||
using vector_type = get_vector_type_t<T, 4>;
|
||||
auto collected_bboxes_vPtr = vector_type::get_pointer(collected_bboxes);
|
||||
|
||||
for (int i = 0; i < boxes; i++)
|
||||
{
|
||||
auto prior_id = indices[i];
|
||||
if (prior_id != -1)
|
||||
{
|
||||
BoundingBox bbox1;
|
||||
{
|
||||
vector_type box;
|
||||
v_load(box, collected_bboxes_vPtr[i]);
|
||||
|
||||
bbox1.xmin = box.data[0];
|
||||
bbox1.ymin = box.data[1];
|
||||
bbox1.xmax = box.data[2];
|
||||
bbox1.ymax = box.data[3];
|
||||
}
|
||||
|
||||
for (auto j : block_stride_range<>(i + 1, boxes))
|
||||
{
|
||||
prior_id = indices[j];
|
||||
if (prior_id == -1)
|
||||
continue;
|
||||
|
||||
BoundingBox bbox2;
|
||||
{
|
||||
vector_type box;
|
||||
v_load_ldg(box, collected_bboxes_vPtr[j]);
|
||||
|
||||
bbox2.xmin = box.data[0];
|
||||
bbox2.ymin = box.data[1];
|
||||
bbox2.xmax = box.data[2];
|
||||
bbox2.ymax = box.data[3];
|
||||
}
|
||||
|
||||
using device::min;
|
||||
using device::max;
|
||||
|
||||
BoundingBox intersect_bbox;
|
||||
intersect_bbox.xmin = max(bbox1.xmin, bbox2.xmin);
|
||||
intersect_bbox.ymin = max(bbox1.ymin, bbox2.ymin);
|
||||
intersect_bbox.xmax = min(bbox1.xmax, bbox2.xmax);
|
||||
intersect_bbox.ymax = min(bbox1.ymax, bbox2.ymax);
|
||||
|
||||
float intersect_size = compute_bbox_size<NORMALIZED_BBOX>(intersect_bbox);
|
||||
float bbox1_size = compute_bbox_size<NORMALIZED_BBOX>(bbox1);
|
||||
float bbox2_size = compute_bbox_size<NORMALIZED_BBOX>(bbox2);
|
||||
|
||||
using device::fast_divide_ftz;
|
||||
float iou = fast_divide_ftz(intersect_size, bbox1_size + bbox2_size - intersect_size);
|
||||
if (iou > nms_threshold)
|
||||
indices[j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
count[0] = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (auto i : block_stride_range<>(boxes))
|
||||
{
|
||||
auto prior_id = indices[i];
|
||||
if(prior_id != -1)
|
||||
{
|
||||
const index_type idx = atomicAdd(&count[0], 1);
|
||||
indices[idx] = prior_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t BINS, int BLOCK_SIZE>
|
||||
__launch_bounds__(BLOCK_SIZE)
|
||||
__global__ void nms_collect(
|
||||
Span<int> kept_indices, Span<int> kept_count, View<int> indices_, View<int> count, View<T> scores_, float threshold,
|
||||
size_type num_classes, size_type num_priors, size_type classwise_topK, size_type keepTopK, index_type background_class_id)
|
||||
{
|
||||
// sorting algorithm is documented in detail in findTopK kernel comments
|
||||
// no explanations are provided here
|
||||
|
||||
// kept_indices: [batch_size, keepTopK]
|
||||
// kept_count: [batch_size]
|
||||
|
||||
const auto b = blockIdx.x;
|
||||
|
||||
__shared__ int bins[BINS];
|
||||
|
||||
#pragma unroll
|
||||
for (int unroll = 0; unroll < BINS / BLOCK_SIZE; unroll++)
|
||||
bins[unroll * BLOCK_SIZE + threadIdx.x] = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int c = 0; c < num_classes; c++)
|
||||
{
|
||||
if (c == background_class_id)
|
||||
continue;
|
||||
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
const auto indices = indices_.data() + (b * num_classes + c) * classwise_topK;
|
||||
const auto scores = scores_.data() + (b * num_classes + c) * num_priors;
|
||||
|
||||
auto boxes = count[b * num_classes + c];
|
||||
|
||||
for (auto i : block_stride_range<BLOCK_SIZE>(boxes))
|
||||
{
|
||||
auto prior_id = indices[i];
|
||||
const float confidence = load_ldg(scores[prior_id]);
|
||||
if (confidence > threshold)
|
||||
{
|
||||
using device::fast_divide_ftz;
|
||||
auto conf_scaled = fast_divide_ftz(confidence - threshold, 1 - threshold);
|
||||
|
||||
using device::clamp;
|
||||
int bin_index = conf_scaled * BINS;
|
||||
bin_index = clamp<int>(bin_index, 0, BINS - 1) - 1; // shift left by one
|
||||
|
||||
if (bin_index >= 0)
|
||||
atomicAdd(&bins[bin_index], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
constexpr int WARP_SIZE = 32; /* must be equal to warpSize */
|
||||
// FORWARD_COMPATIBILITY_TAG: WARP_SIZE_DEPENDENT_CODE
|
||||
|
||||
if (threadIdx.x < WARP_SIZE)
|
||||
{
|
||||
static_assert(BINS % WARP_SIZE == 0, "number of bins must be a multiple of warp size");
|
||||
|
||||
const int thread_id = threadIdx.x;
|
||||
const int inverse_lane_id = WARP_SIZE - thread_id - 1;
|
||||
|
||||
int previous_group_first_element = 0;
|
||||
for (int iter = BINS / WARP_SIZE - 1; iter >= 0; iter--)
|
||||
{
|
||||
const index_type idx = iter * WARP_SIZE + thread_id;
|
||||
auto value = bins[idx];
|
||||
|
||||
for (int i = 1; i < WARP_SIZE; i *= 2)
|
||||
{
|
||||
auto n = __shfl_down_sync(0xFFFFFFFF, value, i);
|
||||
if (inverse_lane_id >= i)
|
||||
value += n;
|
||||
}
|
||||
|
||||
value += previous_group_first_element;
|
||||
bins[idx] = value;
|
||||
|
||||
previous_group_first_element = __shfl_sync(0xFFFFFFFF, value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
kept_count[b] = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int c = 0; c < num_classes; c++)
|
||||
{
|
||||
if (c == background_class_id)
|
||||
continue;
|
||||
|
||||
const auto indices = indices_.data() + (b * num_classes + c) * classwise_topK;
|
||||
const auto scores = scores_.data() + (b * num_classes + c) * num_priors;
|
||||
|
||||
auto boxes = count[b * num_classes + c];
|
||||
|
||||
for (auto i : block_stride_range<BLOCK_SIZE>(boxes))
|
||||
{
|
||||
auto prior_id = indices[i];
|
||||
const float confidence = load_ldg(scores[prior_id]);
|
||||
if (confidence > threshold)
|
||||
{
|
||||
using device::fast_divide_ftz;
|
||||
auto conf_scaled = fast_divide_ftz(confidence - threshold, 1 - threshold);
|
||||
|
||||
using device::clamp;
|
||||
int bin_index = conf_scaled * BINS;
|
||||
bin_index = clamp<int>(bin_index, 0, BINS - 1);
|
||||
|
||||
const index_type idx = atomicAdd(&bins[bin_index], 1);
|
||||
if (idx < keepTopK)
|
||||
{
|
||||
kept_indices[b * keepTopK + idx] = c * num_priors + prior_id;
|
||||
atomicAdd(&kept_count[b], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void consolidate_detections(Span<T> output,
|
||||
View<int> kept_indices, View<int> kept_count, View<T> decoded_bboxes, View<T> scores, bool share_location,
|
||||
size_type batch_size, size_type num_classes, size_type num_priors, size_type keepTopK, DevicePtr<int> num_detections)
|
||||
{
|
||||
using vector_type = get_vector_type_t<T, 4>;
|
||||
auto decoded_bboxes_vPtr = vector_type::get_pointer(decoded_bboxes.data());
|
||||
|
||||
// output: [1, 1, batch_size * keepTopK, 7]
|
||||
// kept_indices: [batch_size, keepTopK]
|
||||
// kept_count: [batch_size]
|
||||
// decoded_bboxes: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
for (int b = 0; b < batch_size; b++)
|
||||
{
|
||||
for (auto i : grid_stride_range(kept_count[b]))
|
||||
{
|
||||
auto score_id = kept_indices[b * keepTopK + i];
|
||||
auto c = score_id / num_priors;
|
||||
auto prior_id = score_id % num_priors;
|
||||
|
||||
const auto confidence = scores[b * num_classes * num_priors + score_id];
|
||||
|
||||
index_type bbox_id;
|
||||
if (share_location)
|
||||
{
|
||||
// decoded_bboxes: [batch_size, num_priors, 1, 4]
|
||||
bbox_id = b * num_priors + prior_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// decoded_bboxes: [batch_size, num_priors, num_classes, 4]
|
||||
bbox_id = (b * num_priors + prior_id) * num_classes + c;
|
||||
}
|
||||
|
||||
vector_type bbox;
|
||||
v_load(bbox, decoded_bboxes_vPtr[bbox_id]);
|
||||
|
||||
auto output_id = atomicAdd(num_detections.get(), 1);
|
||||
output[output_id * 7 + 0] = b;
|
||||
output[output_id * 7 + 1] = c;
|
||||
output[output_id * 7 + 2] = confidence;
|
||||
output[output_id * 7 + 3] = bbox.data[0];
|
||||
output[output_id * 7 + 4] = bbox.data[1];
|
||||
output[output_id * 7 + 5] = bbox.data[2];
|
||||
output[output_id * 7 + 6] = bbox.data[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, bool SHARE_LOCATION, bool VARIANCE_ENCODED_IN_TARGET, bool CORNER_TRUE_CENTER_FALSE, bool CLIP_BBOX> static
|
||||
void launch_decode_boxes_kernel(const Stream& stream, Span<T> decoded_bboxes, View<T> locations, View<T> priors,
|
||||
bool transpose_location, bool normalized_bbox,
|
||||
size_type num_loc_classes, index_type background_class_id,
|
||||
float clip_width, float clip_height)
|
||||
{
|
||||
auto kernel = raw::decode_bbox<T, SHARE_LOCATION, VARIANCE_ENCODED_IN_TARGET, CORNER_TRUE_CENTER_FALSE, CLIP_BBOX>;
|
||||
auto policy = make_policy(kernel, decoded_bboxes.size() / 4, 0, stream);
|
||||
launch_kernel(kernel, policy, decoded_bboxes, locations, priors, transpose_location, normalized_bbox, num_loc_classes, background_class_id, clip_width, clip_height);
|
||||
}
|
||||
|
||||
template <class T, unsigned int current, class ...Args> static
|
||||
typename std::enable_if<current == 0, void>
|
||||
::type dispatch_decode_bboxes(int selector, Args&& ...args) {
|
||||
if(selector == 0)
|
||||
launch_decode_boxes_kernel<T, 0, 0, 0, 0>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T, unsigned int current, class ...Args> static
|
||||
typename std::enable_if<current != 0, void>
|
||||
::type dispatch_decode_bboxes(int selector, Args&& ...args) {
|
||||
if(selector == current)
|
||||
launch_decode_boxes_kernel<T,
|
||||
static_cast<bool>(current & 8),
|
||||
static_cast<bool>(current & 4),
|
||||
static_cast<bool>(current & 2),
|
||||
static_cast<bool>(current & 1)>(std::forward<Args>(args)...);
|
||||
else
|
||||
dispatch_decode_bboxes<T, current - 1, Args...>(selector, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void decode_bboxes(const Stream& stream, Span<T> output, View<T> locations, View<T> priors,
|
||||
std::size_t num_loc_classes,
|
||||
bool share_location, std::size_t background_class_id,
|
||||
bool transpose_location, bool variance_encoded_in_target,
|
||||
bool corner_true_or_center_false, bool normalized_bbox,
|
||||
bool clip_box, float clip_width, float clip_height)
|
||||
{
|
||||
/* `config` combines three kernel template options into one number using which a bit of TMP code can
|
||||
* run through all possible combinations and instantiate the correct template
|
||||
*/
|
||||
unsigned int config = (share_location << 3 | variance_encoded_in_target << 2 | corner_true_or_center_false << 1 | clip_box);
|
||||
dispatch_decode_bboxes<T, 15>(config, stream, output, locations, priors, transpose_location, normalized_bbox, num_loc_classes, background_class_id, clip_width, clip_height);
|
||||
}
|
||||
|
||||
template void decode_bboxes(const Stream&, Span<__half>, View<__half>, View<__half>, std::size_t, bool, std::size_t, bool, bool, bool, bool, bool, float, float);
|
||||
template void decode_bboxes(const Stream&, Span<float>, View<float>, View<float>, std::size_t, bool, std::size_t, bool, bool, bool, bool, bool, float, float);
|
||||
|
||||
template <class T>
|
||||
void findTopK(const Stream& stream, TensorSpan<int> indices, TensorSpan<int> count, TensorView<T> scores, std::size_t background_class_id, float threshold)
|
||||
{
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
const auto batch_size = indices.get_axis_size(0);
|
||||
CV_Assert(count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(scores.get_axis_size(0) == batch_size);
|
||||
|
||||
const auto num_classes = indices.get_axis_size(1);
|
||||
CV_Assert(count.get_axis_size(1) == num_classes);
|
||||
CV_Assert(scores.get_axis_size(1) == num_classes);
|
||||
|
||||
const auto classwise_topK = indices.get_axis_size(2);
|
||||
const auto num_priors = scores.get_axis_size(2);
|
||||
|
||||
/* each block processes one class from each batch */
|
||||
constexpr auto BLOCK_SIZE = 256;
|
||||
|
||||
dim3 grid_size(num_classes, batch_size);
|
||||
dim3 block_size(BLOCK_SIZE);
|
||||
auto policy = execution_policy(grid_size, block_size, stream);
|
||||
|
||||
auto kernel = raw::findTopK<T, 2048, BLOCK_SIZE>;
|
||||
launch_kernel(kernel, policy, indices, count, scores, threshold, classwise_topK, num_classes, num_priors, background_class_id);
|
||||
}
|
||||
|
||||
template void findTopK(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<__half>, std::size_t, float);
|
||||
template void findTopK(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<float>, std::size_t, float);
|
||||
|
||||
template <class T>
|
||||
void box_collect(const Stream& stream, TensorSpan<T> collected_bboxes, TensorView<T> decoded_bboxes, TensorView<int> indices, TensorView<int> count, bool share_location, std::size_t background_class_id)
|
||||
{
|
||||
// collected_bboxes: [batch_size, num_classes, classwise_topK, 4]
|
||||
// decoded_bboxes: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
|
||||
const auto batch_size = collected_bboxes.get_axis_size(0);
|
||||
CV_Assert(decoded_bboxes.get_axis_size(0) == batch_size);
|
||||
CV_Assert(indices.get_axis_size(0) == batch_size);
|
||||
CV_Assert(count.get_axis_size(0) == batch_size);
|
||||
|
||||
const auto num_classes = collected_bboxes.get_axis_size(1);
|
||||
CV_Assert(indices.get_axis_size(1) == num_classes);
|
||||
CV_Assert(count.get_axis_size(1) == num_classes);
|
||||
|
||||
const auto classwise_topK = collected_bboxes.get_axis_size(2);
|
||||
CV_Assert(indices.get_axis_size(2) == classwise_topK);
|
||||
|
||||
const auto num_priors = decoded_bboxes.get_axis_size(1);
|
||||
|
||||
CV_Assert(!share_location || decoded_bboxes.get_axis_size(2) == 1);
|
||||
|
||||
constexpr int BLOCK_SIZE = 256;
|
||||
|
||||
/* each block processes one class from each batch */
|
||||
dim3 grid_size(num_classes, batch_size);
|
||||
dim3 block_size(BLOCK_SIZE);
|
||||
auto policy = execution_policy(grid_size, block_size, stream);
|
||||
|
||||
auto kernel = raw::box_collect<T>;
|
||||
launch_kernel(kernel, policy, collected_bboxes, decoded_bboxes, indices, count, share_location, num_priors, num_classes, classwise_topK, background_class_id);
|
||||
}
|
||||
|
||||
template void box_collect(const Stream&, TensorSpan<float>, TensorView<float>, TensorView<int>, TensorView<int>, bool, std::size_t);
|
||||
template void box_collect(const Stream&, TensorSpan<__half>, TensorView<__half>, TensorView<int>, TensorView<int>, bool, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void blockwise_class_nms(const Stream& stream, TensorSpan<int> indices, TensorSpan<int> count, TensorView<T> collected_bboxes,
|
||||
bool normalized_bbox, std::size_t background_class_id, float nms_threshold)
|
||||
{
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// collected_bboxes: [batch_size, num_classes, classwise_topK, 4]
|
||||
|
||||
const auto batch_size = indices.get_axis_size(0);
|
||||
CV_Assert(count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(collected_bboxes.get_axis_size(0) == batch_size);
|
||||
|
||||
const auto num_classes = indices.get_axis_size(1);
|
||||
CV_Assert(count.get_axis_size(1) == num_classes);
|
||||
CV_Assert(collected_bboxes.get_axis_size(1) == num_classes);
|
||||
|
||||
const auto classwise_topK = indices.get_axis_size(2);
|
||||
CV_Assert(collected_bboxes.get_axis_size(2) == classwise_topK);
|
||||
|
||||
/* each block processes one class from each batch */
|
||||
auto num_blocks = batch_size * num_classes;
|
||||
auto num_threads = std::max<std::size_t>(std::min<std::size_t>(1024, classwise_topK), 32);
|
||||
|
||||
dim3 grid_size(num_blocks);
|
||||
dim3 block_size(num_threads);
|
||||
auto policy = execution_policy(grid_size, block_size, stream);
|
||||
|
||||
if (normalized_bbox)
|
||||
{
|
||||
auto kernel = raw::blockwise_class_nms<T, true>;
|
||||
launch_kernel(kernel, policy, indices, count, collected_bboxes, num_classes, classwise_topK, background_class_id, nms_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto kernel = raw::blockwise_class_nms<T, false>;
|
||||
launch_kernel(kernel, policy, indices, count, collected_bboxes, num_classes, classwise_topK, background_class_id, nms_threshold);
|
||||
}
|
||||
}
|
||||
|
||||
template void blockwise_class_nms(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<__half>, bool, std::size_t, float);
|
||||
template void blockwise_class_nms(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<float>, bool, std::size_t, float);
|
||||
|
||||
template <class T>
|
||||
void nms_collect(const Stream& stream, TensorSpan<int> kept_indices, TensorSpan<int> kept_count,
|
||||
TensorView<int> indices, TensorView<int> count, TensorView<T> scores, float threshold, std::size_t background_class_id)
|
||||
{
|
||||
// kept_indices: [batch_size, keepTopK]
|
||||
// kept_count: [batch_size]
|
||||
|
||||
// indices: [batch_size, num_classes, classwise_topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
auto batch_size = kept_indices.get_axis_size(0);
|
||||
CV_Assert(kept_count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(indices.get_axis_size(0) == batch_size);
|
||||
CV_Assert(count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(scores.get_axis_size(0) == batch_size);
|
||||
|
||||
auto keepTopK = kept_indices.get_axis_size(1);
|
||||
|
||||
auto num_classes = indices.get_axis_size(1);
|
||||
CV_Assert(count.get_axis_size(1) == num_classes);
|
||||
CV_Assert(scores.get_axis_size(1) == num_classes);
|
||||
|
||||
auto classwise_topK = indices.get_axis_size(2);
|
||||
auto num_priors = scores.get_axis_size(2);
|
||||
|
||||
auto num_blocks = batch_size;
|
||||
constexpr int BLOCK_SIZE = 1024;
|
||||
|
||||
dim3 grid_size(num_blocks);
|
||||
dim3 block_size(BLOCK_SIZE);
|
||||
auto policy = execution_policy(grid_size, block_size, stream);
|
||||
|
||||
auto kernel = raw::nms_collect<T, 1024, BLOCK_SIZE>;
|
||||
launch_kernel(kernel, policy, kept_indices, kept_count, indices, count, scores, threshold, num_classes, num_priors, classwise_topK, keepTopK, background_class_id);
|
||||
}
|
||||
|
||||
template void nms_collect(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<int>, TensorView<int>, TensorView<__half>, float, std::size_t);
|
||||
template void nms_collect(const Stream&, TensorSpan<int>, TensorSpan<int>, TensorView<int>, TensorView<int>, TensorView<float>, float, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void consolidate_detections(const Stream& stream, TensorSpan<T> output,
|
||||
TensorView<int> kept_indices, TensorView<int> kept_count,
|
||||
TensorView<T> decoded_bboxes, TensorView<T> scores, bool share_location, DevicePtr<int> num_detections)
|
||||
{
|
||||
// output: [1, 1, batch_size * keepTopK, 7]
|
||||
// kept_indices: [batch_size, keepTopK]
|
||||
// kept_count: [batch_size]
|
||||
// decoded_bboxes: [batch_size, num_priors, num_loc_classes, 4]
|
||||
// scores: [batch_size, num_classes, num_priors]
|
||||
|
||||
auto batch_size = kept_indices.get_axis_size(0);
|
||||
CV_Assert(kept_count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(decoded_bboxes.get_axis_size(0) == batch_size);
|
||||
CV_Assert(scores.get_axis_size(0) == batch_size);
|
||||
|
||||
auto keepTopK = kept_indices.get_axis_size(1);
|
||||
|
||||
auto num_classes = scores.get_axis_size(1);
|
||||
auto num_priors = scores.get_axis_size(2);
|
||||
|
||||
CV_Assert(batch_size * keepTopK * 7 == output.size());
|
||||
|
||||
auto kernel = raw::consolidate_detections<T>;
|
||||
auto policy = make_policy(kernel, keepTopK, 0, stream);
|
||||
launch_kernel(kernel, policy, output, kept_indices, kept_count, decoded_bboxes, scores, share_location, batch_size, num_classes, num_priors, keepTopK, num_detections);
|
||||
}
|
||||
|
||||
template void consolidate_detections(const Stream&, TensorSpan<__half>, TensorView<int>, TensorView<int>, TensorView<__half>, TensorView<__half>, bool, DevicePtr<int>);
|
||||
template void consolidate_detections(const Stream&, TensorSpan<float>, TensorView<int>, TensorView<int>, TensorView<float>, TensorView<float>, bool, DevicePtr<int>);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,125 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "functors.hpp"
|
||||
#include "types.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, class EltwiseOp, class ActivationOp, std::size_t N>
|
||||
__global__ void eltwise_op_generic_op_vec(Span<T> output, View<T> x, View<T> y, const typename EltwiseOp::Params eltwise_params, const typename ActivationOp::Params act_params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
auto x_vPtr = vector_type::get_pointer(x.data());
|
||||
auto y_vPtr = vector_type::get_pointer(y.data());
|
||||
|
||||
EltwiseOp eltwise_op(eltwise_params);
|
||||
ActivationOp activation_op(act_params);
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
vector_type vec_x, vec_y;
|
||||
v_load(vec_x, x_vPtr[i]);
|
||||
v_load(vec_y, y_vPtr[i]);
|
||||
for(int j = 0; j < vec_x.size(); j++)
|
||||
vec_x.data[j] = activation_op(eltwise_op(vec_x.data[j], vec_y.data[j]));
|
||||
v_store(output_vPtr[i], vec_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, class ActivationOp, std::size_t N> static
|
||||
void launch_vectorized_eltwise_op_generic_op(const Stream& stream, Span<T> output, View<T> x, View<T> y, const typename EltwiseOp::Params& eltwise_params, const typename ActivationOp::Params& act_params) {
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(x, N));
|
||||
CV_Assert(is_fully_aligned<T>(y, N));
|
||||
|
||||
auto kernel = raw::eltwise_op_generic_op_vec<T, EltwiseOp, ActivationOp, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, x, y, eltwise_params, act_params);
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, class ActivationOp> static
|
||||
void eltwise_op_generic_op(const Stream& stream, Span<T> output, View<T> x, View<T> y, const typename EltwiseOp::Params& eltwise_params = {}, const typename ActivationOp::Params& act_params = {}) {
|
||||
CV_Assert(output.size() == x.size());
|
||||
CV_Assert(output.size() == y.size());
|
||||
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(x, 4) && is_fully_aligned<T>(y, 4)) {
|
||||
launch_vectorized_eltwise_op_generic_op<T, EltwiseOp, ActivationOp, 4>(stream, output, x, y, eltwise_params, act_params);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(x, 2) && is_fully_aligned<T>(y, 4)) {
|
||||
launch_vectorized_eltwise_op_generic_op<T, EltwiseOp, ActivationOp, 2>(stream, output, x, y, eltwise_params, act_params);
|
||||
} else {
|
||||
launch_vectorized_eltwise_op_generic_op<T, EltwiseOp, ActivationOp, 1>(stream, output, x, y, eltwise_params, act_params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_relu(const Stream& stream, Span<T> output, View<T> x, View<T> y, T slope) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, ReLUFunctor<T>>(stream, output, x, y, {}, {slope});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_clipped_relu(const Stream& stream, Span<T> output, View<T> x, View<T> y, T floor, T ceiling) {
|
||||
CV_Assert(static_cast<double>(floor) <= static_cast<double>(ceiling));
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, ClippedReLUFunctor<T>>(stream, output, x, y, {}, {floor, ceiling});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_tanh(const Stream& stream, Span<T> output, View<T> x, View<T> y) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, TanHFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_swish(const Stream& stream, Span<T> output, View<T> x, View<T> y) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, SwishFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_mish(const Stream& stream, Span<T> output, View<T> x, View<T> y) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, MishFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_sigmoid(const Stream& stream, Span<T> output, View<T> x, View<T> y) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, SigmoidFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2_power(const Stream& stream, Span<T> output, View<T> x, View<T> y, T exp, T scale, T shift) {
|
||||
eltwise_op_generic_op<T, SumFunctor<T>, PowerFunctor<T>>(stream, output, x, y, {}, {exp, scale, shift});
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void eltwise_sum_2_relu<__half>(const Stream&, Span<__half>, View<__half>, View<__half>, __half);
|
||||
template void eltwise_sum_2_clipped_relu<__half>(const Stream&, Span<__half>, View<__half>, View<__half>, __half, __half);
|
||||
template void eltwise_sum_2_tanh<__half>(const Stream&, Span<__half>, View<__half>, View<__half>);
|
||||
template void eltwise_sum_2_swish<__half>(const Stream&, Span<__half>, View<__half>, View<__half>);
|
||||
template void eltwise_sum_2_mish<__half>(const Stream&, Span<__half>, View<__half>, View<__half>);
|
||||
template void eltwise_sum_2_sigmoid<__half>(const Stream&, Span<__half>, View<__half>, View<__half>);
|
||||
template void eltwise_sum_2_power<__half>(const Stream&, Span<__half>, View<__half>, View<__half>, __half, __half, __half);
|
||||
#endif
|
||||
|
||||
template void eltwise_sum_2_relu<float>(const Stream&, Span<float>, View<float>, View<float>, float);
|
||||
template void eltwise_sum_2_clipped_relu<float>(const Stream&, Span<float>, View<float>, View<float>, float, float);
|
||||
template void eltwise_sum_2_tanh<float>(const Stream&, Span<float>, View<float>, View<float>);
|
||||
template void eltwise_sum_2_swish<float>(const Stream&, Span<float>, View<float>, View<float>);
|
||||
template void eltwise_sum_2_mish<float>(const Stream&, Span<float>, View<float>, View<float>);
|
||||
template void eltwise_sum_2_sigmoid<float>(const Stream&, Span<float>, View<float>, View<float>);
|
||||
template void eltwise_sum_2_power<float>(const Stream&, Span<float>, View<float>, View<float>, float, float, float);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,426 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "functors.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "kernel_dispatcher.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, class EltwiseOp, std::size_t N>
|
||||
__global__ void eltwise_op_vec(Span<T> output, View<T> x, View<T> y, const typename EltwiseOp::Params params) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
auto x_vPtr = vector_type::get_pointer(x.data());
|
||||
auto y_vPtr = vector_type::get_pointer(y.data());
|
||||
|
||||
EltwiseOp eltwise_op(params);
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
vector_type vec_x, vec_y;
|
||||
v_load(vec_x, x_vPtr[i]);
|
||||
v_load(vec_y, y_vPtr[i]);
|
||||
for (int j = 0; j < vector_type::size(); j++)
|
||||
vec_x.data[j] = eltwise_op(vec_x.data[j], vec_y.data[j]);
|
||||
v_store(output_vPtr[i], vec_x);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, std::size_t Rank>
|
||||
__global__ void eltwise_op_bcast(
|
||||
Span<T> output, array<size_type, Rank> out_strides,
|
||||
View<T> x, array<size_type, Rank> x_strides, array<bool, Rank> x_bcast,
|
||||
View<T> y, array<size_type, Rank> y_strides, array<bool, Rank> y_bcast,
|
||||
const typename EltwiseOp::Params params) {
|
||||
EltwiseOp eltwise_op(params);
|
||||
|
||||
for (auto i : grid_stride_range(output.size())) {
|
||||
index_type out_index = i / out_strides[0];
|
||||
index_type x_index = x_bcast[0] ? 0 : out_index * x_strides[0];
|
||||
index_type y_index = y_bcast[0] ? 0 : out_index * y_strides[0];
|
||||
|
||||
for (int j = 1; j < Rank; j++)
|
||||
{
|
||||
out_index = (i % out_strides[j - 1]) / out_strides[j];
|
||||
if (!x_bcast[j])
|
||||
x_index += out_index * x_strides[j];
|
||||
if (!y_bcast[j])
|
||||
y_index += out_index * y_strides[j];
|
||||
}
|
||||
|
||||
output[i] = eltwise_op(x[x_index], y[y_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, std::size_t N> static
|
||||
void launch_vectorized_eltwise_op(const Stream& stream, Span<T> output, View<T> x, View<T> y, const typename EltwiseOp::Params& params) {
|
||||
CV_Assert(x.size() == y.size());
|
||||
CV_Assert(x.size() == output.size());
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(x, N));
|
||||
CV_Assert(is_fully_aligned<T>(y, N));
|
||||
|
||||
auto kernel = raw::eltwise_op_vec<T, EltwiseOp, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, x, y, params);
|
||||
}
|
||||
|
||||
template <class T, class EltwiseOp, std::size_t Rank> static
|
||||
void launch_eltwise_op_bcast(
|
||||
const Stream& stream,
|
||||
Span<T> output, const std::vector<std::size_t>& outStride,
|
||||
View<T> x, const std::vector<std::size_t>& inStride1, const std::vector<int>& inBcast1,
|
||||
View<T> y, const std::vector<std::size_t>& inStride2, const std::vector<int>& inBcast2,
|
||||
const typename EltwiseOp::Params& params)
|
||||
{
|
||||
CV_Assert(outStride.size() == Rank);
|
||||
CV_Assert(inStride1.size() == Rank);
|
||||
CV_Assert(inStride2.size() == Rank);
|
||||
CV_Assert(inBcast1.size() == Rank);
|
||||
CV_Assert(inBcast2.size() == Rank);
|
||||
|
||||
array<size_type, Rank> outStride_k, inStride1_k, inStride2_k;
|
||||
outStride_k.assign(std::begin(outStride), std::end(outStride));
|
||||
inStride1_k.assign(std::begin(inStride1), std::end(inStride1));
|
||||
inStride2_k.assign(std::begin(inStride2), std::end(inStride2));
|
||||
|
||||
array<bool, Rank> inBcast1_k, inBcast2_k;
|
||||
inBcast1_k.assign(std::begin(inBcast1), std::end(inBcast1));
|
||||
inBcast2_k.assign(std::begin(inBcast2), std::end(inBcast2));
|
||||
|
||||
auto kernel = raw::eltwise_op_bcast<T, EltwiseOp, Rank>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, outStride_k, x, inStride1_k, inBcast1_k, y, inStride2_k, inBcast2_k, params);
|
||||
}
|
||||
|
||||
GENERATE_KERNEL_DISPATCHER_2TP(eltwise_op_bcast_dispatcher, launch_eltwise_op_bcast);
|
||||
|
||||
template <class T, class EltwiseOp> static
|
||||
void eltwise_op(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y, const typename EltwiseOp::Params& params = {}) {
|
||||
if (is_shape_same(output, x) && is_shape_same(output, y))
|
||||
{
|
||||
/* no broadcasting; use fast path */
|
||||
CV_Assert(x.size() == y.size());
|
||||
CV_Assert(x.size() == output.size());
|
||||
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(x, 4) && is_fully_aligned<T>(y, 4)) {
|
||||
launch_vectorized_eltwise_op<T, EltwiseOp, 4>(stream, output, x, y, params);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(x, 2) && is_fully_aligned<T>(y, 2)) {
|
||||
launch_vectorized_eltwise_op<T, EltwiseOp, 2>(stream, output, x, y, params);
|
||||
} else {
|
||||
launch_vectorized_eltwise_op<T, EltwiseOp, 1>(stream, output, x, y, params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto inShape1 = x.shape_as_vector();
|
||||
auto inShape2 = y.shape_as_vector();
|
||||
auto outShape = output.shape_as_vector();
|
||||
|
||||
std::size_t x_ndims = inShape1.size(), y_ndims = inShape2.size();
|
||||
if (x_ndims >= y_ndims) {
|
||||
for (std::size_t i = 0; i < (x_ndims - y_ndims); i++) {
|
||||
inShape2.insert(inShape2.begin(), 1);
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = 0; i < (y_ndims - x_ndims); i++) {
|
||||
inShape1.insert(inShape1.begin(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
CV_Assert(is_shape_compatible1(outShape, inShape1));
|
||||
CV_Assert(is_shape_compatible1(outShape, inShape2));
|
||||
|
||||
/* matching singleton axes in both input tensors can be eliminated
|
||||
*
|
||||
* Reasoning:
|
||||
* ----------
|
||||
* Singleton axes do not contribute towards address calculation. They are redundant
|
||||
* unless there is broadcasting. If both input tensors have singleton axis at a
|
||||
* specified position, there is no broadcasting on that axis.
|
||||
*
|
||||
* Example:
|
||||
* ---------
|
||||
* x: [1, 256, 32, 32] -> [256, 32, 32]
|
||||
* y: [1, 256, 1, 1] -> [256, 1, 1]
|
||||
*/
|
||||
int eliminate_times = 0;
|
||||
for (std::size_t i = 0; i < outShape.size(); i++) {
|
||||
if (inShape1[i] == 1 && inShape2[i] == 1 && outShape[i] == 1 && i != (outShape.size() - 1)) {
|
||||
eliminate_times++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (eliminate_times > 0) {
|
||||
for (int i = 0; i < eliminate_times; i++) {
|
||||
inShape1.erase(inShape1.begin());
|
||||
inShape2.erase(inShape2.begin());
|
||||
outShape.erase(outShape.begin());
|
||||
}
|
||||
}
|
||||
|
||||
/* contiguous axes that do not broadcast can be merged into one axis
|
||||
*
|
||||
* Example:
|
||||
* ---------
|
||||
* x: [32, 8, 8] -> [32, 64]
|
||||
* y: [1, 8, 8] -> [1, 64]
|
||||
*/
|
||||
for (int i = 0; i < inShape1.size(); i++) {
|
||||
/* check if axis `i` requires any broadcasting */
|
||||
if (inShape1[i] == inShape2[i]) {
|
||||
/* loop invariant: `i` is the first axis in the contiguous axis sequence */
|
||||
|
||||
int j = i + 1; /* `j` is the axis which we will attempt to merge */
|
||||
while (j < inShape1.size() && inShape1[j] == inShape2[j]) {
|
||||
CV_Assert(outShape[j] == inShape1[j]);
|
||||
|
||||
/* `j` axis is also used fully; merge `i` and `j` */
|
||||
auto new_size = inShape1[i] * inShape1[j];
|
||||
inShape1[i] = new_size;
|
||||
inShape2[i] = new_size;
|
||||
// outShape should be changed after merged
|
||||
auto output_new_size = outShape[i] * outShape[j];
|
||||
outShape[i] = output_new_size;
|
||||
|
||||
/* delete axis `j` */
|
||||
inShape1.erase(std::begin(inShape1) + j);
|
||||
inShape2.erase(std::begin(inShape2) + j);
|
||||
outShape.erase(std::begin(outShape) + j);
|
||||
|
||||
/* optimizations should not break the invariants */
|
||||
CV_Assert(inShape1.size() == outShape.size());
|
||||
CV_Assert(inShape2.size() == outShape.size());
|
||||
CV_Assert(inShape1[i] == outShape[i]);
|
||||
CV_Assert(inShape2[i] == outShape[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* contiguous broadcasting axes on the same tensor can be merged into one axis
|
||||
*
|
||||
* Example:
|
||||
* ---------
|
||||
* x: [256, 8, 8] -> [256, 64]
|
||||
* y: [256, 1, 1] -> [256, 1]
|
||||
*/
|
||||
for (int i = 0; i < inShape1.size(); i++) {
|
||||
/* check if axis `i` requires any broadcasting in tensor 1 */
|
||||
if (inShape1[i] == 1 && inShape2[i] != 1) {
|
||||
/* loop invariant: `i` is the first axis in the contiguous axis sequence */
|
||||
|
||||
int j = i + 1; /* `j` is the axis which we will attempt to merge */
|
||||
while (j < inShape1.size() && inShape1[j] == 1 && inShape2[j] != 1) {
|
||||
CV_Assert(outShape[j] == inShape2[j]);
|
||||
|
||||
/* `j` axis is also used fully; merge `i` and `j` */
|
||||
inShape1[i] = 1;
|
||||
inShape2[i] = inShape2[i] * inShape2[j];
|
||||
outShape[i] = inShape2[i];
|
||||
|
||||
/* delete axis `j` */
|
||||
inShape1.erase(std::begin(inShape1) + j);
|
||||
inShape2.erase(std::begin(inShape2) + j);
|
||||
outShape.erase(std::begin(outShape) + j);
|
||||
|
||||
/* optimizations should not break the invariants */
|
||||
CV_Assert(inShape1.size() == outShape.size());
|
||||
CV_Assert(inShape2.size() == outShape.size());
|
||||
CV_Assert(inShape1[i] == 1);
|
||||
CV_Assert(inShape2[i] == outShape[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if axis `i` requires any broadcasting in tensor 2 */
|
||||
if (inShape1[i] != 1 && inShape2[i] == 1) {
|
||||
/* loop invariant: `i` is the first axis in the contiguous axis sequence */
|
||||
|
||||
int j = i + 1; /* `j` is the axis which we will attempt to merge */
|
||||
while (j < inShape1.size() && inShape1[j] != 1 && inShape2[j] == 1) {
|
||||
CV_Assert(outShape[j] == inShape1[j]);
|
||||
|
||||
/* `j` axis is also used fully; merge `i` and `j` */
|
||||
inShape1[i] = inShape1[i] * inShape1[j];
|
||||
inShape2[i] = 1;
|
||||
outShape[i] = inShape1[i];
|
||||
|
||||
/* delete axis `j` */
|
||||
inShape1.erase(std::begin(inShape1) + j);
|
||||
inShape2.erase(std::begin(inShape2) + j);
|
||||
outShape.erase(std::begin(outShape) + j);
|
||||
|
||||
/* optimizations should not break the invariants */
|
||||
CV_Assert(inShape1.size() == outShape.size());
|
||||
CV_Assert(inShape2.size() == outShape.size());
|
||||
CV_Assert(inShape1[i] == outShape[i]);
|
||||
CV_Assert(inShape2[i] == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto rank = outShape.size();
|
||||
|
||||
std::vector<std::size_t> inStride1(rank), inStride2(rank), outStride(rank);
|
||||
inStride1.back() = 1;
|
||||
inStride2.back() = 1;
|
||||
outStride.back() = 1;
|
||||
/* garbage, ..., garbage, 1 */
|
||||
|
||||
std::copy(std::begin(inShape1) + 1, std::end(inShape1), std::begin(inStride1));
|
||||
std::copy(std::begin(inShape2) + 1, std::end(inShape2), std::begin(inStride2));
|
||||
std::copy(std::begin(outShape) + 1, std::end(outShape), std::begin(outStride));
|
||||
/* dim[0], dim[1], ..., dim[-1], 1 */
|
||||
|
||||
std::partial_sum(inStride1.rbegin(), inStride1.rend(), inStride1.rbegin(), std::multiplies<std::size_t>());
|
||||
std::partial_sum(inStride2.rbegin(), inStride2.rend(), inStride2.rbegin(), std::multiplies<std::size_t>());
|
||||
std::partial_sum(outStride.rbegin(), outStride.rend(), outStride.rbegin(), std::multiplies<std::size_t>());
|
||||
/* stride[0], stride[1], ..., stride[-2], 1 */
|
||||
|
||||
std::vector<int> inBcast1(rank), inBcast2(rank);
|
||||
std::transform(std::begin(inShape1), std::end(inShape1), std::begin(inBcast1), [](std::size_t sz) { return sz == 1; });
|
||||
std::transform(std::begin(inShape2), std::end(inShape2), std::begin(inBcast2), [](std::size_t sz) { return sz == 1; });
|
||||
|
||||
CV_Assert(1 <= rank && rank <= CSL_MAX_TENSOR_RANK);
|
||||
eltwise_op_bcast_dispatcher<T, EltwiseOp, 1, CSL_MAX_TENSOR_RANK>(rank, stream, output, outStride, x, inStride1, inBcast1, y, inStride2, inBcast2, params);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_max_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, MaxFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_min_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, MinFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, SumFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sum_coeff_2(const Stream& stream, TensorSpan<T> output, T coeff_x, TensorView<T> x, T coeff_y, TensorView<T> y) {
|
||||
eltwise_op<T, ScaledSumFunctor<T>>(stream, output, x, y, {coeff_x, coeff_y});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_prod_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, ProductFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_div_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, DivFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_sub_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, SubFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_mod_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, ModFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_fmod_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, FModFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void eltwise_pow_2(const Stream& stream, TensorSpan<T> output, TensorView<T> x, TensorView<T> y) {
|
||||
eltwise_op<T, PowFunctor<T>>(stream, output, x, y);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<__half>, __half, TensorView<__half>, __half, TensorView<__half>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<__half> output, TensorView<__half> x, TensorView<__half> y);
|
||||
#endif
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<float>, float, TensorView<float>, float, TensorView<float>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<float> output, TensorView<float> x, TensorView<float> y);
|
||||
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<int8_t>, int8_t, TensorView<int8_t>, int8_t, TensorView<int8_t>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<int8_t> output, TensorView<int8_t> x, TensorView<int8_t> y);
|
||||
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<uint8_t>, uint8_t, TensorView<uint8_t>, uint8_t, TensorView<uint8_t>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<uint8_t> output, TensorView<uint8_t> x, TensorView<uint8_t> y);
|
||||
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<int32_t>, int32_t, TensorView<int32_t>, int32_t, TensorView<int32_t>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<int32_t> output, TensorView<int32_t> x, TensorView<int32_t> y);
|
||||
|
||||
template void eltwise_mod_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_fmod_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_sub_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_div_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_prod_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_sum_coeff_2(const Stream&, TensorSpan<int64_t>, int64_t, TensorView<int64_t>, int64_t, TensorView<int64_t>);
|
||||
template void eltwise_sum_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_max_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_min_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
template void eltwise_pow_2(const Stream& stream, TensorSpan<int64_t> output, TensorView<int64_t> x, TensorView<int64_t> y);
|
||||
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_EXECUTION_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_EXECUTION_HPP
|
||||
|
||||
#include "../cuda4dnn/csl/error.hpp"
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl {
|
||||
|
||||
struct execution_policy {
|
||||
execution_policy(dim3 grid_size, dim3 block_size)
|
||||
: grid{ grid_size }, block{ block_size }, sharedMem{ 0 }, stream{ 0 } { }
|
||||
|
||||
execution_policy(dim3 grid_size, dim3 block_size, std::size_t shared_mem)
|
||||
: grid{ grid_size }, block{ block_size }, sharedMem{ shared_mem }, stream{ nullptr } { }
|
||||
|
||||
execution_policy(dim3 grid_size, dim3 block_size, const Stream& strm)
|
||||
: grid{ grid_size }, block{ block_size }, sharedMem{ 0 }, stream{ strm.get() } { }
|
||||
|
||||
execution_policy(dim3 grid_size, dim3 block_size, std::size_t shared_mem, const Stream& strm)
|
||||
: grid{ grid_size }, block{ block_size }, sharedMem{ shared_mem }, stream{ strm.get() } { }
|
||||
|
||||
dim3 grid;
|
||||
dim3 block;
|
||||
std::size_t sharedMem;
|
||||
cudaStream_t stream;
|
||||
};
|
||||
|
||||
/* this overload shouldn't be necessary; we should always provide a bound on the number of threads */
|
||||
/*
|
||||
template <class Kernel> inline
|
||||
execution_policy make_policy(Kernel kernel, std::size_t sharedMem = 0, const Stream& stream = 0) {
|
||||
int grid_size, block_size;
|
||||
CUDA4DNN_CHECK_CUDA(cudaOccupancyMaxPotentialBlockSize(&grid_size, &block_size, kernel, sharedMem));
|
||||
return execution_policy(grid_size, block_size, sharedMem, stream);
|
||||
}*/
|
||||
|
||||
template <class Kernel> inline
|
||||
execution_policy make_policy(Kernel kernel, std::size_t max_threads, std::size_t sharedMem = 0, const Stream& stream = 0) {
|
||||
CV_Assert(max_threads > 0);
|
||||
|
||||
int grid_size = 0, block_size = 0;
|
||||
CUDA4DNN_CHECK_CUDA(cudaOccupancyMaxPotentialBlockSize(&grid_size, &block_size, kernel, sharedMem));
|
||||
if (grid_size * block_size > max_threads) {
|
||||
grid_size = (max_threads + block_size - 1) / block_size;
|
||||
if (block_size > max_threads)
|
||||
block_size = max_threads;
|
||||
}
|
||||
|
||||
CV_Assert(grid_size >= 1 && block_size >= 1);
|
||||
return execution_policy(grid_size, block_size, sharedMem, stream);
|
||||
}
|
||||
|
||||
template <class Kernel, typename ...Args> inline
|
||||
void launch_kernel(Kernel kernel, Args ...args) {
|
||||
auto policy = make_policy(kernel);
|
||||
kernel <<<policy.grid, policy.block>>> (args...);
|
||||
}
|
||||
|
||||
template <class Kernel, typename ...Args> inline
|
||||
void launch_kernel(Kernel kernel, dim3 grid, dim3 block, Args ...args) {
|
||||
kernel <<<grid, block>>> (args...);
|
||||
}
|
||||
|
||||
template <class Kernel, typename ...Args> inline
|
||||
void launch_kernel(Kernel kernel, execution_policy policy, Args ...args) {
|
||||
kernel <<<policy.grid, policy.block, policy.sharedMem, policy.stream>>> (args...);
|
||||
}
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::csl */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_EXECUTION_HPP */
|
||||
@@ -0,0 +1,107 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, std::size_t N>
|
||||
__global__ void fill_vec(Span<T> output, T value) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
vector_type vec;
|
||||
for (int j = 0; j < vector_type::size(); j++)
|
||||
vec.data[j] = value;
|
||||
v_store(output_vPtr[i], vec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
__global__ void copy_vec(Span<T> output, View<T> input) {
|
||||
using vector_type = get_vector_type_t<T, N>;
|
||||
auto input_vPtr = vector_type::get_pointer(input.data());
|
||||
auto output_vPtr = vector_type::get_pointer(output.data());
|
||||
for (auto i : grid_stride_range(output.size() / vector_type::size())) {
|
||||
vector_type vec;
|
||||
v_load(vec, input_vPtr[i]);
|
||||
v_store(output_vPtr[i], vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t N> static
|
||||
void launch_vectorized_fill(const Stream& stream, Span<T> output, T value) {
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
|
||||
auto kernel = raw::fill_vec<T, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void fill(const Stream& stream, Span<T> output, T value) {
|
||||
if (is_fully_aligned<T>(output, 4)) {
|
||||
launch_vectorized_fill<T, 4>(stream, output, value);
|
||||
} else if (is_fully_aligned<T>(output, 2)) {
|
||||
launch_vectorized_fill<T, 2>(stream, output, value);
|
||||
} else {
|
||||
launch_vectorized_fill<T, 1>(stream, output, value);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void fill(const Stream&, Span<__half>, __half);
|
||||
#endif
|
||||
template void fill(const Stream&, Span<float>, float);
|
||||
template void fill(const Stream&, Span<int8_t>, int8_t);
|
||||
template void fill(const Stream&, Span<uint8_t>, uint8_t);
|
||||
template void fill(const Stream&, Span<int>, int);
|
||||
template void fill(const Stream&, Span<int64_t>, int64_t);
|
||||
template void fill(const Stream&, Span<bool>, bool);
|
||||
|
||||
template <class T, std::size_t N> static
|
||||
void launch_vectorized_copy(const Stream& stream, Span<T> output, View<T> input) {
|
||||
CV_Assert(is_fully_aligned<T>(output, N));
|
||||
CV_Assert(is_fully_aligned<T>(input, N));
|
||||
|
||||
auto kernel = raw::copy_vec<T, N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, input);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void copy(const Stream& stream, Span<T> output, View<T> input) {
|
||||
if (is_fully_aligned<T>(output, 4) && is_fully_aligned<T>(input, 4)) {
|
||||
launch_vectorized_copy<T, 4>(stream, output, input);
|
||||
} else if (is_fully_aligned<T>(output, 2) && is_fully_aligned<T>(input, 2)) {
|
||||
launch_vectorized_copy<T, 2>(stream, output, input);
|
||||
} else {
|
||||
launch_vectorized_copy<T, 1>(stream, output, input);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void copy(const Stream&, Span<__half>, View<__half>);
|
||||
#endif
|
||||
template void copy(const Stream&, Span<float>, View<float>);
|
||||
template void copy(const Stream&, Span<int8_t>, View<int8_t>);
|
||||
template void copy(const Stream&, Span<uint8_t>, View<uint8_t>);
|
||||
template void copy(const Stream&, Span<int32_t>, View<int32_t>);
|
||||
template void copy(const Stream&, Span<int64_t>, View<int64_t>);
|
||||
template void copy(const Stream&, Span<bool>, View<bool>);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <std::size_t N>
|
||||
__global__ void fp32_to_fp16(Span<__half> output, View<float> input) {
|
||||
using output_vector_type = get_vector_type_t<__half, N>;
|
||||
using input_vector_type = get_vector_type_t<float, N>;
|
||||
|
||||
auto output_vPtr = output_vector_type::get_pointer(output.data());
|
||||
auto input_vPtr = input_vector_type::get_pointer(input.data());
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / output_vector_type::size())) {
|
||||
input_vector_type in_vec;
|
||||
v_load(in_vec, input_vPtr[i]);
|
||||
|
||||
output_vector_type out_vec;
|
||||
for (int j = 0; j < output_vector_type::size(); j++)
|
||||
out_vec.data[j] = __float2half(in_vec.data[j]);
|
||||
|
||||
v_store(output_vPtr[i], out_vec);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
__global__ void fp16_to_fp32(Span<float> output, View<__half> input) {
|
||||
using output_vector_type = get_vector_type_t<float, N>;
|
||||
using input_vector_type = get_vector_type_t<__half, N>;
|
||||
|
||||
auto output_vPtr = output_vector_type::get_pointer(output.data());
|
||||
auto input_vPtr = input_vector_type::get_pointer(input.data());
|
||||
|
||||
for (auto i : grid_stride_range(output.size() / output_vector_type::size())) {
|
||||
input_vector_type in_vec;
|
||||
v_load(in_vec, input_vPtr[i]);
|
||||
|
||||
output_vector_type out_vec;
|
||||
for (int j = 0; j < output_vector_type::size(); j++)
|
||||
out_vec.data[j] = __half2float(in_vec.data[j]);
|
||||
|
||||
v_store(output_vPtr[i], out_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t N> static
|
||||
void launch_vectorized_fp32_to_fp16(const Stream& stream, Span<__half> output, View<float> input) {
|
||||
CV_Assert(is_fully_aligned<__half>(output, N));
|
||||
CV_Assert(is_fully_aligned<float>(input, N));
|
||||
|
||||
auto kernel = raw::fp32_to_fp16<N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, input);
|
||||
}
|
||||
|
||||
void fp32_to_fp16(const Stream& stream, Span<__half> output, View<float> input) {
|
||||
if (is_fully_aligned<__half>(output, 4) && is_fully_aligned<float>(input, 4)) {
|
||||
launch_vectorized_fp32_to_fp16<4>(stream, output, input);
|
||||
} else if (is_fully_aligned<__half>(output, 2) && is_fully_aligned<float>(input, 2)) {
|
||||
launch_vectorized_fp32_to_fp16<2>(stream, output, input);
|
||||
} else {
|
||||
launch_vectorized_fp32_to_fp16<1>(stream, output, input);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t N> static
|
||||
void launch_vectorized_fp16_to_fp32(const Stream& stream, Span<float> output, View<__half> input) {
|
||||
CV_Assert(is_fully_aligned<float>(output, N));
|
||||
CV_Assert(is_fully_aligned<__half>(input, N));
|
||||
|
||||
auto kernel = raw::fp16_to_fp32<N>;
|
||||
auto policy = make_policy(kernel, output.size() / N, 0, stream);
|
||||
launch_kernel(kernel, policy, output, input);
|
||||
}
|
||||
|
||||
void fp16_to_fp32(const Stream& stream, Span<float> output, View<__half> input) {
|
||||
if (is_fully_aligned<float>(output, 4) && is_fully_aligned<__half>(input, 4)) {
|
||||
launch_vectorized_fp16_to_fp32<4>(stream, output, input);
|
||||
} else if (is_fully_aligned<float>(output, 2) && is_fully_aligned<__half>(input, 2)) {
|
||||
launch_vectorized_fp16_to_fp32<2>(stream, output, input);
|
||||
} else {
|
||||
launch_vectorized_fp16_to_fp32<1>(stream, output, input);
|
||||
}
|
||||
}
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,853 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_FUNCTORS_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_FUNCTORS_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/nvcc_defs.hpp"
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
template <class T>
|
||||
struct IdentityFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE IdentityFunctor() { }
|
||||
CUDA4DNN_DEVICE IdentityFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ReLUFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : slope(0) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T slope_) : slope(slope_) { }
|
||||
T slope;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ReLUFunctor() : ReLUFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ReLUFunctor(const Params& params) : slope(params.slope) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::log1pexp;
|
||||
return value >= T(0) ? value : slope * value;
|
||||
}
|
||||
|
||||
T slope;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ClippedReLUFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : floor(0), ceiling(6) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T floor_, T ceiling_) : floor(floor_), ceiling(ceiling_) { }
|
||||
T floor, ceiling;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ClippedReLUFunctor() : ClippedReLUFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ClippedReLUFunctor(const Params& params) : floor{params.floor}, ceiling{params.ceiling} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::clamp;
|
||||
return clamp(value, floor, ceiling);
|
||||
}
|
||||
|
||||
T floor, ceiling;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct TanHFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE TanHFunctor() { }
|
||||
CUDA4DNN_DEVICE TanHFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::tanh;
|
||||
return tanh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SwishFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SwishFunctor() { }
|
||||
CUDA4DNN_DEVICE SwishFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
// f(x) = x * sigmoid(x)
|
||||
using csl::device::fast_divide;
|
||||
using csl::device::fast_exp;
|
||||
return fast_divide(value, static_cast<T>(1) + fast_exp(-value));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct MishFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE MishFunctor() { }
|
||||
CUDA4DNN_DEVICE MishFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::tanh;
|
||||
using csl::device::log1pexp;
|
||||
return value * tanh(log1pexp(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MishFunctor<float> {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE MishFunctor() { }
|
||||
CUDA4DNN_DEVICE MishFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE float operator()(float value) {
|
||||
// f(x) = x * tanh(log1pexp(x));
|
||||
using csl::device::fast_divide;
|
||||
using csl::device::fast_exp;
|
||||
|
||||
auto e = fast_exp(value);
|
||||
auto n = e * e + 2 * e;
|
||||
if (value <= -0.6f)
|
||||
return value * fast_divide(n, n + 2);
|
||||
return value - 2 * fast_divide(value, n + 2);
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <>
|
||||
struct MishFunctor<__half> {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE MishFunctor() { }
|
||||
CUDA4DNN_DEVICE MishFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE __half operator()(__half value) {
|
||||
return MishFunctor<float>()(value);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct SigmoidFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SigmoidFunctor() { }
|
||||
CUDA4DNN_DEVICE SigmoidFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::fast_sigmoid;
|
||||
return fast_sigmoid(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ELUFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : alpha(1) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T alpha_) : alpha(alpha_) { }
|
||||
T alpha;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ELUFunctor() : ELUFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ELUFunctor(const Params& params) : alpha{params.alpha} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::expm1;
|
||||
return value >= T(0) ? value : alpha * expm1(value);
|
||||
}
|
||||
|
||||
T alpha;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AbsFunctor {
|
||||
struct Params { };
|
||||
|
||||
CUDA4DNN_DEVICE AbsFunctor() { }
|
||||
CUDA4DNN_DEVICE AbsFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::abs;
|
||||
return abs(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct BNLLFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE BNLLFunctor() { }
|
||||
CUDA4DNN_DEVICE BNLLFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::log1pexp;
|
||||
return value > T(0) ? value + log1pexp(-value) : log1pexp(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct CeilFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE CeilFunctor() { }
|
||||
CUDA4DNN_DEVICE CeilFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::ceil;
|
||||
return ceil(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct FloorFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE FloorFunctor() { }
|
||||
CUDA4DNN_DEVICE FloorFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::floor;
|
||||
return floor(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct LogFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE LogFunctor() { }
|
||||
CUDA4DNN_DEVICE LogFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::log;
|
||||
return log(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct RintFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE RintFunctor() { }
|
||||
CUDA4DNN_DEVICE RintFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::rint;
|
||||
return rint(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SqrtFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SqrtFunctor() { }
|
||||
CUDA4DNN_DEVICE SqrtFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::sqrt;
|
||||
return sqrt(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct NotFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE NotFunctor() { }
|
||||
CUDA4DNN_DEVICE NotFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::floor;
|
||||
return floor(static_cast<T>(1.) - value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AcosFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AcosFunctor() { }
|
||||
CUDA4DNN_DEVICE AcosFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::acos;
|
||||
return acos(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AcoshFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AcoshFunctor() { }
|
||||
CUDA4DNN_DEVICE AcoshFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::acosh;
|
||||
return acosh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AsinFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AsinFunctor() { }
|
||||
CUDA4DNN_DEVICE AsinFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::asin;
|
||||
return asin(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AsinhFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AsinhFunctor() { }
|
||||
CUDA4DNN_DEVICE AsinhFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::asinh;
|
||||
return asinh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AtanFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AtanFunctor() { }
|
||||
CUDA4DNN_DEVICE AtanFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::atan;
|
||||
return atan(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AtanhFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE AtanhFunctor() { }
|
||||
CUDA4DNN_DEVICE AtanhFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::atanh;
|
||||
return atanh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct CosFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE CosFunctor() { }
|
||||
CUDA4DNN_DEVICE CosFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::cos;
|
||||
return cos(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct CoshFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE CoshFunctor() { }
|
||||
CUDA4DNN_DEVICE CoshFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::cosh;
|
||||
return cosh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ErfFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ErfFunctor() { }
|
||||
CUDA4DNN_DEVICE ErfFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::erf;
|
||||
return erf(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct HardSwishFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE HardSwishFunctor() { }
|
||||
CUDA4DNN_DEVICE HardSwishFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::clamp; // saturate?
|
||||
return value * clamp(value / static_cast<T>(6.f) + static_cast<T>(0.5f), static_cast<T>(0.f), static_cast<T>(1.f));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SinFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SinFunctor() { }
|
||||
CUDA4DNN_DEVICE SinFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::sin;
|
||||
return sin(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SinhFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SinhFunctor() { }
|
||||
CUDA4DNN_DEVICE SinhFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::sinh;
|
||||
return sinh(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SoftplusFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SoftplusFunctor() { }
|
||||
CUDA4DNN_DEVICE SoftplusFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::log1pexp;
|
||||
return log1pexp(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SoftsignFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SoftsignFunctor() { }
|
||||
CUDA4DNN_DEVICE SoftsignFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::abs;
|
||||
return value / (static_cast<T>(1.f) + abs(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct TanFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE TanFunctor() { }
|
||||
CUDA4DNN_DEVICE TanFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::tan;
|
||||
return tan(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct CeluFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : alpha(1) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T alpha_) : alpha(alpha_) { }
|
||||
T alpha;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE CeluFunctor() : CeluFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE CeluFunctor(const Params& params) : alpha{params.alpha} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::min;
|
||||
using csl::device::max;
|
||||
using csl::device::expm1;
|
||||
return max(T(0), value) + min(T(0), alpha * expm1(value / alpha));
|
||||
}
|
||||
|
||||
T alpha;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct HardSigmoidFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : alpha(0.2), beta(0.5) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T alpha_, T beta_) : alpha(alpha_), beta(beta_) { }
|
||||
T alpha, beta;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE HardSigmoidFunctor() : HardSigmoidFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE HardSigmoidFunctor(const Params& params): alpha{params.alpha}, beta{params.beta} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::clamp;
|
||||
return clamp(alpha * value + beta, T(0), T(1));
|
||||
}
|
||||
|
||||
T alpha, beta;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SeluFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : alpha(1.6732632423543772848170429916717),
|
||||
gamma(1.0507009873554804934193349852946) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T alpha_, T gamma_) : alpha(alpha_), gamma(gamma_) { }
|
||||
T alpha, gamma;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SeluFunctor() : SeluFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE SeluFunctor(const Params& params): alpha{params.alpha}, gamma{params.gamma} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::expm1;
|
||||
return gamma * (value > T(0) ? value : alpha * expm1(value));
|
||||
}
|
||||
|
||||
T alpha, gamma;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GeluFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE GeluFunctor() { }
|
||||
CUDA4DNN_DEVICE GeluFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::erf;
|
||||
return static_cast<T>(0.5f) * value * (static_cast<T>(1.f) + erf(value * static_cast<T>(M_SQRT1_2)));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ThresholdedReluFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : alpha(1) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T alpha_) : alpha(alpha_) { }
|
||||
T alpha;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ThresholdedReluFunctor() : ThresholdedReluFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ThresholdedReluFunctor(const Params& params) : alpha{params.alpha} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
return (value > alpha) ? value : T(0);
|
||||
}
|
||||
|
||||
T alpha;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct PowerFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : exp(1), scale(1), shift(0) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T exp_, T scale_, T shift_) : exp(exp_), scale(scale_), shift(shift_) { }
|
||||
T exp, scale, shift;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE PowerFunctor() : PowerFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE PowerFunctor(const Params& params) : exp{params.exp}, scale{params.scale}, shift{params.shift} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::pow;
|
||||
return pow(shift + scale * value, exp);
|
||||
}
|
||||
|
||||
T exp, scale, shift;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ExpFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : normScale(1), normShift(0) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T nScale_, T nShift_) : normScale(nScale_), normShift(nShift_) { }
|
||||
T normScale, normShift;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ExpFunctor() : ExpFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ExpFunctor(const Params& params) : normScale{params.normScale}, normShift{params.normShift} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
using csl::device::fast_exp;
|
||||
return fast_exp(normShift + normScale * value);
|
||||
}
|
||||
|
||||
T normScale, normShift;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct MaxFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE MaxFunctor() { }
|
||||
CUDA4DNN_DEVICE MaxFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) {
|
||||
using csl::device::max;
|
||||
return max(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct MinFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE MinFunctor() { }
|
||||
CUDA4DNN_DEVICE MinFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) {
|
||||
using csl::device::min;
|
||||
return min(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SumFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SumFunctor() { }
|
||||
CUDA4DNN_DEVICE SumFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) { return x + y; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ScaledSumFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : scale_x(1), scale_y(1) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T scale_x_, T scale_y_) : scale_x(scale_x_), scale_y(scale_y_) { }
|
||||
T scale_x, scale_y;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ScaledSumFunctor() : scale_x(1), scale_y(1) { }
|
||||
CUDA4DNN_DEVICE ScaledSumFunctor(const Params& params) : scale_x{params.scale_x}, scale_y{params.scale_y} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) { return scale_x * x + scale_y * y; }
|
||||
|
||||
T scale_x, scale_y;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ProductFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ProductFunctor() { }
|
||||
CUDA4DNN_DEVICE ProductFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) { return x * y; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct DivFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE DivFunctor() { }
|
||||
CUDA4DNN_DEVICE DivFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) { return x / y; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SubFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() { }
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SubFunctor() { }
|
||||
CUDA4DNN_DEVICE SubFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) { return x - y; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SignFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() {}
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE SignFunctor() { }
|
||||
CUDA4DNN_DEVICE SignFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
return value > T(0) ? T(1) : (value < T(0) ? T(-1) : T(0));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ShrinkFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() : bias(0), lambd(0.5) { }
|
||||
CUDA4DNN_HOST_DEVICE Params(T bias_, T lambd_) : bias(bias_), lambd(lambd_) { }
|
||||
T bias, lambd;
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ShrinkFunctor() : ShrinkFunctor(Params{}) { }
|
||||
CUDA4DNN_DEVICE ShrinkFunctor(const Params& params) : bias{params.bias}, lambd{params.lambd} { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
return value > lambd ? value - bias : (value < -lambd ? value + bias : T(0));
|
||||
}
|
||||
|
||||
T bias, lambd;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ReciprocalFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() {}
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ReciprocalFunctor() { }
|
||||
CUDA4DNN_DEVICE ReciprocalFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T value) {
|
||||
return T(1.f)/value;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ModFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() {}
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE ModFunctor() { }
|
||||
CUDA4DNN_DEVICE ModFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) {
|
||||
int res = (int)x % (int)y;
|
||||
T zero = T(0);
|
||||
if ((res > (int)zero && y < zero) || (res < (int)zero && y > zero)) {
|
||||
res += (int)y;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct FModFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() {}
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE FModFunctor() { }
|
||||
CUDA4DNN_DEVICE FModFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) {
|
||||
using csl::device::fmod;
|
||||
return fmod(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct PowFunctor {
|
||||
struct Params {
|
||||
CUDA4DNN_HOST_DEVICE Params() {}
|
||||
};
|
||||
|
||||
CUDA4DNN_DEVICE PowFunctor() { }
|
||||
CUDA4DNN_DEVICE PowFunctor(const Params& params) { }
|
||||
|
||||
CUDA4DNN_DEVICE T operator()(T x, T y) {
|
||||
using csl::device::pow;
|
||||
return pow(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_FUNCTORS_HPP */
|
||||
@@ -0,0 +1,467 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "bbox_utils.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "block_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "vector_traits.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
|
||||
template <class T, bool NORMALIZED_BBOX, int BLOCK_SIZE>
|
||||
__launch_bounds__(BLOCK_SIZE)
|
||||
__global__ void grid_nms(Span<unsigned int> mask_, Span<int> count_, View<T> bboxes_, size_type num_classes, index_type background_class_id, size_type topK, size_type topK_gs, float nms_threshold)
|
||||
{
|
||||
// topK_gs is topK rounded upwards to some size
|
||||
|
||||
// mask: [batch_size, num_classes, topK_gs, topK_gs / 32]
|
||||
// bboxes: [batch_size, num_classes, topK, 4]
|
||||
// count: [batch_size, num_classes]
|
||||
|
||||
const index_type c = blockIdx.y;
|
||||
const index_type b = blockIdx.z;
|
||||
|
||||
if (c == background_class_id)
|
||||
return;
|
||||
|
||||
auto mask = mask_.data() + (b * num_classes + c) * topK_gs * topK_gs / 32;
|
||||
auto bboxes = bboxes_.data() + (b * num_classes + c) * topK * 4;
|
||||
auto count = count_.data() + b * num_classes + c;
|
||||
|
||||
const auto boxes = *count;
|
||||
if (boxes == 0)
|
||||
return;
|
||||
|
||||
/* We divide the set of boxes into groups containing BLOCK_SIZE boxes */
|
||||
const auto num_groups = (boxes + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||
|
||||
/* We need to calculate IOUs for every pair of boxes. We can generalize and say that
|
||||
* we need to compute IOUs of every group with every other group including itself.
|
||||
*/
|
||||
// Each block processes a pair of groups.
|
||||
const index_type group_i = blockIdx.x % num_groups;
|
||||
const index_type group_j = blockIdx.x / num_groups;
|
||||
|
||||
/* we use __syncthreads() later but note that the following condition will cause all threads
|
||||
* in the block to exit; hence, no thread will execute a divergent __syncthreads()
|
||||
*/
|
||||
if (group_i >= num_groups || group_j >= num_groups)
|
||||
return;
|
||||
|
||||
/* Note that IOU(A, B) = IOU(B, A). Hence, if we compute IOU(GROUP_A, GROUP_B), we do not need
|
||||
* to compute IOU(GROUP_B, GROUP_A). We still have to compute IOU(GROUP_A, GROUP_A) though since
|
||||
* each group has many boxes and we need IOUs amongst boxes within a group.
|
||||
*
|
||||
* We arbitrarily choose a scheme to exit : exit if group_i is greater than group_j. This way we only
|
||||
* compute IOUs between groups once. While nearly half the blocks are wasted, it's ok since they exit
|
||||
* early on and the working blocks are compute heavy.
|
||||
*/
|
||||
if (group_i > group_j)
|
||||
return;
|
||||
|
||||
/* the following variables contain the absolute box number of the first box of their respective groups */
|
||||
const auto group_i_offset = group_i * BLOCK_SIZE;
|
||||
const auto group_j_offset = group_j * BLOCK_SIZE;
|
||||
|
||||
/* MAIN LOOP LOGIC:
|
||||
* We compare a box `i` from group_i with all boxes in group_j in each iteration. The box `j` is fixed
|
||||
* for each thread. The `j` exactly maps to the thread index. Hence, the `j` is a loop invariant. Each
|
||||
* thread of the block computes the overlap between box `i` and its box `j`.
|
||||
*
|
||||
* for (int i = 0; i < BLOCK_SIZE; i++)
|
||||
* {
|
||||
* // i = box 1
|
||||
* // j = threadIdx.x = box 2
|
||||
* }
|
||||
*/
|
||||
|
||||
/* The `j` box is fixed for each thread. All `i` boxes will be required for every thread.
|
||||
* We store the `i` boxes in shared memory to allow global memory coalescing.
|
||||
*/
|
||||
using vector_type = get_vector_type_t<T, 4>;
|
||||
__shared__ vector_type group_i_boxes[BLOCK_SIZE];
|
||||
|
||||
/* We will precompute the sizes of `i` boxes in the code where we load them. The size computation
|
||||
* is distributed across the block. Otherwise, all threads will have to compute the size of the same
|
||||
* box simultaneously in the main loop. The size is computed while the memory subsystem is busy
|
||||
* servicing requests for box coordinates; the compute resources would otherwise be idle in this phase.
|
||||
*/
|
||||
/* we store the size as a float since the size can exceed fp16 limits for unnormalized boxes */
|
||||
__shared__ float group_i_size[BLOCK_SIZE];
|
||||
|
||||
const auto bboxes_vPtr = vector_type::get_pointer(bboxes);
|
||||
|
||||
// load `i` boxes and precompute their sizes
|
||||
{
|
||||
int i = threadIdx.x;
|
||||
if (group_i_offset + i < boxes)
|
||||
{
|
||||
vector_type box;
|
||||
v_load(box, bboxes_vPtr[group_i_offset + i]);
|
||||
v_store(group_i_boxes[i], box);
|
||||
|
||||
BoundingBox bbox;
|
||||
bbox.xmin = box.data[0];
|
||||
bbox.ymin = box.data[1];
|
||||
bbox.xmax = box.data[2];
|
||||
bbox.ymax = box.data[3];
|
||||
|
||||
group_i_size[i] = compute_bbox_size<NORMALIZED_BBOX>(bbox);
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
/* We compute overlap between boxes and check if the IOU exceeds the nms threshold.
|
||||
* We store the result (exceeds or below nms_thresold) in a two-dimensional matrix.
|
||||
* (i, j) is set to one if the overlap between i and j is within the nms threshold.
|
||||
* We pack 32 results into one 32-bit integer. The effective memory layout of the
|
||||
* matrix hence is (BLOCK_SIZE, BLOCK_SIZE / 32).
|
||||
*/
|
||||
__shared__ unsigned int mask_shared[BLOCK_SIZE * BLOCK_SIZE / 32];
|
||||
|
||||
// load box `j` and precompute its size (fixed per thread)
|
||||
BoundingBox bbox_j;
|
||||
float bbox_j_size = 0;
|
||||
if (group_j_offset + threadIdx.x < boxes)
|
||||
{
|
||||
vector_type box;
|
||||
v_load(box, bboxes_vPtr[group_j_offset + threadIdx.x]);
|
||||
|
||||
bbox_j.xmin = box.data[0];
|
||||
bbox_j.ymin = box.data[1];
|
||||
bbox_j.xmax = box.data[2];
|
||||
bbox_j.ymax = box.data[3];
|
||||
|
||||
bbox_j_size = compute_bbox_size<NORMALIZED_BBOX>(bbox_j);
|
||||
}
|
||||
|
||||
/* Each thread computes a predicate which is broadcasted across the warp to obtain a 32-bit mask.
|
||||
* The lane zero thread of each warp saves the mask. We store the offset to the mask array beforehand
|
||||
* to save cycles in the compute-intensive main loop.
|
||||
*/
|
||||
auto mask_offset = threadIdx.x / 32;
|
||||
|
||||
/* The main loop is compute intensive and causes the kernel to be overall compute-bound. Hence,
|
||||
* this loop has been highly tuned. Please profile and verify carefully before making changes.
|
||||
*/
|
||||
/* UNROLL_SIZE is the number of boxes that must be processed per iteration. We manually unroll
|
||||
* the loop since the compiler cannot effectively unroll on its own presumably due to presence
|
||||
* of instructions forcing warp synchronization.
|
||||
*/
|
||||
constexpr int UNROLL_SIZE = 4;
|
||||
|
||||
#pragma unroll 8
|
||||
for (int s = 0; s < BLOCK_SIZE; s += UNROLL_SIZE)
|
||||
{
|
||||
bool do_not_reject_j[UNROLL_SIZE];
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < UNROLL_SIZE; k++)
|
||||
{
|
||||
int i = s + k;
|
||||
|
||||
/* The number of boxes need not necessarily be a multiple of BLOCK_SIZE.
|
||||
* However, the shared memory allocated can hold BLOCK_SIZE boxes from
|
||||
* each group. Accessing the undefined regions of shared memory is
|
||||
* a valid memory operation as long as the memory has been allocated.
|
||||
*
|
||||
* The condition below is only required when one of the groups does not
|
||||
* fully filled with valid boxes. This situations are relatively rare. It's
|
||||
* more common to see both groups completely filled.
|
||||
*
|
||||
* We comment this condition to improve the performance of the common case.
|
||||
* This leads to a net improvement.
|
||||
*/
|
||||
// if (group_i_offset + i < boxes && group_j_offset + threadIdx.x < boxes)
|
||||
{
|
||||
BoundingBox bbox_i;
|
||||
float bbox_i_size;
|
||||
{
|
||||
vector_type box;
|
||||
v_load(box, group_i_boxes[i]);
|
||||
bbox_i.xmin = box.data[0];
|
||||
bbox_i.ymin = box.data[1];
|
||||
bbox_i.xmax = box.data[2];
|
||||
bbox_i.ymax = box.data[3];
|
||||
|
||||
bbox_i_size = group_i_size[i];
|
||||
}
|
||||
|
||||
using device::min;
|
||||
using device::max;
|
||||
|
||||
BoundingBox intersect_bbox;
|
||||
intersect_bbox.xmin = max(bbox_i.xmin, bbox_j.xmin);
|
||||
intersect_bbox.ymin = max(bbox_i.ymin, bbox_j.ymin);
|
||||
intersect_bbox.xmax = min(bbox_i.xmax, bbox_j.xmax);
|
||||
intersect_bbox.ymax = min(bbox_i.ymax, bbox_j.ymax);
|
||||
|
||||
float intersect_size = compute_bbox_size<NORMALIZED_BBOX>(intersect_bbox);
|
||||
|
||||
using device::fast_divide_ftz;
|
||||
float iou = fast_divide_ftz(intersect_size, bbox_i_size + bbox_j_size - intersect_size);
|
||||
do_not_reject_j[k] = iou <= nms_threshold;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < UNROLL_SIZE; k++)
|
||||
{
|
||||
// FORWARD_COMPATIBILITY_TAG: WARP_SIZE_DEPENDENT_CODE
|
||||
auto predicate = __ballot_sync(0xFFFFFFFF, do_not_reject_j[k]);
|
||||
if (threadIdx.x % 32 == 0)
|
||||
mask_shared[mask_offset] = predicate;
|
||||
|
||||
/* The following operation should logically be inside the previous if branch. Note that `mask_offset`
|
||||
* is only used by lane zero threads. Hence, there is no harm in executing it other threads as it is
|
||||
* unused there.
|
||||
*
|
||||
* Keeping it inside prevents the compiler from treating it as a constexpr addition to the address in
|
||||
* successive unrolled iterations. A register is used and instructions are emitted to multiply the
|
||||
* addend by four to obtain the byte offset. Pulling it out of the branch makes the compiler do constexpr
|
||||
* addition on the address in successive unrolled iterations.
|
||||
*/
|
||||
mask_offset += BLOCK_SIZE / 32;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
/* The mask data is organized as a two-dimensional bit matrix of size topK_gs * topK_gs.
|
||||
* (i, j) is set to true if the overlap between `i` and `j` is beyond the nms threshold.
|
||||
* We pack 32 results into one 32-bit integer. So the effective memory layout is topK_gs * topK_gs / 32.
|
||||
*/
|
||||
|
||||
/* Each box `i` was compared with BLOCK_SIZE `j` boxes. This amounts to BLOCK_SIZE / 32
|
||||
* 32-bit integers per box `i`.
|
||||
*/
|
||||
using mask_vector_type = get_vector_type_t<unsigned int, BLOCK_SIZE / 32>;
|
||||
|
||||
const int i = threadIdx.x;
|
||||
|
||||
auto mask_shared_vPtr = mask_vector_type::get_pointer(DevicePtr<unsigned>(mask_shared));
|
||||
mask_vector_type temp;
|
||||
v_load(temp, mask_shared_vPtr[i]);
|
||||
for (int i = 0; i < mask_vector_type::size(); i++)
|
||||
temp.data[i] = __brev(temp.data[i]);
|
||||
|
||||
auto mask_vPtr = mask_vector_type::get_pointer(mask);
|
||||
v_store(mask_vPtr[((group_i_offset + i) * topK_gs + group_j_offset) / 32 / mask_vector_type::size()], temp);
|
||||
}
|
||||
|
||||
template <int ITEMS_PER_THREAD, int BLOCK_SIZE>
|
||||
__launch_bounds__(BLOCK_SIZE)
|
||||
__global__ void grid_nms_collect(Span<int> indices_, Span<int> count_, View<unsigned int> mask_, size_type num_classes, index_type background_class_id, size_type topK, size_type topK_gs_by32)
|
||||
{
|
||||
const index_type c = blockIdx.x;
|
||||
if (c == background_class_id)
|
||||
return;
|
||||
|
||||
const index_type b = blockIdx.y;
|
||||
|
||||
// topK_gs is topK rounded upwards to some size
|
||||
|
||||
// indices: [batch_size, num_classes, topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// mask: [batch_size, num_classes, topK_gs, topK_gs / 32]
|
||||
|
||||
auto indices = indices_.data() + (b * num_classes + c) * topK;
|
||||
auto count = count_.data() + (b * num_classes + c);
|
||||
auto mask = mask_.data() + (b * num_classes + c) * topK_gs_by32 * 32 * topK_gs_by32;
|
||||
|
||||
const auto boxes = *count;
|
||||
if (boxes == 0)
|
||||
return;
|
||||
|
||||
/* We have a fixed number of threads and an arbitrary number of boxes. We use an array of
|
||||
* bits to store which boxes haven't been eliminated and which are still active. We organize
|
||||
* the array of bits into a matrix of bits of the shape (num_rows, BLOCK_SIZE, 32) which
|
||||
* is equivalent to (num_rows, BLOCK_SIZE) where the type is a 32-bit unsigned integer.
|
||||
* `num_rows` is the minimum number of rows required to cover all the boxes.
|
||||
*
|
||||
* Each thread handles a specific column in the matrix. To improve performance, we process
|
||||
* `ITEMS_PER_THREAD` number of elements per thread. This changes the shape to (num_rows,
|
||||
* ROW_WIDTH) where ROW_WIDTH is BLOCK_SIZE * ITEMS_PER_THREAD.
|
||||
*/
|
||||
constexpr int ROW_WIDTH = BLOCK_SIZE * ITEMS_PER_THREAD;
|
||||
|
||||
const index_type num_32b_masks = static_cast<unsigned>(boxes + 31) / 32;
|
||||
const index_type num_rows = static_cast<unsigned>(num_32b_masks + ROW_WIDTH - 1) / ROW_WIDTH;
|
||||
|
||||
extern __shared__ unsigned int active_boxes[]; // the matrix described earlier
|
||||
|
||||
#pragma unroll 1
|
||||
for (auto idx : block_stride_range<BLOCK_SIZE>(num_32b_masks))
|
||||
active_boxes[idx] = (idx == num_32b_masks - 1) ? __brev((1u << (boxes % 32)) - 1) : 0xFFFFFFFF;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
using vector_type = get_vector_type_t<unsigned int, ITEMS_PER_THREAD>;
|
||||
auto mask_vPtr = vector_type::get_pointer(mask);
|
||||
auto shared_vPtr = vector_type::get_pointer(DevicePtr<unsigned>(active_boxes));
|
||||
|
||||
int index_temp;
|
||||
int thread0_count = 0;
|
||||
int thread_id = threadIdx.x;
|
||||
|
||||
for (int step = 0; step < num_32b_masks; step++)
|
||||
{
|
||||
auto current_active = active_boxes[step];
|
||||
while (current_active)
|
||||
{
|
||||
const index_type bit = __clz(current_active);
|
||||
const index_type i = step * 32 + bit;
|
||||
|
||||
const int mask_offset = static_cast<unsigned>(i * topK_gs_by32) / ITEMS_PER_THREAD;
|
||||
|
||||
/* We fetch the index from the memory and store it in a register. We will not use it until
|
||||
* much later. This helps avoid a long scoreboard stall.
|
||||
*/
|
||||
if (thread_id == 0)
|
||||
index_temp = indices[i];
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
active_boxes[step] = current_active ^ (0x80000000 >> bit);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
#pragma unroll 1
|
||||
for (int r = 0; r < num_rows; r++)
|
||||
{
|
||||
const int idx = r * BLOCK_SIZE + thread_id;
|
||||
if ((step & ~(ITEMS_PER_THREAD - 1)) <= idx * ITEMS_PER_THREAD && idx * ITEMS_PER_THREAD < num_32b_masks)
|
||||
{
|
||||
auto active_boxes_vec = shared_vPtr[idx];
|
||||
auto mask_vec = mask_vPtr[mask_offset + idx];
|
||||
for (int i = 0; i < vector_type::size(); i++)
|
||||
active_boxes_vec.data[i] &= mask_vec.data[i];
|
||||
shared_vPtr[idx] = active_boxes_vec;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (thread_id == 0)
|
||||
{
|
||||
indices[thread0_count] = index_temp;
|
||||
thread0_count++;
|
||||
}
|
||||
|
||||
current_active = active_boxes[step];
|
||||
}
|
||||
}
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
*count = thread0_count;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int GROUP_SIZE = 128;
|
||||
|
||||
static std::size_t getAlignedTopK(std::size_t topK)
|
||||
{
|
||||
auto remainder = topK % GROUP_SIZE;
|
||||
if (remainder == 0)
|
||||
return topK;
|
||||
return topK + (GROUP_SIZE - remainder);
|
||||
}
|
||||
|
||||
std::size_t getGridNMSWorkspaceSizePerBatchItem(std::size_t num_classes, std::size_t classwise_topK)
|
||||
{
|
||||
auto topK_gs = getAlignedTopK(classwise_topK);
|
||||
return num_classes * topK_gs * topK_gs / 32 * sizeof(unsigned int);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void grid_nms(const Stream& stream, Span<unsigned int> workspace, TensorSpan<int> indices, TensorSpan<int> count, TensorView<T> bboxes, int background_class_id, bool normalized_bbox, float nms_threshold)
|
||||
{
|
||||
// workspace: [batch_size, num_classes, topK_gs, topK_gs / 32]
|
||||
// indices: [batch_size, num_classes, topK]
|
||||
// count: [batch_size, num_classes]
|
||||
// bboxes: [batch_size, num_classes, topK, 4] (only first count[b][c] boxes are read)
|
||||
|
||||
const auto batch_size = indices.get_axis_size(0);
|
||||
CV_Assert(count.get_axis_size(0) == batch_size);
|
||||
CV_Assert(bboxes.get_axis_size(0) == batch_size);
|
||||
|
||||
const auto num_classes = indices.get_axis_size(1);
|
||||
CV_Assert(count.get_axis_size(1) == num_classes);
|
||||
CV_Assert(bboxes.get_axis_size(1) == num_classes);
|
||||
|
||||
const auto topK = indices.get_axis_size(2);
|
||||
CV_Assert(bboxes.get_axis_size(2) == topK);
|
||||
|
||||
CV_Assert(bboxes.get_axis_size(3) == 4);
|
||||
|
||||
const auto topK_gs = getAlignedTopK(topK);
|
||||
CV_Assert(workspace.size() >= topK_gs * topK_gs / 32);
|
||||
|
||||
const auto boxes = topK;
|
||||
const auto num_groups = (boxes + GROUP_SIZE - 1) / GROUP_SIZE;
|
||||
|
||||
{
|
||||
// grid = (num_groups * num_groups, num_classes, batch_size)
|
||||
// if the background class is the last class, we can reduce grid y dim by one
|
||||
auto grid_num_classes = num_classes; //(background_class_id == num_classes - 1) ? num_classes - 1 : num_classes;
|
||||
|
||||
constexpr int BLOCK_SIZE = GROUP_SIZE;
|
||||
|
||||
dim3 grid_size(num_groups * num_groups, grid_num_classes, batch_size);
|
||||
dim3 block_size(BLOCK_SIZE);
|
||||
auto policy = execution_policy(grid_size, block_size, stream);
|
||||
|
||||
if (normalized_bbox)
|
||||
{
|
||||
auto kernel = raw::grid_nms<T, true, BLOCK_SIZE>;
|
||||
launch_kernel(kernel, policy, workspace, count, bboxes, num_classes, background_class_id, topK, topK_gs, nms_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto kernel = raw::grid_nms<T, false, BLOCK_SIZE>;
|
||||
launch_kernel(kernel, policy, workspace, count, bboxes, num_classes, background_class_id, topK, topK_gs, nms_threshold);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// grid = (num_classes, batch_size)
|
||||
// if the background class is the last class, we can reduce grid x dim by one
|
||||
auto grid_num_classes = num_classes; //(background_class_id == num_classes - 1) ? num_classes - 1 : num_classes;
|
||||
|
||||
constexpr int BLOCK_SIZE = 64;
|
||||
|
||||
constexpr int ITEMS_PER_THREAD = 4;
|
||||
auto kernel = raw::grid_nms_collect<ITEMS_PER_THREAD, BLOCK_SIZE>;
|
||||
|
||||
dim3 grid_size(grid_num_classes, batch_size);
|
||||
|
||||
auto sharedMem = topK_gs / 32 * 4;
|
||||
auto policy = execution_policy(grid_size, BLOCK_SIZE, sharedMem, stream);
|
||||
launch_kernel(kernel, policy, indices, count, workspace, num_classes, background_class_id, topK, topK_gs / 32);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t getGridNMSWorkspaceSizePerBatchItem(std::size_t num_classes, std::size_t classwise_topK);
|
||||
|
||||
template void grid_nms(const Stream& stream, Span<unsigned int> workspace, TensorSpan<int> indices, TensorSpan<int> count, TensorView<__half> bboxes, int, bool normalized_bbox, float nms_threshold);
|
||||
template void grid_nms(const Stream& stream, Span<unsigned int> workspace, TensorSpan<int> indices, TensorSpan<int> count, TensorView<float> bboxes, int, bool normalized_bbox, float nms_threshold);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_GRID_STRIDE_RANGE_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_GRID_STRIDE_RANGE_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
#include "index_helpers.hpp"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <int dim, class index_type = device::index_type, class size_type = device::size_type>
|
||||
class grid_stride_range_generic {
|
||||
public:
|
||||
__device__ grid_stride_range_generic(index_type to_) : from(0), to(to_) { }
|
||||
__device__ grid_stride_range_generic(index_type from_, index_type to_) : from(from_), to(to_) { }
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
__device__ iterator(index_type pos_) : pos(pos_) {}
|
||||
|
||||
/* these iterators return the index when dereferenced; this allows us to loop
|
||||
* through the indices using a range based for loop
|
||||
*/
|
||||
__device__ index_type operator*() const { return pos; }
|
||||
|
||||
__device__ iterator& operator++() {
|
||||
pos += getGridDim<dim>() * static_cast<index_type>(getBlockDim<dim>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
__device__ bool operator!=(const iterator& other) const {
|
||||
/* NOTE HACK
|
||||
* 'pos' can move in large steps (see operator++)
|
||||
* expansion of range for loop uses != as the loop condition
|
||||
* => operator!= must return false if 'pos' crosses the end
|
||||
*/
|
||||
return pos < other.pos;
|
||||
}
|
||||
|
||||
private:
|
||||
index_type pos;
|
||||
};
|
||||
|
||||
__device__ iterator begin() const {
|
||||
return iterator(from + getBlockDim<dim>() * getBlockIdx<dim>() + getThreadIdx<dim>());
|
||||
}
|
||||
|
||||
__device__ iterator end() const {
|
||||
return iterator(to);
|
||||
}
|
||||
|
||||
private:
|
||||
index_type from, to;
|
||||
};
|
||||
|
||||
using grid_stride_range_x = grid_stride_range_generic<0>;
|
||||
using grid_stride_range_y = grid_stride_range_generic<1>;
|
||||
using grid_stride_range_z = grid_stride_range_generic<2>;
|
||||
using grid_stride_range = grid_stride_range_x;
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_GRID_STRIDE_RANGE_HPP */
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_INDEX_HELPERS_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_INDEX_HELPERS_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
namespace detail {
|
||||
using dim3_member_type = decltype(dim3::x);
|
||||
using uint3_member_type = decltype(uint3::x);
|
||||
}
|
||||
|
||||
template <int> __device__ detail::dim3_member_type getGridDim();
|
||||
template <> inline __device__ detail::dim3_member_type getGridDim<0>() { return gridDim.x; }
|
||||
template <> inline __device__ detail::dim3_member_type getGridDim<1>() { return gridDim.y; }
|
||||
template <> inline __device__ detail::dim3_member_type getGridDim<2>() { return gridDim.z; }
|
||||
|
||||
template <int> __device__ detail::dim3_member_type getBlockDim();
|
||||
template <> inline __device__ detail::dim3_member_type getBlockDim<0>() { return blockDim.x; }
|
||||
template <> inline __device__ detail::dim3_member_type getBlockDim<1>() { return blockDim.y; }
|
||||
template <> inline __device__ detail::dim3_member_type getBlockDim<2>() { return blockDim.z; }
|
||||
|
||||
template <int> __device__ detail::uint3_member_type getBlockIdx();
|
||||
template <> inline __device__ detail::uint3_member_type getBlockIdx<0>() { return blockIdx.x; }
|
||||
template <> inline __device__ detail::uint3_member_type getBlockIdx<1>() { return blockIdx.y; }
|
||||
template <> inline __device__ detail::uint3_member_type getBlockIdx<2>() { return blockIdx.z; }
|
||||
|
||||
template <int> __device__ detail::uint3_member_type getThreadIdx();
|
||||
template <> inline __device__ detail::uint3_member_type getThreadIdx<0>() { return threadIdx.x; }
|
||||
template <> inline __device__ detail::uint3_member_type getThreadIdx<1>() { return threadIdx.y; }
|
||||
template <> inline __device__ detail::uint3_member_type getThreadIdx<2>() { return threadIdx.z; }
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_INDEX_HELPERS_HPP */
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
/* The performance of many kernels are highly dependent on the tensor rank. Instead of having
|
||||
* one kernel which can work with the maximally ranked tensors, we make one kernel for each supported
|
||||
* tensor rank. This is to ensure that the requirements of the maximally ranked tensors do not take a
|
||||
* toll on the performance of the operation for low ranked tensors. Hence, many kernels take the tensor
|
||||
* rank as a template parameter.
|
||||
*
|
||||
* The kernel is a template and we have different instantiations for each rank. This causes the following pattern
|
||||
* to arise frequently:
|
||||
*
|
||||
* if(rank == 3)
|
||||
* kernel<T, 3>();
|
||||
* else if(rank == 2)
|
||||
* kernel<T, 2>();
|
||||
* else
|
||||
* kernel<T, 1>();
|
||||
*
|
||||
* The rank is a runtime variable. To facilitate creation of such structures, we use GENERATE_KERNEL_DISPATCHER.
|
||||
* This macro creates a function which selects the correct kernel instantiation at runtime.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* // function which setups the kernel and launches it
|
||||
* template <class T, std::size_t Rank>
|
||||
* void launch_some_kernel(...);
|
||||
*
|
||||
* // creates the dispatcher named "some_dispatcher" which invokes the correct instantiation of "launch_some_kernel"
|
||||
* GENERATE_KERNEL_DISPATCHER(some_dispatcher, launch_some_kernel);
|
||||
*
|
||||
* // internal API function
|
||||
* template <class T>
|
||||
* void some(...) {
|
||||
* // ...
|
||||
* auto rank = input.rank();
|
||||
* some_dispatcher<T, MIN_RANK, MAX_RANK>(rank, ...);
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
* name name of the dispatcher function that is generated
|
||||
* func template function that requires runtime selection
|
||||
*
|
||||
* T first template parameter to `func`
|
||||
* start starting rank
|
||||
* end ending rank (inclusive)
|
||||
*
|
||||
* Executes func<T, selector> based on runtime `selector` argument given `selector` lies
|
||||
* within the range [start, end]. If outside the range, no instantiation of `func` is executed.
|
||||
*/
|
||||
#define GENERATE_KERNEL_DISPATCHER(name,func); \
|
||||
template <class T, std::size_t start, std::size_t end, class... Args> static \
|
||||
typename std::enable_if<start == end, void> \
|
||||
::type name(int selector, Args&& ...args) { \
|
||||
if(selector == start) \
|
||||
func<T, start>(std::forward<Args>(args)...); \
|
||||
} \
|
||||
\
|
||||
template <class T, std::size_t start, std::size_t end, class... Args> static \
|
||||
typename std::enable_if<start != end, void> \
|
||||
::type name(int selector, Args&& ...args) { \
|
||||
if(selector == start) \
|
||||
func<T, start>(std::forward<Args>(args)...); \
|
||||
else \
|
||||
name<T, start + 1, end, Args...>(selector, std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
// Same as GENERATE_KERNEL_DISPATCHER but takes two class template parameters T and TP1 instead of just T
|
||||
#define GENERATE_KERNEL_DISPATCHER_2TP(name,func); \
|
||||
template <class TP1, class TP2, std::size_t start, std::size_t end, class... Args> static \
|
||||
typename std::enable_if<start == end, void> \
|
||||
::type name(int selector, Args&& ...args) { \
|
||||
if(selector == start) \
|
||||
func<TP1, TP2, start>(std::forward<Args>(args)...); \
|
||||
} \
|
||||
\
|
||||
template <class TP1, class TP2, std::size_t start, std::size_t end, class... Args> static \
|
||||
typename std::enable_if<start != end, void> \
|
||||
::type name(int selector, Args&& ...args) { \
|
||||
if(selector == start) \
|
||||
func<TP1, TP2, start>(std::forward<Args>(args)...); \
|
||||
else \
|
||||
name<TP1, TP2, start + 1, end, Args...>(selector, std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP */
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_LIMITS_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_LIMITS_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <class T>
|
||||
struct numeric_limits;
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <>
|
||||
struct numeric_limits<__half> {
|
||||
__device__ static __half min() { return 0.0000610; }
|
||||
__device__ static __half max() { return 65504.0; }
|
||||
__device__ static __half lowest() { return -65504.0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct numeric_limits<float> {
|
||||
__device__ static float min() { return FLT_MIN; }
|
||||
__device__ static float max() { return FLT_MAX; }
|
||||
__device__ static float lowest() { return -FLT_MAX; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct numeric_limits<signed char> {
|
||||
__device__ static signed char min() { return 1; }
|
||||
__device__ static signed char max() { return SCHAR_MAX; }
|
||||
__device__ static signed char lowest() { return SCHAR_MIN; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct numeric_limits<unsigned char> {
|
||||
__device__ static unsigned char min() { return 1; }
|
||||
__device__ static unsigned char max() { return UCHAR_MAX; }
|
||||
__device__ static unsigned char lowest() { return 0; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct numeric_limits<int32_t> {
|
||||
__device__ static int32_t min() { return 1; }
|
||||
__device__ static int32_t max() { return INT_MAX; }
|
||||
__device__ static int32_t lowest() { return INT_MIN; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct numeric_limits<int64_t> {
|
||||
__device__ static int64_t min() { return 1; }
|
||||
__device__ static int64_t max() { return LLONG_MAX; }
|
||||
__device__ static int64_t lowest() { return LLONG_MIN; }
|
||||
};
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_LIMITS_HPP */
|
||||
@@ -0,0 +1,267 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_MATH_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_MATH_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <class T> __device__ T abs(T val) { return (val < T(0) ? -val : val); }
|
||||
template <> inline __device__ float abs(float val) { return fabsf(val); }
|
||||
template <> inline __device__ double abs(double val) { return fabs(val); }
|
||||
|
||||
template <class T> __device__ T exp(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half exp(__half val) { return hexp(val); }
|
||||
#endif
|
||||
template <> inline __device__ float exp(float val) { return expf(val); }
|
||||
template <> inline __device__ double exp(double val) { return ::exp(val); }
|
||||
|
||||
template <class T> __device__ T expm1(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half expm1(__half val) { return hexp(val) - __half(1); }
|
||||
#endif
|
||||
template <> inline __device__ float expm1(float val) { return expm1f(val); }
|
||||
template <> inline __device__ double expm1(double val) { return ::expm1(val); }
|
||||
|
||||
template <class T> __device__ T max(T x, T y) { return (x > y ? x : y); }
|
||||
template <> inline __device__ float max(float x, float y) { return fmaxf(x, y); }
|
||||
template <> inline __device__ double max(double x, double y) { return fmax(x, y); }
|
||||
|
||||
template <class T> __device__ T min(T x, T y) { return (x > y ? y : x); }
|
||||
template <> inline __device__ float min(float x, float y) { return fminf(x, y); }
|
||||
template <> inline __device__ double min(double x, double y) { return fmin(x, y); }
|
||||
|
||||
template <class T> __device__ T fmod(T x, T y) { return x % y; }
|
||||
template <> inline __device__ float fmod(float x, float y) { return fmodf(x, y); }
|
||||
template <> inline __device__ double fmod(double x, double y) { return fmod(x, y); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ half fmod(half x, half y) { return fmodf((float)x, (float)y); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T log1p(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half log1p(__half val) { return hlog(__half(1) + val); }
|
||||
#endif
|
||||
template <> inline __device__ float log1p(float val) { return log1pf(val); }
|
||||
|
||||
template <class T> __device__ T log1pexp(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half log1pexp(__half val) {
|
||||
if (val <= __half(-4.0))
|
||||
return exp(val);
|
||||
else if (val <= __half(8.0))
|
||||
return log1p(exp(val));
|
||||
else if (val <= __half(8.7))
|
||||
return val + exp(-val);
|
||||
else
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
template <> inline __device__ float log1pexp(float val) {
|
||||
if (val <= -20)
|
||||
return expf(val);
|
||||
else if (val <= 9.0)
|
||||
return log1pf(expf(val));
|
||||
else if (val <= 14.6)
|
||||
return val + exp(-val);
|
||||
else
|
||||
return val;
|
||||
}
|
||||
template <> inline __device__ double log1pexp(double val) {
|
||||
if (val <= -37)
|
||||
return exp(val);
|
||||
else if (val <= 18)
|
||||
return log1p(exp(val));
|
||||
else if (val <= 33.3)
|
||||
return val + exp(-val);
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T> __device__ T tanh(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half tanh(__half val) { return tanhf(val); }
|
||||
#endif
|
||||
template <> inline __device__ float tanh(float val) { return tanhf(val); }
|
||||
template <> inline __device__ double tanh(double val) { return ::tanh(val); }
|
||||
|
||||
// caution: overflow warning casting from double to low-bit types
|
||||
template <class T> __device__ T pow(T val, T exp) { return T(::pow(double(val), double(exp))); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half pow(__half val, __half exp) { return powf(val, exp); }
|
||||
#endif
|
||||
template <> inline __device__ float pow(float val, float exp) { return powf(val, exp); }
|
||||
template <> inline __device__ double pow(double val, double exp) { return ::pow(val, exp); }
|
||||
|
||||
template <class T> __device__ T sqrt(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half sqrt(__half val) { return hsqrt(val); }
|
||||
#endif
|
||||
template <> inline __device__ float sqrt(float val) { return sqrtf(val); }
|
||||
template <> inline __device__ double sqrt(double val) { return ::sqrt(val); }
|
||||
|
||||
template <class T> __device__ T rsqrt(T val);
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half rsqrt(__half val) { return hrsqrt(val); }
|
||||
#endif
|
||||
template <> inline __device__ float rsqrt(float val) { return rsqrtf(val); }
|
||||
template <> inline __device__ double rsqrt(double val) { return ::rsqrt(val); }
|
||||
|
||||
template <class T> __device__ T sigmoid(T val) { return T(1) / (T(1) + exp(-val)); }
|
||||
|
||||
template <class T> __device__ T clamp(T value, T lower, T upper) { return min(max(value, lower), upper); }
|
||||
|
||||
template <class T> __device__ long lround(T value);
|
||||
template <> inline __device__ long lround(double value) { return ::lround(value); }
|
||||
template <> inline __device__ long lround(float value) { return lroundf(value); }
|
||||
|
||||
template <class T> __device__ T round(T value);
|
||||
template <> inline __device__ double round(double value) { return ::round(value); }
|
||||
template <> inline __device__ float round(float value) { return roundf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half round(__half value) { return hrint(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T floor(T value);
|
||||
template <> inline __device__ double floor(double value) { return ::floor(value); }
|
||||
template <> inline __device__ float floor(float value) { return floorf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half floor(__half value) { return hfloor(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T log(T value);
|
||||
template <> inline __device__ double log(double value) { return ::log(value); }
|
||||
template <> inline __device__ float log(float value) { return logf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half log(__half value) { return hlog(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T rint(T value);
|
||||
template <> inline __device__ double rint(double value) { return ::rint(value); }
|
||||
template <> inline __device__ float rint(float value) { return rintf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half rint(__half value) { return hrint(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T acos(T value);
|
||||
template <> inline __device__ double acos(double value) { return ::acos(value); }
|
||||
template <> inline __device__ float acos(float value) { return acosf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half acos(__half value) { return acosf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T acosh(T value);
|
||||
template <> inline __device__ double acosh(double value) { return ::acosh(value); }
|
||||
template <> inline __device__ float acosh(float value) { return acoshf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half acosh(__half value) { return acoshf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T asin(T value);
|
||||
template <> inline __device__ double asin(double value) { return ::asin(value); }
|
||||
template <> inline __device__ float asin(float value) { return asinf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half asin(__half value) { return asinf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T asinh(T value);
|
||||
template <> inline __device__ double asinh(double value) { return ::asinh(value); }
|
||||
template <> inline __device__ float asinh(float value) { return asinhf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half asinh(__half value) { return asinhf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T atan(T value);
|
||||
template <> inline __device__ double atan(double value) { return ::atan(value); }
|
||||
template <> inline __device__ float atan(float value) { return atanf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half atan(__half value) { return atanf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T atanh(T value);
|
||||
template <> inline __device__ double atanh(double value) { return ::atanh(value); }
|
||||
template <> inline __device__ float atanh(float value) { return atanhf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half atanh(__half value) { return atanhf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T cos(T value);
|
||||
template <> inline __device__ double cos(double value) { return ::cos(value); }
|
||||
template <> inline __device__ float cos(float value) { return cosf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half cos(__half value) { return hcos(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T cosh(T value);
|
||||
template <> inline __device__ double cosh(double value) { return ::cosh(value); }
|
||||
template <> inline __device__ float cosh(float value) { return coshf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half cosh(__half value) { return coshf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T erf(T value);
|
||||
template <> inline __device__ double erf(double value) { return ::erf(value); }
|
||||
template <> inline __device__ float erf(float value) { return erff(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half erf(__half value) { return erff(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T sin(T value);
|
||||
template <> inline __device__ double sin(double value) { return ::sin(value); }
|
||||
template <> inline __device__ float sin(float value) { return sinf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half sin(__half value) { return hsin(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T sinh(T value);
|
||||
template <> inline __device__ double sinh(double value) { return ::sinh(value); }
|
||||
template <> inline __device__ float sinh(float value) { return sinhf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half sinh(__half value) { return sinhf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T tan(T value);
|
||||
template <> inline __device__ double tan(double value) { return ::tan(value); }
|
||||
template <> inline __device__ float tan(float value) { return tanf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half tan(__half value) { return tanf(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T ceil(T value);
|
||||
template <> inline __device__ double ceil(double value) { return ::ceil(value); }
|
||||
template <> inline __device__ float ceil(float value) { return ceilf(value); }
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template <> inline __device__ __half ceil(__half value) { return hceil(value); }
|
||||
#endif
|
||||
|
||||
template <class T> __device__ T mul_ftz(T x, T y) { return x * y; }
|
||||
template <> inline __device__ float mul_ftz(float x, float y) {
|
||||
float result;
|
||||
asm("mul.ftz.f32 %0, %1, %2;" : "=f"(result) : "f"(x), "f"(y));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> __device__ T fast_divide(T x, T y) { return x / y; }
|
||||
template <> inline __device__ float fast_divide(float x, float y) { return __fdividef(x, y); }
|
||||
|
||||
template <class T> __device__ T fast_divide_ftz(T x, T y) { return fast_divide(x, y); }
|
||||
template <> inline __device__ float fast_divide_ftz(float x, float y) {
|
||||
float result;
|
||||
asm("div.approx.ftz.f32 %0, %1, %2;" : "=f"(result) : "f"(x), "f"(y));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> __device__ T fast_exp(T value) { return exp(value); }
|
||||
template <> inline __device__ float fast_exp(float value) { return __expf(value); }
|
||||
|
||||
template <class T> __device__ T fast_sigmoid(T value) { return sigmoid(value); }
|
||||
template <> inline __device__ float fast_sigmoid(float value) { return __fdividef(1, 1 + __expf(-value)); }
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_MATH_HPP */
|
||||
@@ -0,0 +1,428 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "array.hpp"
|
||||
#include "limits.hpp"
|
||||
#include "types.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include "../cuda4dnn/kernels/fill_copy.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, class T_INDEX, std::size_t Order,
|
||||
typename std::enable_if<Order == 1 || Order == 2 || Order == 3, bool>::type = true> /* Order has been hardcoded; see code */
|
||||
__global__ void max_pooling_with_indices(
|
||||
Span<T> output, Span<T_INDEX> indices, View<T> input, size_type channels,
|
||||
array<size_type, Order> out_spatial_dims, array<size_type, Order> in_spatial_dims,
|
||||
array<size_type, Order> window_size, array<size_type, Order> strides, array<size_type, Order> padding_left)
|
||||
{
|
||||
/* every element in the output is mapped to a window in the input and each thread processes several windows */
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
size_type out_spatial_size = 1;
|
||||
array<index_type, Order> window_idx;
|
||||
for (int i = Order - 1; i >= 0; i--) {
|
||||
window_idx[i] = (idx / out_spatial_size) % out_spatial_dims[i];
|
||||
out_spatial_size *= out_spatial_dims[i];
|
||||
}
|
||||
|
||||
const index_type n = idx / (out_spatial_size * channels);
|
||||
const index_type c = (idx / out_spatial_size) % channels;
|
||||
|
||||
array<index_type, Order> start;
|
||||
for(int i = 0; i < Order; i++)
|
||||
start[i] = window_idx[i] * strides[i] - padding_left[i];
|
||||
|
||||
array<index_type, Order> end;
|
||||
for (int i = 0; i < Order; i++) {
|
||||
using device::min;
|
||||
end[i] = min<index_type>(start[i] + window_size[i], in_spatial_dims[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Order; i++) {
|
||||
using device::max;
|
||||
start[i] = max(start[i], 0);
|
||||
}
|
||||
|
||||
T max_value = numeric_limits<T>::lowest();
|
||||
index_type max_idx = -1;
|
||||
|
||||
size_type in_spatial_size = 1;
|
||||
for (int i = 0; i < Order; i++)
|
||||
in_spatial_size *= in_spatial_dims[i];
|
||||
|
||||
const auto outer_offset = (n * channels + c) * in_spatial_size;
|
||||
if (Order == 1) {
|
||||
array<index_type, Order> idx;
|
||||
for (idx[0] = start[0]; idx[0] != end[0]; idx[0]++) {
|
||||
index_type offset = 0;
|
||||
index_type stride = 1;
|
||||
for (int i = Order - 1; i >= 0; i--) {
|
||||
offset += stride * idx[i];
|
||||
stride *= in_spatial_dims[i];
|
||||
}
|
||||
|
||||
if (input[outer_offset + offset] > max_value) {
|
||||
max_idx = offset;
|
||||
max_value = input[outer_offset + offset];
|
||||
}
|
||||
}
|
||||
} else if (Order == 2) {
|
||||
array<index_type, Order> idx;
|
||||
for (idx[0] = start[0]; idx[0] != end[0]; idx[0]++) {
|
||||
for (idx[1] = start[1]; idx[1] != end[1]; idx[1]++) {
|
||||
index_type offset = 0;
|
||||
index_type stride = 1;
|
||||
for (int i = Order - 1; i >= 0; i--) {
|
||||
offset += stride * idx[i];
|
||||
stride *= in_spatial_dims[i];
|
||||
}
|
||||
|
||||
if (input[outer_offset + offset] > max_value) {
|
||||
max_idx = offset;
|
||||
max_value = input[outer_offset + offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(Order == 3) {
|
||||
array<index_type, Order> idx;
|
||||
for (idx[0] = start[0]; idx[0] != end[0]; idx[0]++) {
|
||||
for (idx[1] = start[1]; idx[1] != end[1]; idx[1]++) {
|
||||
for (idx[2] = start[2]; idx[2] != end[2]; idx[2]++) {
|
||||
index_type offset = 0;
|
||||
index_type stride = 1;
|
||||
for (int i = Order - 1; i >= 0; i--) {
|
||||
offset += stride * idx[i];
|
||||
stride *= in_spatial_dims[i];
|
||||
}
|
||||
|
||||
if (input[outer_offset + offset] > max_value) {
|
||||
max_idx = offset;
|
||||
max_value = input[outer_offset + offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output[idx] = max_value;
|
||||
indices[idx] = max_idx;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class T_INDEX, std::size_t Order>
|
||||
__global__ void max_unpooling(
|
||||
Span<T> output, View<T> input, View<T_INDEX> indices, size_type channels,
|
||||
array<size_type, Order> out_spatial_dims, array<size_type, Order> in_spatial_dims,
|
||||
array<size_type, Order> window_size, array<size_type, Order> strides, array<size_type, Order> padding_left)
|
||||
{
|
||||
/* the output has already been zero filled */
|
||||
/* Every input value represents a window in the output. The max unpooling operation
|
||||
* copies the input value to exactly one location in the output window which is given
|
||||
* by the indices tensor.
|
||||
*/
|
||||
for (auto idx : grid_stride_range(input.size())) {
|
||||
size_type in_spatial_size = 1;
|
||||
array<index_type, Order> window_idx;
|
||||
for (int i = Order - 1; i >= 0; i--) {
|
||||
window_idx[i] = (idx / in_spatial_size) % in_spatial_dims[i];
|
||||
in_spatial_size *= in_spatial_dims[i];
|
||||
}
|
||||
|
||||
const index_type n = idx / (in_spatial_size * channels);
|
||||
const index_type c = (idx / in_spatial_size) % channels;
|
||||
|
||||
array<index_type, Order> start;
|
||||
for (int i = 0; i < Order; i++) {
|
||||
using device::min;
|
||||
using device::max;
|
||||
start[i] = max(0, min(window_idx[i] * strides[i] - padding_left[i], out_spatial_dims[i] - 1));
|
||||
}
|
||||
|
||||
size_type out_spatial_size = 1;
|
||||
for (int i = 0; i < Order; i++)
|
||||
out_spatial_size *= out_spatial_dims[i];
|
||||
|
||||
index_type outer_offset = (n * channels + c) * out_spatial_size;
|
||||
output[outer_offset + indices[idx]] = input[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class T_INDEX, std::size_t Order> static
|
||||
void launch_max_pooling_kernel(
|
||||
const Stream& stream,
|
||||
Span<T> output, Span<T_INDEX> indices, View<T> input, std::size_t channels,
|
||||
const std::vector<std::size_t>& out_spatial_dims, const std::vector<std::size_t>& in_spatial_dims,
|
||||
const std::vector<std::size_t>& window_size,
|
||||
const std::vector<std::size_t>& strides, const std::vector<std::size_t>& padding_left)
|
||||
{
|
||||
CV_Assert(indices.size() == output.size());
|
||||
CV_Assert(out_spatial_dims.size() == Order);
|
||||
CV_Assert(in_spatial_dims.size() == Order);
|
||||
CV_Assert(window_size.size() == Order);
|
||||
CV_Assert(strides.size() == Order);
|
||||
CV_Assert(padding_left.size() == Order);
|
||||
|
||||
array<size_type, Order> out_spatial_dims_k, in_spatial_dims_k;
|
||||
out_spatial_dims_k.assign(std::begin(out_spatial_dims), std::end(out_spatial_dims));
|
||||
in_spatial_dims_k.assign(std::begin(in_spatial_dims), std::end(in_spatial_dims));
|
||||
|
||||
array<size_type, Order> window_size_k, strides_k, padding_left_k;
|
||||
window_size_k.assign(std::begin(window_size), std::end(window_size));
|
||||
strides_k.assign(std::begin(strides), std::end(strides));
|
||||
padding_left_k.assign(std::begin(padding_left), std::end(padding_left));
|
||||
|
||||
auto kernel = raw::max_pooling_with_indices<T, T_INDEX, Order>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, indices, input, channels,
|
||||
out_spatial_dims_k, in_spatial_dims_k, window_size_k, strides_k, padding_left_k);
|
||||
}
|
||||
|
||||
template <class T, class T_INDEX>
|
||||
void max_pooling_with_indices(
|
||||
const Stream& stream,
|
||||
TensorSpan<T> output, TensorSpan<T_INDEX> indices, TensorView<T> input,
|
||||
const std::vector<std::size_t>& window_size, const std::vector<std::size_t>& strides,
|
||||
const std::vector<std::size_t>& padding_left)
|
||||
{
|
||||
CV_Assert(is_shape_same(output, indices));
|
||||
CV_Assert(input.get_axis_size(1) == output.get_axis_size(1));
|
||||
|
||||
auto order = window_size.size();
|
||||
CV_Assert(strides.size() == order);
|
||||
CV_Assert(padding_left.size() == order);
|
||||
CV_Assert(output.rank() == order + 2);
|
||||
CV_Assert(input.rank() == order + 2);
|
||||
|
||||
std::vector<std::size_t> out_spatial_dims(order), in_spatial_dims(order);
|
||||
for (int i = 0; i < order; i++) {
|
||||
in_spatial_dims[i] = input.get_axis_size(2 + i);
|
||||
out_spatial_dims[i] = output.get_axis_size(2 + i);
|
||||
}
|
||||
|
||||
CV_Assert(1 <= order && order <= 3);
|
||||
std::size_t channels = input.get_axis_size(1);
|
||||
if (order == 3) {
|
||||
launch_max_pooling_kernel<T, T_INDEX, 3>(stream, output, indices, input, channels,
|
||||
out_spatial_dims, in_spatial_dims, window_size, strides, padding_left);
|
||||
} else if (order == 2) {
|
||||
launch_max_pooling_kernel<T, T_INDEX, 2>(stream, output, indices, input, channels,
|
||||
out_spatial_dims, in_spatial_dims, window_size, strides, padding_left);
|
||||
} else if (order == 1) {
|
||||
launch_max_pooling_kernel<T, T_INDEX, 1>(stream, output, indices, input, channels,
|
||||
out_spatial_dims, in_spatial_dims, window_size, strides, padding_left);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<__half>, TensorSpan<int32_t>, TensorView<__half>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<__half>, TensorSpan<int64_t>, TensorView<__half>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
#endif
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<float>, TensorSpan<int32_t>, TensorView<float>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<float>, TensorSpan<int64_t>, TensorView<float>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int8_t>, TensorSpan<int32_t>, TensorView<int8_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int8_t>, TensorSpan<int64_t>, TensorView<int8_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<uint8_t>, TensorSpan<int32_t>, TensorView<uint8_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<uint8_t>, TensorSpan<int64_t>, TensorView<uint8_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int32_t>, TensorSpan<int32_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int32_t>, TensorSpan<int64_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int64_t>, TensorSpan<int32_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_pooling_with_indices(const Stream&,
|
||||
TensorSpan<int64_t>, TensorSpan<int64_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template <class T, class T_INDEX, std::size_t Order> static
|
||||
void launch_max_unpooling_kernel(
|
||||
const Stream& stream,
|
||||
Span<T> output, View<T> input, View<T_INDEX> indices, std::size_t channels,
|
||||
const std::vector<std::size_t>& out_spatial_dims, const std::vector<std::size_t>& in_spatial_dims,
|
||||
const std::vector<std::size_t>& window_size,
|
||||
const std::vector<std::size_t>& strides, const std::vector<std::size_t>& padding_left)
|
||||
{
|
||||
CV_Assert(out_spatial_dims.size() == Order);
|
||||
CV_Assert(in_spatial_dims.size() == Order);
|
||||
CV_Assert(window_size.size() == Order);
|
||||
CV_Assert(strides.size() == Order);
|
||||
CV_Assert(padding_left.size() == Order);
|
||||
CV_Assert(indices.size() == input.size());
|
||||
|
||||
array<size_type, Order> out_spatial_dims_k, in_spatial_dims_k;
|
||||
out_spatial_dims_k.assign(std::begin(out_spatial_dims), std::end(out_spatial_dims));
|
||||
in_spatial_dims_k.assign(std::begin(in_spatial_dims), std::end(in_spatial_dims));
|
||||
|
||||
array<size_type, Order> window_size_k, strides_k, padding_left_k;
|
||||
window_size_k.assign(std::begin(window_size), std::end(window_size));
|
||||
strides_k.assign(std::begin(strides), std::end(strides));
|
||||
padding_left_k.assign(std::begin(padding_left), std::end(padding_left));
|
||||
|
||||
auto kernel = raw::max_unpooling<T, T_INDEX, Order>;
|
||||
auto policy = make_policy(kernel, input.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, indices, channels,
|
||||
out_spatial_dims_k, in_spatial_dims_k, window_size_k, strides_k, padding_left_k);
|
||||
}
|
||||
|
||||
template <class T, class T_INDEX>
|
||||
void max_unpooling(
|
||||
const Stream& stream,
|
||||
TensorSpan<T> output, TensorView<T> input, TensorView<T_INDEX> indices,
|
||||
const std::vector<std::size_t>& window_size, const std::vector<std::size_t>& strides,
|
||||
const std::vector<std::size_t>& padding_left)
|
||||
{
|
||||
CV_Assert(is_shape_same(input, indices));
|
||||
CV_Assert(input.get_axis_size(1) == output.get_axis_size(1));
|
||||
|
||||
auto order = window_size.size();
|
||||
CV_Assert(strides.size() == order);
|
||||
CV_Assert(padding_left.size() == order);
|
||||
CV_Assert(output.rank() == order + 2);
|
||||
CV_Assert(input.rank() == order + 2);
|
||||
|
||||
std::vector<std::size_t> out_spatial_dims(order), in_spatial_dims(order);
|
||||
for (int i = 0; i < order; i++) {
|
||||
in_spatial_dims[i] = input.get_axis_size(2 + i);
|
||||
out_spatial_dims[i] = output.get_axis_size(2 + i);
|
||||
}
|
||||
|
||||
kernels::fill<T>(stream, output, 0.0);
|
||||
|
||||
/* only max_unpooling2d and max_unpooling3d are supported */
|
||||
CV_Assert(2 <= order && order <= 3);
|
||||
std::size_t channels = input.get_axis_size(1);
|
||||
if (order == 3) {
|
||||
launch_max_unpooling_kernel<T, T_INDEX, 3>(stream, output, input, indices, channels,
|
||||
out_spatial_dims, in_spatial_dims, window_size, strides, padding_left);
|
||||
} else if (order == 2) {
|
||||
launch_max_unpooling_kernel<T, T_INDEX, 2>(stream, output, input, indices, channels,
|
||||
out_spatial_dims, in_spatial_dims, window_size, strides, padding_left);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<__half>, TensorView<__half>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<__half>, TensorView<__half>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
#endif
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<float>, TensorView<float>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<float>, TensorView<float>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int8_t>, TensorView<int8_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int8_t>, TensorView<int8_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<uint8_t>, TensorView<uint8_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<uint8_t>, TensorView<uint8_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int32_t>, TensorView<int32_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int32_t>, TensorView<int32_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int64_t>, TensorView<int64_t>, TensorView<int32_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
template void max_unpooling(const Stream&,
|
||||
TensorSpan<int64_t>, TensorView<int64_t>, TensorView<int64_t>,
|
||||
const std::vector<std::size_t>&, const std::vector<std::size_t>&,
|
||||
const std::vector<std::size_t>&);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
#ifndef OPENCV_DNN_SRC_CUDA_MEMORY_HPP
|
||||
#define OPENCV_DNN_SRC_CUDA_MEMORY_HPP
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace device {
|
||||
|
||||
template <class T>
|
||||
__device__ T load_ldg(const T& src) {
|
||||
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 350)
|
||||
return __ldg(&src);
|
||||
#else
|
||||
return src;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__device__ T load_ldg(const T* src) {
|
||||
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 350)
|
||||
return __ldg(src);
|
||||
#else
|
||||
return *src;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}}}} /* namespace cv::dnn::cuda4dnn::csl::device */
|
||||
|
||||
#endif /* OPENCV_DNN_SRC_CUDA_MEMORY_HPP */
|
||||
@@ -0,0 +1,258 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "types.hpp"
|
||||
#include "atomics.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T>
|
||||
__global__ void reduce_mean(Span<float> means, View<T> input, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(input.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
atomicAdd(&means[outer_idx], static_cast<float>(input[idx]) / inner_size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void reduce_mean_sqr_sum(Span<float> means, Span<float> sum_sqrs, View<T> input, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(input.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
auto x = static_cast<float>(input[idx]);
|
||||
atomicAdd(&means[outer_idx], x / inner_size);
|
||||
atomicAdd(&sum_sqrs[outer_idx], x * x);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void compute_normalization_scale(Span<float> scale, View<float> means, View<float> sums_sqr, size_type inner_size, float eps) {
|
||||
for (auto idx : grid_stride_range(scale.size())) {
|
||||
auto mean = means[idx];
|
||||
auto var = sums_sqr[idx] / inner_size - mean * mean;
|
||||
using device::rsqrt;
|
||||
scale[idx] = rsqrt(eps + var);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean(Span<T> output, View<T> input, View<float> means, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
output[idx] = static_cast<float>(input[idx]) - means[outer_idx];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean_variance(Span<T> output, View<T> input, View<float> means, View<float> scale, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
output[idx] = (static_cast<float>(input[idx]) - means[outer_idx]) * scale[outer_idx];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean_variance_channelwise(Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, size_type inner_size, size_type C) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
const index_type c = outer_idx % C;
|
||||
auto s = static_cast<float>(scale[c]) * inv_stddev[outer_idx];
|
||||
auto b = static_cast<float>(bias[c]);
|
||||
output[idx] = (static_cast<float>(input[idx]) - means[outer_idx]) * s + b;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean_variance_groupwise(Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, size_type inner_size, size_type C, size_type num_groups, size_type group_size) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
const index_type c = outer_idx % C;
|
||||
const index_type group_idx = outer_idx / group_size;
|
||||
auto s = static_cast<float>(scale[c]) * inv_stddev[group_idx];
|
||||
auto b = static_cast<float>(bias[c]);
|
||||
output[idx] = (static_cast<float>(input[idx]) - means[group_idx]) * s + b;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean_variance_layernorm(Span<T> output, View<T> input, View<T> scale, View<float> means, View<float> inv_stddev, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
const index_type inner_idx = idx % inner_size;
|
||||
auto s = static_cast<float>(scale[inner_idx]) * inv_stddev[outer_idx];
|
||||
output[idx] = (static_cast<float>(input[idx]) - means[outer_idx]) * s;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void normalize_mean_variance_layernorm_with_bias(Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, size_type inner_size) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / inner_size;
|
||||
const index_type inner_idx = idx % inner_size;
|
||||
auto s = static_cast<float>(scale[inner_idx]) * inv_stddev[outer_idx];
|
||||
auto b = static_cast<float>(bias[inner_idx]);
|
||||
output[idx] = (static_cast<float>(input[idx]) - means[outer_idx]) * s + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void reduce_mean(const Stream& stream, Span<float> means, View<T> input, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
|
||||
auto kernel = raw::reduce_mean<T>;
|
||||
auto policy = make_policy(kernel, input.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, means, input, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void reduce_mean(const Stream&, Span<float>, View<__half>, std::size_t);
|
||||
#endif
|
||||
template void reduce_mean(const Stream&, Span<float>, View<float>, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void reduce_mean_sqr_sum(const Stream& stream, Span<float> means, Span<float> sum_sqrs, View<T> input, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
CV_Assert(input.size() / inner_size == sum_sqrs.size());
|
||||
|
||||
auto kernel = raw::reduce_mean_sqr_sum<T>;
|
||||
auto policy = make_policy(kernel, input.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, means, sum_sqrs, input, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void reduce_mean_sqr_sum(const Stream&, Span<float>, Span<float>, View<__half>, std::size_t);
|
||||
#endif
|
||||
template void reduce_mean_sqr_sum(const Stream&, Span<float>, Span<float>, View<float>, std::size_t);
|
||||
|
||||
void compute_normalization_scale(const Stream& stream, Span<float> scale, View<float> means, View<float> sum_sqrs, std::size_t inner_size, float eps)
|
||||
{
|
||||
CV_Assert(scale.size() == means.size());
|
||||
CV_Assert(scale.size() == sum_sqrs.size());
|
||||
|
||||
auto kernel = raw::compute_normalization_scale;
|
||||
auto policy = make_policy(kernel, scale.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, scale, means, sum_sqrs, inner_size, eps);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void normalize_mean(const Stream& stream, Span<T> output, View<T> input, View<float> means, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(output.size() == input.size());
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
|
||||
auto kernel = raw::normalize_mean<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, means, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean(const Stream&, Span<__half>, View<__half>, View<float>, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean(const Stream&, Span<float>, View<float>, View<float>, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void normalize_mean_variance(const Stream& stream, Span<T> output, View<T> input, View<float> means, View<float> scale, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(input.size() == output.size());
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
CV_Assert(input.size() / inner_size == scale.size());
|
||||
|
||||
auto kernel = raw::normalize_mean_variance<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, means, scale, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean_variance(const Stream&, Span<__half>, View<__half>, View<float>, View<float>, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean_variance(const Stream&, Span<float>, View<float>, View<float>, View<float>, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void normalize_mean_variance_channelwise(const Stream& stream, Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, std::size_t inner_size, std::size_t C)
|
||||
{
|
||||
CV_Assert(input.size() == output.size());
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
CV_Assert(means.size() == inv_stddev.size());
|
||||
|
||||
auto kernel = raw::normalize_mean_variance_channelwise<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, scale, bias, means, inv_stddev, inner_size, C);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean_variance_channelwise(const Stream&, Span<__half> /*output*/, View<__half> /*input*/, View<__half> /*scale*/, View<__half> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean_variance_channelwise(const Stream&, Span<float> /*output*/, View<float> /*input*/, View<float> /*scale*/, View<float> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void normalize_mean_variance_groupwise(const Stream& stream, Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, std::size_t inner_size, std::size_t C, std::size_t num_groups, std::size_t group_size)
|
||||
{
|
||||
CV_Assert(input.size() == output.size());
|
||||
CV_Assert(input.size() / inner_size == means.size() * group_size);
|
||||
CV_Assert(means.size() == inv_stddev.size());
|
||||
|
||||
auto kernel = raw::normalize_mean_variance_groupwise<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, scale, bias, means, inv_stddev, inner_size, C, num_groups, group_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean_variance_groupwise(const Stream&, Span<__half> /*output*/, View<__half> /*input*/, View<__half> /*scale*/, View<__half> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t, std::size_t, std::size_t, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean_variance_groupwise(const Stream&, Span<float> /*output*/, View<float> /*input*/, View<float> /*scale*/, View<float> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t, std::size_t, std::size_t, std::size_t);
|
||||
|
||||
|
||||
template <class T>
|
||||
void normalize_mean_variance_layernorm(const Stream& stream, Span<T> output, View<T> input, View<T> scale, View<float> means, View<float> inv_stddev, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(input.size() == output.size());
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
CV_Assert(means.size() == inv_stddev.size());
|
||||
|
||||
auto kernel = raw::normalize_mean_variance_layernorm<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, scale, means, inv_stddev, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean_variance_layernorm(const Stream&, Span<__half> /*output*/, View<__half> /*input*/, View<__half> /*scale*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean_variance_layernorm(const Stream&, Span<float> /*output*/, View<float> /*input*/, View<float> /*scale*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t);
|
||||
|
||||
template <class T>
|
||||
void normalize_mean_variance_layernorm(const Stream& stream, Span<T> output, View<T> input, View<T> scale, View<T> bias, View<float> means, View<float> inv_stddev, std::size_t inner_size)
|
||||
{
|
||||
CV_Assert(input.size() == output.size());
|
||||
CV_Assert(input.size() / inner_size == means.size());
|
||||
CV_Assert(means.size() == inv_stddev.size());
|
||||
|
||||
auto kernel = raw::normalize_mean_variance_layernorm_with_bias<T>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, input, scale, bias, means, inv_stddev, inner_size);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize_mean_variance_layernorm(const Stream&, Span<__half> /*output*/, View<__half> /*input*/, View<__half> /*scale*/, View<__half> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t);
|
||||
#endif
|
||||
template void normalize_mean_variance_layernorm(const Stream&, Span<float> /*output*/, View<float> /*input*/, View<float> /*scale*/, View<float> /*bias*/, View<float> /*means*/, View<float> /*inv_stddev*/, std::size_t);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,123 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "math.hpp"
|
||||
#include "types.hpp"
|
||||
#include "atomics.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include "../cuda4dnn/kernels/fill_copy.hpp"
|
||||
#include "../cuda4dnn/kernels/scale_shift.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T>
|
||||
__global__ void reduce_sum_abs(Span<T> output, View<T> input, size_type outer_stride, size_type mid_stride) {
|
||||
for (auto idx : grid_stride_range(input.size())) {
|
||||
const index_type outer_idx = idx / outer_stride;
|
||||
const index_type inner_idx = idx % mid_stride;
|
||||
|
||||
const index_type sum_idx = outer_idx * mid_stride + inner_idx;
|
||||
atomicAdd(&output[sum_idx], device::abs(input[idx]));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void reciprocal(Span<T> output, T epsilon) {
|
||||
for (auto idx : grid_stride_range(output.size()))
|
||||
output[idx] = T(1) / (output[idx] + epsilon);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void reduce_sum_squared(Span<T> output, View<T> input, size_type outer_stride, size_type mid_stride) {
|
||||
for (auto idx : grid_stride_range(input.size())) {
|
||||
const index_type outer_idx = idx / outer_stride;
|
||||
const index_type inner_idx = idx % mid_stride;
|
||||
|
||||
const index_type sum_idx = outer_idx * mid_stride + inner_idx;
|
||||
atomicAdd(&output[sum_idx], input[idx] * input[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void rsqrt(Span<T> output, T epsilon) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
using device::sqrt;
|
||||
output[idx] = T(1) / sqrt(output[idx] + epsilon);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__global__ void apply_norm(Span<T> output, View<T> input, size_type outer_stride, size_type mid_stride, View<T> sums) {
|
||||
for (auto idx : grid_stride_range(output.size())) {
|
||||
const index_type outer_idx = idx / outer_stride;
|
||||
const index_type inner_idx = idx % mid_stride;
|
||||
|
||||
const index_type sum_idx = outer_idx * mid_stride + inner_idx;
|
||||
output[idx] = input[idx] * sums[sum_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void normalize(
|
||||
const Stream& stream,
|
||||
Span<T> output,
|
||||
View<T> input, std::size_t outer_size, std::size_t mid_size, std::size_t inner_size, std::size_t norm, T epsilon,
|
||||
Span<T> workspace)
|
||||
{
|
||||
CV_Assert(output.size() == input.size());
|
||||
CV_Assert(output.size() == outer_size * mid_size * inner_size);
|
||||
CV_Assert(norm == 1 || norm == 2);
|
||||
CV_Assert(workspace.size() >= outer_size * inner_size);
|
||||
|
||||
auto sums = Span<T>(workspace.data(), outer_size * inner_size);
|
||||
|
||||
fill<T>(stream, sums, 0.0);
|
||||
|
||||
if (norm == 1) {
|
||||
auto reduce_kernel = raw::reduce_sum_abs<T>;
|
||||
auto policy = make_policy(reduce_kernel, input.size(), 0, stream);
|
||||
launch_kernel(reduce_kernel, policy, sums, input, mid_size * inner_size, inner_size);
|
||||
|
||||
auto reciprocal_kernel = raw::reciprocal<T>;
|
||||
policy = make_policy(reciprocal_kernel, sums.size(), 0, stream);
|
||||
launch_kernel(reciprocal_kernel, policy, sums, epsilon);
|
||||
} else {
|
||||
auto reduce_kernel = raw::reduce_sum_squared<T>;
|
||||
auto policy = make_policy(reduce_kernel, input.size(), 0, stream);
|
||||
launch_kernel(reduce_kernel, policy, sums, input, mid_size * inner_size, inner_size);
|
||||
|
||||
auto rsqrt_kernel = raw::rsqrt<T>;
|
||||
policy = make_policy(rsqrt_kernel, sums.size(), 0, stream);
|
||||
launch_kernel(rsqrt_kernel, policy, sums, epsilon);
|
||||
}
|
||||
|
||||
auto scale_kernel = raw::apply_norm<T>;
|
||||
auto policy = make_policy(scale_kernel, output.size(), 0, stream);
|
||||
launch_kernel(scale_kernel, policy, output, input, mid_size * inner_size, inner_size, sums);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void normalize(const Stream&, Span<__half>, View<__half>, std::size_t, std::size_t, std::size_t, std::size_t, __half, Span<__half>);
|
||||
#endif
|
||||
template void normalize(const Stream&, Span<float>, View<float>, std::size_t, std::size_t, std::size_t, std::size_t, float, Span<float>);
|
||||
|
||||
}}}} /* namespace cv::dnn::cuda4dnn::kernels */
|
||||
@@ -0,0 +1,206 @@
|
||||
// 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 <cuda_runtime.h>
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "math.hpp"
|
||||
#include "types.hpp"
|
||||
#include "grid_stride_range.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "kernel_dispatcher.hpp"
|
||||
|
||||
#include "../cuda4dnn/csl/stream.hpp"
|
||||
#include "../cuda4dnn/csl/tensor.hpp"
|
||||
#include "../cuda4dnn/csl/span.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
using namespace cv::dnn::cuda4dnn::csl;
|
||||
using namespace cv::dnn::cuda4dnn::csl::device;
|
||||
|
||||
namespace cv { namespace dnn { namespace cuda4dnn { namespace kernels {
|
||||
|
||||
namespace raw {
|
||||
template <class T, std::size_t Rank>
|
||||
__global__ void copy_with_reflection101(
|
||||
Span<T> output, array<size_type, Rank> out_strides, array<index_type, Rank> start, array<index_type, Rank> end,
|
||||
View<T> input, array<size_type, Rank> in_strides)
|
||||
{
|
||||
for (auto i : grid_stride_range(output.size())) {
|
||||
/* compute output axis indices corresponding to element 'i' */
|
||||
array<index_type, Rank> out_index;
|
||||
out_index[0] = i / out_strides[0];
|
||||
for (int j = 1; j < Rank; j++)
|
||||
out_index[j] = (i % out_strides[j - 1]) / out_strides[j];
|
||||
|
||||
/* compute input axis indices corresponding to output axis indices */
|
||||
array<index_type, Rank> in_index;
|
||||
for (int j = 0; j < Rank; j++) {
|
||||
/* if out_index < start, the point is in the left reflection region
|
||||
* the reflected value's index is the absolute value of the difference
|
||||
*
|
||||
* otherwise, if the value is in the copy region, out_index - start gives the input index
|
||||
*/
|
||||
using device::abs;
|
||||
in_index[j] = abs(out_index[j] - start[j]);
|
||||
|
||||
/* if out_index >= end, it's in the right reflection region */
|
||||
if (out_index[j] >= end[j])
|
||||
in_index[j] = (end[j] - start[j]) - (out_index[j] - end[j]) - 2;
|
||||
}
|
||||
|
||||
/* compute input element number from input axis indices */
|
||||
index_type iidx = 0;
|
||||
for (int j = 0; j < Rank; j++)
|
||||
iidx += in_index[j] * in_strides[j];
|
||||
|
||||
output[i] = input[iidx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::size_t Rank> static
|
||||
void launch_copy_with_reflection101(
|
||||
const Stream& stream,
|
||||
Span<T> output, const std::vector<std::size_t>& outStride,
|
||||
View<T> input, const std::vector<std::size_t>& inStride,
|
||||
const std::vector<std::pair<std::size_t, std::size_t>>& ranges)
|
||||
{
|
||||
CV_Assert(outStride.size() == Rank);
|
||||
CV_Assert(inStride.size() == Rank);
|
||||
CV_Assert(ranges.size() == Rank);
|
||||
|
||||
array<size_type, Rank> outStride_k, inStride_k;
|
||||
outStride_k.assign(std::begin(outStride), std::end(outStride));
|
||||
inStride_k.assign(std::begin(inStride), std::end(inStride));
|
||||
|
||||
array<index_type, Rank> start_k, end_k;
|
||||
for (int i = 0; i < Rank; i++) {
|
||||
start_k[i] = ranges[i].first;
|
||||
end_k[i] = ranges[i].second;
|
||||
}
|
||||
|
||||
auto kernel = raw::copy_with_reflection101<T, Rank>;
|
||||
auto policy = make_policy(kernel, output.size(), 0, stream);
|
||||
launch_kernel(kernel, policy, output, outStride_k, start_k, end_k, input, inStride_k);
|
||||
}
|
||||
|
||||
GENERATE_KERNEL_DISPATCHER(copy_with_reflection101_dispatcher, launch_copy_with_reflection101);
|
||||
|
||||
template <class T>
|
||||
void copy_with_reflection101(
|
||||
const Stream& stream,
|
||||
TensorSpan<T> output, TensorView<T> input,
|
||||
std::vector<std::pair<std::size_t, std::size_t>> ranges)
|
||||
{
|
||||
CV_Assert(output.rank() == input.rank());
|
||||
CV_Assert(output.rank() == ranges.size());
|
||||
|
||||
/* squeezable axes at the beginning of both tensors can be eliminated
|
||||
*
|
||||
* Reasoning:
|
||||
* ----------
|
||||
* Suppose an item's indices in the input tensor is [i1, i2, ...]. The indices in the
|
||||
* output tensor will be [i1 + off1, i2 + off2, ...]. The rest of the elements in the output are padding.
|
||||
* The padding operation essentially copies items from the input tensor to new locations in the output tensor
|
||||
* and pads the remaining.
|
||||
*
|
||||
* If the size of the first axis of the input and output tensor is unity, the input and output indices
|
||||
* for all the elements will be of the form be [0, i2, ...] and [0, i2 + off2, ...] respectively. Note that
|
||||
* there cannot be extra padding since the axes have unit size. The first index does not contribute to the
|
||||
* element's address calculation and hence does nothing apart from eating up few cycles.
|
||||
*/
|
||||
while (input.get_axis_size(0) == 1 && output.get_axis_size(0) == 1) {
|
||||
CV_Assert(ranges[0].first == 0 && ranges[0].second == 1);
|
||||
|
||||
input.squeeze(0);
|
||||
output.squeeze(0);
|
||||
ranges.erase(std::begin(ranges));
|
||||
|
||||
CV_Assert(output.rank() == input.rank());
|
||||
CV_Assert(output.rank() == ranges.size());
|
||||
}
|
||||
|
||||
auto inShape = input.shape_as_vector();
|
||||
auto outShape = output.shape_as_vector();
|
||||
|
||||
/* contiguous axes which do not have any padding can be combined into one axis
|
||||
*
|
||||
* Reasoning:
|
||||
* ----------
|
||||
* Suppose an item's indices in the input tensor is [i1, i2, i3, ...]. Let the first two axes not have any
|
||||
* padding. The indices in the output tensor will be [i1, i2, i3 + off3, ...].
|
||||
*
|
||||
* Each axis in the contiguous unpadded axes sequence will add an offset of iN * strideN. In the above example,
|
||||
* the two axes add a total offset of `i1 * stride1 + i2 * stride2`. We can merge the two axes into one axis with
|
||||
* a size of `size1 * size2`. The new offset added will be `i12 * stride2` as the kernel iterates through `i12`.
|
||||
* Note that `i12` is actually `(i1 * size2 + i2)` in the original tensor.
|
||||
*/
|
||||
for (int i = 0; i < inShape.size(); i++) {
|
||||
/* check if axis `i` requires any padding */
|
||||
if (ranges[i].first == 0 && ranges[i].second == inShape[i]) {
|
||||
/* loop invariant: `i` is the first axis in the contiguous unpadded axis sequence */
|
||||
CV_Assert(inShape[i] == outShape[i]);
|
||||
|
||||
/* we now iterate through the axes which follow and try to merge */
|
||||
int j = i + 1; /* `j` is the axis which we will attempt to merge */
|
||||
while (j < inShape.size() && ranges[j].first == 0 && ranges[j].second == inShape[j]) {
|
||||
CV_Assert(inShape[j] == outShape[j]);
|
||||
|
||||
/* `j` is also unpadded; merge `i` and `j` */
|
||||
auto new_size = inShape[i] * inShape[j];
|
||||
inShape[i] = new_size;
|
||||
outShape[i] = new_size;
|
||||
ranges[i].second = new_size;
|
||||
|
||||
/* delete axis `j` */
|
||||
inShape.erase(std::begin(inShape) + j);
|
||||
outShape.erase(std::begin(outShape) + j);
|
||||
ranges.erase(std::begin(ranges) + j);
|
||||
|
||||
/* optimizations should not break the invariants */
|
||||
CV_Assert(inShape.size() == outShape.size());
|
||||
CV_Assert(inShape.size() == ranges.size());
|
||||
CV_Assert(inShape[i] == outShape[i]);
|
||||
CV_Assert(ranges[i].first == 0 && ranges[i].second == inShape[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto rank = inShape.size();
|
||||
|
||||
std::vector<std::size_t> inStride(rank), outStride(rank);
|
||||
inStride.back() = 1;
|
||||
outStride.back() = 1;
|
||||
/* garbage, ..., garbage, 1 */
|
||||
|
||||
std::copy(std::begin(inShape) + 1, std::end(inShape), std::begin(inStride));
|
||||
std::copy(std::begin(outShape) + 1, std::end(outShape), std::begin(outStride));
|
||||
/* dim[0], dim[1], ..., dim[-1], 1 */
|
||||
|
||||
std::partial_sum(inStride.rbegin(), inStride.rend(), inStride.rbegin(), std::multiplies<int>());
|
||||
std::partial_sum(outStride.rbegin(), outStride.rend(), outStride.rbegin(), std::multiplies<int>());
|
||||
/* stride[0], stride[1], ..., stride[-2], 1 */
|
||||
|
||||
CV_Assert(1 <= rank && rank <= CSL_MAX_TENSOR_RANK);
|
||||
copy_with_reflection101_dispatcher<T, 1, CSL_MAX_TENSOR_RANK>(rank, stream, output, outStride, input, inStride, ranges);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 530)
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<__half>, TensorView<__half>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
#endif
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<float>, TensorView<float>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<int8_t>, TensorView<int8_t>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<uint8_t>, TensorView<uint8_t>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<int32_t>, TensorView<int32_t>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<int64_t>, TensorView<int64_t>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
template void copy_with_reflection101(const Stream&, TensorSpan<bool>, TensorView<bool>, std::vector<std::pair<std::size_t, std::size_t>> ranges);
|
||||
|
||||
}}}} /* namespace namespace cv::dnn::cuda4dnn::kernels */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user