From bd8e6b7e146a91e1acaa1fc5a86433d290257497 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 3 Aug 2017 17:43:52 +0300 Subject: [PATCH] Make external cv::dnn::Importer usage is deprecated --- modules/dnn/include/opencv2/dnn/all_layers.hpp | 2 +- modules/dnn/include/opencv2/dnn/dnn.hpp | 24 ++++++++++++------ modules/dnn/misc/java/test/DnnTensorFlowTest.java | 7 +---- modules/dnn/src/caffe/caffe_importer.cpp | 17 +++---------- modules/dnn/src/tensorflow/tf_importer.cpp | 5 ++-- modules/dnn/src/torch/torch_importer.cpp | 5 ++-- modules/dnn/test/test_caffe_importer.cpp | 31 ++++++++--------------- modules/dnn/test/test_layers.cpp | 25 +++++------------- modules/dnn/test/test_tf_importer.cpp | 10 +++----- modules/dnn/test/test_torch_importer.cpp | 18 +++++-------- modules/java/CMakeLists.txt | 7 ++++- modules/python/python2/CMakeLists.txt | 6 +++++ modules/python/python3/CMakeLists.txt | 6 +++++ modules/python/src2/hdr_parser.py | 3 ++- samples/dnn/fcn_semsegm.cpp | 22 +++------------- samples/dnn/ssd_object_detection.cpp | 24 +++--------------- samples/dnn/tf_inception.cpp | 22 +++------------- 17 files changed, 85 insertions(+), 149 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index ef61efd..bdb5424 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -55,7 +55,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN Classes listed here, in fact, provides C++ API for creating intances of bult-in layers. In addition to this way of layers instantiation, there is a more common factory API (see @ref dnnLayerFactory), it allows to create layers dynamically (by name) and register new ones. - You can use both API, but factory API is less convinient for native C++ programming and basically designed for use inside importers (see @ref Importer, @ref createCaffeImporter(), @ref createTorchImporter()). + 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: diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index add54f6..be54356 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -598,23 +598,27 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN Ptr impl; }; - /** @brief Small interface class for loading trained serialized models of different dnn-frameworks. */ + /** + * @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_WRAP virtual void populateNet(Net net) = 0; + CV_DEPRECATED CV_WRAP virtual void populateNet(Net net) = 0; virtual ~Importer(); }; - /** @brief Creates the importer of Caffe framework network. + /** + * @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_EXPORTS_W Ptr createCaffeImporter(const String &prototxt, const String &caffeModel = String()); + 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. @@ -631,13 +635,17 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN */ CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true); - /** @brief Creates the importer of TensorFlow framework network. + /** + * @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_EXPORTS_W Ptr createTensorflowImporter(const String &model); + CV_DEPRECATED CV_EXPORTS_W Ptr createTensorflowImporter(const String &model); - /** @brief Creates the importer of Torch7 framework network. + /** + * @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. * @param isBinary specifies whether the network was serialized in ascii mode or binary. * @returns Pointer to the created importer, NULL in failure cases. @@ -663,7 +671,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN * * Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported. */ - CV_EXPORTS_W Ptr createTorchImporter(const String &filename, bool isBinary = true); + CV_DEPRECATED CV_EXPORTS_W Ptr createTorchImporter(const String &filename, 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(). diff --git a/modules/dnn/misc/java/test/DnnTensorFlowTest.java b/modules/dnn/misc/java/test/DnnTensorFlowTest.java index b4116e8..388237d 100644 --- a/modules/dnn/misc/java/test/DnnTensorFlowTest.java +++ b/modules/dnn/misc/java/test/DnnTensorFlowTest.java @@ -51,12 +51,7 @@ public class DnnTensorFlowTest extends OpenCVTestCase { sourceImageFile = f.toString(); if(!f.exists()) throw new Exception("Test image is missing: " + sourceImageFile); - net = new Net(); - if(net.empty()) { - Importer importer = Dnn.createTensorflowImporter(modelFileName); - importer.populateNet(net); - } - + net = Dnn.readNetFromTensorflow(modelFileName); } public void testGetLayerTypes() { diff --git a/modules/dnn/src/caffe/caffe_importer.cpp b/modules/dnn/src/caffe/caffe_importer.cpp index c075651..fd5335e 100644 --- a/modules/dnn/src/caffe/caffe_importer.cpp +++ b/modules/dnn/src/caffe/caffe_importer.cpp @@ -370,24 +370,15 @@ Ptr createCaffeImporter(const String &prototxt, const String &caffeMod return Ptr(new CaffeImporter(prototxt.c_str(), caffeModel.c_str())); } -#else //HAVE_PROTOBUF - -Ptr createCaffeImporter(const String&, const String&) -{ - CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from Caffe models"); - return Ptr(); -} - -#endif //HAVE_PROTOBUF - Net readNetFromCaffe(const String &prototxt, const String &caffeModel /*= String()*/) { - Ptr caffeImporter = createCaffeImporter(prototxt, caffeModel); + CaffeImporter caffeImporter(prototxt.c_str(), caffeModel.c_str()); Net net; - if (caffeImporter) - caffeImporter->populateNet(net); + caffeImporter.populateNet(net); return net; } +#endif //HAVE_PROTOBUF + CV__DNN_EXPERIMENTAL_NS_END }} // namespace diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index d7fd076..0797986 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1045,10 +1045,9 @@ Ptr createTensorflowImporter(const String&) Net readNetFromTensorflow(const String &model) { - Ptr importer = createTensorflowImporter(model); + TFImporter importer(model.c_str()); Net net; - if (importer) - importer->populateNet(net); + importer.populateNet(net); return net; } diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp index 1cb1b48..56c55d6 100644 --- a/modules/dnn/src/torch/torch_importer.cpp +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -1150,10 +1150,9 @@ Net readNetFromTorch(const String &model, bool isBinary) { CV_TRACE_FUNCTION(); - Ptr importer = createTorchImporter(model, isBinary); + TorchImporter importer(model, isBinary); Net net; - if (importer) - importer->populateNet(net); + importer.populateNet(net); return net; } diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp index 7fe7f1d..7512225 100644 --- a/modules/dnn/test/test_caffe_importer.cpp +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -57,22 +57,14 @@ static std::string _tf(TString filename) TEST(Test_Caffe, read_gtsrb) { - Net net; - { - Ptr importer = createCaffeImporter(_tf("gtsrb.prototxt"), ""); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); - } + Net net = readNetFromCaffe(_tf("gtsrb.prototxt")); + ASSERT_FALSE(net.empty()); } TEST(Test_Caffe, read_googlenet) { - Net net; - { - Ptr importer = createCaffeImporter(_tf("bvlc_googlenet.prototxt"), ""); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); - } + Net net = readNetFromCaffe(_tf("bvlc_googlenet.prototxt")); + ASSERT_FALSE(net.empty()); } TEST(Reproducibility_AlexNet, Accuracy) @@ -81,9 +73,8 @@ TEST(Reproducibility_AlexNet, Accuracy) { const string proto = findDataFile("dnn/bvlc_alexnet.prototxt", false); const string model = findDataFile("dnn/bvlc_alexnet.caffemodel", false); - Ptr importer = createCaffeImporter(proto, model); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromCaffe(proto, model); + ASSERT_FALSE(net.empty()); } Mat sample = imread(_tf("grace_hopper_227.png")); @@ -107,9 +98,8 @@ TEST(Reproducibility_FCN, Accuracy) { const string proto = findDataFile("dnn/fcn8s-heavy-pascal.prototxt", false); const string model = findDataFile("dnn/fcn8s-heavy-pascal.caffemodel", false); - Ptr importer = createCaffeImporter(proto, model); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromCaffe(proto, model); + ASSERT_FALSE(net.empty()); } Mat sample = imread(_tf("street.png")); @@ -136,9 +126,8 @@ TEST(Reproducibility_SSD, Accuracy) { const string proto = findDataFile("dnn/ssd_vgg16.prototxt", false); const string model = findDataFile("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", false); - Ptr importer = createCaffeImporter(proto, model); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromCaffe(proto, model); + ASSERT_FALSE(net.empty()); } Mat sample = imread(_tf("street.png")); diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 4ca06ef..ff33be5 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -108,12 +108,8 @@ void testLayerUsingCaffeModels(String basename, bool useCaffeModel = false, bool cv::setNumThreads(cv::getNumberOfCPUs()); - Net net; - { - Ptr importer = createCaffeImporter(prototxt, (useCaffeModel) ? caffemodel : String()); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); - } + Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String()); + ASSERT_FALSE(net.empty()); Mat inp = blobFromNPY(inpfile); Mat ref = blobFromNPY(outfile); @@ -252,12 +248,8 @@ TEST(Layer_Test_Concat, Accuracy) static void test_Reshape_Split_Slice_layers() { - Net net; - { - Ptr importer = createCaffeImporter(_tf("reshape_and_slice_routines.prototxt")); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); - } + Net net = readNetFromCaffe(_tf("reshape_and_slice_routines.prototxt")); + ASSERT_FALSE(net.empty()); Mat input(6, 12, CV_32F); RNG rng(0); @@ -276,12 +268,9 @@ TEST(Layer_Test_Reshape_Split_Slice, Accuracy) TEST(Layer_Conv_Elu, Accuracy) { - Net net; - { - Ptr importer = createTensorflowImporter(_tf("layer_elu_model.pb")); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); - } + Net net = readNetFromTensorflow(_tf("layer_elu_model.pb")); + ASSERT_FALSE(net.empty()); + Mat inp = blobFromNPY(_tf("layer_elu_in.npy")); Mat ref = blobFromNPY(_tf("layer_elu_out.npy")); diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 6d5df73..d145bdf 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -29,9 +29,8 @@ TEST(Test_TensorFlow, read_inception) Net net; { const string model = findDataFile("dnn/tensorflow_inception_graph.pb", false); - Ptr importer = createTensorflowImporter(model); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromTensorflow(model); + ASSERT_FALSE(net.empty()); } Mat sample = imread(_tf("grace_hopper_227.png")); @@ -53,9 +52,8 @@ TEST(Test_TensorFlow, inception_accuracy) Net net; { const string model = findDataFile("dnn/tensorflow_inception_graph.pb", false); - Ptr importer = createTensorflowImporter(model); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + net = readNetFromTensorflow(model); + ASSERT_FALSE(net.empty()); } Mat sample = imread(_tf("grace_hopper_227.png")); diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index c46f3a9..fa444ed 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -66,11 +66,8 @@ static std::string _tf(TStr filename, bool inTorchDir = true) TEST(Torch_Importer, simple_read) { Net net; - Ptr importer; - - ASSERT_NO_THROW( importer = createTorchImporter(_tf("net_simple_net.txt"), false) ); - ASSERT_TRUE( importer != NULL ); - importer->populateNet(net); + ASSERT_NO_THROW(net = readNetFromTorch(_tf("net_simple_net.txt"), false)); + ASSERT_FALSE(net.empty()); } static void runTorchNet(String prefix, String outLayerName = "", @@ -78,10 +75,8 @@ static void runTorchNet(String prefix, String outLayerName = "", { String suffix = (isBinary) ? ".dat" : ".txt"; - Net net; - Ptr importer = createTorchImporter(_tf(prefix + "_net" + suffix), isBinary); - ASSERT_TRUE(importer != NULL); - importer->populateNet(net); + Net net = readNetFromTorch(_tf(prefix + "_net" + suffix), isBinary); + ASSERT_FALSE(net.empty()); Mat inp, outRef; ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) ); @@ -200,9 +195,8 @@ 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_FALSE(net.empty()); } Mat sample = imread(_tf("street.png", false)); diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 2f49eb2..37c4af2 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -413,7 +413,12 @@ endif(ANDROID) # workarounding lack of `__attribute__ ((visibility("default")))` in jni_md.h/JNIEXPORT string(REPLACE "-fvisibility=hidden" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-const-variable -Wundef) +if(MSVC) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996) +else() + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-const-variable -Wundef -Wdeprecated-declarations) +endif() + ocv_add_library(${the_module} SHARED ${handwritten_h_sources} ${handwritten_cpp_sources} ${generated_cpp_sources} ${copied_files} diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index 37e20fe..bf55ef8 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -13,3 +13,9 @@ include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) + +if(MSVC) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996) +else() + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations) +endif() diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt index da86ba5..b3a7253 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -12,3 +12,9 @@ include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) + +if(MSVC) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996) +else() + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations) +endif() diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 0999a43..61afe6a 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -410,7 +410,8 @@ class CppHeaderParser(object): # note that we do not strip "static" prefix, which does matter; # it means class methods, not instance methods decl_str = self.batch_replace(decl_str, [("virtual", ""), ("static inline", ""), ("inline", ""),\ - ("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("CV_CDECL", ""), ("CV_WRAP ", " "), ("CV_INLINE", "")]).strip() + ("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("CV_CDECL", ""), ("CV_WRAP ", " "), ("CV_INLINE", ""), + ("CV_DEPRECATED", "")]).strip() static_method = False context = top[0] diff --git a/samples/dnn/fcn_semsegm.cpp b/samples/dnn/fcn_semsegm.cpp index e8ae04e..94ff267 100644 --- a/samples/dnn/fcn_semsegm.cpp +++ b/samples/dnn/fcn_semsegm.cpp @@ -91,19 +91,11 @@ int main(int argc, char **argv) vector colors = readColors(); - //! [Create the importer of Caffe model] - Ptr importer; - try //Try to import Caffe GoogleNet model - { - importer = dnn::createCaffeImporter(modelTxt, modelBin); - } - catch (const cv::Exception &err) //Importer can throw errors, we will catch them - { - cerr << err.msg << endl; - } - //! [Create the importer of Caffe model] + //! [Initialize network] + dnn::Net net = readNetFromCaffe(modelTxt, modelBin); + //! [Initialize network] - if (!importer) + if (net.empty()) { cerr << "Can't load network by using the following files: " << endl; cerr << "prototxt: " << modelTxt << endl; @@ -113,12 +105,6 @@ int main(int argc, char **argv) exit(-1); } - //! [Initialize network] - dnn::Net net; - importer->populateNet(net); - importer.release(); //We don't need importer anymore - //! [Initialize network] - //! [Prepare blob] Mat img = imread(imageFile); if (img.empty()) diff --git a/samples/dnn/ssd_object_detection.cpp b/samples/dnn/ssd_object_detection.cpp index 7a51d3d..214dd91 100644 --- a/samples/dnn/ssd_object_detection.cpp +++ b/samples/dnn/ssd_object_detection.cpp @@ -65,21 +65,11 @@ int main(int argc, char** argv) String modelConfiguration = parser.get("proto"); String modelBinary = parser.get("model"); - //! [Create the importer of Caffe model] - Ptr importer; - - // Import Caffe SSD model - try - { - importer = dnn::createCaffeImporter(modelConfiguration, modelBinary); - } - catch (const cv::Exception &err) //Importer can throw errors, we will catch them - { - cerr << err.msg << endl; - } - //! [Create the importer of Caffe model] + //! [Initialize network] + dnn::Net net = readNetFromCaffe(modelConfiguration, modelBinary); + //! [Initialize network] - if (!importer) + if (net.empty()) { cerr << "Can't load network by using the following files: " << endl; cerr << "prototxt: " << modelConfiguration << endl; @@ -89,12 +79,6 @@ int main(int argc, char** argv) exit(-1); } - //! [Initialize network] - dnn::Net net; - importer->populateNet(net); - importer.release(); //We don't need importer anymore - //! [Initialize network] - cv::Mat frame = cv::imread(parser.get("image"), -1); if (frame.channels() == 4) diff --git a/samples/dnn/tf_inception.cpp b/samples/dnn/tf_inception.cpp index 44af4ce..f184d39 100644 --- a/samples/dnn/tf_inception.cpp +++ b/samples/dnn/tf_inception.cpp @@ -59,31 +59,17 @@ int main(int argc, char **argv) String classNamesFile = parser.get("c_names"); String resultFile = parser.get("result"); - //! [Create the importer of TensorFlow model] - Ptr importer; - try //Try to import TensorFlow AlexNet model - { - importer = dnn::createTensorflowImporter(modelFile); - } - catch (const cv::Exception &err) //Importer can throw errors, we will catch them - { - std::cerr << err.msg << std::endl; - } - //! [Create the importer of Caffe model] + //! [Initialize network] + dnn::Net net = readNetFromTensorflow(modelFile); + //! [Initialize network] - if (!importer) + if (net.empty()) { std::cerr << "Can't load network by using the mode file: " << std::endl; std::cerr << modelFile << std::endl; exit(-1); } - //! [Initialize network] - dnn::Net net; - importer->populateNet(net); - importer.release(); //We don't need importer anymore - //! [Initialize network] - //! [Prepare blob] Mat img = imread(imageFile); if (img.empty()) -- 2.7.4