From 6aabd6cc7a0fd1008e65b8aa8aa3c7eca03e7a3e Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 18 Dec 2017 17:22:57 +0300 Subject: [PATCH] Remove cv::dnn::Importer --- modules/dnn/CMakeLists.txt | 12 ---- modules/dnn/include/opencv2/dnn/all_layers.hpp | 2 +- modules/dnn/include/opencv2/dnn/dnn.hpp | 76 ++++++-------------------- modules/dnn/perf/perf_caffe.cpp | 20 +++++-- modules/dnn/perf/perf_net.cpp | 20 ++++++- modules/dnn/src/caffe/caffe_importer.cpp | 13 +---- modules/dnn/src/darknet/darknet_importer.cpp | 8 +-- modules/dnn/src/dnn.cpp | 2 - modules/dnn/src/tensorflow/tf_importer.cpp | 16 +----- modules/dnn/src/torch/THDiskFile.cpp | 2 - modules/dnn/src/torch/THFile.cpp | 2 - modules/dnn/src/torch/THFile.h | 2 - modules/dnn/src/torch/THGeneral.cpp | 3 - modules/dnn/src/torch/torch_importer.cpp | 41 ++------------ modules/dnn/test/test_torch_importer.cpp | 9 +-- 15 files changed, 62 insertions(+), 166 deletions(-) diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index b36bfe5..77c6247 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -97,15 +97,3 @@ if(BUILD_PERF_TESTS) endif() endif() endif() - -# ---------------------------------------------------------------------------- -# Torch7 importer of blobs and models, produced by Torch.nn module -# ---------------------------------------------------------------------------- -OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer" ON) -if(${the_module}_BUILD_TORCH_IMPORTER) - message(STATUS "Torch importer has been enabled. To run the tests you have to install Torch " - "('th' executable should be available) " - "and generate testdata using opencv_extra/testdata/dnn/generate_torch_models.py script.") - add_definitions(-DENABLE_TORCH_IMPORTER=1) - ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files -endif() diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index b0d78f5..78fd23a 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN You can use both API, but factory API is less convinient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTorch(), @ref readNetFromTensorflow()). Bult-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers. - In partuclar, the following layers and Caffe @ref Importer were tested to reproduce Caffe functionality: + In partuclar, the following layers and Caffe importer were tested to reproduce Caffe functionality: - Convolution - Deconvolution - Pooling diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 24cabc2..3ded147 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -426,15 +426,6 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN void forward(std::vector >& outputBlobs, const std::vector& outBlobNames); - //TODO: - /** @brief Optimized forward. - * @warning Not implemented yet. - * @details Makes forward only those layers which weren't changed after previous forward(). - */ - void forwardOpt(LayerId toLayer); - /** @overload */ - void forwardOpt(const std::vector &toLayers); - /** * @brief Compile Halide layers. * @param[in] scheduler Path to YAML file with scheduling directives. @@ -609,38 +600,18 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN Ptr impl; }; - /** - * @deprecated Deprecated as external interface. Will be for internal needs only. - * @brief Small interface class for loading trained serialized models of different dnn-frameworks. */ - class CV_EXPORTS_W Importer : public Algorithm - { - public: - - /** @brief Adds loaded layers into the @p net and sets connections between them. */ - CV_DEPRECATED CV_WRAP virtual void populateNet(Net net) = 0; - - virtual ~Importer(); - }; - /** @brief Reads a network model stored in Darknet model files. * @param cfgFile path to the .cfg file with text description of the network architecture. * @param darknetModel path to the .weights file with learned network. * @returns Network object that ready to do forward, throw an exception in failure cases. - * @details This is shortcut consisting from DarknetImporter and Net::populateNet calls. + * @returns Net object. */ CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String()); - /** - * @deprecated Use @ref readNetFromCaffe instead. - * @brief Creates the importer of Caffe framework network. - * @param prototxt path to the .prototxt file with text description of the network architecture. - * @param caffeModel path to the .caffemodel file with learned network. - * @returns Pointer to the created importer, NULL in failure cases. - */ - CV_DEPRECATED CV_EXPORTS_W Ptr createCaffeImporter(const String &prototxt, const String &caffeModel = String()); - - /** @brief Reads a network model stored in Caffe model files. - * @details This is shortcut consisting from createCaffeImporter and Net::populateNet calls. + /** @brief Reads a network model stored in Caffe framework's format. + * @param prototxt path to the .prototxt file with text description of the network architecture. + * @param caffeModel path to the .caffemodel file with learned network. + * @returns Net object. */ CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String()); @@ -651,16 +622,21 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN * @param lenProto length of bufferProto * @param bufferModel buffer containing the content of the .caffemodel file * @param lenModel length of bufferModel + * @returns Net object. */ CV_EXPORTS Net readNetFromCaffe(const char *bufferProto, size_t lenProto, const char *bufferModel = NULL, size_t lenModel = 0); - /** @brief Reads a network model stored in Tensorflow model file. - * @details This is shortcut consisting from createTensorflowImporter and Net::populateNet calls. + /** @brief Reads a network model stored in TensorFlow framework's format. + * @param model path to the .pb file with binary protobuf description of the network architecture + * @param config path to the .pbtxt file that contains text graph definition in protobuf format. + * Resulting Net object is built by text graph using weights from a binary one that + * let us make it more flexible. + * @returns Net object. */ CV_EXPORTS_W Net readNetFromTensorflow(const String &model, const String &config = String()); - /** @brief Reads a network model stored in Tensorflow model in memory. + /** @brief Reads a network model stored in TensorFlow framework's format. * @details This is an overloaded member function, provided for convenience. * It differs from the above function only in what argument(s) it accepts. * @param bufferModel buffer containing the content of the pb file @@ -671,27 +647,11 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN CV_EXPORTS Net readNetFromTensorflow(const char *bufferModel, size_t lenModel, const char *bufferConfig = NULL, size_t lenConfig = 0); - /** @brief Reads a network model stored in Torch model file. - * @details This is shortcut consisting from createTorchImporter and Net::populateNet calls. - */ - CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true); - /** - * @deprecated Use @ref readNetFromTensorflow instead. - * @brief Creates the importer of TensorFlow framework network. - * @param model path to the .pb file with binary protobuf description of the network architecture. - * @returns Pointer to the created importer, NULL in failure cases. - */ - CV_DEPRECATED CV_EXPORTS_W Ptr createTensorflowImporter(const String &model); - - /** - * @deprecated Use @ref readNetFromTorch instead. - * @brief Creates the importer of Torch7 framework network. - * @param filename path to the file, dumped from Torch by using torch.save() function. + * @brief Reads a network model stored in Torch7 framework's format. + * @param model path to the file, dumped from Torch by using torch.save() function. * @param isBinary specifies whether the network was serialized in ascii mode or binary. - * @returns Pointer to the created importer, NULL in failure cases. - * - * @warning Torch7 importer is experimental now, you need explicitly set CMake `opencv_dnn_BUILD_TORCH_IMPORTER` flag to compile its. + * @returns Net object. * * @note Ascii mode of Torch serializer is more preferable, because binary mode extensively use `long` type of C language, * which has various bit-length on different systems. @@ -712,10 +672,10 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN * * Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported. */ - CV_DEPRECATED CV_EXPORTS_W Ptr createTorchImporter(const String &filename, bool isBinary = true); + CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true); /** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework. - * @warning This function has the same limitations as createTorchImporter(). + * @warning This function has the same limitations as readNetFromTorch(). */ CV_EXPORTS_W Mat readTorchBlob(const String &filename, bool isBinary = true); /** @brief Creates 4-dimensional blob from image. Optionally resizes and crops @p image from center, diff --git a/modules/dnn/perf/perf_caffe.cpp b/modules/dnn/perf/perf_caffe.cpp index c8817b9..35b2870 100644 --- a/modules/dnn/perf/perf_caffe.cpp +++ b/modules/dnn/perf/perf_caffe.cpp @@ -68,18 +68,18 @@ static caffe::Net* initNet(std::string proto, std::string weights) return net; } -PERF_TEST(GoogLeNet_caffe, CaffePerfTest) +PERF_TEST(AlexNet_caffe, CaffePerfTest) { - caffe::Net* net = initNet("dnn/bvlc_googlenet.prototxt", - "dnn/bvlc_googlenet.caffemodel"); + caffe::Net* net = initNet("dnn/bvlc_alexnet.prototxt", + "dnn/bvlc_alexnet.caffemodel"); TEST_CYCLE() net->Forward(); SANITY_CHECK_NOTHING(); } -PERF_TEST(AlexNet_caffe, CaffePerfTest) +PERF_TEST(GoogLeNet_caffe, CaffePerfTest) { - caffe::Net* net = initNet("dnn/bvlc_alexnet.prototxt", - "dnn/bvlc_alexnet.caffemodel"); + caffe::Net* net = initNet("dnn/bvlc_googlenet.prototxt", + "dnn/bvlc_googlenet.caffemodel"); TEST_CYCLE() net->Forward(); SANITY_CHECK_NOTHING(); } @@ -100,6 +100,14 @@ PERF_TEST(SqueezeNet_v1_1_caffe, CaffePerfTest) SANITY_CHECK_NOTHING(); } +PERF_TEST(MobileNet_SSD, CaffePerfTest) +{ + caffe::Net* net = initNet("dnn/MobileNetSSD_deploy.prototxt", + "dnn/MobileNetSSD_deploy.caffemodel"); + TEST_CYCLE() net->Forward(); + SANITY_CHECK_NOTHING(); +} + } // namespace cvtest #endif // HAVE_CAFFE diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index 0d6d257..219c702 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -70,7 +70,7 @@ public: } else if (framework == "tensorflow") { - net = cv::dnn::readNetFromTensorflow(weights); + net = cv::dnn::readNetFromTensorflow(weights, proto); } else CV_Error(Error::StsNotImplemented, "Unknown framework " + framework); @@ -148,6 +148,24 @@ PERF_TEST_P_(DNNTestNetwork, SSD) Mat(cv::Size(300, 300), CV_32FC3), "detection_out", "caffe"); } +PERF_TEST_P_(DNNTestNetwork, OpenFace) +{ + processNet("dnn/openface_nn4.small2.v1.t7", "", "", + Mat(cv::Size(96, 96), CV_32FC3), "", "torch"); +} + +PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe) +{ + processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt", "", + Mat(cv::Size(300, 300), CV_32FC3), "detection_out", "caffe"); +} + +PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow) +{ + processNet("dnn/ssd_mobilenet_v1_coco.pb", "ssd_mobilenet_v1_coco.pbtxt", "", + Mat(cv::Size(300, 300), CV_32FC3), "", "tensorflow"); +} + INSTANTIATE_TEST_CASE_P(/*nothing*/, DNNTestNetwork, testing::Combine( ::testing::Values(TEST_DNN_BACKEND), diff --git a/modules/dnn/src/caffe/caffe_importer.cpp b/modules/dnn/src/caffe/caffe_importer.cpp index a219bd5..106793c 100644 --- a/modules/dnn/src/caffe/caffe_importer.cpp +++ b/modules/dnn/src/caffe/caffe_importer.cpp @@ -75,7 +75,7 @@ static cv::String toString(const T &v) return ss.str(); } -class CaffeImporter : public Importer +class CaffeImporter { caffe::NetParameter net; caffe::NetParameter netBinary; @@ -390,21 +390,10 @@ public: dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum); } - - ~CaffeImporter() - { - - } - }; } -Ptr createCaffeImporter(const String &prototxt, const String &caffeModel) -{ - return Ptr(new CaffeImporter(prototxt.c_str(), caffeModel.c_str())); -} - Net readNetFromCaffe(const String &prototxt, const String &caffeModel /*= String()*/) { CaffeImporter caffeImporter(prototxt.c_str(), caffeModel.c_str()); diff --git a/modules/dnn/src/darknet/darknet_importer.cpp b/modules/dnn/src/darknet/darknet_importer.cpp index 18a7bc9..8bd64d0 100644 --- a/modules/dnn/src/darknet/darknet_importer.cpp +++ b/modules/dnn/src/darknet/darknet_importer.cpp @@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN namespace { -class DarknetImporter : public Importer +class DarknetImporter { darknet::NetParameter net; @@ -173,12 +173,6 @@ public: dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum); } - - ~DarknetImporter() - { - - } - }; } diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index b9cb154..b9360b1 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2294,8 +2294,6 @@ int64 Net::getPerfProfile(std::vector& timings) ////////////////////////////////////////////////////////////////////////// -Importer::~Importer() {} - Layer::Layer() { preferableTarget = DNN_TARGET_CPU; } Layer::Layer(const LayerParams ¶ms) diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 0cecd4d..202958d 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -446,14 +446,13 @@ void ExcludeLayer(tensorflow::GraphDef& net, const int layer_index, const int in net.mutable_node()->DeleteSubrange(layer_index, 1); } -class TFImporter : public Importer { +class TFImporter { public: TFImporter(const char *model, const char *config = NULL); TFImporter(const char *dataModel, size_t lenModel, const char *dataConfig = NULL, size_t lenConfig = 0); void populateNet(Net dstNet); - ~TFImporter() {} private: void kernelFromTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob); @@ -1315,19 +1314,6 @@ void TFImporter::populateNet(Net dstNet) } // namespace -Ptr createTensorflowImporter(const String &model) -{ - return Ptr(new TFImporter(model.c_str())); -} - -#else //HAVE_PROTOBUF - -Ptr createTensorflowImporter(const String&) -{ - CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from TensorFlow models"); - return Ptr(); -} - #endif //HAVE_PROTOBUF Net readNetFromTensorflow(const String &model, const String &config) diff --git a/modules/dnn/src/torch/THDiskFile.cpp b/modules/dnn/src/torch/THDiskFile.cpp index 192680e..aad9ecc 100644 --- a/modules/dnn/src/torch/THDiskFile.cpp +++ b/modules/dnn/src/torch/THDiskFile.cpp @@ -1,5 +1,4 @@ #include "../precomp.hpp" -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #include "THGeneral.h" #include "THDiskFile.h" #include "THFilePrivate.h" @@ -517,4 +516,3 @@ THFile *THDiskFile_new(const std::string &name, const char *mode, int isQuiet) } } -#endif diff --git a/modules/dnn/src/torch/THFile.cpp b/modules/dnn/src/torch/THFile.cpp index 081873f..5f7fe1c 100644 --- a/modules/dnn/src/torch/THFile.cpp +++ b/modules/dnn/src/torch/THFile.cpp @@ -1,5 +1,4 @@ #include "../precomp.hpp" -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #include "THFile.h" #include "THFilePrivate.h" @@ -119,4 +118,3 @@ IMPLEMENT_THFILE_SCALAR(Float, float) IMPLEMENT_THFILE_SCALAR(Double, double) } // namespace -#endif diff --git a/modules/dnn/src/torch/THFile.h b/modules/dnn/src/torch/THFile.h index 5ac3af2..14e3fbf 100644 --- a/modules/dnn/src/torch/THFile.h +++ b/modules/dnn/src/torch/THFile.h @@ -2,7 +2,6 @@ #define TH_FILE_INC //#include "THStorage.h" -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #include "opencv2/core/hal/interface.h" #include "THGeneral.h" @@ -51,5 +50,4 @@ TH_API long THFile_position(THFile *self); TH_API void THFile_close(THFile *self); TH_API void THFile_free(THFile *self); } // namespace -#endif //defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #endif //TH_FILE_INC diff --git a/modules/dnn/src/torch/THGeneral.cpp b/modules/dnn/src/torch/THGeneral.cpp index b0f38e0..8a52745 100644 --- a/modules/dnn/src/torch/THGeneral.cpp +++ b/modules/dnn/src/torch/THGeneral.cpp @@ -1,5 +1,4 @@ #include "../precomp.hpp" -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #if defined(TH_DISABLE_HEAP_TRACKING) #elif (defined(__unix) || defined(_WIN32)) @@ -9,5 +8,3 @@ #endif #include "THGeneral.h" - -#endif diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp index df5f1db..b664d79 100644 --- a/modules/dnn/src/torch/torch_importer.cpp +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -47,15 +47,12 @@ #include #include -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER #include "THDiskFile.h" -#endif namespace cv { namespace dnn { CV__DNN_EXPERIMENTAL_NS_BEGIN -#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER using namespace TH; //#ifdef NDEBUG @@ -95,7 +92,7 @@ static inline bool endsWith(const String &str, const char *substr) return str.rfind(substr) == str.length() - strlen(substr); } -struct TorchImporter : public ::cv::dnn::Importer +struct TorchImporter { typedef std::map > TensorsMap; Net net; @@ -1191,19 +1188,13 @@ struct TorchImporter : public ::cv::dnn::Importer } }; -Ptr createTorchImporter(const String &filename, bool isBinary) -{ - return Ptr(new TorchImporter(filename, isBinary)); -} - - Mat readTorchBlob(const String &filename, bool isBinary) { - Ptr importer(new TorchImporter(filename, isBinary)); - importer->readObject(); - CV_Assert(importer->tensors.size() == 1); + TorchImporter importer(filename, isBinary); + importer.readObject(); + CV_Assert(importer.tensors.size() == 1); - return importer->tensors.begin()->second; + return importer.tensors.begin()->second; } Net readNetFromTorch(const String &model, bool isBinary) @@ -1216,27 +1207,5 @@ Net readNetFromTorch(const String &model, bool isBinary) return net; } -#else - -Ptr createTorchImporter(const String&, bool) -{ - CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build"); - return Ptr(); -} - -Mat readTorchBlob(const String&, bool) -{ - CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build"); - return Mat(); -} - -Net readNetFromTorch(const String &model, bool isBinary) -{ - CV_Error(Error::StsNotImplemented, "Torch importer is disabled in current build"); - return Net(); -} - -#endif //defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER - CV__DNN_EXPERIMENTAL_NS_END }} // namespace diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index c90ddeb..cbac6c5 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -39,8 +39,6 @@ // //M*/ -#ifdef ENABLE_TORCH_IMPORTER - #include "test_precomp.hpp" #include "npy_blob.hpp" #include @@ -316,9 +314,8 @@ OCL_TEST(Torch_Importer, ENet_accuracy) Net net; { const string model = findDataFile("dnn/Enet-model-best.net", false); - Ptr importer = createTorchImporter(model, true); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromTorch(model, true); + ASSERT_TRUE(!net.empty()); } net.setPreferableBackend(DNN_BACKEND_DEFAULT); @@ -421,5 +418,3 @@ OCL_TEST(Torch_Importer, FastNeuralStyle_accuracy) } } - -#endif -- 2.7.4