From 8c221981bf7e2c8eb87302d70000aa246641487c Mon Sep 17 00:00:00 2001 From: Anastasia M Date: Tue, 26 Jan 2021 14:06:15 +0300 Subject: [PATCH] Merge pull request #17604 from LupusSanctus:am/pytorch_tf_cls_tutorial [GSoC] Added TF and PyTorch classification conversion cases * Added TF and PyTorch classification conversion cases * Modified structure, some processing scripts. Added evaluation pipeline * Minor structure change * Removed extra functions, minor structure change * Modified structure, code corrections * Updated classification code block, added classification tutorials * Added minor modifications of paths * Classification block corrections in accordance with comments --- .../images/opencv_resnet50_test_res_c.jpg | Bin 0 -> 60324 bytes .../pytorch_resnet50_opencv_test_res.jpg | Bin 0 -> 30033 bytes .../images/squirrel_cls.jpg | Bin 0 -> 62311 bytes .../images/tf_mobilenet_opencv_test_res.jpg | Bin 0 -> 62512 bytes ...pytorch_cls_model_conversion_c_tutorial.md | 220 +++++++++++ .../pytorch_cls_model_conversion_tutorial.md | 362 ++++++++++++++++++ .../tf_cls_model_conversion_tutorial.md | 360 +++++++++++++++++ .../dnn_text_spotting.markdown | 1 + .../dnn/table_of_content_dnn.markdown | 9 + samples/data/squirrel_cls.jpg | Bin 0 -> 62311 bytes samples/dnn/classification.cpp | 54 ++- samples/dnn/classification.py | 189 +++++---- .../dnn_conversion/common/abstract_model.py | 23 ++ .../classification/cls_accuracy_evaluator.py | 96 +++++ .../classification/cls_data_fetcher.py | 87 +++++ .../dnn_conversion/common/img_utils.py | 19 + .../common/test/cls_model_test_pipeline.py | 60 +++ .../test/configs/default_preprocess_config.py | 37 ++ .../common/test/configs/test_config.py | 40 ++ .../common/test/model_test_pipeline.py | 126 ++++++ .../dnn_conversion/common/utils.py | 153 ++++++++ .../pytorch/classification/py_to_py_cls.py | 71 ++++ .../classification/py_to_py_resnet50.py | 139 +++++++ .../classification/py_to_py_resnet50_onnx.py | 50 +++ .../dnn_conversion/pytorch/pytorch_model.py | 98 +++++ .../dnn_conversion/requirements.txt | 9 + .../tf/classification/py_to_py_cls.py | 104 +++++ .../tf/classification/py_to_py_mobilenet.py | 142 +++++++ .../dnn_conversion/tf/tf_model.py | 112 ++++++ 29 files changed, 2463 insertions(+), 98 deletions(-) create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/images/opencv_resnet50_test_res_c.jpg create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/images/pytorch_resnet50_opencv_test_res.jpg create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/images/squirrel_cls.jpg create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/images/tf_mobilenet_opencv_test_res.jpg create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_c_tutorial.md create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_tutorial.md create mode 100644 doc/tutorials/dnn/dnn_pytorch_tf_classification/tf_cls_model_conversion_tutorial.md create mode 100644 samples/data/squirrel_cls.jpg create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/abstract_model.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_accuracy_evaluator.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_data_fetcher.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/img_utils.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/test/cls_model_test_pipeline.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/default_preprocess_config.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/test/model_test_pipeline.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/common/utils.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_cls.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50_onnx.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/pytorch/pytorch_model.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_cls.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_mobilenet.py create mode 100644 samples/dnn/dnn_model_runner/dnn_conversion/tf/tf_model.py diff --git a/doc/tutorials/dnn/dnn_pytorch_tf_classification/images/opencv_resnet50_test_res_c.jpg b/doc/tutorials/dnn/dnn_pytorch_tf_classification/images/opencv_resnet50_test_res_c.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d1ba30378167ae1c5971a3e080592f941e7be6c GIT binary patch literal 60324 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 literal 0 HcmV?d00001 diff --git a/doc/tutorials/dnn/dnn_pytorch_tf_classification/images/pytorch_resnet50_opencv_test_res.jpg b/doc/tutorials/dnn/dnn_pytorch_tf_classification/images/pytorch_resnet50_opencv_test_res.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7bee270616a7a076c7add5d72b75d4be178931b1 GIT binary patch literal 30033 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%0Ag`O9zD|K*ZZ3A$o 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 b^#1_j;{4|a&T?R<$3It$G{N983!nelOj%Y0 literal 0 HcmV?d00001 diff --git a/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_c_tutorial.md b/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_c_tutorial.md new file mode 100644 index 0000000000..1807caf0b4 --- /dev/null +++ b/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_c_tutorial.md @@ -0,0 +1,220 @@ +# Conversion of PyTorch Classification Models and Launch with OpenCV C++ {#pytorch_cls_c_tutorial_dnn_conversion} + +@prev_tutorial{pytorch_cls_tutorial_dnn_conversion} + +| | | +| -: | :- | +| Original author | Anastasia Murzova | +| Compatibility | OpenCV >= 4.5 | + +## Goals +In this tutorial you will learn how to: +* convert PyTorch classification models into ONNX format +* run converted PyTorch model with OpenCV C/C++ API +* provide model inference + +We will explore the above-listed points by the example of ResNet-50 architecture. + +## Introduction +Let's briefly view the key concepts involved in the pipeline of PyTorch models transition with OpenCV API. The initial step in conversion of PyTorch models into cv::dnn::Net +is model transferring into [ONNX](https://onnx.ai/about.html) format. ONNX aims at the interchangeability of the neural networks between various frameworks. There is a built-in function in PyTorch for ONNX conversion: [``torch.onnx.export``](https://pytorch.org/docs/stable/onnx.html#torch.onnx.export). +Further the obtained ``.onnx`` model is passed into cv::dnn::readNetFromONNX or cv::dnn::readNet. + +## Requirements +To be able to experiment with the below code you will need to install a set of libraries. We will use a virtual environment with python3.7+ for this: + +```console +virtualenv -p /usr/bin/python3.7 +source /bin/activate +``` + +For OpenCV-Python building from source, follow the corresponding instructions from the @ref tutorial_py_table_of_contents_setup. + +Before you start the installation of the libraries, you can customize the [requirements.txt](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt), excluding or including (for example, ``opencv-python``) some dependencies. +The below line initiates requirements installation into the previously activated virtual environment: + +```console +pip install -r requirements.txt +``` + +## Practice +In this part we are going to cover the following points: +1. create a classification model conversion pipeline +2. provide the inference, process prediction results + +### Model Conversion Pipeline +The code in this subchapter is located in the ``samples/dnn/dnn_model_runner`` module and can be executed with the line: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_resnet50_onnx +``` + +The following code contains the description of the below-listed steps: +1. instantiate PyTorch model +2. convert PyTorch model into ``.onnx`` + +```python +# initialize PyTorch ResNet-50 model +original_model = models.resnet50(pretrained=True) + +# get the path to the converted into ONNX PyTorch model +full_model_path = get_pytorch_onnx_model(original_model) +print("PyTorch ResNet-50 model was successfully converted: ", full_model_path) +``` + +``get_pytorch_onnx_model(original_model)`` function is based on ``torch.onnx.export(...)`` call: + +```python +# define the directory for further converted model save +onnx_model_path = "models" +# define the name of further converted model +onnx_model_name = "resnet50.onnx" + +# create directory for further converted model +os.makedirs(onnx_model_path, exist_ok=True) + +# get full path to the converted model +full_model_path = os.path.join(onnx_model_path, onnx_model_name) + +# generate model input +generated_input = Variable( + torch.randn(1, 3, 224, 224) +) + +# model export into ONNX format +torch.onnx.export( + original_model, + generated_input, + full_model_path, + verbose=True, + input_names=["input"], + output_names=["output"], + opset_version=11 +) +``` + +After the successful execution of the above code we will get the following output: + +```console +PyTorch ResNet-50 model was successfully converted: models/resnet50.onnx +``` + +The proposed in ``dnn/samples`` module ``dnn_model_runner`` allows us to reproduce the above conversion steps for the following PyTorch classification models: +* alexnet +* vgg11 +* vgg13 +* vgg16 +* vgg19 +* resnet18 +* resnet34 +* resnet50 +* resnet101 +* resnet152 +* squeezenet1_0 +* squeezenet1_1 +* resnext50_32x4d +* resnext101_32x8d +* wide_resnet50_2 +* wide_resnet101_2 + +To obtain the converted model, the following line should be executed: + +``` +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name --evaluate False +``` + +For the ResNet-50 case the below line should be run: + +``` +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name resnet50 --evaluate False +``` + +The default root directory for the converted model storage is defined in module ``CommonConfig``: + +```python +@dataclass +class CommonConfig: + output_data_root_dir: str = "dnn_model_runner/dnn_conversion" +``` + +Thus, the converted ResNet-50 will be saved in ``dnn_model_runner/dnn_conversion/models``. + +### Inference Pipeline +Now we can use ```models/resnet50.onnx``` for the inference pipeline using OpenCV C/C++ API. The implemented pipeline can be found in [samples/dnn/classification.cpp](https://github.com/opencv/opencv/blob/master/samples/dnn/classification.cpp). +After the build of samples (``BUILD_EXAMPLES`` flag value should be ``ON``), the appropriate ``example_dnn_classification`` executable file will be provided. + +To provide model inference we will use the below [squirrel photo](https://www.pexels.com/photo/brown-squirrel-eating-1564292) (under [CC0](https://www.pexels.com/terms-of-service/) license) corresponding to ImageNet class ID 335: +```console +fox squirrel, eastern fox squirrel, Sciurus niger +``` + +![Classification model input image](images/squirrel_cls.jpg) + +For the label decoding of the obtained prediction, we also need ``imagenet_classes.txt`` file, which contains the full list of the ImageNet classes. + +In this tutorial we will run the inference process for the converted PyTorch ResNet-50 model from the build (``samples/build``) directory: + +``` +./dnn/example_dnn_classification --model=../dnn/models/resnet50.onnx --input=../data/squirrel_cls.jpg --width=224 --height=224 --rgb=true --scale="0.003921569" --mean="123.675 116.28 103.53" --std="0.229 0.224 0.225" --crop=true --initial_width=256 --initial_height=256 --classes=../data/dnn/classification_classes_ILSVRC2012.txt +``` + +Let's explore ``classification.cpp`` key points step by step: + +1. read the model with cv::dnn::readNet, initialize the network: + +```cpp +Net net = readNet(model, config, framework); +``` + +The ``model`` parameter value is taken from ``--model`` key. In our case, it is ``resnet50.onnx``. + +* preprocess input image: + +```cpp +if (rszWidth != 0 && rszHeight != 0) +{ + resize(frame, frame, Size(rszWidth, rszHeight)); +} + +// Create a 4D blob from a frame +blobFromImage(frame, blob, scale, Size(inpWidth, inpHeight), mean, swapRB, crop); + +// Check std values. +if (std.val[0] != 0.0 && std.val[1] != 0.0 && std.val[2] != 0.0) +{ + // Divide blob by std. + divide(blob, std, blob); +} +``` + +In this step we use cv::dnn::blobFromImage function to prepare model input. +We set ``Size(rszWidth, rszHeight)`` with ``--initial_width=256 --initial_height=256`` for the initial image resize as it's described in [PyTorch ResNet inference pipeline](https://pytorch.org/hub/pytorch_vision_resnet/). + +It should be noted that firstly in cv::dnn::blobFromImage mean value is subtracted and only then pixel values are multiplied by scale. +Thus, we use ``--mean="123.675 116.28 103.53"``, which is equivalent to ``[0.485, 0.456, 0.406]`` multiplied by ``255.0`` to reproduce the original image preprocessing order for PyTorch classification models: + +```python +img /= 255.0 +img -= [0.485, 0.456, 0.406] +img /= [0.229, 0.224, 0.225] +``` + +* make forward pass: + +```cpp +net.setInput(blob); +Mat prob = net.forward(); +``` + +* process the prediction: + +```cpp +Point classIdPoint; +double confidence; +minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint); +int classId = classIdPoint.x; +``` + +Here we choose the most likely object class. The ``classId`` result for our case is 335 - fox squirrel, eastern fox squirrel, Sciurus niger: + +![ResNet50 OpenCV C++ inference output](images/opencv_resnet50_test_res_c.jpg) diff --git a/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_tutorial.md b/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_tutorial.md new file mode 100644 index 0000000000..409d2f5a49 --- /dev/null +++ b/doc/tutorials/dnn/dnn_pytorch_tf_classification/pytorch_cls_model_conversion_tutorial.md @@ -0,0 +1,362 @@ +# Conversion of PyTorch Classification Models and Launch with OpenCV Python {#pytorch_cls_tutorial_dnn_conversion} + +@prev_tutorial{tutorial_dnn_OCR} +@next_tutorial{pytorch_cls_c_tutorial_dnn_conversion} + +| | | +| -: | :- | +| Original author | Anastasia Murzova | +| Compatibility | OpenCV >= 4.5 | + +## Goals +In this tutorial you will learn how to: +* convert PyTorch classification models into ONNX format +* run converted PyTorch model with OpenCV Python API +* obtain an evaluation of the PyTorch and OpenCV DNN models. + +We will explore the above-listed points by the example of the ResNet-50 architecture. + +## Introduction +Let's briefly view the key concepts involved in the pipeline of PyTorch models transition with OpenCV API. The initial step in conversion of PyTorch models into cv.dnn.Net +is model transferring into [ONNX](https://onnx.ai/about.html) format. ONNX aims at the interchangeability of the neural networks between various frameworks. There is a built-in function in PyTorch for ONNX conversion: [``torch.onnx.export``](https://pytorch.org/docs/stable/onnx.html#torch.onnx.export). +Further the obtained ``.onnx`` model is passed into cv.dnn.readNetFromONNX. + +## Requirements +To be able to experiment with the below code you will need to install a set of libraries. We will use a virtual environment with python3.7+ for this: + +```console +virtualenv -p /usr/bin/python3.7 +source /bin/activate +``` + +For OpenCV-Python building from source, follow the corresponding instructions from the @ref tutorial_py_table_of_contents_setup. + +Before you start the installation of the libraries, you can customize the [requirements.txt](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt), excluding or including (for example, ``opencv-python``) some dependencies. +The below line initiates requirements installation into the previously activated virtual environment: + +```console +pip install -r requirements.txt +``` + +## Practice +In this part we are going to cover the following points: +1. create a classification model conversion pipeline and provide the inference +2. evaluate and test classification models + +If you'd like merely to run evaluation or test model pipelines, the "Model Conversion Pipeline" part can be skipped. + +### Model Conversion Pipeline +The code in this subchapter is located in the ``dnn_model_runner`` module and can be executed with the line: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_resnet50 +``` + +The following code contains the description of the below-listed steps: +1. instantiate PyTorch model +2. convert PyTorch model into ``.onnx`` +3. read the transferred network with OpenCV API +4. prepare input data +5. provide inference + +```python +# initialize PyTorch ResNet-50 model +original_model = models.resnet50(pretrained=True) + +# get the path to the converted into ONNX PyTorch model +full_model_path = get_pytorch_onnx_model(original_model) + +# read converted .onnx model with OpenCV API +opencv_net = cv2.dnn.readNetFromONNX(full_model_path) +print("OpenCV model was successfully read. Layer IDs: \n", opencv_net.getLayerNames()) + +# get preprocessed image +input_img = get_preprocessed_img("../data/squirrel_cls.jpg") + +# get ImageNet labels +imagenet_labels = get_imagenet_labels("../data/dnn/classification_classes_ILSVRC2012.txt") + +# obtain OpenCV DNN predictions +get_opencv_dnn_prediction(opencv_net, input_img, imagenet_labels) + +# obtain original PyTorch ResNet50 predictions +get_pytorch_dnn_prediction(original_model, input_img, imagenet_labels) +``` + +To provide model inference we will use the below [squirrel photo](https://www.pexels.com/photo/brown-squirrel-eating-1564292) (under [CC0](https://www.pexels.com/terms-of-service/) license) corresponding to ImageNet class ID 335: +```console +fox squirrel, eastern fox squirrel, Sciurus niger +``` + +![Classification model input image](images/squirrel_cls.jpg) + +For the label decoding of the obtained prediction, we also need ``imagenet_classes.txt`` file, which contains the full list of the ImageNet classes. + +Let's go deeper into each step by the example of pretrained PyTorch ResNet-50: +* instantiate PyTorch ResNet-50 model: + +```python +# initialize PyTorch ResNet-50 model +original_model = models.resnet50(pretrained=True) +``` + +* convert PyTorch model into ONNX: + +```python +# define the directory for further converted model save +onnx_model_path = "models" +# define the name of further converted model +onnx_model_name = "resnet50.onnx" + +# create directory for further converted model +os.makedirs(onnx_model_path, exist_ok=True) + +# get full path to the converted model +full_model_path = os.path.join(onnx_model_path, onnx_model_name) + +# generate model input +generated_input = Variable( + torch.randn(1, 3, 224, 224) +) + +# model export into ONNX format +torch.onnx.export( + original_model, + generated_input, + full_model_path, + verbose=True, + input_names=["input"], + output_names=["output"], + opset_version=11 +) +``` + +After the successful execution of the above code, we will get ``models/resnet50.onnx``. + +* read the transferred network with cv.dnn.readNetFromONNX passing the obtained in the previous step ONNX model into it: + +```python +# read converted .onnx model with OpenCV API +opencv_net = cv2.dnn.readNetFromONNX(full_model_path) +``` + +* prepare input data: + +```python +# read the image +input_img = cv2.imread(img_path, cv2.IMREAD_COLOR) +input_img = input_img.astype(np.float32) + +input_img = cv2.resize(input_img, (256, 256)) + +# define preprocess parameters +mean = np.array([0.485, 0.456, 0.406]) * 255.0 +scale = 1 / 255.0 +std = [0.229, 0.224, 0.225] + +# prepare input blob to fit the model input: +# 1. subtract mean +# 2. scale to set pixel values from 0 to 1 +input_blob = cv2.dnn.blobFromImage( + image=input_img, + scalefactor=scale, + size=(224, 224), # img target size + mean=mean, + swapRB=True, # BGR -> RGB + crop=True # center crop +) +# 3. divide by std +input_blob[0] /= np.asarray(std, dtype=np.float32).reshape(3, 1, 1) +``` + +In this step we read the image and prepare model input with cv.dnn.blobFromImage function, which returns 4-dimensional blob. +It should be noted that firstly in cv.dnn.blobFromImage mean value is subtracted and only then pixel values are multiplied by scale. Thus, ``mean`` is multiplied by ``255.0`` to reproduce the original image preprocessing order: + +```python +img /= 255.0 +img -= [0.485, 0.456, 0.406] +img /= [0.229, 0.224, 0.225] +``` + +* OpenCV cv.dnn.Net inference: + +```python +# set OpenCV DNN input +opencv_net.setInput(preproc_img) + +# OpenCV DNN inference +out = opencv_net.forward() +print("OpenCV DNN prediction: \n") +print("* shape: ", out.shape) + +# get the predicted class ID +imagenet_class_id = np.argmax(out) + +# get confidence +confidence = out[0][imagenet_class_id] +print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) +print("* confidence: {:.4f}".format(confidence)) +``` + +After the above code execution we will get the following output: + +```console +OpenCV DNN prediction: +* shape: (1, 1000) +* class ID: 335, label: fox squirrel, eastern fox squirrel, Sciurus niger +* confidence: 14.8308 +``` + +* PyTorch ResNet-50 model inference: + +```python +original_net.eval() +preproc_img = torch.FloatTensor(preproc_img) + +# inference +out = original_net(preproc_img) +print("\nPyTorch model prediction: \n") +print("* shape: ", out.shape) + +# get the predicted class ID +imagenet_class_id = torch.argmax(out, axis=1).item() +print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + +# get confidence +confidence = out[0][imagenet_class_id] +print("* confidence: {:.4f}".format(confidence.item())) +``` + +After the above code launching we will get the following output: + +```console +PyTorch model prediction: +* shape: torch.Size([1, 1000]) +* class ID: 335, label: fox squirrel, eastern fox squirrel, Sciurus niger +* confidence: 14.8308 +``` + +The inference results of the original ResNet-50 model and cv.dnn.Net are equal. For the extended evaluation of the models we can use ``py_to_py_cls`` of the ``dnn_model_runner`` module. This module part will be described in the next subchapter. + +### Evaluation of the Models + +The proposed in ``samples/dnn`` ``dnn_model_runner`` module allows to run the full evaluation pipeline on the ImageNet dataset and test execution for the following PyTorch classification models: +* alexnet +* vgg11 +* vgg13 +* vgg16 +* vgg19 +* resnet18 +* resnet34 +* resnet50 +* resnet101 +* resnet152 +* squeezenet1_0 +* squeezenet1_1 +* resnext50_32x4d +* resnext101_32x8d +* wide_resnet50_2 +* wide_resnet101_2 + +This list can be also extended with further appropriate evaluation pipeline configuration. + +#### Evaluation Mode + +The below line represents running of the module in the evaluation mode: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name +``` + +Chosen from the list classification model will be read into OpenCV cv.dnn.Net object. Evaluation results of PyTorch and OpenCV models (accuracy, inference time, L1) will be written into the log file. Inference time values will be also depicted in a chart to generalize the obtained model information. + +Necessary evaluation configurations are defined in the [test_config.py](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) and can be modified in accordance with actual paths of data location: + +```python +@dataclass +class TestClsConfig: + batch_size: int = 50 + frame_size: int = 224 + img_root_dir: str = "./ILSVRC2012_img_val" + # location of image-class matching + img_cls_file: str = "./val.txt" + bgr_to_rgb: bool = True +``` + +To initiate the evaluation of the PyTorch ResNet-50, run the following line: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name resnet50 +``` + +After script launch, the log file with evaluation data will be generated in ``dnn_model_runner/dnn_conversion/logs``: + +```console +The model PyTorch resnet50 was successfully obtained and converted to OpenCV DNN resnet50 +===== Running evaluation of the model with the following params: + * val data location: ./ILSVRC2012_img_val + * log file location: dnn_model_runner/dnn_conversion/logs/PyTorch_resnet50_log.txt +``` + +#### Test Mode + +The below line represents running of the module in the test mode, namely it provides the steps for the model inference: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name --test True --default_img_preprocess --evaluate False +``` + +Here ``default_img_preprocess`` key defines whether you'd like to parametrize the model test process with some particular values or use the default values, for example, ``scale``, ``mean`` or ``std``. + +Test configuration is represented in [test_config.py](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) ``TestClsModuleConfig`` class: + +```python +@dataclass +class TestClsModuleConfig: + cls_test_data_dir: str = "../data" + test_module_name: str = "classification" + test_module_path: str = "classification.py" + input_img: str = os.path.join(cls_test_data_dir, "squirrel_cls.jpg") + model: str = "" + + frame_height: str = str(TestClsConfig.frame_size) + frame_width: str = str(TestClsConfig.frame_size) + scale: str = "1.0" + mean: List[str] = field(default_factory=lambda: ["0.0", "0.0", "0.0"]) + std: List[str] = field(default_factory=list) + crop: str = "False" + rgb: str = "True" + rsz_height: str = "" + rsz_width: str = "" + classes: str = os.path.join(cls_test_data_dir, "dnn", "classification_classes_ILSVRC2012.txt") +``` + +The default image preprocessing options are defined in [default_preprocess_config.py](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/default_preprocess_config.py). For instance: + +```python +BASE_IMG_SCALE_FACTOR = 1 / 255.0 +PYTORCH_RSZ_HEIGHT = 256 +PYTORCH_RSZ_WIDTH = 256 + +pytorch_resize_input_blob = { + "mean": ["123.675", "116.28", "103.53"], + "scale": str(BASE_IMG_SCALE_FACTOR), + "std": ["0.229", "0.224", "0.225"], + "crop": "True", + "rgb": "True", + "rsz_height": str(PYTORCH_RSZ_HEIGHT), + "rsz_width": str(PYTORCH_RSZ_WIDTH) +} +``` + +The basis of the model testing is represented in [samples/dnn/classification.py](https://github.com/opencv/opencv/blob/master/samples/dnn/classification.py). ``classification.py`` can be executed autonomously with provided converted model in ``--input`` and populated parameters for cv.dnn.blobFromImage. + +To reproduce from scratch the described in "Model Conversion Pipeline" OpenCV steps with ``dnn_model_runner`` execute the below line: + +```console +python -m dnn_model_runner.dnn_conversion.pytorch.classification.py_to_py_cls --model_name resnet50 --test True --default_img_preprocess True --evaluate False +``` + +The network prediction is depicted in the top left corner of the output window: + +![ResNet50 OpenCV inference output](images/pytorch_resnet50_opencv_test_res.jpg) diff --git a/doc/tutorials/dnn/dnn_pytorch_tf_classification/tf_cls_model_conversion_tutorial.md b/doc/tutorials/dnn/dnn_pytorch_tf_classification/tf_cls_model_conversion_tutorial.md new file mode 100644 index 0000000000..c2da541029 --- /dev/null +++ b/doc/tutorials/dnn/dnn_pytorch_tf_classification/tf_cls_model_conversion_tutorial.md @@ -0,0 +1,360 @@ +# Conversion of TensorFlow Classification Models and Launch with OpenCV Python {#tf_cls_tutorial_dnn_conversion} + +| | | +| -: | :- | +| Original author | Anastasia Murzova | +| Compatibility | OpenCV >= 4.5 | + +## Goals +In this tutorial you will learn how to: +* obtain frozen graphs of TensorFlow (TF) classification models +* run converted TensorFlow model with OpenCV Python API +* obtain an evaluation of the TensorFlow and OpenCV DNN models + +We will explore the above-listed points by the example of MobileNet architecture. + +## Introduction +Let's briefly view the key concepts involved in the pipeline of TensorFlow models transition with OpenCV API. The initial step in conversion of TensorFlow models into cv.dnn.Net +is obtaining the frozen TF model graph. Frozen graph defines the combination of the model graph structure with kept values of the required variables, for example, weights. Usually the frozen graph is saved in [protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) (```.pb```) files. +After the model ``.pb`` file was generated it can be read with cv.dnn.readNetFromTensorflow function. + +## Requirements +To be able to experiment with the below code you will need to install a set of libraries. We will use a virtual environment with python3.7+ for this: + +```console +virtualenv -p /usr/bin/python3.7 +source /bin/activate +``` + +For OpenCV-Python building from source, follow the corresponding instructions from the @ref tutorial_py_table_of_contents_setup. + +Before you start the installation of the libraries, you can customize the [requirements.txt](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt), excluding or including (for example, ``opencv-python``) some dependencies. +The below line initiates requirements installation into the previously activated virtual environment: + +```console +pip install -r requirements.txt +``` + +## Practice +In this part we are going to cover the following points: +1. create a TF classification model conversion pipeline and provide the inference +2. evaluate and test TF classification models + +If you'd like merely to run evaluation or test model pipelines, the "Model Conversion Pipeline" tutorial part can be skipped. + +### Model Conversion Pipeline +The code in this subchapter is located in the ``dnn_model_runner`` module and can be executed with the line: + +```console +python -m dnn_model_runner.dnn_conversion.tf.classification.py_to_py_mobilenet +``` + +The following code contains the description of the below-listed steps: +1. instantiate TF model +2. create TF frozen graph +3. read TF frozen graph with OpenCV API +4. prepare input data +5. provide inference + +```python +# initialize TF MobileNet model +original_tf_model = MobileNet( + include_top=True, + weights="imagenet" +) + +# get TF frozen graph path +full_pb_path = get_tf_model_proto(original_tf_model) + +# read frozen graph with OpenCV API +opencv_net = cv2.dnn.readNetFromTensorflow(full_pb_path) +print("OpenCV model was successfully read. Model layers: \n", opencv_net.getLayerNames()) + +# get preprocessed image +input_img = get_preprocessed_img("../data/squirrel_cls.jpg") + +# get ImageNet labels +imagenet_labels = get_imagenet_labels("../data/dnn/classification_classes_ILSVRC2012.txt") + +# obtain OpenCV DNN predictions +get_opencv_dnn_prediction(opencv_net, input_img, imagenet_labels) + +# obtain TF model predictions +get_tf_dnn_prediction(original_tf_model, input_img, imagenet_labels) +``` + +To provide model inference we will use the below [squirrel photo](https://www.pexels.com/photo/brown-squirrel-eating-1564292) (under [CC0](https://www.pexels.com/terms-of-service/) license) corresponding to ImageNet class ID 335: +```console +fox squirrel, eastern fox squirrel, Sciurus niger +``` + +![Classification model input image](images/squirrel_cls.jpg) + +For the label decoding of the obtained prediction, we also need ``imagenet_classes.txt`` file, which contains the full list of the ImageNet classes. + +Let's go deeper into each step by the example of pretrained TF MobileNet: +* instantiate TF model: + +```python +# initialize TF MobileNet model +original_tf_model = MobileNet( + include_top=True, + weights="imagenet" +) +``` + +* create TF frozen graph + +```python +# define the directory for .pb model +pb_model_path = "models" + +# define the name of .pb model +pb_model_name = "mobilenet.pb" + +# create directory for further converted model +os.makedirs(pb_model_path, exist_ok=True) + +# get model TF graph +tf_model_graph = tf.function(lambda x: tf_model(x)) + +# get concrete function +tf_model_graph = tf_model_graph.get_concrete_function( + tf.TensorSpec(tf_model.inputs[0].shape, tf_model.inputs[0].dtype)) + +# obtain frozen concrete function +frozen_tf_func = convert_variables_to_constants_v2(tf_model_graph) +# get frozen graph +frozen_tf_func.graph.as_graph_def() + +# save full tf model +tf.io.write_graph(graph_or_graph_def=frozen_tf_func.graph, + logdir=pb_model_path, + name=pb_model_name, + as_text=False) +``` + +After the successful execution of the above code, we will get a frozen graph in ``models/mobilenet.pb``. + +* read TF frozen graph with with cv.dnn.readNetFromTensorflow passing the obtained in the previous step ``mobilenet.pb`` into it: + +```python +# get TF frozen graph path +full_pb_path = get_tf_model_proto(original_tf_model) +``` + +* prepare input data with cv2.dnn.blobFromImage function: + +```python +# read the image +input_img = cv2.imread(img_path, cv2.IMREAD_COLOR) +input_img = input_img.astype(np.float32) + +# define preprocess parameters +mean = np.array([1.0, 1.0, 1.0]) * 127.5 +scale = 1 / 127.5 + +# prepare input blob to fit the model input: +# 1. subtract mean +# 2. scale to set pixel values from 0 to 1 +input_blob = cv2.dnn.blobFromImage( + image=input_img, + scalefactor=scale, + size=(224, 224), # img target size + mean=mean, + swapRB=True, # BGR -> RGB + crop=True # center crop +) +print("Input blob shape: {}\n".format(input_blob.shape)) +``` + +Please, pay attention at the preprocessing order in the cv2.dnn.blobFromImage function. Firstly, the mean value is subtracted and only then pixel values are multiplied by the defined scale. +Therefore, to reproduce the image preprocessing pipeline from the TF [``mobilenet.preprocess_input``](https://github.com/tensorflow/tensorflow/blob/02032fb477e9417197132648ec81e75beee9063a/tensorflow/python/keras/applications/mobilenet.py#L443-L445) function, we multiply ``mean`` by ``127.5``. + +As a result, 4-dimensional ``input_blob`` was obtained: + + ``Input blob shape: (1, 3, 224, 224)`` + +* provide OpenCV cv.dnn.Net inference: + +```python +# set OpenCV DNN input +opencv_net.setInput(preproc_img) + +# OpenCV DNN inference +out = opencv_net.forward() +print("OpenCV DNN prediction: \n") +print("* shape: ", out.shape) + +# get the predicted class ID +imagenet_class_id = np.argmax(out) + +# get confidence +confidence = out[0][imagenet_class_id] +print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) +print("* confidence: {:.4f}\n".format(confidence)) +``` + +After the above code execution we will get the following output: + +```console +OpenCV DNN prediction: +* shape: (1, 1000) +* class ID: 335, label: fox squirrel, eastern fox squirrel, Sciurus niger +* confidence: 0.9525 +``` + +* provide TF MobileNet inference: + +```python +# inference +preproc_img = preproc_img.transpose(0, 2, 3, 1) +print("TF input blob shape: {}\n".format(preproc_img.shape)) + +out = original_net(preproc_img) + +print("\nTensorFlow model prediction: \n") +print("* shape: ", out.shape) + +# get the predicted class ID +imagenet_class_id = np.argmax(out) +print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + +# get confidence +confidence = out[0][imagenet_class_id] +print("* confidence: {:.4f}".format(confidence)) +``` + +To fit TF model input, ``input_blob`` was transposed: + +```console +TF input blob shape: (1, 224, 224, 3) +``` + +TF inference results are the following: + +```console +TensorFlow model prediction: +* shape: (1, 1000) +* class ID: 335, label: fox squirrel, eastern fox squirrel, Sciurus niger +* confidence: 0.9525 +``` + +As it can be seen from the experiments OpenCV and TF inference results are equal. + +### Evaluation of the Models + +The proposed in ``dnn/samples`` ``dnn_model_runner`` module allows to run the full evaluation pipeline on the ImageNet dataset and test execution for the following TensorFlow classification models: +* vgg16 +* vgg19 +* resnet50 +* resnet101 +* resnet152 +* densenet121 +* densenet169 +* densenet201 +* inceptionresnetv2 +* inceptionv3 +* mobilenet +* mobilenetv2 +* nasnetlarge +* nasnetmobile +* xception + +This list can be also extended with further appropriate evaluation pipeline configuration. + +#### Evaluation Mode + +To below line represents running of the module in the evaluation mode: + +```console +python -m dnn_model_runner.dnn_conversion.tf.classification.py_to_py_cls --model_name +``` + +Chosen from the list classification model will be read into OpenCV ``cv.dnn_Net`` object. Evaluation results of TF and OpenCV models (accuracy, inference time, L1) will be written into the log file. Inference time values will be also depicted in a chart to generalize the obtained model information. + +Necessary evaluation configurations are defined in the [test_config.py](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) and can be modified in accordance with actual paths of data location:: + +```python +@dataclass +class TestClsConfig: + batch_size: int = 50 + frame_size: int = 224 + img_root_dir: str = "./ILSVRC2012_img_val" + # location of image-class matching + img_cls_file: str = "./val.txt" + bgr_to_rgb: bool = True +``` + +The values from ``TestClsConfig`` can be customized in accordance with chosen model. + +To initiate the evaluation of the TensorFlow MobileNet, run the following line: + +```console +python -m dnn_model_runner.dnn_conversion.tf.classification.py_to_py_cls --model_name mobilenet +``` + +After script launch, the log file with evaluation data will be generated in ``dnn_model_runner/dnn_conversion/logs``: + +```console +===== Running evaluation of the model with the following params: + * val data location: ./ILSVRC2012_img_val + * log file location: dnn_model_runner/dnn_conversion/logs/TF_mobilenet_log.txt +``` + +#### Test Mode + +The below line represents running of the module in the test mode, namely it provides the steps for the model inference: + +```console +python -m dnn_model_runner.dnn_conversion.tf.classification.py_to_py_cls --model_name --test True --default_img_preprocess --evaluate False +``` + +Here ``default_img_preprocess`` key defines whether you'd like to parametrize the model test process with some particular values or use the default values, for example, ``scale``, ``mean`` or ``std``. + +Test configuration is represented in [test_config.py](https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py) ``TestClsModuleConfig`` class: + +```python +@dataclass +class TestClsModuleConfig: + cls_test_data_dir: str = "../data" + test_module_name: str = "classification" + test_module_path: str = "classification.py" + input_img: str = os.path.join(cls_test_data_dir, "squirrel_cls.jpg") + model: str = "" + + frame_height: str = str(TestClsConfig.frame_size) + frame_width: str = str(TestClsConfig.frame_size) + scale: str = "1.0" + mean: List[str] = field(default_factory=lambda: ["0.0", "0.0", "0.0"]) + std: List[str] = field(default_factory=list) + crop: str = "False" + rgb: str = "True" + rsz_height: str = "" + rsz_width: str = "" + classes: str = os.path.join(cls_test_data_dir, "dnn", "classification_classes_ILSVRC2012.txt") +``` + +The default image preprocessing options are defined in ``default_preprocess_config.py``. For instance, for MobileNet: + +```python +tf_input_blob = { + "mean": ["127.5", "127.5", "127.5"], + "scale": str(1 / 127.5), + "std": [], + "crop": "True", + "rgb": "True" +} +``` + +The basis of the model testing is represented in [samples/dnn/classification.py](https://github.com/opencv/opencv/blob/master/samples/dnn/classification.py). ``classification.py`` can be executed autonomously with provided converted model in ``--input`` and populated parameters for cv.dnn.blobFromImage. + +To reproduce from scratch the described in "Model Conversion Pipeline" OpenCV steps with ``dnn_model_runner`` execute the below line: + +```console +python -m dnn_model_runner.dnn_conversion.tf.classification.py_to_py_cls --model_name mobilenet --test True --default_img_preprocess True --evaluate False +``` + +The network prediction is depicted in the top left corner of the output window: + +![TF MobileNet OpenCV inference output](images/tf_mobilenet_opencv_test_res.jpg) diff --git a/doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown b/doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown index 603ae9adec..5f28b6ce7a 100644 --- a/doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown +++ b/doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown @@ -3,6 +3,7 @@ @tableofcontents @prev_tutorial{tutorial_dnn_OCR} +@next_tutorial{pytorch_cls_tutorial_dnn_conversion} | | | | -: | :- | diff --git a/doc/tutorials/dnn/table_of_content_dnn.markdown b/doc/tutorials/dnn/table_of_content_dnn.markdown index dd3e596827..a74554ffb8 100644 --- a/doc/tutorials/dnn/table_of_content_dnn.markdown +++ b/doc/tutorials/dnn/table_of_content_dnn.markdown @@ -10,3 +10,12 @@ Deep Neural Networks (dnn module) {#tutorial_table_of_content_dnn} - @subpage tutorial_dnn_custom_layers - @subpage tutorial_dnn_OCR - @subpage tutorial_dnn_text_spotting + +#### PyTorch models with OpenCV +In this section you will find the guides, which describe how to run classification, segmentation and detection PyTorch DNN models with OpenCV. +- @subpage pytorch_cls_tutorial_dnn_conversion +- @subpage pytorch_cls_c_tutorial_dnn_conversion + +#### TensorFlow models with OpenCV +In this section you will find the guides, which describe how to run classification, segmentation and detection TensorFlow DNN models with OpenCV. +- @subpage tf_cls_tutorial_dnn_conversion diff --git a/samples/data/squirrel_cls.jpg b/samples/data/squirrel_cls.jpg new file mode 100644 index 0000000000000000000000000000000000000000..289b13bbd35a2a0b44626ed938d7ab943b102f0f GIT binary patch literal 62311 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"initial_width"); + int rszHeight = parser.get("initial_height"); float scale = parser.get("scale"); Scalar mean = parser.get("mean"); + Scalar std = parser.get("std"); bool swapRB = parser.get("rgb"); + bool crop = parser.get("crop"); int inpWidth = parser.get("width"); int inpHeight = parser.get("height"); String model = findFile(parser.get("model")); @@ -108,8 +116,20 @@ int main(int argc, char** argv) break; } + if (rszWidth != 0 && rszHeight != 0) + { + resize(frame, frame, Size(rszWidth, rszHeight)); + } + //! [Create a 4D blob from a frame] - blobFromImage(frame, blob, scale, Size(inpWidth, inpHeight), mean, swapRB, false); + blobFromImage(frame, blob, scale, Size(inpWidth, inpHeight), mean, swapRB, crop); + + // Check std values. + if (std.val[0] != 0.0 && std.val[1] != 0.0 && std.val[2] != 0.0) + { + // Divide blob by std. + divide(blob, std, blob); + } //! [Create a 4D blob from a frame] //! [Set input blob] diff --git a/samples/dnn/classification.py b/samples/dnn/classification.py index 1c6908a2bc..558c8b0bdc 100644 --- a/samples/dnn/classification.py +++ b/samples/dnn/classification.py @@ -1,85 +1,112 @@ -import cv2 as cv import argparse -import numpy as np +import cv2 as cv +import numpy as np from common import * -backends = (cv.dnn.DNN_BACKEND_DEFAULT, cv.dnn.DNN_BACKEND_HALIDE, cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_BACKEND_OPENCV) -targets = (cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_OPENCL, cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD, cv.dnn.DNN_TARGET_HDDL) - -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'], - help='Optional name of an origin framework of the model. ' - 'Detect it automatically if it does not set.') -parser.add_argument('--backend', choices=backends, default=cv.dnn.DNN_BACKEND_DEFAULT, type=int, - help="Choose one of computation backends: " - "%d: automatically (by default), " - "%d: Halide language (http://halide-lang.org/), " - "%d: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), " - "%d: OpenCV implementation" % backends) -parser.add_argument('--target', choices=targets, default=cv.dnn.DNN_TARGET_CPU, type=int, - help='Choose one of target computation devices: ' - '%d: CPU target (by default), ' - '%d: OpenCL, ' - '%d: OpenCL fp16 (half-float precision), ' - '%d: NCS2 VPU, ' - '%d: HDDL VPU' % targets) -args, _ = parser.parse_known_args() -add_preproc_args(args.zoo, parser, 'classification') -parser = argparse.ArgumentParser(parents=[parser], - description='Use this script to run classification deep learning networks using OpenCV.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -args = parser.parse_args() - -args.model = findFile(args.model) -args.config = findFile(args.config) -args.classes = findFile(args.classes) - -# Load names of classes -classes = None -if args.classes: - with open(args.classes, 'rt') as f: - classes = f.read().rstrip('\n').split('\n') - -# Load a network -net = cv.dnn.readNet(args.model, args.config, args.framework) -net.setPreferableBackend(args.backend) -net.setPreferableTarget(args.target) - -winName = 'Deep learning image classification in OpenCV' -cv.namedWindow(winName, cv.WINDOW_NORMAL) - -cap = cv.VideoCapture(args.input if args.input else 0) -while cv.waitKey(1) < 0: - hasFrame, frame = cap.read() - if not hasFrame: - cv.waitKey() - break - - # Create a 4D blob from a frame. - inpWidth = args.width if args.width else frame.shape[1] - inpHeight = args.height if args.height else frame.shape[0] - blob = cv.dnn.blobFromImage(frame, args.scale, (inpWidth, inpHeight), args.mean, args.rgb, crop=False) - - # Run a model - net.setInput(blob) - out = net.forward() - - # Get a class with a highest score. - out = out.flatten() - classId = np.argmax(out) - confidence = out[classId] - - # Put efficiency information. - t, _ = net.getPerfProfile() - label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency()) - cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0)) - - # Print predicted class. - label = '%s: %.4f' % (classes[classId] if classes else 'Class #%d' % classId, confidence) - cv.putText(frame, label, (0, 40), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0)) - - cv.imshow(winName, frame) + +def get_args_parser(func_args): + backends = (cv.dnn.DNN_BACKEND_DEFAULT, cv.dnn.DNN_BACKEND_HALIDE, cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, + cv.dnn.DNN_BACKEND_OPENCV) + targets = (cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_OPENCL, cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD, + cv.dnn.DNN_TARGET_HDDL) + + 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'], + 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, + help='Preprocess input image by dividing on a standard deviation.') + parser.add_argument('--crop', type=bool, default=False, + help='Preprocess input image by dividing on a standard deviation.') + parser.add_argument('--initial_width', type=int, + help='Preprocess input image by initial resizing to a specific width.') + parser.add_argument('--initial_height', type=int, + help='Preprocess input image by initial resizing to a specific height.') + parser.add_argument('--backend', choices=backends, default=cv.dnn.DNN_BACKEND_DEFAULT, type=int, + help="Choose one of computation backends: " + "%d: automatically (by default), " + "%d: Halide language (http://halide-lang.org/), " + "%d: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), " + "%d: OpenCV implementation" % backends) + parser.add_argument('--target', choices=targets, default=cv.dnn.DNN_TARGET_CPU, type=int, + help='Choose one of target computation devices: ' + '%d: CPU target (by default), ' + '%d: OpenCL, ' + '%d: OpenCL fp16 (half-float precision), ' + '%d: NCS2 VPU, ' + '%d: HDDL VPU' % targets) + + args, _ = parser.parse_known_args() + add_preproc_args(args.zoo, parser, 'classification') + parser = argparse.ArgumentParser(parents=[parser], + description='Use this script to run classification deep learning networks using OpenCV.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + return parser.parse_args(func_args) + + +def main(func_args=None): + args = get_args_parser(func_args) + args.model = findFile(args.model) + args.config = findFile(args.config) + args.classes = findFile(args.classes) + + # Load names of classes + classes = None + if args.classes: + with open(args.classes, 'rt') as f: + classes = f.read().rstrip('\n').split('\n') + + # Load a network + net = cv.dnn.readNet(args.model, args.config, args.framework) + net.setPreferableBackend(args.backend) + net.setPreferableTarget(args.target) + + winName = 'Deep learning image classification in OpenCV' + cv.namedWindow(winName, cv.WINDOW_NORMAL) + + cap = cv.VideoCapture(args.input if args.input else 0) + while cv.waitKey(1) < 0: + hasFrame, frame = cap.read() + if not hasFrame: + cv.waitKey() + break + + # Create a 4D blob from a frame. + inpWidth = args.width if args.width else frame.shape[1] + inpHeight = args.height if args.height else frame.shape[0] + + if args.initial_width and args.initial_height: + frame = cv.resize(frame, (args.initial_width, args.initial_height)) + + blob = cv.dnn.blobFromImage(frame, args.scale, (inpWidth, inpHeight), args.mean, args.rgb, crop=args.crop) + if args.std: + blob[0] /= np.asarray(args.std, dtype=np.float32).reshape(3, 1, 1) + + # Run a model + net.setInput(blob) + out = net.forward() + + # Get a class with a highest score. + out = out.flatten() + classId = np.argmax(out) + confidence = out[classId] + + # Put efficiency information. + t, _ = net.getPerfProfile() + label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency()) + cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0)) + + # Print predicted class. + label = '%s: %.4f' % (classes[classId] if classes else 'Class #%d' % classId, confidence) + cv.putText(frame, label, (0, 40), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0)) + + cv.imshow(winName, frame) + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/abstract_model.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/abstract_model.py new file mode 100644 index 0000000000..c968c53dc2 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/abstract_model.py @@ -0,0 +1,23 @@ +from abc import ABC, ABCMeta, abstractmethod + + +class AbstractModel(ABC): + + @abstractmethod + def get_prepared_models(self): + pass + + +class Framework(object): + in_blob_name = '' + out_blob_name = '' + + __metaclass__ = ABCMeta + + @abstractmethod + def get_name(self): + pass + + @abstractmethod + def get_output(self, input_blob): + pass diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_accuracy_evaluator.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_accuracy_evaluator.py new file mode 100644 index 0000000000..5028f9248d --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_accuracy_evaluator.py @@ -0,0 +1,96 @@ +import sys +import time + +import numpy as np + +from ...utils import get_final_summary_info + + +class ClsAccEvaluation: + log = sys.stdout + img_classes = {} + batch_size = 0 + + def __init__(self, log_path, img_classes_file, batch_size): + self.log = open(log_path, 'w') + self.img_classes = self.read_classes(img_classes_file) + self.batch_size = batch_size + + # collect the accuracies for both models + self.general_quality_metric = [] + self.general_inference_time = [] + + @staticmethod + def read_classes(img_classes_file): + result = {} + with open(img_classes_file) as file: + for l in file.readlines(): + result[l.split()[0]] = int(l.split()[1]) + return result + + def get_correct_answers(self, img_list, net_output_blob): + correct_answers = 0 + for i in range(len(img_list)): + indexes = np.argsort(net_output_blob[i])[-5:] + correct_index = self.img_classes[img_list[i]] + if correct_index in indexes: + correct_answers += 1 + return correct_answers + + def process(self, frameworks, data_fetcher): + sorted_imgs_names = sorted(self.img_classes.keys()) + correct_answers = [0] * len(frameworks) + samples_handled = 0 + blobs_l1_diff = [0] * len(frameworks) + blobs_l1_diff_count = [0] * len(frameworks) + blobs_l_inf_diff = [sys.float_info.min] * len(frameworks) + inference_time = [0.0] * len(frameworks) + + for x in range(0, len(sorted_imgs_names), self.batch_size): + sublist = sorted_imgs_names[x:x + self.batch_size] + batch = data_fetcher.get_batch(sublist) + + samples_handled += len(sublist) + fw_accuracy = [] + fw_time = [] + frameworks_out = [] + for i in range(len(frameworks)): + start = time.time() + out = frameworks[i].get_output(batch) + end = time.time() + correct_answers[i] += self.get_correct_answers(sublist, out) + fw_accuracy.append(100 * correct_answers[i] / float(samples_handled)) + frameworks_out.append(out) + inference_time[i] += end - start + fw_time.append(inference_time[i] / samples_handled * 1000) + print(samples_handled, 'Accuracy for', frameworks[i].get_name() + ':', fw_accuracy[i], file=self.log) + print("Inference time, ms ", frameworks[i].get_name(), fw_time[i], file=self.log) + + self.general_quality_metric.append(fw_accuracy) + self.general_inference_time.append(fw_time) + + for i in range(1, len(frameworks)): + log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':' + diff = np.abs(frameworks_out[0] - frameworks_out[i]) + l1_diff = np.sum(diff) / diff.size + print(samples_handled, "L1 difference", log_str, l1_diff, file=self.log) + blobs_l1_diff[i] += l1_diff + blobs_l1_diff_count[i] += 1 + if np.max(diff) > blobs_l_inf_diff[i]: + blobs_l_inf_diff[i] = np.max(diff) + print(samples_handled, "L_INF difference", log_str, blobs_l_inf_diff[i], file=self.log) + + self.log.flush() + + for i in range(1, len(blobs_l1_diff)): + log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':' + print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log) + + print( + get_final_summary_info( + self.general_quality_metric, + self.general_inference_time, + "accuracy" + ), + file=self.log + ) diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_data_fetcher.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_data_fetcher.py new file mode 100644 index 0000000000..805f540669 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/evaluation/classification/cls_data_fetcher.py @@ -0,0 +1,87 @@ +import os +from abc import ABCMeta, abstractmethod + +import cv2 +import numpy as np + +from ...img_utils import read_rgb_img, get_pytorch_preprocess +from ...test.configs.default_preprocess_config import PYTORCH_RSZ_HEIGHT, PYTORCH_RSZ_WIDTH + + +class DataFetch(object): + imgs_dir = '' + frame_size = 0 + bgr_to_rgb = False + + __metaclass__ = ABCMeta + + @abstractmethod + def preprocess(self, img): + pass + + @staticmethod + def reshape_img(img): + img = img[:, :, 0:3].transpose(2, 0, 1) + return np.expand_dims(img, 0) + + def center_crop(self, img): + cols = img.shape[1] + rows = img.shape[0] + + y1 = round((rows - self.frame_size) / 2) + y2 = round(y1 + self.frame_size) + x1 = round((cols - self.frame_size) / 2) + x2 = round(x1 + self.frame_size) + return img[y1:y2, x1:x2] + + def initial_preprocess(self, img): + min_dim = min(img.shape[-3], img.shape[-2]) + resize_ratio = self.frame_size / float(min_dim) + + img = cv2.resize(img, (0, 0), fx=resize_ratio, fy=resize_ratio) + img = self.center_crop(img) + return img + + def get_preprocessed_img(self, img_path): + image_data = read_rgb_img(img_path, self.bgr_to_rgb) + image_data = self.preprocess(image_data) + return self.reshape_img(image_data) + + def get_batch(self, img_names): + assert type(img_names) is list + batch = np.zeros((len(img_names), 3, self.frame_size, self.frame_size)).astype(np.float32) + + for i in range(len(img_names)): + img_name = img_names[i] + img_file = os.path.join(self.imgs_dir, img_name) + assert os.path.exists(img_file) + + batch[i] = self.get_preprocessed_img(img_file) + return batch + + +class PyTorchPreprocessedFetch(DataFetch): + def __init__(self, pytorch_cls_config, preprocess_input=None): + self.imgs_dir = pytorch_cls_config.img_root_dir + self.frame_size = pytorch_cls_config.frame_size + self.bgr_to_rgb = pytorch_cls_config.bgr_to_rgb + self.preprocess_input = preprocess_input + + def preprocess(self, img): + img = cv2.resize(img, (PYTORCH_RSZ_WIDTH, PYTORCH_RSZ_HEIGHT)) + img = self.center_crop(img) + if self.preprocess_input: + return self.presprocess_input(img) + return get_pytorch_preprocess(img) + + +class TFPreprocessedFetch(DataFetch): + def __init__(self, tf_cls_config, preprocess_input): + self.imgs_dir = tf_cls_config.img_root_dir + self.frame_size = tf_cls_config.frame_size + self.bgr_to_rgb = tf_cls_config.bgr_to_rgb + self.preprocess_input = preprocess_input + + def preprocess(self, img): + img = self.initial_preprocess(img) + return self.preprocess_input(img) diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/img_utils.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/img_utils.py new file mode 100644 index 0000000000..3e17ec8755 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/img_utils.py @@ -0,0 +1,19 @@ +import cv2 +import numpy as np + +from .test.configs.default_preprocess_config import BASE_IMG_SCALE_FACTOR + + +def read_rgb_img(img_file, is_bgr_to_rgb=True): + img = cv2.imread(img_file, cv2.IMREAD_COLOR) + if is_bgr_to_rgb: + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + return img + + +def get_pytorch_preprocess(img): + img = img.astype(np.float32) + img *= BASE_IMG_SCALE_FACTOR + img -= [0.485, 0.456, 0.406] + img /= [0.229, 0.224, 0.225] + return img diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/test/cls_model_test_pipeline.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/cls_model_test_pipeline.py new file mode 100644 index 0000000000..757d5130b5 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/cls_model_test_pipeline.py @@ -0,0 +1,60 @@ +from .configs.test_config import TestClsConfig, TestClsModuleConfig +from .model_test_pipeline import ModelTestPipeline +from ..evaluation.classification.cls_accuracy_evaluator import ClsAccEvaluation +from ..utils import get_test_module + + +class ClsModelTestPipeline(ModelTestPipeline): + def __init__( + self, + network_model, + model_processor, + dnn_model_processor, + data_fetcher, + img_processor=None, + cls_args_parser=None, + default_input_blob_preproc=None + ): + super(ClsModelTestPipeline, self).__init__( + network_model, + model_processor, + dnn_model_processor + ) + + if cls_args_parser: + self._parser = cls_args_parser + + self.test_config = TestClsConfig() + + parser_args = self._parser.parse_args() + + if parser_args.test: + self._test_module_config = TestClsModuleConfig() + self._test_module = get_test_module( + self._test_module_config.test_module_name, + self._test_module_config.test_module_path + ) + + if parser_args.default_img_preprocess: + self._default_input_blob_preproc = default_input_blob_preproc + if parser_args.evaluate: + self._data_fetcher = data_fetcher(self.test_config, img_processor) + + def _configure_test_module_params(self): + self._test_module_param_list.extend(( + '--crop', self._test_module_config.crop, + '--std', *self._test_module_config.std + )) + + if self._test_module_config.rsz_height and self._test_module_config.rsz_width: + self._test_module_param_list.extend(( + '--initial_height', self._test_module_config.rsz_height, + '--initial_width', self._test_module_config.rsz_width, + )) + + def _configure_acc_eval(self, log_path): + self._accuracy_evaluator = ClsAccEvaluation( + log_path, + self.test_config.img_cls_file, + self.test_config.batch_size + ) diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/default_preprocess_config.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/default_preprocess_config.py new file mode 100644 index 0000000000..e7ade9158d --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/default_preprocess_config.py @@ -0,0 +1,37 @@ +BASE_IMG_SCALE_FACTOR = 1 / 255.0 +PYTORCH_RSZ_HEIGHT = 256 +PYTORCH_RSZ_WIDTH = 256 + +pytorch_resize_input_blob = { + "mean": ["123.675", "116.28", "103.53"], + "scale": str(BASE_IMG_SCALE_FACTOR), + "std": ["0.229", "0.224", "0.225"], + "crop": "True", + "rgb": True, + "rsz_height": str(PYTORCH_RSZ_HEIGHT), + "rsz_width": str(PYTORCH_RSZ_WIDTH) +} + +pytorch_input_blob = { + "mean": ["123.675", "116.28", "103.53"], + "scale": str(BASE_IMG_SCALE_FACTOR), + "std": ["0.229", "0.224", "0.225"], + "crop": "True", + "rgb": True +} + +tf_input_blob = { + "scale": str(1 / 127.5), + "mean": ["127.5", "127.5", "127.5"], + "std": [], + "crop": "True", + "rgb": True +} + +tf_model_blob_caffe_mode = { + "mean": ["103.939", "116.779", "123.68"], + "scale": "1.0", + "std": [], + "crop": "True", + "rgb": False +} diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py new file mode 100644 index 0000000000..55680918e6 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/configs/test_config.py @@ -0,0 +1,40 @@ +import os +from dataclasses import dataclass, field +from typing import List + + +@dataclass +class CommonConfig: + output_data_root_dir: str = "dnn_model_runner/dnn_conversion" + logs_dir: str = os.path.join(output_data_root_dir, "logs") + log_file_path: str = os.path.join(logs_dir, "{}_log.txt") + + +@dataclass +class TestClsConfig: + batch_size: int = 1 + frame_size: int = 224 + img_root_dir: str = "./ILSVRC2012_img_val" + # location of image-class matching + img_cls_file: str = "./val.txt" + bgr_to_rgb: bool = True + + +@dataclass +class TestClsModuleConfig: + cls_test_data_dir: str = "../data" + test_module_name: str = "classification" + test_module_path: str = "classification.py" + input_img: str = os.path.join(cls_test_data_dir, "squirrel_cls.jpg") + model: str = "" + + frame_height: str = str(TestClsConfig.frame_size) + frame_width: str = str(TestClsConfig.frame_size) + scale: str = "1.0" + mean: List[str] = field(default_factory=lambda: ["0.0", "0.0", "0.0"]) + std: List[str] = field(default_factory=list) + crop: str = "False" + rgb: str = "True" + rsz_height: str = "" + rsz_width: str = "" + classes: str = os.path.join(cls_test_data_dir, "dnn", "classification_classes_ILSVRC2012.txt") diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/test/model_test_pipeline.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/model_test_pipeline.py new file mode 100644 index 0000000000..38b9c38e60 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/test/model_test_pipeline.py @@ -0,0 +1,126 @@ +import os + +import numpy as np + +from .configs.test_config import CommonConfig +from ..utils import create_parser, plot_acc + + +class ModelTestPipeline: + def __init__( + self, + network_model, + model_processor, + dnn_model_processor + ): + self._net_model = network_model + self._model_processor = model_processor + self._dnn_model_processor = dnn_model_processor + + self._parser = create_parser() + + self._test_module = None + self._test_module_config = None + self._test_module_param_list = None + + self.test_config = None + self._data_fetcher = None + + self._default_input_blob_preproc = None + self._accuracy_evaluator = None + + def init_test_pipeline(self): + cmd_args = self._parser.parse_args() + model_dict = self._net_model.get_prepared_models() + + model_names = list(model_dict.keys()) + print( + "The model {} was successfully obtained and converted to OpenCV {}".format(model_names[0], model_names[1]) + ) + + if cmd_args.test: + if not self._test_module_config.model: + self._test_module_config.model = self._net_model.model_path["full_path"] + + if cmd_args.default_img_preprocess: + self._test_module_config.scale = self._default_input_blob_preproc["scale"] + self._test_module_config.mean = self._default_input_blob_preproc["mean"] + self._test_module_config.std = self._default_input_blob_preproc["std"] + self._test_module_config.crop = self._default_input_blob_preproc["crop"] + + if "rsz_height" in self._default_input_blob_preproc and "rsz_width" in self._default_input_blob_preproc: + self._test_module_config.rsz_height = self._default_input_blob_preproc["rsz_height"] + self._test_module_config.rsz_width = self._default_input_blob_preproc["rsz_width"] + + self._test_module_param_list = [ + '--model', self._test_module_config.model, + '--input', self._test_module_config.input_img, + '--width', self._test_module_config.frame_width, + '--height', self._test_module_config.frame_height, + '--scale', self._test_module_config.scale, + '--mean', *self._test_module_config.mean, + '--std', *self._test_module_config.std, + '--classes', self._test_module_config.classes, + ] + + if self._default_input_blob_preproc["rgb"]: + self._test_module_param_list.append('--rgb') + + self._configure_test_module_params() + + self._test_module.main( + self._test_module_param_list + ) + + if cmd_args.evaluate: + original_model_name = model_names[0] + dnn_model_name = model_names[1] + + self.run_test_pipeline( + [ + self._model_processor(model_dict[original_model_name], original_model_name), + self._dnn_model_processor(model_dict[dnn_model_name], dnn_model_name) + ], + original_model_name.replace(" ", "_") + ) + + def run_test_pipeline( + self, + models_list, + formatted_exp_name, + is_plot_acc=True + ): + log_path, logs_dir = self._configure_eval_log(formatted_exp_name) + + print( + "===== Running evaluation of the model with the following params:\n" + "\t* val data location: {}\n" + "\t* log file location: {}\n".format( + self.test_config.img_root_dir, + log_path + ) + ) + + os.makedirs(logs_dir, exist_ok=True) + + self._configure_acc_eval(log_path) + self._accuracy_evaluator.process(models_list, self._data_fetcher) + + if is_plot_acc: + plot_acc( + np.array(self._accuracy_evaluator.general_inference_time), + formatted_exp_name + ) + + print("===== End of the evaluation pipeline =====") + + def _configure_acc_eval(self, log_path): + pass + + def _configure_test_module_params(self): + pass + + @staticmethod + def _configure_eval_log(formatted_exp_name): + common_test_config = CommonConfig() + return common_test_config.log_file_path.format(formatted_exp_name), common_test_config.logs_dir diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/common/utils.py b/samples/dnn/dnn_model_runner/dnn_conversion/common/utils.py new file mode 100644 index 0000000000..cf24dd385b --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/common/utils.py @@ -0,0 +1,153 @@ +import argparse +import importlib.util +import os +import random + +import matplotlib.pyplot as plt +import numpy as np +import tensorflow as tf +import torch + +from .test.configs.test_config import CommonConfig + +SEED_VAL = 42 +DNN_LIB = "DNN" +# common path for model savings +MODEL_PATH_ROOT = os.path.join(CommonConfig().output_data_root_dir, "{}/models") + + +def get_full_model_path(lib_name, model_full_name): + model_path = MODEL_PATH_ROOT.format(lib_name) + return { + "path": model_path, + "full_path": os.path.join(model_path, model_full_name) + } + + +def plot_acc(data_list, experiment_name): + plt.figure(figsize=[8, 6]) + plt.plot(data_list[:, 0], "r", linewidth=2.5, label="Original Model") + plt.plot(data_list[:, 1], "b", linewidth=2.5, label="Converted DNN Model") + plt.xlabel("Iterations ", fontsize=15) + plt.ylabel("Time (ms)", fontsize=15) + plt.title(experiment_name, fontsize=15) + plt.legend() + full_path_to_fig = os.path.join(CommonConfig().output_data_root_dir, experiment_name + ".png") + plt.savefig(full_path_to_fig, bbox_inches="tight") + + +def get_final_summary_info(general_quality_metric, general_inference_time, metric_name): + general_quality_metric = np.array(general_quality_metric) + general_inference_time = np.array(general_inference_time) + summary_line = "===== End of processing. General results:\n" + "\t* mean {} for the original model: {}\t" + "\t* mean time (min) for the original model inferences: {}\n" + "\t* mean {} for the DNN model: {}\t" + "\t* mean time (min) for the DNN model inferences: {}\n".format( + metric_name, np.mean(general_quality_metric[:, 0]), + np.mean(general_inference_time[:, 0]) / 60000, + metric_name, np.mean(general_quality_metric[:, 1]), + np.mean(general_inference_time[:, 1]) / 60000, + ) + return summary_line + + +def set_common_reproducibility(): + random.seed(SEED_VAL) + np.random.seed(SEED_VAL) + + +def set_pytorch_env(): + set_common_reproducibility() + torch.manual_seed(SEED_VAL) + torch.set_printoptions(precision=10) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(SEED_VAL) + torch.backends.cudnn_benchmark_enabled = False + torch.backends.cudnn.deterministic = True + + +def set_tf_env(is_use_gpu=True): + set_common_reproducibility() + tf.random.set_seed(SEED_VAL) + os.environ["TF_DETERMINISTIC_OPS"] = "1" + + if tf.config.list_physical_devices("GPU") and is_use_gpu: + gpu_devices = tf.config.list_physical_devices("GPU") + tf.config.experimental.set_visible_devices(gpu_devices[0], "GPU") + tf.config.experimental.set_memory_growth(gpu_devices[0], True) + os.environ["TF_USE_CUDNN"] = "1" + else: + os.environ["CUDA_VISIBLE_DEVICES"] = "-1" + + +def str_bool(input_val): + if input_val.lower() in ('yes', 'true', 't', 'y', '1'): + return True + elif input_val.lower() in ('no', 'false', 'f', 'n', '0'): + return False + else: + raise argparse.ArgumentTypeError('Boolean value was expected') + + +def get_formatted_model_list(model_list): + note_line = 'Please, choose the model from the below list:\n' + spaces_to_set = ' ' * (len(note_line) - 2) + return note_line + ''.join([spaces_to_set, '{} \n'] * len(model_list)).format(*model_list) + + +def model_str(model_list): + def type_model_list(input_val): + if input_val.lower() in model_list: + return input_val.lower() + else: + raise argparse.ArgumentTypeError( + 'The model is currently unavailable for test.\n' + + get_formatted_model_list(model_list) + ) + + return type_model_list + + +def get_test_module(test_module_name, test_module_path): + module_spec = importlib.util.spec_from_file_location(test_module_name, test_module_path) + test_module = importlib.util.module_from_spec(module_spec) + module_spec.loader.exec_module(test_module) + module_spec.loader.exec_module(test_module) + return test_module + + +def create_parser(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument( + "--test", + type=str_bool, + help="Define whether you'd like to run the model with OpenCV for testing.", + default=False + ), + parser.add_argument( + "--default_img_preprocess", + type=str_bool, + help="Define whether you'd like to preprocess the input image with defined" + " PyTorch or TF functions for model test with OpenCV.", + default=False + ), + parser.add_argument( + "--evaluate", + type=str_bool, + help="Define whether you'd like to run evaluation of the models (ex.: TF vs OpenCV networks).", + default=True + ) + return parser + + +def create_extended_parser(model_list): + parser = create_parser() + parser.add_argument( + "--model_name", + type=model_str(model_list=model_list), + help="\nDefine the model name to test.\n" + + get_formatted_model_list(model_list), + required=True + ) + return parser diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_cls.py b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_cls.py new file mode 100644 index 0000000000..abbd7389f8 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_cls.py @@ -0,0 +1,71 @@ +from torchvision import models + +from ..pytorch_model import ( + PyTorchModelPreparer, + PyTorchModelProcessor, + PyTorchDnnModelProcessor +) +from ...common.evaluation.classification.cls_data_fetcher import PyTorchPreprocessedFetch +from ...common.test.cls_model_test_pipeline import ClsModelTestPipeline +from ...common.test.configs.default_preprocess_config import pytorch_resize_input_blob +from ...common.test.configs.test_config import TestClsConfig +from ...common.utils import set_pytorch_env, create_extended_parser + +model_dict = { + "alexnet": models.alexnet, + + "vgg11": models.vgg11, + "vgg13": models.vgg13, + "vgg16": models.vgg16, + "vgg19": models.vgg19, + + "resnet18": models.resnet18, + "resnet34": models.resnet34, + "resnet50": models.resnet50, + "resnet101": models.resnet101, + "resnet152": models.resnet152, + + "squeezenet1_0": models.squeezenet1_0, + "squeezenet1_1": models.squeezenet1_1, + + "resnext50_32x4d": models.resnext50_32x4d, + "resnext101_32x8d": models.resnext101_32x8d, + + "wide_resnet50_2": models.wide_resnet50_2, + "wide_resnet101_2": models.wide_resnet101_2 +} + + +class PyTorchClsModel(PyTorchModelPreparer): + def __init__(self, height, width, model_name, original_model): + super(PyTorchClsModel, self).__init__(height, width, model_name, original_model) + + +def main(): + set_pytorch_env() + + parser = create_extended_parser(list(model_dict.keys())) + cmd_args = parser.parse_args() + model_name = cmd_args.model_name + + cls_model = PyTorchClsModel( + height=TestClsConfig().frame_size, + width=TestClsConfig().frame_size, + model_name=model_name, + original_model=model_dict[model_name](pretrained=True) + ) + + pytorch_cls_pipeline = ClsModelTestPipeline( + network_model=cls_model, + model_processor=PyTorchModelProcessor, + dnn_model_processor=PyTorchDnnModelProcessor, + data_fetcher=PyTorchPreprocessedFetch, + cls_args_parser=parser, + default_input_blob_preproc=pytorch_resize_input_blob + ) + + pytorch_cls_pipeline.init_test_pipeline() + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50.py b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50.py new file mode 100644 index 0000000000..3a228bf1da --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50.py @@ -0,0 +1,139 @@ +import os + +import cv2 +import numpy as np +import torch +import torch.onnx +from torch.autograd import Variable +from torchvision import models + + +def get_pytorch_onnx_model(original_model): + # define the directory for further converted model save + onnx_model_path = "models" + # define the name of further converted model + onnx_model_name = "resnet50.onnx" + + # create directory for further converted model + os.makedirs(onnx_model_path, exist_ok=True) + + # get full path to the converted model + full_model_path = os.path.join(onnx_model_path, onnx_model_name) + + # generate model input + generated_input = Variable( + torch.randn(1, 3, 224, 224) + ) + + # model export into ONNX format + torch.onnx.export( + original_model, + generated_input, + full_model_path, + verbose=True, + input_names=["input"], + output_names=["output"], + opset_version=11 + ) + + return full_model_path + + +def get_preprocessed_img(img_path): + # read the image + input_img = cv2.imread(img_path, cv2.IMREAD_COLOR) + input_img = input_img.astype(np.float32) + + input_img = cv2.resize(input_img, (256, 256)) + + # define preprocess parameters + mean = np.array([0.485, 0.456, 0.406]) * 255.0 + scale = 1 / 255.0 + std = [0.229, 0.224, 0.225] + + # prepare input blob to fit the model input: + # 1. subtract mean + # 2. scale to set pixel values from 0 to 1 + input_blob = cv2.dnn.blobFromImage( + image=input_img, + scalefactor=scale, + size=(224, 224), # img target size + mean=mean, + swapRB=True, # BGR -> RGB + crop=True # center crop + ) + # 3. divide by std + input_blob[0] /= np.asarray(std, dtype=np.float32).reshape(3, 1, 1) + return input_blob + + +def get_imagenet_labels(labels_path): + with open(labels_path) as f: + imagenet_labels = [line.strip() for line in f.readlines()] + return imagenet_labels + + +def get_opencv_dnn_prediction(opencv_net, preproc_img, imagenet_labels): + # set OpenCV DNN input + opencv_net.setInput(preproc_img) + + # OpenCV DNN inference + out = opencv_net.forward() + print("OpenCV DNN prediction: \n") + print("* shape: ", out.shape) + + # get the predicted class ID + imagenet_class_id = np.argmax(out) + + # get confidence + confidence = out[0][imagenet_class_id] + print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + print("* confidence: {:.4f}".format(confidence)) + + +def get_pytorch_dnn_prediction(original_net, preproc_img, imagenet_labels): + original_net.eval() + preproc_img = torch.FloatTensor(preproc_img) + + # inference + with torch.no_grad(): + out = original_net(preproc_img) + + print("\nPyTorch model prediction: \n") + print("* shape: ", out.shape) + + # get the predicted class ID + imagenet_class_id = torch.argmax(out, axis=1).item() + print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + + # get confidence + confidence = out[0][imagenet_class_id] + print("* confidence: {:.4f}".format(confidence.item())) + + +def main(): + # initialize PyTorch ResNet-50 model + original_model = models.resnet50(pretrained=True) + + # get the path to the converted into ONNX PyTorch model + full_model_path = get_pytorch_onnx_model(original_model) + + # read converted .onnx model with OpenCV API + opencv_net = cv2.dnn.readNetFromONNX(full_model_path) + print("OpenCV model was successfully read. Layer IDs: \n", opencv_net.getLayerNames()) + + # get preprocessed image + input_img = get_preprocessed_img("../data/squirrel_cls.jpg") + + # get ImageNet labels + imagenet_labels = get_imagenet_labels("../data/dnn/classification_classes_ILSVRC2012.txt") + + # obtain OpenCV DNN predictions + get_opencv_dnn_prediction(opencv_net, input_img, imagenet_labels) + + # obtain original PyTorch ResNet50 predictions + get_pytorch_dnn_prediction(original_model, input_img, imagenet_labels) + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50_onnx.py b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50_onnx.py new file mode 100644 index 0000000000..969c359946 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/classification/py_to_py_resnet50_onnx.py @@ -0,0 +1,50 @@ +import os + +import torch +import torch.onnx +from torch.autograd import Variable +from torchvision import models + + +def get_pytorch_onnx_model(original_model): + # define the directory for further converted model save + onnx_model_path = "models" + # define the name of further converted model + onnx_model_name = "resnet50.onnx" + + # create directory for further converted model + os.makedirs(onnx_model_path, exist_ok=True) + + # get full path to the converted model + full_model_path = os.path.join(onnx_model_path, onnx_model_name) + + # generate model input + generated_input = Variable( + torch.randn(1, 3, 224, 224) + ) + + # model export into ONNX format + torch.onnx.export( + original_model, + generated_input, + full_model_path, + verbose=True, + input_names=["input"], + output_names=["output"], + opset_version=11 + ) + + return full_model_path + + +def main(): + # initialize PyTorch ResNet-50 model + original_model = models.resnet50(pretrained=True) + + # get the path to the converted into ONNX PyTorch model + full_model_path = get_pytorch_onnx_model(original_model) + print("PyTorch ResNet-50 model was successfully converted: ", full_model_path) + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/pytorch_model.py b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/pytorch_model.py new file mode 100644 index 0000000000..cb32004c55 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/pytorch/pytorch_model.py @@ -0,0 +1,98 @@ +import os + +import cv2 +import torch.onnx +from torch.autograd import Variable + +from ..common.abstract_model import AbstractModel, Framework +from ..common.utils import DNN_LIB, get_full_model_path + +CURRENT_LIB = "PyTorch" +MODEL_FORMAT = ".onnx" + + +class PyTorchModelPreparer(AbstractModel): + + def __init__( + self, + height, + width, + model_name="default", + original_model=object, + batch_size=1, + default_input_name="input", + default_output_name="output" + ): + self._height = height + self._width = width + self._model_name = model_name + self._original_model = original_model + self._batch_size = batch_size + self._default_input_name = default_input_name + self._default_output_name = default_output_name + + self.model_path = self._set_model_path() + self._dnn_model = self._set_dnn_model() + + def _set_dnn_model(self): + generated_input = Variable(torch.randn( + self._batch_size, 3, self._height, self._width) + ) + os.makedirs(self.model_path["path"], exist_ok=True) + torch.onnx.export( + self._original_model, + generated_input, + self.model_path["full_path"], + verbose=True, + input_names=[self._default_input_name], + output_names=[self._default_output_name], + opset_version=11 + ) + + return cv2.dnn.readNetFromONNX(self.model_path["full_path"]) + + def _set_model_path(self): + model_to_save = self._model_name + MODEL_FORMAT + return get_full_model_path(CURRENT_LIB.lower(), model_to_save) + + def get_prepared_models(self): + return { + CURRENT_LIB + " " + self._model_name: self._original_model, + DNN_LIB + " " + self._model_name: self._dnn_model + } + + +class PyTorchModelProcessor(Framework): + def __init__(self, prepared_model, model_name): + self._prepared_model = prepared_model + self._name = model_name + + def get_output(self, input_blob): + tensor = torch.FloatTensor(input_blob) + self._prepared_model.eval() + + with torch.no_grad(): + model_out = self._prepared_model(tensor) + + # segmentation case + if len(model_out) == 2: + model_out = model_out['out'] + + out = model_out.detach().numpy() + return out + + def get_name(self): + return self._name + + +class PyTorchDnnModelProcessor(Framework): + def __init__(self, prepared_dnn_model, model_name): + self._prepared_dnn_model = prepared_dnn_model + self._name = model_name + + def get_output(self, input_blob): + self._prepared_dnn_model.setInput(input_blob, '') + return self._prepared_dnn_model.forward() + + def get_name(self): + return self._name diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt b/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt new file mode 100644 index 0000000000..65ab56ad66 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt @@ -0,0 +1,9 @@ +# Python 3.7.5 +onnx>=1.7.0 +numpy>=1.19.1 + +torch>=1.5.1 +torchvision>=0.6.1 + +tensorflow>=2.1.0 +tensorflow-gpu>=2.1.0 diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_cls.py b/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_cls.py new file mode 100644 index 0000000000..0eabe876cb --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_cls.py @@ -0,0 +1,104 @@ +from tensorflow.keras.applications import ( + VGG16, vgg16, + VGG19, vgg19, + + ResNet50, resnet, + ResNet101, + ResNet152, + + DenseNet121, densenet, + DenseNet169, + DenseNet201, + + InceptionResNetV2, inception_resnet_v2, + InceptionV3, inception_v3, + + MobileNet, mobilenet, + MobileNetV2, mobilenet_v2, + + NASNetLarge, nasnet, + NASNetMobile, + + Xception, xception +) + +from ..tf_model import TFModelPreparer +from ..tf_model import ( + TFModelProcessor, + TFDnnModelProcessor +) +from ...common.evaluation.classification.cls_data_fetcher import TFPreprocessedFetch +from ...common.test.cls_model_test_pipeline import ClsModelTestPipeline +from ...common.test.configs.default_preprocess_config import ( + tf_input_blob, + pytorch_input_blob, + tf_model_blob_caffe_mode +) +from ...common.utils import set_tf_env, create_extended_parser + +model_dict = { + "vgg16": [VGG16, vgg16, tf_model_blob_caffe_mode], + "vgg19": [VGG19, vgg19, tf_model_blob_caffe_mode], + + "resnet50": [ResNet50, resnet, tf_model_blob_caffe_mode], + "resnet101": [ResNet101, resnet, tf_model_blob_caffe_mode], + "resnet152": [ResNet152, resnet, tf_model_blob_caffe_mode], + + "densenet121": [DenseNet121, densenet, pytorch_input_blob], + "densenet169": [DenseNet169, densenet, pytorch_input_blob], + "densenet201": [DenseNet201, densenet, pytorch_input_blob], + + "inceptionresnetv2": [InceptionResNetV2, inception_resnet_v2, tf_input_blob], + "inceptionv3": [InceptionV3, inception_v3, tf_input_blob], + + "mobilenet": [MobileNet, mobilenet, tf_input_blob], + "mobilenetv2": [MobileNetV2, mobilenet_v2, tf_input_blob], + + "nasnetlarge": [NASNetLarge, nasnet, tf_input_blob], + "nasnetmobile": [NASNetMobile, nasnet, tf_input_blob], + + "xception": [Xception, xception, tf_input_blob] +} + +CNN_CLASS_ID = 0 +CNN_UTILS_ID = 1 +DEFAULT_BLOB_PARAMS_ID = 2 + + +class TFClsModel(TFModelPreparer): + def __init__(self, model_name, original_model): + super(TFClsModel, self).__init__(model_name, original_model) + + +def main(): + set_tf_env() + + parser = create_extended_parser(list(model_dict.keys())) + cmd_args = parser.parse_args() + + model_name = cmd_args.model_name + model_name_val = model_dict[model_name] + + cls_model = TFClsModel( + model_name=model_name, + original_model=model_name_val[CNN_CLASS_ID]( + include_top=True, + weights="imagenet" + ) + ) + + tf_cls_pipeline = ClsModelTestPipeline( + network_model=cls_model, + model_processor=TFModelProcessor, + dnn_model_processor=TFDnnModelProcessor, + data_fetcher=TFPreprocessedFetch, + img_processor=model_name_val[CNN_UTILS_ID].preprocess_input, + cls_args_parser=parser, + default_input_blob_preproc=model_name_val[DEFAULT_BLOB_PARAMS_ID] + ) + + tf_cls_pipeline.init_test_pipeline() + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_mobilenet.py b/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_mobilenet.py new file mode 100644 index 0000000000..ebc6cfe542 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/tf/classification/py_to_py_mobilenet.py @@ -0,0 +1,142 @@ +import os + +import cv2 +import numpy as np +import tensorflow as tf +from tensorflow.keras.applications import MobileNet +from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2 + +from ...common.utils import set_tf_env + + +def get_tf_model_proto(tf_model): + # define the directory for .pb model + pb_model_path = "models" + + # define the name of .pb model + pb_model_name = "mobilenet.pb" + + # create directory for further converted model + os.makedirs(pb_model_path, exist_ok=True) + + # get model TF graph + tf_model_graph = tf.function(lambda x: tf_model(x)) + + # get concrete function + tf_model_graph = tf_model_graph.get_concrete_function( + tf.TensorSpec(tf_model.inputs[0].shape, tf_model.inputs[0].dtype)) + + # obtain frozen concrete function + frozen_tf_func = convert_variables_to_constants_v2(tf_model_graph) + # get frozen graph + frozen_tf_func.graph.as_graph_def() + + # save full tf model + tf.io.write_graph(graph_or_graph_def=frozen_tf_func.graph, + logdir=pb_model_path, + name=pb_model_name, + as_text=False) + + return os.path.join(pb_model_path, pb_model_name) + + +def get_preprocessed_img(img_path): + # read the image + input_img = cv2.imread(img_path, cv2.IMREAD_COLOR) + input_img = input_img.astype(np.float32) + + # define preprocess parameters + mean = np.array([1.0, 1.0, 1.0]) * 127.5 + scale = 1 / 127.5 + + # prepare input blob to fit the model input: + # 1. subtract mean + # 2. scale to set pixel values from 0 to 1 + input_blob = cv2.dnn.blobFromImage( + image=input_img, + scalefactor=scale, + size=(224, 224), # img target size + mean=mean, + swapRB=True, # BGR -> RGB + crop=True # center crop + ) + print("Input blob shape: {}\n".format(input_blob.shape)) + + return input_blob + + +def get_imagenet_labels(labels_path): + with open(labels_path) as f: + imagenet_labels = [line.strip() for line in f.readlines()] + return imagenet_labels + + +def get_opencv_dnn_prediction(opencv_net, preproc_img, imagenet_labels): + # set OpenCV DNN input + opencv_net.setInput(preproc_img) + + # OpenCV DNN inference + out = opencv_net.forward() + print("OpenCV DNN prediction: \n") + print("* shape: ", out.shape) + + # get the predicted class ID + imagenet_class_id = np.argmax(out) + + # get confidence + confidence = out[0][imagenet_class_id] + print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + print("* confidence: {:.4f}\n".format(confidence)) + + +def get_tf_dnn_prediction(original_net, preproc_img, imagenet_labels): + # inference + preproc_img = preproc_img.transpose(0, 2, 3, 1) + print("TF input blob shape: {}\n".format(preproc_img.shape)) + + out = original_net(preproc_img) + + print("\nTensorFlow model prediction: \n") + print("* shape: ", out.shape) + + # get the predicted class ID + imagenet_class_id = np.argmax(out) + print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id])) + + # get confidence + confidence = out[0][imagenet_class_id] + print("* confidence: {:.4f}".format(confidence)) + + +def main(): + # configure TF launching + set_tf_env() + + # initialize TF MobileNet model + original_tf_model = MobileNet( + include_top=True, + weights="imagenet" + ) + + # get TF frozen graph path + full_pb_path = get_tf_model_proto(original_tf_model) + + # read frozen graph with OpenCV API + opencv_net = cv2.dnn.readNetFromTensorflow(full_pb_path) + print("OpenCV model was successfully read. Model layers: \n", opencv_net.getLayerNames()) + + # get preprocessed image + input_img = get_preprocessed_img("../data/squirrel_cls.jpg") + + # get ImageNet labels + imagenet_labels = get_imagenet_labels("../data/dnn/classification_classes_ILSVRC2012.txt") + + # obtain OpenCV DNN predictions + get_opencv_dnn_prediction(opencv_net, input_img, imagenet_labels) + + # obtain TF model predictions + get_tf_dnn_prediction(original_tf_model, input_img, imagenet_labels) + + +if __name__ == "__main__": + main() diff --git a/samples/dnn/dnn_model_runner/dnn_conversion/tf/tf_model.py b/samples/dnn/dnn_model_runner/dnn_conversion/tf/tf_model.py new file mode 100644 index 0000000000..2411821ed6 --- /dev/null +++ b/samples/dnn/dnn_model_runner/dnn_conversion/tf/tf_model.py @@ -0,0 +1,112 @@ +import cv2 +import tensorflow as tf +from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2 + +from ..common.abstract_model import AbstractModel, Framework +from ..common.utils import DNN_LIB, get_full_model_path + +CURRENT_LIB = "TF" +MODEL_FORMAT = ".pb" + + +class TFModelPreparer(AbstractModel): + """ Class for the preparation of the TF models: original and converted OpenCV Net. + + Args: + model_name: TF model name + original_model: TF configured model object or session + is_ready_graph: indicates whether ready .pb file already exists + tf_model_graph_path: path to the existing frozen TF graph + """ + + def __init__( + self, + model_name="default", + original_model=None, + is_ready_graph=False, + tf_model_graph_path="" + ): + self._model_name = model_name + self._original_model = original_model + self._model_to_save = "" + + self._is_ready_to_transfer_graph = is_ready_graph + self.model_path = self._set_model_path(tf_model_graph_path) + self._dnn_model = self._set_dnn_model() + + def _set_dnn_model(self): + if not self._is_ready_to_transfer_graph: + # get model TF graph + tf_model_graph = tf.function(lambda x: self._original_model(x)) + + tf_model_graph = tf_model_graph.get_concrete_function( + tf.TensorSpec(self._original_model.inputs[0].shape, self._original_model.inputs[0].dtype)) + + # obtain frozen concrete function + frozen_tf_func = convert_variables_to_constants_v2(tf_model_graph) + frozen_tf_func.graph.as_graph_def() + + # save full TF model + tf.io.write_graph(graph_or_graph_def=frozen_tf_func.graph, + logdir=self.model_path["path"], + name=self._model_to_save, + as_text=False) + + return cv2.dnn.readNetFromTensorflow(self.model_path["full_path"]) + + def _set_model_path(self, tf_pb_file_path): + """ Method for setting model paths. + + Args: + tf_pb_file_path: path to the existing TF .pb + + Returns: + dictionary, where full_path key means saved model path and its full name. + """ + model_paths_dict = { + "path": "", + "full_path": tf_pb_file_path + } + + if not self._is_ready_to_transfer_graph: + self._model_to_save = self._model_name + MODEL_FORMAT + model_paths_dict = get_full_model_path(CURRENT_LIB.lower(), self._model_to_save) + + return model_paths_dict + + def get_prepared_models(self): + original_lib_name = CURRENT_LIB + " " + self._model_name + configured_model_dict = { + original_lib_name: self._original_model, + DNN_LIB + " " + self._model_name: self._dnn_model + } + return configured_model_dict + + +class TFModelProcessor(Framework): + def __init__(self, prepared_model, model_name): + self._prepared_model = prepared_model + self._name = model_name + + def get_output(self, input_blob): + assert len(input_blob.shape) == 4 + batch_tf = input_blob.transpose(0, 2, 3, 1) + out = self._prepared_model(batch_tf) + return out + + def get_name(self): + return CURRENT_LIB + + +class TFDnnModelProcessor(Framework): + def __init__(self, prepared_dnn_model, model_name): + self._prepared_dnn_model = prepared_dnn_model + self._name = model_name + + def get_output(self, input_blob): + self._prepared_dnn_model.setInput(input_blob) + ret_val = self._prepared_dnn_model.forward() + return ret_val + + def get_name(self): + return DNN_LIB