From b71be65f5785acdfa20c1aba49e0a6f02e4523b4 Mon Sep 17 00:00:00 2001 From: alexlyulkov Date: Thu, 26 Oct 2023 15:27:56 +0700 Subject: [PATCH] Merge pull request #24294 from alexlyulkov:al/remove-torch7-from-dnn Remove torch (old torch7) from dnn in 5.x #24294 Merge with https://github.com/opencv/opencv_extra/pull/1097 Completely removed torch (old torch7) from dnn: - removed modules/dnn/src/torch directory that contained torch7 model parser - removed readNetFromTorch() and readTorchBlob() public functions - removed torch7 references from comments and help texts - replaced links to t7 models by links to similar onnx models in js_style_transfer turtorial (similar to https://github.com/opencv/opencv/pull/24245/files) --- .../js_style_transfer_model_info.json | 76 +- modules/dnn/CMakeLists.txt | 2 +- .../dnn/include/opencv2/dnn/all_layers.hpp | 4 +- modules/dnn/include/opencv2/dnn/dnn.hpp | 38 +- modules/dnn/perf/perf_net.cpp | 23 +- modules/dnn/src/dnn_read.cpp | 6 - modules/dnn/src/torch/COPYRIGHT.txt | 36 - modules/dnn/src/torch/THDiskFile.cpp | 530 ------- modules/dnn/src/torch/THDiskFile.h | 22 - modules/dnn/src/torch/THFile.cpp | 120 -- modules/dnn/src/torch/THFile.h | 53 - modules/dnn/src/torch/THFilePrivate.h | 37 - modules/dnn/src/torch/THGeneral.cpp | 2 - modules/dnn/src/torch/THGeneral.h | 22 - modules/dnn/src/torch/torch_importer.cpp | 1267 ----------------- .../dnn/test/cityscapes_semsegm_test_enet.py | 140 -- modules/dnn/test/test_backends.cpp | 49 +- modules/dnn/test/test_misc.cpp | 2 - modules/dnn/test/test_torch_importer.cpp | 664 --------- platforms/js/opencv_js.config.py | 2 +- samples/dnn/classification.py | 2 +- samples/dnn/common.hpp | 2 +- samples/dnn/common.py | 2 +- samples/dnn/models.yml | 15 - samples/dnn/object_detection.py | 2 +- samples/dnn/segmentation.py | 2 +- 26 files changed, 41 insertions(+), 3079 deletions(-) delete mode 100644 modules/dnn/src/torch/COPYRIGHT.txt delete mode 100644 modules/dnn/src/torch/THDiskFile.cpp delete mode 100644 modules/dnn/src/torch/THDiskFile.h delete mode 100644 modules/dnn/src/torch/THFile.cpp delete mode 100644 modules/dnn/src/torch/THFile.h delete mode 100644 modules/dnn/src/torch/THFilePrivate.h delete mode 100644 modules/dnn/src/torch/THGeneral.cpp delete mode 100644 modules/dnn/src/torch/THGeneral.h delete mode 100644 modules/dnn/src/torch/torch_importer.cpp delete mode 100644 modules/dnn/test/cityscapes_semsegm_test_enet.py delete mode 100644 modules/dnn/test/test_torch_importer.cpp diff --git a/doc/js_tutorials/js_assets/js_style_transfer_model_info.json b/doc/js_tutorials/js_assets/js_style_transfer_model_info.json index 9cc66018a0..04258298dc 100644 --- a/doc/js_tutorials/js_assets/js_style_transfer_model_info.json +++ b/doc/js_tutorials/js_assets/js_style_transfer_model_info.json @@ -1,76 +1,44 @@ { - "torch": [ + "onnx": [ { - "model": "candy.t7", + "model": "mosaic-9.onnx", "inputSize": "224, 224", - "mean": "104, 117, 123", + "mean": "0, 0, 0", "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/candy.t7" + "swapRB": "true", + "modelUrl": "https://media.githubusercontent.com/media/onnx/models/main/vision/style_transfer/fast_neural_style/model/mosaic-9.onnx" }, { - "model": "composition_vii.t7", + "model": "candy-9.onnx", "inputSize": "224, 224", - "mean": "104, 117, 123", + "mean": "0, 0, 0", "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//eccv16/composition_vii.t7" + "swapRB": "true", + "modelUrl": "https://media.githubusercontent.com/media/onnx/models/main/vision/style_transfer/fast_neural_style/model/candy-9.onnx" }, { - "model": "feathers.t7", + "model": "rain-princess-9.onnx", "inputSize": "224, 224", - "mean": "104, 117, 123", + "mean": "0, 0, 0", "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/feathers.t7" + "swapRB": "true", + "modelUrl": "https://media.githubusercontent.com/media/onnx/models/main/vision/style_transfer/fast_neural_style/model/rain-princess-9.onnx" }, { - "model": "la_muse.t7", + "model": "udnie-9.onnx", "inputSize": "224, 224", - "mean": "104, 117, 123", + "mean": "0, 0, 0", "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/la_muse.t7" + "swapRB": "true", + "modelUrl": "https://media.githubusercontent.com/media/onnx/models/main/vision/style_transfer/fast_neural_style/model/udnie-9.onnx" }, { - "model": "mosaic.t7", + "model": "pointilism-9.onnx", "inputSize": "224, 224", - "mean": "104, 117, 123", + "mean": "0, 0, 0", "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/mosaic.t7" - }, - { - "model": "starry_night.t7", - "inputSize": "224, 224", - "mean": "104, 117, 123", - "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//eccv16/starry_night.t7" - }, - { - "model": "the_scream.t7", - "inputSize": "224, 224", - "mean": "104, 117, 123", - "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/the_scream.t7" - }, - { - "model": "the_wave.t7", - "inputSize": "224, 224", - "mean": "104, 117, 123", - "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//eccv16/the_wave.t7" - }, - { - "model": "udnie.t7", - "inputSize": "224, 224", - "mean": "104, 117, 123", - "std": "1", - "swapRB": "false", - "modelUrl": "https://cs.stanford.edu/people/jcjohns/fast-neural-style/models//instance_norm/udnie.t7" + "swapRB": "true", + "modelUrl": "https://media.githubusercontent.com/media/onnx/models/main/vision/style_transfer/fast_neural_style/model/pointilism-9.onnx" } ] -} \ No newline at end of file +} diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 5963eb68d3..681625816c 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -209,7 +209,7 @@ 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_utils.cpp$|/src/dnn_read.cpp$|/src/registry.cpp$|/src/backend.cpp$" # importers - "/src/(caffe|darknet|onnx|tensorflow|torch)/" + "/src/(caffe|darknet|onnx|tensorflow)/" # executors "/src/(cuda|cuda4dnn|ocl4dnn|vkcom|webnn)/" ) diff --git a/modules/dnn/include/opencv2/dnn/all_layers.hpp b/modules/dnn/include/opencv2/dnn/all_layers.hpp index 587eda102f..2f2bc6b548 100644 --- a/modules/dnn/include/opencv2/dnn/all_layers.hpp +++ b/modules/dnn/include/opencv2/dnn/all_layers.hpp @@ -55,9 +55,9 @@ CV__DNN_INLINE_NS_BEGIN Classes listed here, in fact, provides C++ API for creating instances of built-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 convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTorch(), @ref readNetFromTensorflow()). + You can use both API, but factory API is less convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTensorflow()). - Built-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers. + Built-in layers partially reproduce functionality of corresponding ONNX, TensorFlow and Caffe layers. In particular, the following layers and Caffe importer were tested to reproduce Caffe functionality: - Convolution - Deconvolution diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 39ef6435e4..76bf277bc1 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -934,41 +934,12 @@ CV__DNN_INLINE_NS_BEGIN */ CV_EXPORTS Net readNetFromTFLite(const char *bufferModel, size_t lenModel); - /** - * @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. - * @param evaluate specifies testing phase of network. If true, it's similar to evaluate() method in Torch. - * @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. - * - * The loading file must contain serialized nn.Module object - * with importing network. Try to eliminate a custom objects from serialazing data to avoid importing errors. - * - * List of supported layers (i.e. object instances derived from Torch nn.Module class): - * - nn.Sequential - * - nn.Parallel - * - nn.Concat - * - nn.Linear - * - nn.SpatialConvolution - * - nn.SpatialMaxPooling, nn.SpatialAveragePooling - * - nn.ReLU, nn.TanH, nn.Sigmoid - * - nn.Reshape - * - nn.SoftMax, nn.LogSoftMax - * - * Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported. - */ - CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true, bool evaluate = true); - /** * @brief Read deep learning network represented in one of the supported formats. * @param[in] model Binary file contains trained weights. The following file * extensions are expected for models from different frameworks: * * `*.caffemodel` (Caffe, http://caffe.berkeleyvision.org/) * * `*.pb` (TensorFlow, https://www.tensorflow.org/) - * * `*.t7` | `*.net` (Torch, http://torch.ch/) * * `*.weights` (Darknet, https://pjreddie.com/darknet/) * * `*.bin` (DLDT, https://software.intel.com/openvino-toolkit) * * `*.onnx` (ONNX, https://onnx.ai/) @@ -982,8 +953,8 @@ CV__DNN_INLINE_NS_BEGIN * @returns Net object. * * This function automatically detects an origin framework of trained model - * and calls an appropriate function such @ref readNetFromCaffe, @ref readNetFromTensorflow, - * @ref readNetFromTorch or @ref readNetFromDarknet. An order of @p model and @p config + * and calls an appropriate function such @ref readNetFromCaffe, @ref readNetFromTensorflow + * or @ref readNetFromDarknet. An order of @p model and @p config * arguments does not matter. */ CV_EXPORTS_W Net readNet(const String& model, const String& config = "", const String& framework = ""); @@ -1000,11 +971,6 @@ CV__DNN_INLINE_NS_BEGIN CV_EXPORTS_W Net readNet(const String& framework, const std::vector& bufferModel, const std::vector& bufferConfig = std::vector()); - /** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework. - * @warning This function has the same limitations as readNetFromTorch(). - */ - CV_EXPORTS_W Mat readTorchBlob(const String &filename, bool isBinary = true); - /** @brief Load a network from Intel's Model Optimizer intermediate representation. * @param[in] xml XML configuration file with network's topology. * @param[in] bin Binary file with trained weights. diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index 46484e82c5..96c4aea124 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -109,32 +109,11 @@ PERF_TEST_P_(DNNTestNetwork, Inception_5h) processNet("dnn/tensorflow_inception_graph.pb", "", cv::Size(224, 224), "softmax2"); } -PERF_TEST_P_(DNNTestNetwork, ENet) -{ - if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) || - (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)) - throw SkipTestException(""); -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2021010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) - throw SkipTestException(""); -#endif - processNet("dnn/Enet-model-best.net", "", cv::Size(512, 256)); -} - PERF_TEST_P_(DNNTestNetwork, SSD) { processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", "dnn/ssd_vgg16.prototxt", cv::Size(300, 300)); } -PERF_TEST_P_(DNNTestNetwork, OpenFace) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_HDDL)) - throw SkipTestException(""); -#endif - processNet("dnn/openface_nn4.small2.v1.t7", "", cv::Size(96, 96)); -} - PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe) { processNet("dnn/MobileNetSSD_deploy_19e3ec3.caffemodel", "dnn/MobileNetSSD_deploy_19e3ec3.prototxt", cv::Size(300, 300)); @@ -248,7 +227,7 @@ PERF_TEST_P_(DNNTestNetwork, EAST_text_detection) PERF_TEST_P_(DNNTestNetwork, FastNeuralStyle_eccv16) { - processNet("dnn/fast_neural_style_eccv16_starry_night.t7", "", cv::Size(320, 240)); + processNet("", "dnn/mosaic-9.onnx", cv::Size(224, 224)); } PERF_TEST_P_(DNNTestNetwork, Inception_v2_Faster_RCNN) diff --git a/modules/dnn/src/dnn_read.cpp b/modules/dnn/src/dnn_read.cpp index 9c06ced3c4..437d19559c 100644 --- a/modules/dnn/src/dnn_read.cpp +++ b/modules/dnn/src/dnn_read.cpp @@ -33,10 +33,6 @@ Net readNet(const String& _model, const String& _config, const String& _framewor { return readNetFromTFLite(model); } - if (framework == "torch" || modelExt == "t7" || modelExt == "net" || configExt == "t7" || configExt == "net") - { - return readNetFromTorch(model.empty() ? config : model); - } if (framework == "darknet" || modelExt == "weights" || configExt == "weights" || modelExt == "cfg" || configExt == "cfg") { if (modelExt == "cfg" || configExt == "weights") @@ -66,8 +62,6 @@ Net readNet(const String& _framework, const std::vector& bufferModel, return readNetFromTensorflow(bufferModel, bufferConfig); else if (framework == "darknet") return readNetFromDarknet(bufferConfig, bufferModel); - else if (framework == "torch") - CV_Error(Error::StsNotImplemented, "Reading Torch models from buffers"); else if (framework == "dldt") return readNetFromModelOptimizer(bufferConfig, bufferModel); else if (framework == "tflite") diff --git a/modules/dnn/src/torch/COPYRIGHT.txt b/modules/dnn/src/torch/COPYRIGHT.txt deleted file mode 100644 index bc002b78ab..0000000000 --- a/modules/dnn/src/torch/COPYRIGHT.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) -Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) -Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) -Copyright (c) 2011-2013 NYU (Clement Farabet) -Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) -Copyright (c) 2006 Idiap Research Institute (Samy Bengio) -Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) - -All rights reserved. - -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. - -3. Neither the names of Deepmind Technologies, NYU, NEC Laboratories America - and IDIAP Research Institute nor the names of its 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 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. diff --git a/modules/dnn/src/torch/THDiskFile.cpp b/modules/dnn/src/torch/THDiskFile.cpp deleted file mode 100644 index bede95e021..0000000000 --- a/modules/dnn/src/torch/THDiskFile.cpp +++ /dev/null @@ -1,530 +0,0 @@ -#include "../precomp.hpp" -#include "THGeneral.h" -#include "THDiskFile.h" -#include "THFilePrivate.h" - -namespace TH -{ - -typedef struct THDiskFile__ -{ - THFile file; - - FILE *handle; - int isNativeEncoding; - int longSize; - -} THDiskFile; - -static int THDiskFile_isOpened(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)self; - return (dfself->handle != NULL); -} - -/* workaround mac osx lion ***insane*** fread bug */ -#ifdef __APPLE__ -static size_t fread__(void *ptr, size_t size, size_t nitems, FILE *stream) -{ - size_t nread = 0; - while(!feof(stream) && !ferror(stream) && (nread < nitems)) - nread += fread((char*)ptr+nread*size, size, std::min(2147483648UL/size, nitems-nread), stream); - return nread; -} -#else -#define fread__ fread -#endif - -#define READ_WRITE_METHODS(TYPE, TYPEC, ASCII_READ_ELEM, ASCII_WRITE_ELEM) \ - static long THDiskFile_read##TYPEC(THFile *self, TYPE *data, long n) \ - { \ - THDiskFile *dfself = (THDiskFile*)(self); \ - long nread = 0L; \ - \ - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \ - THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); \ - \ - if(dfself->file.isBinary) \ - { \ - nread = fread__(data, sizeof(TYPE), n, dfself->handle); \ - if(!dfself->isNativeEncoding && (sizeof(TYPE) > 1) && (nread > 0)) \ - THDiskFile_reverseMemory(data, data, sizeof(TYPE), nread); \ - } \ - else \ - { \ - long i; \ - for(i = 0; i < n; i++) \ - { \ - ASCII_READ_ELEM; /* increment here result and break if wrong */ \ - } \ - if(dfself->file.isAutoSpacing && (n > 0)) \ - { \ - int c = fgetc(dfself->handle); \ - if( (c != '\n') && (c != EOF) ) \ - ungetc(c, dfself->handle); \ - } \ - } \ - \ - if(nread != n) \ - { \ - dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */ \ - if(!dfself->file.isQuiet) \ - THError("read error: read %ld blocks instead of %ld", nread, n);\ - } \ - \ - return nread; \ - } - -static int THDiskFile_mode(const char *mode, int *isReadable, int *isWritable) -{ - *isReadable = 0; - *isWritable = 0; - if(strlen(mode) == 1) - { - if(*mode == 'r') - { - *isReadable = 1; - return 1; - } - else if(*mode == 'w') - { - *isWritable = 1; - return 1; - } - } - else if(strlen(mode) == 2) - { - if(mode[0] == 'r' && mode[1] == 'w') - { - *isReadable = 1; - *isWritable = 1; - return 1; - } - } - return 0; -} - -static void THDiskFile_seek(THFile *self, long position) -{ - THDiskFile *dfself = (THDiskFile*)(self); - - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - -#if defined(_WIN64) - if(_fseeki64(dfself->handle, (__int64)position, SEEK_SET) < 0) -#elif defined(_WIN32) - if(fseek(dfself->handle, (long)position, SEEK_SET) < 0) -#else - if(fseeko(dfself->handle, (off_t)position, SEEK_SET) < 0) -#endif - { - dfself->file.hasError = 1; - if(!dfself->file.isQuiet) - THError("unable to seek at position %ld", position); - } -} - -static void THDiskFile_seekEnd(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - -#if defined(_WIN64) - if(_fseeki64(dfself->handle, 0L, SEEK_END) < 0) -#elif defined(_WIN32) - if(fseek(dfself->handle, 0L, SEEK_END) < 0) -#else - if(fseeko(dfself->handle, 0L, SEEK_END) < 0) -#endif - { - dfself->file.hasError = 1; - if(!dfself->file.isQuiet) - THError("unable to seek at end of file"); - } -} - -static long THDiskFile_position(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - -#if defined(_WIN64) - __int64 offset = _ftelli64(dfself->handle); -#elif defined(_WIN32) - long offset = ftell(dfself->handle); -#else - off_t offset = ftello(dfself->handle); -#endif - if (offset > -1) - return (long)offset; - else if(!dfself->file.isQuiet) - THError("unable to obtain disk file offset (maybe a long overflow occurred)"); - - return 0; -} - -static void THDiskFile_close(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - fclose(dfself->handle); - dfself->handle = NULL; -} - -/* Little and Big Endian */ - -static void THDiskFile_reverseMemory(void *dst, const void *src, long blockSize, long numBlocks) -{ - if(blockSize != 1) - { - long halfBlockSize = blockSize/2; - char *charSrc = (char*)src; - char *charDst = (char*)dst; - long b, i; - for(b = 0; b < numBlocks; b++) - { - for(i = 0; i < halfBlockSize; i++) - { - char z = charSrc[i]; - charDst[i] = charSrc[blockSize-1-i]; - charDst[blockSize-1-i] = z; - } - charSrc += blockSize; - charDst += blockSize; - } - } -} - -int THDiskFile_isLittleEndianCPU(void) -{ - int x = 7; - char *ptr = (char *)&x; - - if(ptr[0] == 0) - return 0; - else - return 1; -} - -int THDiskFile_isBigEndianCPU(void) -{ - return(!THDiskFile_isLittleEndianCPU()); -} - -void THDiskFile_nativeEndianEncoding(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - dfself->isNativeEncoding = 1; -} - -void THDiskFile_littleEndianEncoding(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - dfself->isNativeEncoding = THDiskFile_isLittleEndianCPU(); -} - -void THDiskFile_bigEndianEncoding(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - dfself->isNativeEncoding = !THDiskFile_isLittleEndianCPU(); -} - -/* End of Little and Big Endian Stuff */ - -void THDiskFile_longSize(THFile *self, int size) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - THArgCheck(size == 0 || size == 4 || size == 8, 1, "Invalid long size specified"); - dfself->longSize = size; -} - -void THDiskFile_noBuffer(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - if (setvbuf(dfself->handle, NULL, _IONBF, 0)) { - THError("error: cannot disable buffer"); - } -} - -static void THDiskFile_free(THFile *self) -{ - THDiskFile *dfself = (THDiskFile*)(self); - if(dfself->handle) - fclose(dfself->handle); - THFree(dfself); -} - -/* Note that we do a trick */ -READ_WRITE_METHODS(unsigned char, Byte, - nread = fread(data, 1, n, dfself->handle); break, - nwrite = fwrite(data, 1, n, dfself->handle); break) - -READ_WRITE_METHODS(char, Char, - nread = fread(data, 1, n, dfself->handle); break, - nwrite = fwrite(data, 1, n, dfself->handle); break) - -READ_WRITE_METHODS(short, Short, - int ret = fscanf(dfself->handle, "%hd", &data[i]); if(ret <= 0) break; else nread++, - int ret = fprintf(dfself->handle, "%hd", data[i]); if(ret <= 0) break; else nwrite++) - -READ_WRITE_METHODS(int, Int, - int ret = fscanf(dfself->handle, "%d\n\r", &data[i]); if(ret <= 0) break; else nread++, - int ret = fprintf(dfself->handle, "%d", data[i]); if(ret <= 0) break; else nwrite++) - -/*READ_WRITE_METHODS(long, Long, - int ret = fscanf(dfself->handle, "%ld", &data[i]); if(ret <= 0) break; else nread++, - int ret = fprintf(dfself->handle, "%ld", data[i]); if(ret <= 0) break; else nwrite++)*/ - -READ_WRITE_METHODS(float, Float, - int ret = fscanf(dfself->handle, "%g", &data[i]); if(ret <= 0) break; else nread++, - int ret = fprintf(dfself->handle, "%.9g", data[i]); if(ret <= 0) break; else nwrite++) - -READ_WRITE_METHODS(double, Double, - int ret = fscanf(dfself->handle, "%lg", &data[i]); if(ret <= 0) break; else nread++, - int ret = fprintf(dfself->handle, "%.17g", data[i]); if(ret <= 0) break; else nwrite++) - - -/* For Long we need to rewrite everything, because of the special management of longSize */ -static long THDiskFile_readLong(THFile *self, int64 *data, long n) -{ - THDiskFile *dfself = (THDiskFile*)(self); - long nread = 0L; - - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); - - if(dfself->file.isBinary) - { - if(dfself->longSize == 0 || dfself->longSize == sizeof(int64)) - { - nread = fread__(data, sizeof(int64), n, dfself->handle); - if(!dfself->isNativeEncoding && (sizeof(int64) > 1) && (nread > 0)) - THDiskFile_reverseMemory(data, data, sizeof(int64), nread); - } else if(dfself->longSize == 4) - { - nread = fread__(data, 4, n, dfself->handle); - if(!dfself->isNativeEncoding && (nread > 0)) - THDiskFile_reverseMemory(data, data, 4, nread); - long i; - for(i = nread; i > 0; i--) - data[i-1] = ((int *)data)[i-1]; - } - else /* if(dfself->longSize == 8) */ - { - int big_endian = !THDiskFile_isLittleEndianCPU(); - int32_t *buffer = (int32_t*)THAlloc(8*n); - if (!buffer) - THError("can not allocate buffer"); - nread = fread__(buffer, 8, n, dfself->handle); - long i; - for(i = nread; i > 0; i--) - data[i-1] = buffer[2*(i-1) + big_endian]; - THFree(buffer); - if(!dfself->isNativeEncoding && (nread > 0)) - THDiskFile_reverseMemory(data, data, 4, nread); - } - } - else - { - long i; - for(i = 0; i < n; i++) - { - long d; - int ret = fscanf(dfself->handle, "%ld", &d); if(ret <= 0) break; else nread++; - data[i] = d; - } - if(dfself->file.isAutoSpacing && (n > 0)) - { - int c = fgetc(dfself->handle); - if( (c != '\n') && (c != EOF) ) - ungetc(c, dfself->handle); - } - } - - if(nread != n) - { - dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */ - if(!dfself->file.isQuiet) - THError("read error: read %ld blocks instead of %ld", nread, n); - } - - return nread; -} - - -static long THDiskFile_readString(THFile *self, const char *format, char **str_) -{ - THDiskFile *dfself = (THDiskFile*)(self); - THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); - THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); - THArgCheck((strlen(format) >= 2 ? (format[0] == '*') && (format[1] == 'a' || format[1] == 'l') : 0), 2, "format must be '*a' or '*l'"); - -/* note: the string won't survive long, as it is copied into lua */ -/* so 1024 is not that big... */ -#define TBRS_BSZ 1024L - - if(format[1] == 'a') - { - char *p = (char*)THAlloc(TBRS_BSZ); - long total = TBRS_BSZ; - long pos = 0L; - - if (p == NULL) - THError("read error: failed to allocate buffer"); - for (;;) - { - if(total-pos == 0) /* we need more space! */ - { - total += TBRS_BSZ; - char *new_p = (char*)THRealloc(p, total); - if (new_p == NULL) - { - THFree(p); - THError("read error: failed to reallocate buffer"); - } - p = new_p; - } - pos += fread(p+pos, 1, total-pos, dfself->handle); - if (pos < total) /* eof? */ - { - if(pos == 0L) - { - THFree(p); - dfself->file.hasError = 1; - if(!dfself->file.isQuiet) - THError("read error: read 0 blocks instead of 1"); - - *str_ = NULL; - return 0; - } - *str_ = p; - return pos; - } - } - } - else - { - char *p = (char*)THAlloc(TBRS_BSZ); - long total = TBRS_BSZ; - long pos = 0L; - long size; - - if (p == NULL) - THError("read error: failed to allocate buffer"); - for (;;) - { - if(total-pos <= 1) /* we can only write '\0' in there! */ - { - total += TBRS_BSZ; - char *new_p = (char*)THRealloc(p, total); - if (new_p == NULL) - { - THFree(p); - THError("read error: failed to reallocate buffer"); - } - p = new_p; - } - if (fgets(p+pos, total-pos, dfself->handle) == NULL) /* eof? */ - { - if(pos == 0L) - { - THFree(p); - dfself->file.hasError = 1; - if(!dfself->file.isQuiet) - THError("read error: read 0 blocks instead of 1"); - - *str_ = NULL; - return 0; - } - *str_ = p; - return pos; - } - size = strlen(p+pos); - if (size == 0L || (p+pos)[size-1] != '\n') - { - pos += size; - } - else - { - pos += size-1L; /* do not include `eol' */ - *str_ = p; - return pos; - } - } - } - - *str_ = NULL; - return 0; -} - -THFile *THDiskFile_new(const std::string &name, const char *mode, int isQuiet) -{ - static struct THFileVTable vtable = { - THDiskFile_isOpened, - - THDiskFile_readByte, - THDiskFile_readChar, - THDiskFile_readShort, - THDiskFile_readInt, - THDiskFile_readLong, - THDiskFile_readFloat, - THDiskFile_readDouble, - THDiskFile_readString, - - THDiskFile_seek, - THDiskFile_seekEnd, - THDiskFile_position, - THDiskFile_close, - THDiskFile_free - }; - - int isReadable; - int isWritable; - FILE *handle; - THDiskFile *self; - - THArgCheck(THDiskFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w' or 'rw'"); - - CV_Assert(isReadable && !isWritable); - -#ifdef _MSC_VER - if (fopen_s(&handle, name.c_str(), "rb") != 0) - handle = NULL; -#else - handle = fopen(name.c_str(),"rb"); -#endif - - if(!handle) - { - if(isQuiet) - return 0; - else - THError("cannot open <%s> in mode %c%c", name.c_str(), (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' ')); - } - - self = (THDiskFile*)THAlloc(sizeof(THDiskFile)); - if (!self) - THError("cannot allocate memory for self"); - - self->handle = handle; - self->isNativeEncoding = 1; - self->longSize = 0; - - self->file.vtable = &vtable; - self->file.isQuiet = isQuiet; - self->file.isReadable = isReadable; - self->file.isWritable = isWritable; - self->file.isBinary = 0; - self->file.isAutoSpacing = 1; - self->file.hasError = 0; - - return (THFile*)self; -} - -} diff --git a/modules/dnn/src/torch/THDiskFile.h b/modules/dnn/src/torch/THDiskFile.h deleted file mode 100644 index 68d1141e09..0000000000 --- a/modules/dnn/src/torch/THDiskFile.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TH_DISK_FILE_INC -#define TH_DISK_FILE_INC - -#include "THFile.h" -#include - -namespace TH -{ - -TH_API THFile *THDiskFile_new(const std::string &name, const char *mode, int isQuiet); - -TH_API int THDiskFile_isLittleEndianCPU(void); -TH_API int THDiskFile_isBigEndianCPU(void); -TH_API void THDiskFile_nativeEndianEncoding(THFile *self); -TH_API void THDiskFile_littleEndianEncoding(THFile *self); -TH_API void THDiskFile_bigEndianEncoding(THFile *self); -TH_API void THDiskFile_longSize(THFile *self, int size); -TH_API void THDiskFile_noBuffer(THFile *self); - -} // namespace - -#endif diff --git a/modules/dnn/src/torch/THFile.cpp b/modules/dnn/src/torch/THFile.cpp deleted file mode 100644 index 5f7fe1cf03..0000000000 --- a/modules/dnn/src/torch/THFile.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "../precomp.hpp" -#include "THFile.h" -#include "THFilePrivate.h" - -namespace TH { - -#define IMPLEMENT_THFILE_RW(TYPEC, TYPE) \ - long THFile_read##TYPEC##Raw(THFile *self, TYPE *data, long n) \ - { \ - return (*self->vtable->read##TYPEC)(self, data, n); \ - } - -IMPLEMENT_THFILE_RW(Byte, unsigned char) -IMPLEMENT_THFILE_RW(Char, char) -IMPLEMENT_THFILE_RW(Short, short) -IMPLEMENT_THFILE_RW(Int, int) -IMPLEMENT_THFILE_RW(Long, int64) -IMPLEMENT_THFILE_RW(Float, float) -IMPLEMENT_THFILE_RW(Double, double) - -long THFile_readStringRaw(THFile *self, const char *format, char **str_) -{ - return self->vtable->readString(self, format, str_); -} - -void THFile_seek(THFile *self, long position) -{ - self->vtable->seek(self, position); -} - -void THFile_seekEnd(THFile *self) -{ - self->vtable->seekEnd(self); -} - -long THFile_position(THFile *self) -{ - return self->vtable->position(self); -} - -void THFile_close(THFile *self) -{ - self->vtable->close(self); -} - -void THFile_free(THFile *self) -{ - self->vtable->free(self); -} - -int THFile_isOpened(THFile *self) -{ - return self->vtable->isOpened(self); -} - -#define IMPLEMENT_THFILE_FLAGS(FLAG) \ - int THFile_##FLAG(THFile *self) \ - { \ - return self->FLAG; \ - } - -IMPLEMENT_THFILE_FLAGS(isQuiet) -IMPLEMENT_THFILE_FLAGS(isReadable) -IMPLEMENT_THFILE_FLAGS(isWritable) -IMPLEMENT_THFILE_FLAGS(isBinary) -IMPLEMENT_THFILE_FLAGS(isAutoSpacing) -IMPLEMENT_THFILE_FLAGS(hasError) - -void THFile_binary(THFile *self) -{ - self->isBinary = 1; -} - -void THFile_ascii(THFile *self) -{ - self->isBinary = 0; -} - -void THFile_autoSpacing(THFile *self) -{ - self->isAutoSpacing = 1; -} - -void THFile_noAutoSpacing(THFile *self) -{ - self->isAutoSpacing = 0; -} - -void THFile_quiet(THFile *self) -{ - self->isQuiet = 1; -} - -void THFile_pedantic(THFile *self) -{ - self->isQuiet = 0; -} - -void THFile_clearError(THFile *self) -{ - self->hasError = 0; -} - -#define IMPLEMENT_THFILE_SCALAR(TYPEC, TYPE) \ - TYPE THFile_read##TYPEC##Scalar(THFile *self) \ - { \ - TYPE scalar; \ - THFile_read##TYPEC##Raw(self, &scalar, 1); \ - return scalar; \ - } - -IMPLEMENT_THFILE_SCALAR(Byte, unsigned char) -IMPLEMENT_THFILE_SCALAR(Char, char) -IMPLEMENT_THFILE_SCALAR(Short, short) -IMPLEMENT_THFILE_SCALAR(Int, int) -IMPLEMENT_THFILE_SCALAR(Long, int64) -IMPLEMENT_THFILE_SCALAR(Float, float) -IMPLEMENT_THFILE_SCALAR(Double, double) - -} // namespace diff --git a/modules/dnn/src/torch/THFile.h b/modules/dnn/src/torch/THFile.h deleted file mode 100644 index 14e3fbf1e5..0000000000 --- a/modules/dnn/src/torch/THFile.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef TH_FILE_INC -#define TH_FILE_INC - -//#include "THStorage.h" -#include "opencv2/core/hal/interface.h" -#include "THGeneral.h" - -namespace TH -{ -typedef struct THFile__ THFile; - -TH_API int THFile_isOpened(THFile *self); -TH_API int THFile_isQuiet(THFile *self); -TH_API int THFile_isReadable(THFile *self); -TH_API int THFile_isWritable(THFile *self); -TH_API int THFile_isBinary(THFile *self); -TH_API int THFile_isAutoSpacing(THFile *self); -TH_API int THFile_hasError(THFile *self); - -TH_API void THFile_binary(THFile *self); -TH_API void THFile_ascii(THFile *self); -TH_API void THFile_autoSpacing(THFile *self); -TH_API void THFile_noAutoSpacing(THFile *self); -TH_API void THFile_quiet(THFile *self); -TH_API void THFile_pedantic(THFile *self); -TH_API void THFile_clearError(THFile *self); - -/* scalar */ -TH_API unsigned char THFile_readByteScalar(THFile *self); -TH_API char THFile_readCharScalar(THFile *self); -TH_API short THFile_readShortScalar(THFile *self); -TH_API int THFile_readIntScalar(THFile *self); -TH_API int64 THFile_readLongScalar(THFile *self); -TH_API float THFile_readFloatScalar(THFile *self); -TH_API double THFile_readDoubleScalar(THFile *self); - -/* raw */ -TH_API long THFile_readByteRaw(THFile *self, unsigned char *data, long n); -TH_API long THFile_readCharRaw(THFile *self, char *data, long n); -TH_API long THFile_readShortRaw(THFile *self, short *data, long n); -TH_API long THFile_readIntRaw(THFile *self, int *data, long n); -TH_API long THFile_readLongRaw(THFile *self, int64 *data, long n); -TH_API long THFile_readFloatRaw(THFile *self, float *data, long n); -TH_API long THFile_readDoubleRaw(THFile *self, double *data, long n); -TH_API long THFile_readStringRaw(THFile *self, const char *format, char **str_); /* you must deallocate str_ */ - -TH_API void THFile_seek(THFile *self, long position); -TH_API void THFile_seekEnd(THFile *self); -TH_API long THFile_position(THFile *self); -TH_API void THFile_close(THFile *self); -TH_API void THFile_free(THFile *self); -} // namespace -#endif //TH_FILE_INC diff --git a/modules/dnn/src/torch/THFilePrivate.h b/modules/dnn/src/torch/THFilePrivate.h deleted file mode 100644 index af3890d8e6..0000000000 --- a/modules/dnn/src/torch/THFilePrivate.h +++ /dev/null @@ -1,37 +0,0 @@ -namespace TH { - -struct THFile__ -{ - struct THFileVTable *vtable; - - int isQuiet; - int isReadable; - int isWritable; - int isBinary; - int isAutoSpacing; - int hasError; -}; - -/* virtual table definition */ - -struct THFileVTable -{ - int (*isOpened)(THFile *self); - - long (*readByte)(THFile *self, unsigned char *data, long n); - long (*readChar)(THFile *self, char *data, long n); - long (*readShort)(THFile *self, short *data, long n); - long (*readInt)(THFile *self, int *data, long n); - long (*readLong)(THFile *self, int64 *data, long n); - long (*readFloat)(THFile *self, float *data, long n); - long (*readDouble)(THFile *self, double *data, long n); - long (*readString)(THFile *self, const char *format, char **str_); - - void (*seek)(THFile *self, long position); - void (*seekEnd)(THFile *self); - long (*position)(THFile *self); - void (*close)(THFile *self); - void (*free)(THFile *self); -}; - -} // namespace diff --git a/modules/dnn/src/torch/THGeneral.cpp b/modules/dnn/src/torch/THGeneral.cpp deleted file mode 100644 index 0c27edc6fb..0000000000 --- a/modules/dnn/src/torch/THGeneral.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "../precomp.hpp" -#include "THGeneral.h" diff --git a/modules/dnn/src/torch/THGeneral.h b/modules/dnn/src/torch/THGeneral.h deleted file mode 100644 index cdcbe3d905..0000000000 --- a/modules/dnn/src/torch/THGeneral.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TH_GENERAL_INC -#define TH_GENERAL_INC - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TH_API - -#define THError(...) CV_Error(cv::Error::StsError, cv::format(__VA_ARGS__)) -#define THArgCheck(cond, ...) CV_Assert(cond) - -#define THAlloc malloc -#define THRealloc realloc -#define THFree free - -#endif diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp deleted file mode 100644 index 3a46c8f7c0..0000000000 --- a/modules/dnn/src/torch/torch_importer.cpp +++ /dev/null @@ -1,1267 +0,0 @@ -/*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 "../precomp.hpp" - -#include - -#include -#include -#include -#include -#include -#include - -#include "THDiskFile.h" - -namespace cv { -namespace dnn { -CV__DNN_INLINE_NS_BEGIN - -using namespace TH; - -//#ifdef NDEBUG -static bool dbgPrint = false; -//#else -//static bool dbgPrint = true; -//#endif - -enum LuaType -{ - TYPE_NIL = 0, - TYPE_NUMBER = 1, - TYPE_STRING = 2, - TYPE_TABLE = 3, - TYPE_TORCH = 4, - TYPE_BOOLEAN = 5, - TYPE_FUNCTION = 6, - TYPE_RECUR_FUNCTION = 8, - LEGACY_TYPE_RECUR_FUNCTION = 7 -}; - -// We use OpenCV's types to manage CV_ELEM_SIZE. -enum TorchType -{ - TYPE_DOUBLE = CV_64F, - TYPE_FLOAT = CV_32F, - TYPE_BYTE = CV_8U, - TYPE_CHAR = CV_8S, - TYPE_SHORT = CV_16S, - TYPE_INT = CV_32S, - TYPE_LONG = CV_32SC2 -}; - -template -static String toString(const T &v) -{ - std::ostringstream ss; - ss << v; - return ss.str(); -} - -static inline bool startsWith(const String &str, const char *substr) -{ - return str.find(substr) == 0; -} - -static inline bool endsWith(const String &str, const char *substr) -{ - return str.rfind(substr) == str.length() - strlen(substr); -} - -struct TorchImporter -{ - FPDenormalsIgnoreHintScope fp_denormals_ignore_scope; - - typedef std::map > TensorsMap; - Net net; - - cv::Ptr file; - std::set readedIndexes; - std::map storages; - std::map tensors; - // Stack with numbers of unconnected layers per scope (Sequential, ConcatTable etc.) - std::vector numUnconnectedLayers; - - struct Module - { - String thName, apiType; - dnn::LayerParams params; - std::vector > modules; - - Module(const String &_thName, const String &_apiType = String()) - : thName(_thName), apiType(_apiType) {} - }; - - Module *rootModule; - Module *curModule; - int moduleCounter; - bool testPhase; - - TorchImporter(String filename, bool isBinary, bool evaluate) - { - CV_TRACE_FUNCTION(); - - rootModule = curModule = NULL; - moduleCounter = 0; - testPhase = evaluate; - - file = cv::Ptr(THDiskFile_new(filename, "r", 0), THFile_free); - CV_Assert(file && THFile_isOpened(file)); - - if (isBinary) - THFile_binary(file); - else - THFile_ascii(file); - } - - /* Simple readers */ - - inline int readInt() - { - return THFile_readIntScalar(file); - } - - inline long readLong() - { - return THFile_readLongScalar(file); - } - - inline bool readBool() - { - return readInt() != 0; - } - - inline double readDouble() - { - return THFile_readDoubleScalar(file); - } - - inline String readString() - { - int size = THFile_readIntScalar(file); - String str(size, '\0'); - THFile_readCharRaw(file, const_cast(str.c_str()), size); - return str; - } - - inline String readTorchClassName() - { - String version = readString(); - return startsWith(version, "V ") ? readString() : version; - } - - inline void readFunction() - { - readString(); - readObject(); - } - - void readTable(int index = -1) - { - index = (index < 0) ? readInt() : index; - - if (readedIndexes.count(index)) - return; - - readedIndexes.insert(index); - - int size = readInt(); - - for (int i = 0; i < size; i++) - { - readObject(); //key - readObject(); //value - } - } - - /* Special readers */ - - static inline int parseTorchType(const String &str, const char *suffix, const char *prefix = "torch.") - { - if (startsWith(str, prefix) && endsWith(str, suffix)) - { - String typeStr = str.substr(strlen(prefix), str.length() - strlen(prefix) - strlen(suffix)); - - if (typeStr == "Double") - return TYPE_DOUBLE; - else if (typeStr == "Float" || typeStr == "Cuda") - return TYPE_FLOAT; - else if (typeStr == "Byte") - return TYPE_BYTE; - else if (typeStr == "Char") - return TYPE_CHAR; - else if (typeStr == "Short") - return TYPE_SHORT; - else if (typeStr == "Int") - return TYPE_INT; - else if (typeStr == "Long") - return TYPE_LONG; - else - CV_Error(Error::StsNotImplemented, "Unknown type \"" + typeStr + "\" of torch class \"" + str + "\""); - } - - return -1; - } - - static int parseTensorType(const String &className) - { - return parseTorchType(className, "Tensor"); - } - - static int parseStorageType(const String &className) - { - return parseTorchType(className, "Storage"); - } - - void readTorchStorage(int index, int type = -1) - { - long size = readLong(); - Mat storageMat; - - switch (type) - { - case TYPE_FLOAT: - storageMat.create(1, size, CV_32F); - THFile_readFloatRaw(file, (float*)storageMat.data, size); - break; - case TYPE_DOUBLE: - storageMat.create(1, size, CV_64F); - THFile_readDoubleRaw(file, (double*)storageMat.data, size); - break; - case TYPE_CHAR: - storageMat.create(1, size, CV_8S); - THFile_readByteRaw(file, (uchar*)storageMat.data, size); - break; - case TYPE_BYTE: - storageMat.create(1, size, CV_8U); - THFile_readByteRaw(file, (uchar*)storageMat.data, size); - break; - case TYPE_SHORT: - storageMat.create(1, size, CV_16S); - THFile_readShortRaw(file, (short*)storageMat.data, size); - break; - case TYPE_INT: - storageMat.create(1, size, CV_32S); - THFile_readIntRaw(file, (int*)storageMat.data, size); - break; - case TYPE_LONG: - { - storageMat.create(1, size, CV_64F); //handle LongStorage as CV_64F Mat - double *buf = storageMat.ptr(); - THFile_readLongRaw(file, (int64*)buf, size); - - for (size_t i = (size_t)size; i-- > 0; ) - buf[i] = ((int64*)buf)[i]; - break; - } - default: - CV_Error(Error::StsInternal, ""); - break; - } - - storages.insert(std::make_pair(index, storageMat)); - } - - void readTorchTable(Dict &scalarParams, TensorsMap &tensorParams) - { - int luaType = readInt(); - int index = readInt(); - - CV_Assert(luaType == TYPE_TABLE && readedIndexes.count(index) == 0); - readedIndexes.insert(index); - - long fpos; - int numPairs = readInt(); - - for (int i = 0; i < numPairs; i++) - { - fpos = THFile_position(file); - int ktype = readInt(); - - if (ktype != TYPE_STRING) //skip non-string fields - { - THFile_seek(file, fpos); - readObject(); //key - readObject(); //value - continue; - } - - String key = readString(); - if (dbgPrint) - std::cout << i << "th key: " << key << "\n"; - - fpos = THFile_position(file); - int vtype = readInt(); - - if (vtype == TYPE_TORCH) - { - int index = readInt(); - int numModules = curModule->modules.size(); - readTorchObject(index); - - if (tensors.count(index)) //tensor was read - { - tensorParams.insert(std::make_pair(key, std::make_pair(index, tensors[index]))); - } - else if (storages.count(index)) //storage was read - { - Mat &matStorage = storages[index]; - Mat matCasted; - matStorage.convertTo(matCasted, CV_64F); - - DictValue scalar = DictValue::arrayReal(matCasted.ptr(), matCasted.total()); - scalarParams.set(key, scalar); - } - else - { - // Only tensors and scalars are supported for table fields. - // i.e. nn.Inception has field `transfer` which is an - // activation layer. So we remove added modules as readTorchObject(index). - while (curModule->modules.size() > numModules) - curModule->modules.pop_back(); - } - } - else if (vtype == TYPE_NUMBER) - { - scalarParams.set(key, readDouble()); - } - else if (vtype == TYPE_STRING) - { - scalarParams.set(key, readString()); - } - else if (vtype == TYPE_BOOLEAN) - { - scalarParams.set(key, readBool()); - } - else - { - THFile_seek(file, fpos); - readObject(); - } - } - - //Debug output - if (dbgPrint) - { - std::cout << "scalarParams:\n"; - std::cout << scalarParams; - - std::cout << "#" << tensorParams.size() << " tensorParams:\n"; - std::map >::const_iterator it; - for (it = tensorParams.begin(); it != tensorParams.end(); it++) - std::cout << it->first << ": Tensor " << it->second.second.size << "\n"; - } - } - - void readTorchTensor(int indexTensor, int typeTensor) - { - int ndims = readInt(); - AutoBuffer sizes(ndims); - AutoBuffer steps(ndims); - THFile_readLongRaw(file, sizes.data(), ndims); - THFile_readLongRaw(file, steps.data(), ndims); - long offset = readLong() - 1; - - //read Storage - int typeidx = readInt(); - CV_Assert(typeidx == TYPE_TORCH || (typeidx == TYPE_NIL && ndims == 0)); - - if (typeidx == TYPE_NIL) - { - tensors.insert(std::make_pair(indexTensor, Mat())); - return; - } - - int indexStorage = readInt(); - if (readedIndexes.count(indexStorage) == 0) - { - String className = readTorchClassName(); - int typeStorage = parseStorageType(className); - CV_Assert(typeStorage >= 0 && typeTensor == typeStorage); - readTorchStorage(indexStorage, typeStorage); - typeTensor = storages[indexStorage].type(); - readedIndexes.insert(indexStorage); - } - - //small check - size_t requireElems = (size_t)offset + (size_t)steps[0] * (size_t)sizes[0]; - size_t storageElems = storages[indexStorage].total(); - if (requireElems > storageElems) - CV_Error(Error::StsBadSize, "Storage has insufficient number of elements for requested Tensor"); - - //convert sizes - AutoBuffer isizes(ndims); - AutoBuffer ssteps(ndims); - for (int i = ndims - 1; i >= 0; i--) - { - isizes[i] = (int)sizes[i]; - ssteps[i] = (size_t)steps[i] * CV_ELEM_SIZE(typeTensor); - } - - //allocate Blob - Mat srcMat(ndims, isizes.data(), typeTensor , storages[indexStorage].ptr() + offset*CV_ELEM_SIZE(typeTensor), ssteps.data()); - int dstType = CV_32F; - - Mat blob; - srcMat.convertTo(blob, dstType); - - tensors.insert(std::make_pair(indexTensor, blob)); - } - - static bool isNNClass(const String &className, String &nnName) - { - const char *prefixes[] = {"nn.", "cunn.", "cudnn.", "fbcunn.", NULL}; - - for (int i = 0; prefixes[i]; i++) - { - if (startsWith(className, prefixes[i])) - { - nnName = className.substr(strlen(prefixes[i])); - return true; - } - } - - return false; - } - - static void convertTorchKernelsParams(const Dict &torchParams, cv::dnn::LayerParams &layerParams) - { - layerParams.set("kernel_h", torchParams.get("kH")); - layerParams.set("kernel_w", torchParams.get("kW")); - layerParams.set("stride_h", torchParams.get("dH")); - layerParams.set("stride_w", torchParams.get("dW")); - layerParams.set("pad_h", torchParams.get("padH", 0)); - layerParams.set("pad_w", torchParams.get("padW", 0)); - } - - void readTorchObject(int index) - { - if(readedIndexes.count(index)) - return; - - String className = readTorchClassName(); - String nnName; - - if (dbgPrint) - std::cout << "Class: " << className << std::endl; - - int type; - if ( (type = parseTensorType(className)) >= 0 ) //is Tensor - { - readTorchTensor(index, type); - } - else if ( (type = parseStorageType(className)) >= 0 ) //is Storage - { - readTorchStorage(index, type); - } - else if (isNNClass(className, nnName)) - { - Dict scalarParams; - TensorsMap tensorParams; - - cv::Ptr newModule(new Module(nnName)); - cv::dnn::LayerParams &layerParams = newModule->params; - - layerParams.set("torch_index", index); - - if (nnName == "Sequential" || nnName == "Parallel" || - nnName == "Concat" || nnName == "ConcatTable" || nnName == "JoinTable" || - nnName == "DepthConcat" || nnName == "Inception") - { - Module *parentModule = curModule; - curModule->modules.push_back(newModule); - curModule = newModule; - readTorchTable(scalarParams, tensorParams); - curModule = parentModule; - - if (nnName == "Parallel") - { - layerParams.set("inputDimension", scalarParams.get("inputDimension")); - layerParams.set("outputDimension", scalarParams.get("outputDimension")); - } - else if (nnName == "Concat" || nnName == "JoinTable" || nnName == "DepthConcat") - { - layerParams.set("dimension", scalarParams.get("dimension")); - } - } - else if (nnName == "SpatialConvolution" || nnName == "SpatialConvolutionMM") - { - newModule->apiType = "Convolution"; - readTorchTable(scalarParams, tensorParams); - - CV_Assert(tensorParams.count("weight")); - layerParams.blobs.push_back(tensorParams["weight"].second); - - bool bias = tensorParams.count("bias") != 0; - layerParams.set("bias_term", bias); - if (bias) - layerParams.blobs.push_back(tensorParams["bias"].second); - - layerParams.set("num_output", scalarParams.get("nOutputPlane")); - convertTorchKernelsParams(scalarParams, layerParams); - - if (nnName == "SpatialConvolutionMM") - { - // Split weights from a [ outCh x inCh*kH*kW ] 2D matrix - // onto a 4D [ outCh x inCh x kH x kW ] blob. - CV_Assert(layerParams.blobs[0].dims == 2); - const int kernel = layerParams.blobs[0].size[1]; // inCh * kH * kW - MatShape kernelShape(4); - kernelShape[0] = layerParams.blobs[0].size[0]; // outCh. - kernelShape[2] = layerParams.get("kernel_h"); - kernelShape[3] = layerParams.get("kernel_w"); - kernelShape[1] = kernel / (kernelShape[2] * kernelShape[3]); // inCh. - layerParams.blobs[0] = layerParams.blobs[0].reshape(1, kernelShape); - } - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialLPPooling") - { - // nn.Sequential { - // [input -> (1) -> (2) -> output] - // (1): nn.Sequential { - // [input -> (1) -> (2) -> (3) -> (4) -> output] - // (1): nn.Power - // (2): nn.SpatialAveragePooling(...) - // (3): nn.MulConstant - // (4): nn.Power - // } - // (2): nn.Sigmoid - // } - // nn.SpatialLPPooling is just a table so we skip it. - readTorchTable(scalarParams, tensorParams); - } - else if (nnName == "SpatialMaxPooling" || nnName == "SpatialAveragePooling") - { - newModule->apiType = "Pooling"; - readTorchTable(scalarParams, tensorParams); - - if (nnName == "SpatialMaxPooling") { - layerParams.set("pool", "MAX"); - layerParams.set("indices_blob_id", tensorParams["indices"].first); - } - if (nnName == "SpatialAveragePooling") - { - layerParams.set("pool", "AVE"); - layerParams.set("ave_pool_padded_area", scalarParams.has("count_include_pad") && - scalarParams.get("count_include_pad")); - } - convertTorchKernelsParams(scalarParams, layerParams); - - CV_Assert(scalarParams.has("ceil_mode")); - layerParams.set("ceil_mode", scalarParams.get("ceil_mode")); - - curModule->modules.push_back(newModule); - } - else if (nnName == "Linear") - { - newModule->apiType = "InnerProduct"; - readTorchTable(scalarParams, tensorParams); - - CV_Assert(tensorParams.count("weight")); - Mat weightBlob = tensorParams["weight"].second; - layerParams.blobs.push_back(weightBlob); - - bool bias = tensorParams.count("bias") != 0; - if (bias) - layerParams.blobs.push_back(tensorParams["bias"].second); - layerParams.set("bias_term", bias); - - layerParams.set("num_output", weightBlob.size[0]); - curModule->modules.push_back(newModule); - } - else if (nnName == "Reshape" || nnName == "View") - { - newModule->apiType = "Reshape"; - - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("size")); - - DictValue dimParam = scalarParams.get("size"); - layerParams.set("dim", dimParam); - - int axis = (int)scalarParams.get("batchMode", true); - layerParams.set("axis", axis); - - curModule->modules.push_back(newModule); - } - else if (nnName == "ReLU") - { - curModule->modules.push_back(cv::Ptr(new Module(nnName, "ReLU"))); - readObject(); - } - else if (nnName == "Tanh") - { - curModule->modules.push_back(cv::Ptr(new Module(nnName, "TanH"))); - readObject(); - } - else if (nnName == "Sigmoid") - { - curModule->modules.push_back(cv::Ptr(new Module(nnName, "Sigmoid"))); - readObject(); - } - else if (nnName == "SpatialBatchNormalization" || nnName == "InstanceNormalization" || - nnName == "BatchNormalization") - { - newModule->apiType = "BatchNorm"; - readTorchTable(scalarParams, tensorParams); - - CV_Assert(scalarParams.has("eps")); - float eps = float(scalarParams.get("eps")); - layerParams.set("eps", eps); - - if (tensorParams.count("running_mean")) - { - layerParams.blobs.push_back(tensorParams["running_mean"].second); - } - else - { - CV_Assert(scalarParams.has("nOutput")); - layerParams.blobs.push_back(Mat::zeros(1, scalarParams.get("nOutput"), CV_32F)); - } - - if (tensorParams.count("running_var")) - { - layerParams.blobs.push_back(tensorParams["running_var"].second); - } - else if (tensorParams.count("running_std")) - { - layerParams.blobs.push_back(tensorParams["running_std"].second); - pow(layerParams.blobs.back(), -2, layerParams.blobs.back()); - subtract(layerParams.blobs.back(), eps, layerParams.blobs.back()); - } - else - { - CV_Assert(scalarParams.has("nOutput")); - layerParams.blobs.push_back(Mat::ones(1, scalarParams.get("nOutput"), CV_32F)); - } - - if (tensorParams.count("weight")) - { - layerParams.set("has_weight", true); - layerParams.blobs.push_back(tensorParams["weight"].second); - } - - if (tensorParams.count("bias")) - { - layerParams.set("has_bias", true); - layerParams.blobs.push_back(tensorParams["bias"].second); - } - - bool trainPhase = scalarParams.get("train", false); - if (nnName == "InstanceNormalization" || (trainPhase && !testPhase)) - { - cv::Ptr mvnModule(new Module(nnName)); - mvnModule->apiType = "MVN"; - curModule->modules.push_back(mvnModule); - - layerParams.blobs[0].setTo(0); // batch norm's mean - layerParams.blobs[1].setTo(1); // batch norm's std - } - - curModule->modules.push_back(newModule); - } - else if (nnName == "PReLU") - { - readTorchTable(scalarParams, tensorParams); - - CV_Assert(tensorParams.count("weight")); - - size_t outputChannels = static_cast(scalarParams.get("nOutputPlane")); - if (outputChannels) { - - CV_Assert(tensorParams["weight"].second.total() == outputChannels); - layerParams.blobs.push_back(tensorParams["weight"].second); - - newModule->apiType = "ChannelsPReLU"; - } - else { - CV_Assert(tensorParams["weight"].second.total() == 1); - float negative_slope = *tensorParams["weight"].second.ptr(); - layerParams.set("negative_slope", negative_slope); - - newModule->apiType = "ReLU"; - } - - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialDropout" || nnName == "Dropout") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("p")); - - if (scalarParams.has("v2") && scalarParams.get("v2")) - { - newModule->apiType = "Identity"; - } - else - { - float scale = 1 - scalarParams.get("p"); - - CV_Assert(scale > 0); - - newModule->apiType = "Power"; - layerParams.set("scale", scale); - } - curModule->modules.push_back(newModule); - } - // TotalVariation layer is from fast-neural-style project: https://github.com/jcjohnson/fast-neural-style - // It's a loss function that has an Identity forward. - else if (nnName == "Identity" || nnName == "TotalVariation") - { - readTorchTable(scalarParams, tensorParams); - newModule->apiType = "Identity"; - curModule->modules.push_back(newModule); - } - else if (nnName == "Normalize") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("p")); - - layerParams.set("p", scalarParams.get("p")); - if (scalarParams.has("eps")) - layerParams.set("eps", scalarParams.get("eps")); - - newModule->apiType = "Normalize"; - curModule->modules.push_back(newModule); - } - else if (nnName == "Padding") - { - readTorchTable(scalarParams, tensorParams); - newModule->apiType = "Padding"; - - CV_Assert(scalarParams.has("pad") && scalarParams.has("dim")); - if (scalarParams.has("index") && scalarParams.get("index") != 1) - CV_Error(Error::StsNotImplemented, "Padding with offset is not implemented"); - - if (scalarParams.has("value")) - layerParams.set("value", scalarParams.get("value")); - - if (scalarParams.has("nInputDim")) - layerParams.set("input_dims", scalarParams.get("nInputDim")); - - int dim = scalarParams.get("dim") - 1; // In Lua we start from 1. - int pad = scalarParams.get("pad"); - - std::vector paddings((dim + 1) * 2, 0); - if (pad > 0) - paddings[dim * 2 + 1] = pad; // Pad after (right). - else - paddings[dim * 2] = -pad; // Pad before (left). - layerParams.set("paddings", DictValue::arrayInt(&paddings[0], paddings.size())); - - curModule->modules.push_back(newModule); - } - else if (nnName == "CAddTable") - { - curModule->modules.push_back(newModule); - readObject(); - } - else if (nnName == "SpatialDilatedConvolution") - { - readTorchTable(scalarParams, tensorParams); - newModule->apiType = "Convolution"; - CV_Assert(scalarParams.has("padW") && - scalarParams.has("padH")&& - scalarParams.has("dW")&& - scalarParams.has("dH")&& - scalarParams.has("dilationW")&& - scalarParams.has("dilationH")&& - scalarParams.has("kW")&& - scalarParams.has("kH")&& - scalarParams.has("nOutputPlane")); - - layerParams.set("kernel_w", static_cast(scalarParams.get("kW"))); - layerParams.set("kernel_h", static_cast(scalarParams.get("kH"))); - layerParams.set("pad_w", static_cast(scalarParams.get("padW"))); - layerParams.set("pad_h", static_cast(scalarParams.get("padH"))); - layerParams.set("stride_w", static_cast(scalarParams.get("dW"))); - layerParams.set("stride_h", static_cast(scalarParams.get("dH"))); - layerParams.set("dilation_w", static_cast(scalarParams.get("dilationW"))); - layerParams.set("dilation_h", static_cast(scalarParams.get("dilationH"))); - layerParams.set("num_output", static_cast(scalarParams.get("nOutputPlane"))); - - layerParams.blobs.push_back(tensorParams["weight"].second); - - bool bias = tensorParams.count("bias"); - layerParams.set("bias_term", bias); - if (bias) - layerParams.blobs.push_back(tensorParams["bias"].second); - - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialFullConvolution") - { - readTorchTable(scalarParams, tensorParams); - newModule->apiType = "Deconvolution"; - CV_Assert(scalarParams.has("padW") && - scalarParams.has("padH")&& - scalarParams.has("dW")&& - scalarParams.has("dH")&& - scalarParams.has("adjW")&& - scalarParams.has("adjH")&& - scalarParams.has("kW")&& - scalarParams.has("kH")&& - scalarParams.has("nOutputPlane")); - - layerParams.set("kernel_w", static_cast(scalarParams.get("kW"))); - layerParams.set("kernel_h", static_cast(scalarParams.get("kH"))); - layerParams.set("pad_w", static_cast(scalarParams.get("padW"))); - layerParams.set("pad_h", static_cast(scalarParams.get("padH"))); - layerParams.set("stride_w", static_cast(scalarParams.get("dW"))); - layerParams.set("stride_h", static_cast(scalarParams.get("dH"))); - layerParams.set("adj_w", static_cast(scalarParams.get("adjW"))); - layerParams.set("adj_h", static_cast(scalarParams.get("adjH"))); - layerParams.set("num_output", static_cast(scalarParams.get("nOutputPlane"))); - - layerParams.blobs.push_back(tensorParams["weight"].second); - - bool bias = tensorParams.count("bias"); - layerParams.set("bias_term", bias); - if (bias) - layerParams.blobs.push_back(tensorParams["bias"].second); - - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialMaxUnpooling") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert(tensorParams.count("indices")); - - layerParams.set("indices_blob_id", tensorParams["indices"].first); - curModule->modules.push_back(newModule); - } - else if (nnName == "LogSoftMax" || nnName == "SoftMax") - { - newModule->apiType = "Softmax"; - layerParams.set("log_softmax", nnName == "LogSoftMax"); - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialCrossMapLRN") - { - newModule->apiType = "LRN"; - readTorchTable(scalarParams, tensorParams); - - CV_Assert(scalarParams.has("alpha")); - CV_Assert(scalarParams.has("beta")); - CV_Assert(scalarParams.has("k")); - CV_Assert(scalarParams.has("size")); - - layerParams.set("norm_region", "ACROSS_CHANNELS"); - layerParams.set("alpha", scalarParams.get("alpha")); - layerParams.set("beta", scalarParams.get("beta")); - layerParams.set("bias", scalarParams.get("k")); - layerParams.set("local_size", scalarParams.get("size")); - layerParams.set("norm_by_size", true); - - curModule->modules.push_back(newModule); - } - else if (nnName == "Square" || nnName == "Sqrt" || nnName == "Power") - { - readTorchTable(scalarParams, tensorParams); - - float power; - if (nnName == "Square") power = 2.0f; - else if (nnName == "Sqrt") power = 0.5f; - else if (nnName == "Power") power = scalarParams.get("pow", 1.0f); - - newModule->apiType = "Power"; - layerParams.set("power", power); - curModule->modules.push_back(newModule); - } - else if (nnName == "MulConstant") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("constant_scalar")); - newModule->apiType = "Power"; - layerParams.set("scale", scalarParams.get("constant_scalar")); - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialZeroPadding" || nnName == "SpatialReflectionPadding") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert_N(scalarParams.has("pad_l"), scalarParams.has("pad_r"), - scalarParams.has("pad_t"), scalarParams.has("pad_b")); - int padTop = scalarParams.get("pad_t"); - int padLeft = scalarParams.get("pad_l"); - int padRight = scalarParams.get("pad_r"); - int padBottom = scalarParams.get("pad_b"); - if (padTop < 0 || padLeft < 0 || padRight < 0 || padBottom < 0) - CV_Error(Error::StsNotImplemented, "SpatialZeroPadding in cropping mode is not implemented"); - - newModule->apiType = "Padding"; - - // Torch's SpatialZeroPadding works with 3- or 4-dimensional input. - // So we add parameter input_dims=3 to ignore batch dimension if it will be. - std::vector paddings(6, 0); // CHW - paddings[2] = padTop; - paddings[3] = padBottom; - paddings[4] = padLeft; - paddings[5] = padRight; - layerParams.set("paddings", DictValue::arrayInt(&paddings[0], paddings.size())); - layerParams.set("input_dims", 3); - - if (nnName == "SpatialReflectionPadding") - layerParams.set("type", "reflect"); - - curModule->modules.push_back(newModule); - } - else if (nnName == "ShaveImage") - { - // ShaveImage layer is from fast-neural-style project: https://github.com/jcjohnson/fast-neural-style - // It may be mapped to Slice layer. - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("size")); - int size = scalarParams.get("size"); - - int begins[] = {0, 0, size, size}; - int ends[] = {INT_MAX, INT_MAX, -size, -size}; - - newModule->apiType = "Slice"; - layerParams.set("begin", DictValue::arrayInt(&begins[0], 4)); - layerParams.set("end", DictValue::arrayInt(&ends[0], 4)); - curModule->modules.push_back(newModule); - } - else if (nnName == "SpatialUpSamplingNearest") - { - readTorchTable(scalarParams, tensorParams); - CV_Assert(scalarParams.has("scale_factor")); - int scale_factor = scalarParams.get("scale_factor"); - newModule->apiType = "Resize"; - layerParams.set("interpolation", "nearest"); - layerParams.set("zoom_factor", scale_factor); - curModule->modules.push_back(newModule); - } - else - { - // Importer does not know how to map Torch's layer type to an OpenCV's one. - // However we parse all the parameters to let user create a custom layer. - readTorchTable(scalarParams, tensorParams); - for (std::map::const_iterator it = scalarParams.begin(); - it != scalarParams.end(); ++it) - { - layerParams.set(it->first, it->second); - } - for (std::map >::iterator it = tensorParams.begin(); - it != tensorParams.end(); ++it) - { - layerParams.blobs.push_back(it->second.second); - } - newModule->apiType = nnName; - curModule->modules.push_back(newModule); - } - } - else - { - CV_Error(Error::StsNotImplemented, "Unsupported Torch class \"" + className + "\""); - } - - readedIndexes.insert(index); - } - - void readObject() - { - int typeidx = readInt(); - - if (typeidx == TYPE_TORCH) - { - int index = readInt(); - readTorchObject(index); - readedIndexes.insert(index); - } - else if (typeidx == TYPE_NIL) - return; - else if (typeidx == TYPE_NUMBER) - readDouble(); - else if (typeidx == TYPE_BOOLEAN) - readBool(); - else if (typeidx == TYPE_STRING) - readString(); - else if (typeidx == TYPE_TABLE) - readTable(); - else - CV_Error(Error::StsNotImplemented, "Unsupported Lua type"); - } - - inline String generateLayerName(const String &label = String()) - { - return "l" + toString(++this->moduleCounter) + "_" + label; - } - - int fill(Module *module, std::vector >& addedModules, int prevLayerId = 0, int prevOutNum = 0) - { - if (module == NULL) - return prevLayerId; - - if (module->apiType.length()) - { - int newLayerId = net.addLayer(generateLayerName(module->apiType), module->apiType, module->params); - net.connect(prevLayerId, prevOutNum, newLayerId, 0); - addedModules.push_back(std::make_pair(newLayerId, module)); - return newLayerId; - } - else - { - if (module->thName == "Sequential" || module->thName == "Inception") - { - for (size_t i = 0; i < module->modules.size(); i++) - { - prevLayerId = fill(module->modules[i], addedModules, prevLayerId, prevOutNum); - prevOutNum = 0; - } - return prevLayerId; - } - else if (module->thName == "Concat") - { - int newId, mergeId; - LayerParams mergeParams; - mergeParams.set("axis", module->params.get("dimension") - 1); - - std::vector branchIds; - for (int i = 0; i < (int)module->modules.size(); i++) - { - newId = fill(module->modules[i], addedModules, prevLayerId, prevOutNum); - branchIds.push_back(newId); - } - - moduleCounter += 1; // Skip split layer creation. See https://github.com/opencv/opencv/pull/9384. - mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); - - for (int i = 0; i < branchIds.size(); i++) - { - net.connect(branchIds[i], 0, mergeId, i); - } - - addedModules.push_back(std::make_pair(mergeId, module)); - return mergeId; - } - else if (module->thName == "DepthConcat") - { - int newId, mergeId; - LayerParams mergeParams; - mergeParams.set("axis", module->params.get("dimension") - 1); - mergeParams.set("padding", true); - - std::vector branchIds; - for (int i = 0; i < (int)module->modules.size(); i++) - { - newId = fill(module->modules[i], addedModules, prevLayerId, prevOutNum); - branchIds.push_back(newId); - } - - mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); - - for (int i = 0; i < branchIds.size(); i++) - { - net.connect(branchIds[i], 0, mergeId, i); - } - - addedModules.push_back(std::make_pair(mergeId, module)); - return mergeId; - } - else if (module->thName == "Parallel") - { - int newId, splitId, mergeId, reshapeId; - - LayerParams splitParams, mergeParams, reshapeParams; - splitParams.set("axis", module->params.get("inputDimension") - 1); - mergeParams.set("axis", module->params.get("outputDimension") - 1); - reshapeParams.set("axis", splitParams.get("axis")); - reshapeParams.set("num_axes", 1); - - splitId = net.addLayer(generateLayerName("torchSplit"), "Slice", splitParams); - reshapeId = net.addLayer(generateLayerName("torchReshape"), "Reshape", reshapeParams); - net.connect(prevLayerId, prevOutNum, splitId, 0); - - std::vector branchIds; - for (int i = 0; i < (int)module->modules.size(); i++) - { - net.connect(splitId, i, reshapeId, i); - newId = fill(module->modules[i], addedModules, reshapeId, i); - branchIds.push_back(newId); - } - - mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); - - for (int i = 0; i < branchIds.size(); i++) - { - net.connect(branchIds[i], 0, mergeId, i); - } - - addedModules.push_back(std::make_pair(mergeId, module)); - return mergeId; - } - else if (module->thName == "ConcatTable") { - int newId = -1; - moduleCounter += 1; // Skip split layer creation. See https://github.com/opencv/opencv/pull/9384. - for (int i = 0; i < (int)module->modules.size(); i++) - { - newId = fill(module->modules[i], addedModules, prevLayerId, prevOutNum); - } - numUnconnectedLayers.push_back(module->modules.size()); - return newId; - } - else if (module->thName == "JoinTable") { - std::vector ids = net.getUnconnectedOutLayers(); - - int mergeId; - LayerParams mergeParams; - mergeParams.set("axis", module->params.get("dimension") - 1); - - mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); - addedModules.push_back(std::make_pair(mergeId, module)); - - // Connect to the last number of unconnected layers. - CV_Assert(!numUnconnectedLayers.empty()); - const int numInputs = numUnconnectedLayers.back(); - numUnconnectedLayers.pop_back(); - CV_Assert(numInputs <= ids.size()); - for (int i = 0; i < numInputs; i++) - { - net.connect(ids[ids.size() - numInputs + i], 0, mergeId, i); - } - - return mergeId; - } - else if (module->thName == "CAddTable") { - String name = generateLayerName("torchCAddTable"); - std::vector ids = net.getUnconnectedOutLayers(); - LayerParams params; - params.set("operation", "sum"); - - - int id = net.addLayer(name, "Eltwise", params); - - // Connect to the last number of unconnected layers. - CV_Assert(!numUnconnectedLayers.empty()); - const int numInputs = numUnconnectedLayers.back(); - numUnconnectedLayers.pop_back(); - CV_Assert(numInputs <= ids.size()); - for (int i = 0; i < numInputs; i++) - { - net.connect(ids[ids.size() - numInputs + i], 0, id, i); - } - - addedModules.push_back(std::make_pair(id, module)); - return id; - } - else if (module->thName == "SpatialMaxUnpooling") { - CV_Assert(module->params.has("indices_blob_id")); - int indicesBlobId = module->params.get("indices_blob_id"); - std::pair poolingLayer; - poolingLayer.first = -1; - - for(int i = 0; i < addedModules.size(); i++) - { - if (addedModules[i].second->apiType == "Pooling" && - addedModules[i].second->params.has("indices_blob_id") && - addedModules[i].second->params.get("indices_blob_id") == indicesBlobId) - { - poolingLayer = addedModules[i]; - break; - } - } - - module->params.set("pool_k_h", poolingLayer.second->params.get("kernel_h")); - module->params.set("pool_k_w", poolingLayer.second->params.get("kernel_w")); - module->params.set("pool_stride_h", poolingLayer.second->params.get("stride_h")); - module->params.set("pool_stride_w", poolingLayer.second->params.get("stride_w")); - module->params.set("pool_pad_h", poolingLayer.second->params.get("pad_h")); - module->params.set("pool_pad_w", poolingLayer.second->params.get("pad_w")); - - String name = generateLayerName("torchMaxUnpooling"); - int id = net.addLayer(name, "MaxUnpool", module->params); - net.connect(prevLayerId, 0, id, 0); - - CV_Assert(poolingLayer.first != -1); - net.connect(poolingLayer.first, 1, id, 1); - - return id; - } - } - - CV_Error(Error::StsInternal, "Unexpected torch container: " + module->thName); - return -1; - } - - void populateNet(Net net_) - { - CV_TRACE_FUNCTION(); - - CV_Assert(rootModule == NULL); - cv::Ptr rootModule_ = cv::makePtr("Sequential"); - rootModule = rootModule_.get(); - curModule = rootModule; - - THFile_seek(file, 0); - readObject(); - - net = net_; - std::vector > addedModules; - fill(rootModule, addedModules); - - rootModule = NULL; - curModule = NULL; - } -}; - -Mat readTorchBlob(const String &filename, bool isBinary) -{ - TorchImporter importer(filename, isBinary, true); - importer.readObject(); - CV_Assert(importer.tensors.size() == 1); - - return importer.tensors.begin()->second; -} - -Net readNetFromTorch(const String &model, bool isBinary, bool evaluate) -{ - CV_TRACE_FUNCTION(); - - TorchImporter importer(model, isBinary, evaluate); - Net net; - importer.populateNet(net); - return net; -} - -CV__DNN_INLINE_NS_END -}} // namespace diff --git a/modules/dnn/test/cityscapes_semsegm_test_enet.py b/modules/dnn/test/cityscapes_semsegm_test_enet.py deleted file mode 100644 index 27070d3360..0000000000 --- a/modules/dnn/test/cityscapes_semsegm_test_enet.py +++ /dev/null @@ -1,140 +0,0 @@ -import numpy as np -import sys -import os -import fnmatch -import argparse - -try: - import cv2 as cv -except ImportError: - raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, ' - 'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)') -try: - import torch -except ImportError: - raise ImportError('Can\'t find pytorch. Please install it by following instructions on the official site') - -from torch.utils.serialization import load_lua -from pascal_semsegm_test_fcn import eval_segm_result, get_conf_mat, get_metrics, DatasetImageFetch, SemSegmEvaluation -from imagenet_cls_test_alexnet import Framework, DnnCaffeModel - - -class NormalizePreproc: - def __init__(self): - pass - - @staticmethod - def process(img): - image_data = np.array(img).transpose(2, 0, 1).astype(np.float32) - image_data = np.expand_dims(image_data, 0) - image_data /= 255.0 - return image_data - - -class CityscapesDataFetch(DatasetImageFetch): - img_dir = '' - segm_dir = '' - segm_files = [] - colors = [] - i = 0 - - def __init__(self, img_dir, segm_dir, preproc): - self.img_dir = img_dir - self.segm_dir = segm_dir - self.segm_files = sorted([img for img in self.locate('*_color.png', segm_dir)]) - self.colors = self.get_colors() - self.data_prepoc = preproc - self.i = 0 - - @staticmethod - def get_colors(): - result = [] - colors_list = ( - (0, 0, 0), (128, 64, 128), (244, 35, 232), (70, 70, 70), (102, 102, 156), (190, 153, 153), (153, 153, 153), - (250, 170, 30), (220, 220, 0), (107, 142, 35), (152, 251, 152), (70, 130, 180), (220, 20, 60), (255, 0, 0), - (0, 0, 142), (0, 0, 70), (0, 60, 100), (0, 80, 100), (0, 0, 230), (119, 11, 32)) - - for c in colors_list: - result.append(DatasetImageFetch.pix_to_c(c)) - return result - - def __iter__(self): - return self - - def next(self): - if self.i < len(self.segm_files): - segm_file = self.segm_files[self.i] - segm = cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1] - segm = cv.resize(segm, (1024, 512), interpolation=cv.INTER_NEAREST) - - img_file = self.rreplace(self.img_dir + segm_file[len(self.segm_dir):], 'gtFine_color', 'leftImg8bit') - assert os.path.exists(img_file) - img = cv.imread(img_file, cv.IMREAD_COLOR)[:, :, ::-1] - img = cv.resize(img, (1024, 512)) - - self.i += 1 - gt = self.color_to_gt(segm, self.colors) - img = self.data_prepoc.process(img) - return img, gt - else: - self.i = 0 - raise StopIteration - - def get_num_classes(self): - return len(self.colors) - - @staticmethod - def locate(pattern, root_path): - for path, dirs, files in os.walk(os.path.abspath(root_path)): - for filename in fnmatch.filter(files, pattern): - yield os.path.join(path, filename) - - @staticmethod - def rreplace(s, old, new, occurrence=1): - li = s.rsplit(old, occurrence) - return new.join(li) - - -class TorchModel(Framework): - net = object - - def __init__(self, model_file): - self.net = load_lua(model_file) - - def get_name(self): - return 'Torch' - - def get_output(self, input_blob): - tensor = torch.FloatTensor(input_blob) - out = self.net.forward(tensor).numpy() - return out - - -class DnnTorchModel(DnnCaffeModel): - net = cv.dnn.Net() - - def __init__(self, model_file): - self.net = cv.dnn.readNetFromTorch(model_file) - - def get_output(self, input_blob): - self.net.setBlob("", input_blob) - self.net.forward() - return self.net.getBlob(self.net.getLayerNames()[-1]) - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--imgs_dir", help="path to Cityscapes validation images dir, imgsfine/leftImg8bit/val") - parser.add_argument("--segm_dir", help="path to Cityscapes dir with segmentation, gtfine/gtFine/val") - parser.add_argument("--model", help="path to torch model, download it here: " - "https://www.dropbox.com/sh/dywzk3gyb12hpe5/AAD5YkUa8XgMpHs2gCRgmCVCa") - parser.add_argument("--log", help="path to logging file") - args = parser.parse_args() - - prep = NormalizePreproc() - df = CityscapesDataFetch(args.imgs_dir, args.segm_dir, prep) - - fw = [TorchModel(args.model), - DnnTorchModel(args.model)] - - segm_eval = SemSegmEvaluation(args.log) - segm_eval.process(fw, df) diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 2faa2c8e60..924fe6a823 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -147,26 +147,6 @@ TEST_P(DNNTestNetwork, Inception_5h) expectNoFallbacksFromCUDA(net); } -TEST_P(DNNTestNetwork, ENet) -{ - applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB); - -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2023000000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); -#endif - if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16); - if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_CPU_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16); - processNet("dnn/Enet-model-best.net", "", Size(512, 512), "l367_Deconvolution", 2e-5, 0.15); - expectNoFallbacksFromCUDA(net); -} - TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe) { applyTestTag(CV_TEST_TAG_MEMORY_512MB); @@ -380,21 +360,6 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages) expectNoFallbacksFromCUDA(net); } -TEST_P(DNNTestNetwork, OpenFace) -{ -#if defined(INF_ENGINE_RELEASE) -#if INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); -#endif -#endif - const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0024 : 0.0; - const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.0071 : 0.0; - processNet("dnn/openface_nn4.small2.v1.t7", "", Size(96, 96), "", l1, lInf); - - expectNoFallbacksFromCUDA(net); -} - TEST_P(DNNTestNetwork, opencv_face_detector) { Mat img = imread(findDataFile("gpu/lbpcascade/er.png")); @@ -482,9 +447,9 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16) #endif Mat img = imread(findDataFile("dnn/googlenet_1.png")); - Mat inp = blobFromImage(img, 1.0, Size(320, 240), Scalar(103.939, 116.779, 123.68), false, false); - // Output image has values in range [-143.526, 148.539]. - float l1 = 2e-4, lInf = 2.4e-3; + Mat inp = blobFromImage(img, 1.0, Size(224, 224), Scalar(0.0, 0.0, 0.0), true, false); + // Output image has values in range [0.0, 255.0]. + float l1 = 5e-4, lInf = 1e-2; if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) { l1 = 0.4; @@ -492,13 +457,13 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16) } else if (target == DNN_TARGET_CUDA_FP16) { - l1 = 0.3; - lInf = 7.6; + l1 = 0.9; + lInf = 16; } else if (target == DNN_TARGET_CPU_FP16) { l1 = 0.4; - lInf = 19.; + lInf = 26.; } else if (target == DNN_TARGET_VULKAN) { @@ -519,7 +484,7 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16) #endif - processNet("dnn/fast_neural_style_eccv16_starry_night.t7", "", inp, "", l1, lInf); + processNet("dnn/mosaic-9.onnx", "", inp, "", l1, lInf); #if defined(HAVE_INF_ENGINE) && INF_ENGINE_VER_MAJOR_GE(2019010000) expectNoFallbacksFromIE(net); #endif diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 0c5fb28c5d..2691df40c6 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -150,8 +150,6 @@ TEST(readNet, Regression) net = readNet(findDataFile("dnn/opencv_face_detector.caffemodel", false), findDataFile("dnn/opencv_face_detector.prototxt")); EXPECT_FALSE(net.empty()); - net = readNet(findDataFile("dnn/openface_nn4.small2.v1.t7", false)); - EXPECT_FALSE(net.empty()); net = readNet(findDataFile("dnn/tiny-yolo-voc.cfg"), findDataFile("dnn/tiny-yolo-voc.weights", false)); EXPECT_FALSE(net.empty()); diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp deleted file mode 100644 index 254422f072..0000000000 --- a/modules/dnn/test/test_torch_importer.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/*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 "test_precomp.hpp" -#include "npy_blob.hpp" -#include -#include // CV_DNN_REGISTER_LAYER_CLASS - -namespace opencv_test -{ - -using namespace std; -using namespace testing; -using namespace cv; -using namespace cv::dnn; - -template -static std::string _tf(TStr filename, bool inTorchDir = true, bool required = true) -{ - String path = "dnn/"; - if (inTorchDir) - path += "torch/"; - path += filename; - return findDataFile(path, required); -} - -TEST(Torch_Importer, simple_read) -{ - Net net; - ASSERT_NO_THROW(net = readNetFromTorch(_tf("net_simple_net.txt"), false)); - ASSERT_FALSE(net.empty()); -} - -class Test_Torch_layers : public DNNTestLayer -{ -public: - void runTorchNet(const String& prefix, String outLayerName = "", - bool check2ndBlob = false, bool isBinary = false, bool evaluate = true, - double l1 = 0.0, double lInf = 0.0) - { - String suffix = (isBinary) ? ".dat" : ".txt"; - - Mat inp, outRef; - ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) ); - ASSERT_NO_THROW( outRef = readTorchBlob(_tf(prefix + "_output" + suffix), isBinary) ); - - checkBackend(backend, target, &inp, &outRef); - - Net net = readNetFromTorch(_tf(prefix + "_net" + suffix), isBinary, evaluate); - ASSERT_FALSE(net.empty()); - - net.setPreferableBackend(backend); - net.setPreferableTarget(target); - - if (outLayerName.empty()) - outLayerName = net.getLayerNames().back(); - - net.setInput(inp); - std::vector outBlobs; - net.forward(outBlobs, outLayerName); - l1 = l1 ? l1 : default_l1; - lInf = lInf ? lInf : default_lInf; - normAssert(outRef, outBlobs[0], "", l1, lInf); - - if (check2ndBlob && backend == DNN_BACKEND_OPENCV) - { - Mat out2 = outBlobs[1]; - Mat ref2 = readTorchBlob(_tf(prefix + "_output_2" + suffix), isBinary); - normAssert(out2, ref2, "", l1, lInf); - } - } -}; - -TEST_P(Test_Torch_layers, run_convolution) -{ - // Output reference values are in range [23.4018, 72.0181] - double l1 = default_l1, lInf = default_lInf; - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) - { - l1 = 0.08; - lInf = 0.43; - } - else if (target == DNN_TARGET_CUDA_FP16) - { - l1 = 0.08; - lInf = 0.5; - } - runTorchNet("net_conv", "", false, true, true, l1, lInf); -} - -TEST_P(Test_Torch_layers, run_pool_max) -{ - if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - if (target == DNN_TARGET_CUDA_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16); - if (target == DNN_TARGET_CPU_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16); - double l1 = 0.0, lInf = 0.0; - runTorchNet("net_pool_max", "", true, false, true, l1, lInf); -} - -TEST_P(Test_Torch_layers, run_pool_ave) -{ - runTorchNet("net_pool_ave"); -} - -TEST_P(Test_Torch_layers, run_reshape_change_batch_size) -{ - runTorchNet("net_reshape"); -} - -TEST_P(Test_Torch_layers, run_reshape) -{ - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - runTorchNet("net_reshape_batch"); - runTorchNet("net_reshape_channels", "", false, true); -} - -TEST_P(Test_Torch_layers, run_reshape_single_sample) -{ - // Reference output values in range [14.4586, 18.4492]. - double l1 = default_l1, lInf = default_lInf; - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) - { - l1 = 0.033; - lInf = 0.05; - } - else if (target == DNN_TARGET_CUDA_FP16) - { - l1 = 0.02; - lInf = 0.04; - } - runTorchNet("net_reshape_single_sample", "", false, false, true, l1, lInf); -} - -TEST_P(Test_Torch_layers, run_linear) -{ - if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - if (target == DNN_TARGET_CPU_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16); - runTorchNet("net_linear_2d"); -} - -TEST_P(Test_Torch_layers, run_concat) -{ - runTorchNet("net_concat", "l5_torchMerge"); -} - -TEST_P(Test_Torch_layers, run_depth_concat) -{ - double lInf = 0.0; - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) - { - lInf = 0.032; - } - else if (target == DNN_TARGET_CUDA_FP16) - { - lInf = 0.03; - } - runTorchNet("net_depth_concat", "", false, true, true, 0.0, lInf); -} - -TEST_P(Test_Torch_layers, run_deconv) -{ - runTorchNet("net_deconv"); -} - -TEST_P(Test_Torch_layers, run_batch_norm) -{ - runTorchNet("net_batch_norm", "", false, true); - runTorchNet("net_batch_norm_train", "", false, true, false); -} - -TEST_P(Test_Torch_layers, net_prelu) -{ - runTorchNet("net_prelu"); -} - -TEST_P(Test_Torch_layers, net_cadd_table) -{ - runTorchNet("net_cadd_table"); -} - -TEST_P(Test_Torch_layers, net_softmax) -{ - runTorchNet("net_softmax"); - runTorchNet("net_softmax_spatial"); -} - -TEST_P(Test_Torch_layers, net_logsoftmax) -{ - runTorchNet("net_logsoftmax"); - runTorchNet("net_logsoftmax_spatial"); -} - -TEST_P(Test_Torch_layers, net_lp_pooling_square) -{ - runTorchNet("net_lp_pooling_square", "", false, true); -} -TEST_P(Test_Torch_layers, net_lp_pooling_power) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); -#endif - runTorchNet("net_lp_pooling_power", "", false, true); -} - -TEST_P(Test_Torch_layers, net_conv_gemm_lrn) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); -#endif - double l1 = 0.0, lInf = 0.0; - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16) - { - l1 = 0.046; - lInf = 0.023; - } - else if (target == DNN_TARGET_MYRIAD) - { - l1 = 0.02; - lInf = 0.05; - } - else if (target == DNN_TARGET_CUDA_FP16) - { - l1 = 0.0042; - lInf = 0.021; - } - // The OpenCL kernels use the native_ math functions which have - // implementation defined accuracy, so we use relaxed thresholds. See - // https://github.com/opencv/opencv/issues/9821 for more details. - else if (target == DNN_TARGET_OPENCL) - { - l1 = 0.02; - lInf = 0.02; - } - runTorchNet("net_conv_gemm_lrn", "", false, true, true, l1, lInf); -} - -TEST_P(Test_Torch_layers, net_inception_block) -{ - runTorchNet("net_inception_block", "", false, true); -} - -TEST_P(Test_Torch_layers, net_normalize) -{ - if(backend == DNN_BACKEND_CUDA) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* only L1 and L2 norms are supported */ - - runTorchNet("net_normalize", "", false, true); -} - -TEST_P(Test_Torch_layers, net_padding) -{ - runTorchNet("net_padding", "", false, true); - runTorchNet("net_spatial_zero_padding", "", false, true); - runTorchNet("net_spatial_reflection_padding", "", false, true); -} - -TEST_P(Test_Torch_layers, net_non_spatial) -{ -#if defined(INF_ENGINE_RELEASE) && ( \ - INF_ENGINE_VER_MAJOR_EQ(2021030000) || \ - INF_ENGINE_VER_MAJOR_EQ(2021040000) \ -) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD) - // 2021.3: crash - // 2021.4: [ GENERAL_ERROR ] AssertionFailed: !out.networkInputs.empty() - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception -#endif - - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && - (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, - CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); - runTorchNet("net_non_spatial", "", false, true); -} - -TEST_P(Test_Torch_layers, run_paralel) -{ - if (backend != DNN_BACKEND_OPENCV || target != DNN_TARGET_CPU) - throw SkipTestException(""); // TODO: Check this - runTorchNet("net_parallel", "l5_torchMerge"); -} - -TEST_P(Test_Torch_layers, net_residual) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE == 2018050000 - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || - target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, - CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); -#endif - runTorchNet("net_residual", "", false, true); -} - -class Test_Torch_nets : public DNNTestLayer {}; - -TEST_P(Test_Torch_nets, OpenFace_accuracy) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); -#endif - checkBackend(); - - const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false); - Net net = readNetFromTorch(model); - - net.setPreferableBackend(backend); - net.setPreferableTarget(target); - - Mat sample = imread(findDataFile("cv/shared/lena.png")); - Mat sampleF32(sample.size(), CV_32FC3); - sample.convertTo(sampleF32, sampleF32.type()); - sampleF32 /= 255; - resize(sampleF32, sampleF32, Size(96, 96), 0, 0, INTER_NEAREST); - - Mat inputBlob = blobFromImage(sampleF32, 1.0, Size(), Scalar(), /*swapRB*/true); - - net.setInput(inputBlob); - Mat out = net.forward(); - - // Reference output values are in range [-0.17212, 0.263492] - // on Myriad problem layer: l4_Pooling - does not use pads_begin - float l1 = 1e-5, lInf = 1e-3; - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16) - { - l1 = 2e-3; - lInf = 5e-3; - } - else if (target == DNN_TARGET_CUDA_FP16) - { - l1 = 0.0004; - lInf = 0.0012; - } - Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true); - normAssert(out, outRef, "", l1, lInf); -} - -static Mat getSegmMask(const Mat& scores) -{ - const int rows = scores.size[2]; - const int cols = scores.size[3]; - const int numClasses = scores.size[1]; - - Mat maxCl = Mat::zeros(rows, cols, CV_8UC1); - Mat maxVal(rows, cols, CV_32FC1, Scalar(0)); - for (int ch = 0; ch < numClasses; ch++) - { - for (int row = 0; row < rows; row++) - { - const float *ptrScore = scores.ptr(0, ch, row); - uint8_t *ptrMaxCl = maxCl.ptr(row); - float *ptrMaxVal = maxVal.ptr(row); - for (int col = 0; col < cols; col++) - { - if (ptrScore[col] > ptrMaxVal[col]) - { - ptrMaxVal[col] = ptrScore[col]; - ptrMaxCl[col] = (uchar)ch; - } - } - } - } - return maxCl; -} - -// Computer per-class intersection over union metric. -static void normAssertSegmentation(const Mat& ref, const Mat& test) -{ - CV_Assert_N(ref.dims == 4, test.dims == 4); - const int numClasses = ref.size[1]; - CV_Assert(numClasses == test.size[1]); - - Mat refMask = getSegmMask(ref); - Mat testMask = getSegmMask(test); - EXPECT_EQ(countNonZero(refMask != testMask), 0); -} - -TEST_P(Test_Torch_nets, ENet_accuracy) -{ - applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB); - checkBackend(); - if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) - throw SkipTestException(""); - if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16); - if (target == DNN_TARGET_CPU_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16); -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); -#else - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) - { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - throw SkipTestException(""); - } -#endif -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2023000000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); -#endif - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) - { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); - throw SkipTestException(""); - } - - Net net; - { - const string model = findDataFile("dnn/Enet-model-best.net", false); - net = readNetFromTorch(model, true); - ASSERT_TRUE(!net.empty()); - } - - net.enableWinograd(false); - net.setPreferableBackend(backend); - net.setPreferableTarget(target); - - Mat sample = imread(_tf("street.png", false)); - Mat inputBlob = blobFromImage(sample, 1./255, Size(), Scalar(), /*swapRB*/true); - - net.setInput(inputBlob, ""); - Mat out = net.forward(); - Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false)); - // Due to numerical instability in Pooling-Unpooling layers (indexes jittering) - // thresholds for ENet must be changed. Accuracy of results was checked on - // Cityscapes dataset and difference in mIOU with Torch is 10E-4% - normAssert(ref, out, "", 0.0005, /*target == DNN_TARGET_CPU ? 0.453 : */0.552); - normAssertSegmentation(ref, out); - - const int N = 3; - for (int i = 0; i < N; i++) - { - net.setInput(inputBlob, ""); - Mat out = net.forward(); - normAssert(ref, out, "", 0.0005, /*target == DNN_TARGET_CPU ? 0.453 : */0.552); - normAssertSegmentation(ref, out); - } -} - -// Check accuracy of style transfer models from https://github.com/jcjohnson/fast-neural-style -// th fast_neural_style.lua \ -// -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \ -// -output_image lena.png \ -// -median_filter 0 \ -// -image_size 0 \ -// -model models/eccv16/starry_night.t7 -// th fast_neural_style.lua \ -// -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \ -// -output_image lena.png \ -// -median_filter 0 \ -// -image_size 0 \ -// -model models/instance_norm/feathers.t7 -TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy) -{ -#if defined INF_ENGINE_RELEASE - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD - && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD - && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); -#endif - - checkBackend(); - -#if defined(INF_ENGINE_RELEASE) -#if INF_ENGINE_RELEASE <= 2018050000 - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); -#endif -#endif - - std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7", - "dnn/fast_neural_style_instance_norm_feathers.t7"}; - std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"}; - - for (int i = 0; i < 2; ++i) - { - const string model = findDataFile(models[i], false); - Net net = readNetFromTorch(model); - - net.setPreferableBackend(backend); - net.setPreferableTarget(target); - - Mat img = imread(findDataFile("dnn/googlenet_1.png")); - Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false); - - net.setInput(inputBlob); - Mat out = net.forward(); - - // Deprocessing. - getPlane(out, 0, 0) += 103.939; - getPlane(out, 0, 1) += 116.779; - getPlane(out, 0, 2) += 123.68; - out = cv::min(cv::max(0, out), 255); - - Mat ref = imread(findDataFile(targets[i])); - Mat refBlob = blobFromImage(ref, 1.0, Size(), Scalar(), false); - - if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) - { - double normL1 = cvtest::norm(refBlob, out, cv::NORM_L1) / refBlob.total(); - if (target == DNN_TARGET_MYRIAD) - EXPECT_LE(normL1, 4.0f); - else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16) - EXPECT_LE(normL1, 1.0f); - else - EXPECT_LE(normL1, 0.6f); - } - else if(target == DNN_TARGET_CUDA_FP16) - { - normAssert(out, refBlob, "", 0.6, 26); - } - else if (target == DNN_TARGET_CPU_FP16) - { - normAssert(out, refBlob, "", 0.62, 25); - } - else - normAssert(out, refBlob, "", 0.5, 1.11); - } -} - -INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_nets, dnnBackendsAndTargets()); - -// Test a custom layer -// https://github.com/torch/nn/blob/master/doc/convolution.md#nn.SpatialUpSamplingNearest -class SpatialUpSamplingNearestLayer CV_FINAL : public Layer -{ -public: - SpatialUpSamplingNearestLayer(const LayerParams ¶ms) : Layer(params) - { - scale = params.get("scale_factor"); - } - - static Ptr create(LayerParams& params) - { - return Ptr(new SpatialUpSamplingNearestLayer(params)); - } - - virtual bool getMemoryShapes(const std::vector > &inputs, - const int requiredOutputs, - std::vector > &outputs, - std::vector > &internals) const CV_OVERRIDE - { - std::vector outShape(4); - outShape[0] = inputs[0][0]; // batch size - outShape[1] = inputs[0][1]; // number of channels - outShape[2] = scale * inputs[0][2]; - outShape[3] = scale * inputs[0][3]; - outputs.assign(1, outShape); - return false; - } - - void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE - { - CV_TRACE_FUNCTION(); - CV_TRACE_ARG_VALUE(name, "name", name.c_str()); - - std::vector inputs, outputs; - inputs_arr.getMatVector(inputs); - outputs_arr.getMatVector(outputs); - - Mat& inp = inputs[0]; - Mat& out = outputs[0]; - const int outHeight = out.size[2]; - const int outWidth = out.size[3]; - for (size_t n = 0; n < inp.size[0]; ++n) - { - for (size_t ch = 0; ch < inp.size[1]; ++ch) - { - resize(getPlane(inp, n, ch), getPlane(out, n, ch), - Size(outWidth, outHeight), 0, 0, INTER_NEAREST); - } - } - } - -private: - int scale; -}; - -TEST_P(Test_Torch_layers, upsampling_nearest) -{ -#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO -#endif - - // Test a custom layer. - CV_DNN_REGISTER_LAYER_CLASS(SpatialUpSamplingNearest, SpatialUpSamplingNearestLayer); - try - { - runTorchNet("net_spatial_upsampling_nearest", "", false, true); - } - catch (...) - { - LayerFactory::unregisterLayer("SpatialUpSamplingNearest"); - throw; - } - LayerFactory::unregisterLayer("SpatialUpSamplingNearest"); - - // Test an implemented layer. - runTorchNet("net_spatial_upsampling_nearest", "", false, true); -} - -INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_layers, dnnBackendsAndTargets()); - -} diff --git a/platforms/js/opencv_js.config.py b/platforms/js/opencv_js.config.py index 12f6254801..b356fdbe9a 100644 --- a/platforms/js/opencv_js.config.py +++ b/platforms/js/opencv_js.config.py @@ -148,7 +148,7 @@ video = { } dnn = {'dnn_Net': ['setInput', 'forward', 'setPreferableBackend'], - '': ['readNetFromCaffe', 'readNetFromTensorflow', 'readNetFromTorch', 'readNetFromDarknet', + '': ['readNetFromCaffe', 'readNetFromTensorflow', 'readNetFromDarknet', 'readNetFromONNX', 'readNetFromTFLite', 'readNet', 'blobFromImage']} features2d = {'Feature2D': ['detect', 'compute', 'detectAndCompute', 'descriptorSize', 'descriptorType', 'defaultNorm', 'empty', 'getDefaultName'], diff --git a/samples/dnn/classification.py b/samples/dnn/classification.py index 0afad1c99f..bbeacc5031 100644 --- a/samples/dnn/classification.py +++ b/samples/dnn/classification.py @@ -16,7 +16,7 @@ def get_args_parser(func_args): help='An optional path to file with preprocessing parameters.') parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.') - parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'torch', 'darknet'], + parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'darknet'], help='Optional name of an origin framework of the model. ' 'Detect it automatically if it does not set.') parser.add_argument('--std', nargs='*', type=float, diff --git a/samples/dnn/common.hpp b/samples/dnn/common.hpp index e88a206cf6..674d1052c5 100644 --- a/samples/dnn/common.hpp +++ b/samples/dnn/common.hpp @@ -77,7 +77,7 @@ std::string genPreprocArguments(const std::string& modelName, const std::string& { return genArgument("model", "Path to a binary file of model contains trained weights. " "It could be a file with extensions .caffemodel (Caffe), " - ".pb (TensorFlow), .t7 or .net (Torch), .weights (Darknet), .bin (OpenVINO).", + ".pb (TensorFlow), .weights (Darknet), .bin (OpenVINO).", modelName, zooFile, 'm') + genArgument("config", "Path to a text file of model contains network configuration. " "It could be a file with extensions .prototxt (Caffe), .pbtxt (TensorFlow), .cfg (Darknet), .xml (OpenVINO).", diff --git a/samples/dnn/common.py b/samples/dnn/common.py index db9283b5d8..14e9a2a496 100644 --- a/samples/dnn/common.py +++ b/samples/dnn/common.py @@ -62,7 +62,7 @@ def add_preproc_args(zoo, parser, sample): add_argument(zoo, parser, 'model', required=True, help='Path to a binary file of model contains trained weights. ' 'It could be a file with extensions .caffemodel (Caffe), ' - '.pb (TensorFlow), .t7 or .net (Torch), .weights (Darknet), .bin (OpenVINO)') + '.pb (TensorFlow), .weights (Darknet), .bin (OpenVINO)') add_argument(zoo, parser, 'config', help='Path to a text file of model contains network configuration. ' 'It could be a file with extensions .prototxt (Caffe), .pbtxt or .config (TensorFlow), .cfg (Darknet), .xml (OpenVINO)') diff --git a/samples/dnn/models.yml b/samples/dnn/models.yml index e645279605..47d732bcf1 100644 --- a/samples/dnn/models.yml +++ b/samples/dnn/models.yml @@ -151,21 +151,6 @@ googlenet: # Semantic segmentation models. ################################################################################ -# ENet road scene segmentation network from https://github.com/e-lab/ENet-training -# Works fine for different input sizes. -enet: - load_info: - url: "https://www.dropbox.com/s/tdde0mawbi5dugq/Enet-model-best.net?dl=1" - sha1: "b4123a73bf464b9ebe9cfc4ab9c2d5c72b161315" - model: "Enet-model-best.net" - mean: [0, 0, 0] - scale: 0.00392 - width: 512 - height: 256 - rgb: true - classes: "enet-classes.txt" - sample: "segmentation" - fcn8s: load_info: url: "http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel" diff --git a/samples/dnn/object_detection.py b/samples/dnn/object_detection.py index ba56525953..67b3bcd08e 100644 --- a/samples/dnn/object_detection.py +++ b/samples/dnn/object_detection.py @@ -24,7 +24,7 @@ parser.add_argument('--out_tf_graph', default='graph.pbtxt', help='For models from TensorFlow Object Detection API, you may ' 'pass a .config file which was used for training through --config ' 'argument. This way an additional .pbtxt file with TensorFlow graph will be created.') -parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'torch', 'darknet', 'dldt'], +parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'darknet', 'dldt'], help='Optional name of an origin framework of the model. ' 'Detect it automatically if it does not set.') parser.add_argument('--thr', type=float, default=0.5, help='Confidence threshold') diff --git a/samples/dnn/segmentation.py b/samples/dnn/segmentation.py index 97bd21dc3e..b3405fcc5e 100644 --- a/samples/dnn/segmentation.py +++ b/samples/dnn/segmentation.py @@ -14,7 +14,7 @@ parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--zoo', default=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models.yml'), help='An optional path to file with preprocessing parameters.') parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.') -parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'torch', 'darknet'], +parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'darknet'], help='Optional name of an origin framework of the model. ' 'Detect it automatically if it does not set.') parser.add_argument('--colors', help='Optional path to a text file with colors for an every class. '