From 1a26f9956c0089bc19386d734582e43a91f727d3 Mon Sep 17 00:00:00 2001 From: Edgar Riba Date: Wed, 8 Feb 2017 14:40:13 +0100 Subject: [PATCH] Merge pull request #720 from edgarriba:dnn-modern GSOC'16 - DNN modern (#720) * dnn_modern module sketelon add FindTinyCNN.cmake and setup CMakeLists.txt add find TBB and NNPACK to CMakeLists.txt add caffe converter skeleton add simple sample eval method return scores Update README.md Update README.md Update README.md * update for tiny-dnn package * add QUIET attribute to CMake to find tiny-dnn * update files due to library rename * disable warning in cmake * replace cnn_size_t -> size_t * disable serializer, remove Caffe dependency and remove tiny-dnn target * check CMake version to enable/disable the module * add -Wno-erro in module target * update README.md with tiny-dnn * remove redunadant CMake codes for TBB and OMP * update CMake to enable C++11 compiler * sync CMake compiler options with upstream project * remove unused FindTBB.cmake * minor fix to add const variables * tiny-cnn -> tiny-dnn --- modules/dnn_modern/CMakeLists.txt | 144 +++++++++++++ modules/dnn_modern/README.md | 44 ++++ modules/dnn_modern/cmake/FindNNPACK.cmake | 54 +++++ modules/dnn_modern/cmake/FindTinyDNN.cmake | 46 ++++ .../dnn_modern/include/opencv2/dnn_modern.hpp | 96 +++++++++ modules/dnn_modern/samples/simple_test.cpp | 91 ++++++++ modules/dnn_modern/src/caffe_converter.cpp | 203 ++++++++++++++++++ modules/dnn_modern/src/dnn_modern_init.cpp | 47 ++++ modules/dnn_modern/src/precomp.hpp | 50 +++++ 9 files changed, 775 insertions(+) create mode 100644 modules/dnn_modern/CMakeLists.txt create mode 100644 modules/dnn_modern/README.md create mode 100644 modules/dnn_modern/cmake/FindNNPACK.cmake create mode 100644 modules/dnn_modern/cmake/FindTinyDNN.cmake create mode 100644 modules/dnn_modern/include/opencv2/dnn_modern.hpp create mode 100644 modules/dnn_modern/samples/simple_test.cpp create mode 100644 modules/dnn_modern/src/caffe_converter.cpp create mode 100644 modules/dnn_modern/src/dnn_modern_init.cpp create mode 100644 modules/dnn_modern/src/precomp.hpp diff --git a/modules/dnn_modern/CMakeLists.txt b/modules/dnn_modern/CMakeLists.txt new file mode 100644 index 000000000..1be8e8268 --- /dev/null +++ b/modules/dnn_modern/CMakeLists.txt @@ -0,0 +1,144 @@ +set(the_description "Modern Deep Learning module") + +if(${CMAKE_VERSION} VERSION_LESS 3.2) + message(STATUS "Module opencv_dnn_modern disabled because CMake version is less than 3.2") + ocv_module_disable(dnn_modern) + return() +endif() + +cmake_policy(SET CMP0028 OLD) + +# Using cmake scripts and modules +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +# ---------------------------------------------------------------------------- +# MODULE REQUIREMENTS +# ---------------------------------------------------------------------------- + +find_package(TinyDNN QUIET) + +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + +if(NOT TinyDNN_FOUND) + message(STATUS "Module opencv_dnn_modern disabled because tiny-dnn was not found") + ocv_module_disable(dnn_modern) + return() +elseif(NOT COMPILER_SUPPORTS_CXX11) + message(STATUS "Module opencv_dnn_modern disabled because your compiler does not support C++11") + ocv_module_disable(dnn_modern) + return() +elseif(APPLE_FRAMEWORK OR ANDROID) + message(STATUS "Module opencv_dnn_modern disabled because you are not under Linux or Win") + ocv_module_disable(dnn_modern) + return() +endif() + +# ---------------------------------------------------------------------------- +# OPTIMIZATION OPTIONS +# ---------------------------------------------------------------------------- + +option(TINYDNN_USE_SSE "Build tiny-dnn with SSE library support" ON) +option(TINYDNN_USE_AVX "Build tiny-dnn with AVX library support" ON) +option(TINYDNN_USE_TBB "Build tiny-dnn with TBB library support" OFF) +option(TINYDNN_USE_OMP "Build tiny-dnn with OMP library support" OFF) +option(TINYDNN_USE_NNPACK "Build tiny-dnn with NNPACK library support" OFF) + +if(TINYDNN_USE_TBB AND HAVE_TBB) + add_definitions(-DCNN_USE_TBB) +elseif(NOT TINYDNN_USE_TBB AND + TINYDNN_USE_OMP AND HAVE_OPENMP) + add_definitions(-DCNN_USE_OMP) +endif() + +if(TINYDNN_USE_NNPACK) + find_package(NNPACK REQUIRED) + add_definitions(-DCNN_USE_NNPACK) + include_directories(SYSTEM ${NNPACK_INCLUDE_DIR}) + include_directories(SYSTEM ${NNPACK_INCLUDE_DIR}/../third-party/pthreadpool/include) + list(APPEND REQUIRED_LIBRARIES ${NNPACK_LIB}) +endif() + +# we need to disable seializer unless we import cereal +add_definitions(-DCNN_NO_SERIALIZATION) + +# NOTE: In case that proto files already exist, +# this is not needed anymore. +find_package(Protobuf) +list(APPEND REQUIRED_LIBRARIES ${PROTOBUF_LIBRARIES}) + +#### +# Setup the compiler options + +# set c++ standard to c++11. +# Note: not working on CMake 2.8. We assume that user has +# a compiler with C++11 support. + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +message(STATUS "C++11 support has been enabled by default.") + +# Unix +if(CMAKE_COMPILER_IS_GNUCXX OR MINGW OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-msse3" COMPILER_HAS_SSE_FLAG) + check_cxx_compiler_flag("-mavx" COMPILER_HAS_AVX_FLAG) + check_cxx_compiler_flag("-mavx2" COMPILER_HAS_AVX2_FLAG) + check_cxx_compiler_flag("-mfma" COMPILER_HAS_AVX2_FLAG) + + # set Streaming SIMD Extension (SSE) instructions + if(USE_SSE AND COMPILER_HAS_SSE_FLAG) + add_definitions(-DCNN_USE_SSE) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -msse3") + endif(USE_SSE AND COMPILER_HAS_SSE_FLAG) + # set Advanced Vector Extensions (AVX) + if(USE_AVX AND COMPILER_HAS_AVX_FLAG) + add_definitions(-DCNN_USE_AVX) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -mavx") + endif(USE_AVX AND COMPILER_HAS_AVX_FLAG) + # set Advanced Vector Extensions 2 (AVX2) + if(USE_AVX2 AND COMPILER_HAS_AVX2_FLAG) + add_definitions(-DCNN_USE_AVX2) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -mavx2 -mfma -march=core-avx2") + endif(USE_AVX2 AND COMPILER_HAS_AVX2_FLAG) + + # include extra flags to the compiler + # TODO: add info about those flags. + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wall -Wpedantic -Wno-narrowing") + set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -O3") + set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -g3 -pthread") +elseif(MSVC) + if(USE_SSE) + add_definitions(-DCNN_USE_SSE) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /arch:SSE2") + endif(USE_SSE) + if(USE_AVX) + add_definitions(-DCNN_USE_AVX) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /arch:AVX") + endif(USE_AVX) + if(USE_AVX2) + add_definitions(-DCNN_USE_AVX2) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /arch:AVX2") + endif(USE_AVX2) + # include specific flags for release and debug modes. + set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} + /Ox /Oi /Ot /Oy /GL /fp:fast /GS-") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") + set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG}") + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /W4 /bigobj") + # this is fine + add_definitions(-D _CRT_SECURE_NO_WARNINGS) + add_definitions(-D _SCL_SECURE_NO_WARNINGS) + # prolly powerless with header-only project + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /MP") +endif() + +# ---------------------------------------------------------------------------- +# DNN-MODERN MODULE +# ---------------------------------------------------------------------------- + +ocv_define_module(dnn_modern opencv_core opencv_imgproc opencv_imgcodecs WRAP python) +ocv_target_link_libraries(${the_module} ${REQUIRED_LIBRARIES}) +ocv_target_include_directories(${the_module} ${TINYDNN_INCLUDE_DIRS}) +target_compile_options(${the_module} PRIVATE "-Wno-error=non-virtual-dtor") diff --git a/modules/dnn_modern/README.md b/modules/dnn_modern/README.md new file mode 100644 index 000000000..a61665476 --- /dev/null +++ b/modules/dnn_modern/README.md @@ -0,0 +1,44 @@ +Modern Deep Learning Module +=========================== + +The module is wrapper to [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn) + +A header only, dependency-free deep learning framework in C++11 + +Installation +------------ + +**Required Dependencies** + - System under Unix or Windows + - C++11 compiler + - tiny-dnn headers + +**How to install tiny-dnn?** + + Download tiny-dnn project somewhere in your system + + cd /opt + git clone https://github.com/tiny-dnn/tiny-dnn.git + + Run your OpenCV CMake pointing to your tiny-dnn headers location + + cd /opt/opencv/build + cmake -DTINYDNN_ROOT=/opt/tiny-dnn .. + make -j4 + +**Extra** + + You can enable some optimizations just for tiny-dnn backend + + cmake -DTINYDNN_USE_SSE=ON .. + cmake -DTINYDNN_USE_AVX=ON .. + + Use third-party multithreading libs: TBB or OMP. + + cmake -DTINYDNN_USE_TBB=ON .. // then disable OMP + cmake -DTINYDNN_USE_OMP=ON .. // then disable TBB + + NNPACK: Acceleration package for neural networks on multi-core CPUs.
+ Check project site for installation: [https://github.com/Maratyszcza/NNPACK](https://github.com/Maratyszcza/NNPACK) + + cmake -DTINYDNN_USE_NNPACK=ON .. // not supported yet for Caffe loader diff --git a/modules/dnn_modern/cmake/FindNNPACK.cmake b/modules/dnn_modern/cmake/FindNNPACK.cmake new file mode 100644 index 000000000..c296de6d8 --- /dev/null +++ b/modules/dnn_modern/cmake/FindNNPACK.cmake @@ -0,0 +1,54 @@ +SET(NNPACK_INCLUDE_SEARCH_PATHS + /usr/include + /usr/local/include + /opt/NNPACK/include + $ENV{NNPACK_ROOT} + $ENV{NNPACK_ROOT}/include +) + +SET(NNPACK_LIB_SEARCH_PATHS + /lib/ + /lib64/ + /usr/lib + /usr/lib64 + /usr/local/lib + /usr/local/lib64 + /opt/NNPACK/lib + $ENV{NNPACK_ROOT} + $ENV{NNPACK_ROOT}/lib + ) + +FIND_PATH(NNPACK_INCLUDE_DIR NAMES nnpack.h PATHS ${NNPACK_INCLUDE_SEARCH_PATHS}) +FIND_LIBRARY(NNPACK_LIB NAMES nnpack PATHS ${NNPACK_LIB_SEARCH_PATHS}) + +SET(NNPACK_FOUND ON) + +# Check include files +IF(NOT NNPACK_INCLUDE_DIR) + SET(NNPACK_FOUND OFF) + MESSAGE(STATUS "Could not find NNPACK include. Turning NNPACK_FOUND off") +ENDIF() + +# Check libraries +IF(NOT NNPACK_LIB) + SET(NNPACK_FOUND OFF) + MESSAGE(STATUS "Could not find NNPACK lib. Turning NNPACK_FOUND off") +ENDIF() + +IF (NNPACK_FOUND) + add_definitions(-DUSE_NNPACK) + IF (NOT NNPACK_FIND_QUIETLY) + MESSAGE(STATUS "Found NNPACK libraries: ${NNPACK_LIB}") + MESSAGE(STATUS "Found NNPACK include: ${NNPACK_INCLUDE_DIR}") + ENDIF (NOT NNPACK_FIND_QUIETLY) +ELSE (NNPACK_FOUND) + IF (NNPACK_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find NNPACK") + ENDIF (NNPACK_FIND_REQUIRED) +ENDIF (NNPACK_FOUND) + +MARK_AS_ADVANCED( + NNPACK_INCLUDE_DIR + NNPACK_LIB + NNPACK +) diff --git a/modules/dnn_modern/cmake/FindTinyDNN.cmake b/modules/dnn_modern/cmake/FindTinyDNN.cmake new file mode 100644 index 000000000..ebfd720d4 --- /dev/null +++ b/modules/dnn_modern/cmake/FindTinyDNN.cmake @@ -0,0 +1,46 @@ +# Locate the tiny-dnn library. +# +# Defines the following variables: +# +# TinyDNN_FOUND - TRUE if the tiny-dnn headers are found +# TINYDNN_INCLUDE_DIRS - The path to tiny-dnn headers +# +# Accepts the following variables as input: +# +# TinyDNN_ROOT - (as a CMake or environment variable) +# The root directory of the tiny-dnn install prefix + +message(STATUS "Looking for tiny_dnn.h") + +set(TINYDNN_INCLUDE_SEARCH_PATHS + /usr/include/tiny_dnn + /usr/local/include/tiny_dnn + /opt/tiny_dnn + $ENV{TINYDNN_ROOT} + ${TINYDNN_ROOT} + ${TINYDNN_ROOT}/tiny_dnn +) + +find_path(TINYDNN_INCLUDE_DIR + NAMES tiny_dnn/tiny_dnn.h + HINTS ${TINYDNN_INCLUDE_SEARCH_PATHS} +) + +# handle the QUIETLY and REQUIRED arguments and set TinyDNN_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(TinyDNN + FOUND_VAR TinyDNN_FOUND + REQUIRED_VARS TINYDNN_INCLUDE_DIR) + +if(TinyDNN_FOUND) + set(TINYDNN_INCLUDE_DIRS ${TINYDNN_INCLUDE_DIR}) + message(STATUS "Looking for tiny_dnn.h - found") + message(STATUS "Found tiny-dnn in: ${TINYDNN_INCLUDE_DIRS}") +else() + message(STATUS "Looking for tiny_dnn.h - not found") +endif() + +mark_as_advanced( + TINYDNN_INCLUDE_DIRS +) diff --git a/modules/dnn_modern/include/opencv2/dnn_modern.hpp b/modules/dnn_modern/include/opencv2/dnn_modern.hpp new file mode 100644 index 000000000..db9a65408 --- /dev/null +++ b/modules/dnn_modern/include/opencv2/dnn_modern.hpp @@ -0,0 +1,96 @@ +/* + 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 + (3-clause BSD License) + + Copyright (C) 2000-2016, Intel Corporation, all rights reserved. + Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. + Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. + Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. + Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. + Copyright (C) 2015-2016, Itseez Inc., all rights reserved. + Third party copyrights are property of their respective owners. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the contributors + may 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 copyright holders 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. + */ + +#ifndef __OPENCV_DNN_M_HPP__ +#define __OPENCV_DNN_M_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/imgproc.hpp" + +/** @defgroup dnn_modern Deep Learning Modern Module +@{ + +Base class for tiny-dnn converter + +@} +*/ + +namespace cv { +namespace dnn2 { + +class CV_EXPORTS_W BaseConverter +{ +public: + virtual ~BaseConverter() {}; + virtual void eval(const cv::InputArray image, std::vector* results) = 0; +}; + +/** @brief Class implementing the CaffeConverter. + +Implementation of tiny-dnn Caffe converter. +Loads a pretrained Caffe model. Only support simple sequential models. + + */ +class CV_EXPORTS_W CaffeConverter : public BaseConverter { + public: + + /** + @param model_file path to the prototxt file. + @param trained_file path to the caffemodel file. + @param mean_file path to binaryproto file. + */ + CV_WRAP static Ptr create(const cv::String& model_file, + const cv::String& trained_file, + const cv::String& mean_file=cv::String()); + + virtual void eval(const cv::InputArray image, std::vector* results) = 0; +}; + +} // namespace dnn2 +} // namespace cv + +#endif + +/* End of file. */ diff --git a/modules/dnn_modern/samples/simple_test.cpp b/modules/dnn_modern/samples/simple_test.cpp new file mode 100644 index 000000000..71b0ab761 --- /dev/null +++ b/modules/dnn_modern/samples/simple_test.cpp @@ -0,0 +1,91 @@ +#include + +#include +#include + +using namespace std; +using namespace cv; +using namespace cv::dnn2; + +static void help() { + cout + << "\n----------------------------------------------------------------------------\n" + << " This program shows how to import a Caffe model using the \n" + << " OpenCV Modern Deep Learning module (DNN2).\n" + << " Usage:\n" + << " example_dnn_modern_simple_test \n" + << " \n" + << " where: model_file is the path to the *.prototxt\n" + << " trained_file is the path to the *.caffemodel\n" + << " mean_file is the path to the *.binaryproto\n" + << " label_file is the path to the labels file\n" + << " image_file is the path to the image to evaluate\n" + << "----------------------------------------------------------------------------\n\n" + << endl; +} + +vector get_label_list(const string& label_file); +void print_n_labels(const vector& labels, + const vector& result, + const int top_n); + +vector get_label_list(const string& label_file) { + string line; + ifstream ifs(label_file.c_str()); + + if (ifs.fail() || ifs.bad()) { + throw runtime_error("failed to open:" + label_file); + } + + vector lines; + while (getline(ifs, line)) lines.push_back(line); + + return lines; +} + +void print_n_labels(const vector& labels, + const vector& result, + const int top_n) { + vector sorted(result.begin(), result.end()); + + partial_sort(sorted.begin(), sorted.begin()+top_n, sorted.end(), greater()); + + for (int i = 0; i < top_n; i++) { + size_t idx = distance(result.begin(), find(result.begin(), result.end(), sorted[i])); + cout << labels[idx] << "," << sorted[i] << endl; + } +} + +int main(int argc, char* argv[]) { + + if (argc < 6) { + help(); + exit(0); + } + + int arg_channel = 1; + string model_file = argv[arg_channel++]; + string trained_file = argv[arg_channel++]; + string mean_file = argv[arg_channel++]; + string label_file = argv[arg_channel++]; + string img_file = argv[arg_channel++]; + + // load Caffe model + Ptr caffe_ptr = CaffeConverter::create( + model_file, trained_file, mean_file); + + // load input image + cv::Mat img = cv::imread(img_file, -1); + + // inference ! + vector scores; + caffe_ptr->eval(img, &scores); + + // retrieve n labels + const int n = 5; + vector labels = get_label_list(label_file); + + print_n_labels(labels, scores, n); + + return 0; +} diff --git a/modules/dnn_modern/src/caffe_converter.cpp b/modules/dnn_modern/src/caffe_converter.cpp new file mode 100644 index 000000000..fb0885ebc --- /dev/null +++ b/modules/dnn_modern/src/caffe_converter.cpp @@ -0,0 +1,203 @@ +/* + 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 + (3-clause BSD License) + + Copyright (C) 2000-2016, Intel Corporation, all rights reserved. + Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. + Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. + Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. + Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. + Copyright (C) 2015-2016, Itseez Inc., all rights reserved. + Third party copyrights are property of their respective owners. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the contributors + may 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 copyright holders 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. + */ + +#include "precomp.hpp" + +#define CNN_USE_CAFFE_CONVERTER +#include + +using namespace tiny_dnn; +using namespace tiny_dnn::activation; +using namespace std; + +namespace cv { +namespace dnn2 { + +/* + !CaffeConverter Implementation + */ +class CaffeConverter_Impl : public CaffeConverter { + public: + explicit CaffeConverter_Impl(const cv::String& model_file, + const cv::String& trained_file, + const cv::String& mean_file) { + net_ = create_net_from_caffe_prototxt(model_file); + reload_weight_from_caffe_protobinary(trained_file, net_.get()); + + const size_t width = (*net_)[0]->in_data_shape()[0].width_; + const size_t height = (*net_)[0]->in_data_shape()[0].height_; + + mean_ = compute_mean(mean_file, width, height); + } + + ~CaffeConverter_Impl() {} + + virtual void eval(const cv::InputArray image, std::vector* results); + + private: + cv::Mat compute_mean(const string& mean_file, const size_t width, + const size_t height); + + cv::ColorConversionCodes get_cvt_codes(const int src_channels, + const int dst_channels); + + void preprocess(const cv::Mat& img, const cv::Mat& mean, + const int num_channels, const cv::Size& geometry, + vector* input_channels); + + cv::Mat mean_; + std::shared_ptr> net_; +}; + +cv::Mat +CaffeConverter_Impl::compute_mean(const string& mean_file, + const size_t width, + const size_t height) { + caffe::BlobProto blob; + ::detail::read_proto_from_binary(mean_file, &blob); + + vector channels; + auto data = blob.mutable_data()->mutable_data(); + + const size_t offset = blob.height() * blob.width(); + + for (int i = 0; i < blob.channels(); i++, data += offset) { + channels.emplace_back(blob.height(), blob.width(), CV_32FC1, data); + } + + cv::Mat mean; + cv::merge(channels, mean); + + return cv::Mat(cv::Size(width, height), mean.type(), cv::mean(mean)); +} + +cv::ColorConversionCodes +CaffeConverter_Impl::get_cvt_codes(const int src_channels, + const int dst_channels) { + assert(src_channels != dst_channels); + + if (dst_channels == 3) { + return src_channels == 1 ? cv::COLOR_GRAY2BGR : cv::COLOR_BGRA2BGR; + } else if (dst_channels == 1) { + return src_channels == 3 ? cv::COLOR_BGR2GRAY : cv::COLOR_BGRA2GRAY; + } else { + throw runtime_error("unsupported color code"); + } +} + +void CaffeConverter_Impl::preprocess(const cv::Mat& img, + const cv::Mat& mean, + const int num_channels, + const cv::Size& geometry, + vector* input_channels) { + cv::Mat sample; + + // convert color + if (img.channels() != num_channels) { + cv::cvtColor(img, sample, + get_cvt_codes(img.channels(), num_channels)); + } else { + sample = img; + } + + // resize + cv::Mat sample_resized; + cv::resize(sample, sample_resized, geometry); + + cv::Mat sample_float; + sample_resized.convertTo(sample_float, + num_channels == 3 ? CV_32FC3 : CV_32FC1); + + // subtract mean + if (mean.size().width > 0) { + cv::Mat sample_normalized; + cv::subtract(sample_float, mean, sample_normalized); + cv::split(sample_normalized, *input_channels); + } + else { + cv::split(sample_float, *input_channels); + } +} + +void CaffeConverter_Impl::eval(const cv::InputArray image, + std::vector* results) { + const cv::Mat img = image.getMat(); + + const size_t channels = (*net_)[0]->in_data_shape()[0].depth_; + const size_t width = (*net_)[0]->in_data_shape()[0].width_; + const size_t height = (*net_)[0]->in_data_shape()[0].height_; + + vector input_channels; + vector inputvec(width*height*channels); + + for (size_t i = 0; i < channels; i++) { + input_channels.emplace_back(height, width, CV_32FC1, + &inputvec[width*height*i]); + } + + // subtract mean from input + preprocess(img, mean_, 3, cv::Size(width, height), &input_channels); + + const vector vec(inputvec.begin(), inputvec.end()); + + // perform inderence + auto result = net_->predict(); + + // allocate output + results->clear(); + results->reserve(result.size()); + + for (size_t i = 0; i < result.size(); i++) { + results->push_back(result[i]); + } +} + +Ptr CaffeConverter::create(const cv::String& model_file, + const cv::String& trained_file, + const cv::String& mean_file) { + return makePtr(model_file, trained_file, mean_file); +} + +} // namespace dnn2 +} // namespace cv diff --git a/modules/dnn_modern/src/dnn_modern_init.cpp b/modules/dnn_modern/src/dnn_modern_init.cpp new file mode 100644 index 000000000..441ec4310 --- /dev/null +++ b/modules/dnn_modern/src/dnn_modern_init.cpp @@ -0,0 +1,47 @@ +/* + 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 + (3-clause BSD License) + + Copyright (C) 2000-2016, Intel Corporation, all rights reserved. + Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. + Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. + Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. + Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. + Copyright (C) 2015-2016, Itseez Inc., all rights reserved. + Third party copyrights are property of their respective owners. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the contributors + may 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 copyright holders 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. + */ + +#include "precomp.hpp" + +//#include diff --git a/modules/dnn_modern/src/precomp.hpp b/modules/dnn_modern/src/precomp.hpp new file mode 100644 index 000000000..8ac69e2a6 --- /dev/null +++ b/modules/dnn_modern/src/precomp.hpp @@ -0,0 +1,50 @@ +/* + 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 + (3-clause BSD License) + + Copyright (C) 2000-2016, Intel Corporation, all rights reserved. + Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. + Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. + Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. + Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved. + Copyright (C) 2015-2016, Itseez Inc., all rights reserved. + Third party copyrights are property of their respective owners. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the contributors + may 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 copyright holders 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. + */ + +#ifndef __OPENCV_PRECOMP_H__ +#define __OPENCV_PRECOMP_H__ + +#include "opencv2/dnn_modern.hpp" + +#endif