Skip to content

Interactive Open Model Zoo as OpenCV module#272

Closed
dkurt wants to merge 27 commits intoopenvinotoolkit:developfrom
dkurt:py_open_model_zoo
Closed

Interactive Open Model Zoo as OpenCV module#272
dkurt wants to merge 27 commits intoopenvinotoolkit:developfrom
dkurt:py_open_model_zoo

Conversation

@dkurt
Copy link
Copy Markdown
Contributor

@dkurt dkurt commented Aug 3, 2019

import cv2 as cv

from cv2.open_model_zoo.topologies import mobilenet_ssd
from cv2.open_model_zoo import DnnDetectionModel

frame = cv.imread('example.jpg')

ssd = mobilenet_ssd()
net = DnnDetectionModel(ssd)

classIds, confidences, boxes = net.detect(frame, confThreshold=0.5)
for box in boxes:
    cv.rectangle(frame, box, (0, 255, 0))

cv.imshow('out', frame)
cv.waitKey()

🐍 🐺 🦁 🙉 🐘 🐧 🐙 🦈 🐭 🐫 🐸 🐜 🐆 🦊 🐟 😼 🪲 🐳 🐨 🕷️ 🐉 🕊️ 🦉 🐰 🐔 🦀 🐝

WIP

  • Add inference. There are multiple options:
    1. Each topology is derived from OpenCV's dnn::Model. Using downloaded models IENetwork can be initialized separately.
    2. Each topology is just meta class which can be casted to dnn::Model or IENetwork
  • Hash verification: do not download if hash is correct and verify hash after downloading (show warning in case of mismatch)
  • Cross platform cache dir (using OPENCV_OPEN_MODEL_ZOO_CACHE_DIR environment variable to change default caching location)
  • Archives management: tar.gz
  • Model Optimizer conversion
  • Added aliases for OpenVINO models (by highest version)
  • Archives management: zip
  • Downloading info: size and progress
  • Downloading and inference tests.
  • OpenCV DNN: input size
  • Documentation at help(topology): description, license etc.
  • Replace pyyaml to own YAML implementation due it's not default Python package (is required only for build)
  • Errors handling (Downloading, Model Optimizer)
  • Remove archives after extract
  • Let user add and override Model Optimizer arguments
  • Keep layout similar to the downloader

related: opencv/opencv#14730

Pipelines

example with text recognition demo API:

import cv2 as cv
import numpy as np

from cv2.open_model_zoo import TextRecognitionPipeline

frame = cv.imread('text.jpg')

p = TextRecognitionPipeline()

rects, texts, confs = p.process(frame)

for rect, text in zip(rects, texts):
    vertices = cv.boxPoints(rect)

    for j in range(4):
        p1 = (vertices[j][0], vertices[j][1])
        p2 = (vertices[(j + 1) % 4][0], vertices[(j + 1) % 4][1])
        cv.line(frame, p1, p2, (0, 255, 0), 1);

    x = np.min(vertices[:,0])
    y = np.min(vertices[:,1])
    cv.putText(frame, text, (x, y), cv.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), thickness=2)

cv.imshow('frame', frame)
cv.waitKey()

res

import cv2 as cv
from cv2.open_model_zoo import HumanPoseEstimation

p = HumanPoseEstimation()

frame = cv.imread('example.png')
poses = p.process(frame)

p.render(frame, poses)

cv.imshow('res', frame)
cv.waitKey()

out

@openvino-pushbot
Copy link
Copy Markdown
Contributor

Can one of the admins verify this patch?

1 similar comment
@openvino-pushbot
Copy link
Copy Markdown
Contributor

Can one of the admins verify this patch?

@dkurt dkurt force-pushed the py_open_model_zoo branch 5 times, most recently from 0d73fbd to 9926897 Compare August 7, 2019 14:01
@snosov1
Copy link
Copy Markdown
Contributor

snosov1 commented Aug 8, 2019

  • Is it really necessary to have such a long prefix? cv.open_model_zoo_TextRecognitionPipeline(det, rec)
  • Do you plan to add the example into the demos folder?

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 8, 2019

Is it really necessary to have such a long prefix? cv.open_model_zoo_TextRecognitionPipeline(det, rec)

@snosov1, For now it's a kind of bug in OpenCV's wrappers (related feature request opencv/opencv#14730). For now there is a workaround for it to define a method with proper name:

class TextRecognitionPipelineImpl
{
    //...
};

Ptr<TextRecognitionPipelineImpl> TextRecognitionPipeline(...) { return new TextRecognitionPipelineImpl(...); }

corresponding Python code:

from cv2.open_model_zoo import TextRecognitionPipeline
p = TextRecognitionPipeline()

Do you plan to add the example into the demos folder?

It'd be nice. In example, add more Python demos for existing C++ ones. The only thing we have to decide is a code duplication: move C++ code from samples to the module and replace it to corresponding APIs.

@snosov1
Copy link
Copy Markdown
Contributor

snosov1 commented Aug 8, 2019

Not sure I understand the answers, Dmitry =)

For now it's a kind of bug in OpenCV's wrappers

Are you saying that it will look "normal" after the merge of the respective PR?

add more Python demos for existing C++ ones.

That's a different story. For starters we should have at least one to showcase this type of usage.

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 8, 2019

@snosov1,

from cv2.open_model_zoo import TextRecognitionPipeline
p = TextRecognitionPipeline()

would be available :) I'll provide the code which do it in future commits.

Maybe one of open questions is name scopes to differ "topologies" from "algorithms". In example,

from cv2.open_model_zoo.topologies import text_detection, text_recognition
from cv2.open_model_zoo import TextRecognitionPipeline

p = TextRecognitionPipeline()

@dkurt dkurt force-pushed the py_open_model_zoo branch 2 times, most recently from 09d5c37 to eaec181 Compare August 10, 2019 19:43
@jrosebr1
Copy link
Copy Markdown

@dkurt This is a really amazing PR, incredible work! If you need help putting together examples of how to use it let me know and I'll publish some content on the PyImageSearch blog 😄

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 11, 2019

Adrian, thank you! That would be great!

@dkurt dkurt force-pushed the py_open_model_zoo branch from 7553cb5 to ce226b7 Compare August 11, 2019 18:52
@jrosebr1
Copy link
Copy Markdown

Absolutely! I'll keep an eye on this PR and once it's merged I'll put something together 😄

I was looking at the TextRecognitionPipeline code -- I assume it's using EAST to localize text in the image, but what about the actual OCR component. What model is being used there?

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 12, 2019

@jrosebr1, text-detection-0004: https://github.com/opencv/open_model_zoo/blob/master/intel_models/text-detection-0004/description/text-detection-0004.md.

I think that next step is to enable these pipelines to with with different kind of models (it could be as EAST text detection as Intel's models).

@IRDonch
Copy link
Copy Markdown

IRDonch commented Aug 12, 2019

Without going into a detailed review, I have a few high level comments:

  1. I'm confused as to how this is supposed to be used. OMZ is included into the OpenVINO toolkit as source code, while OpenCV is included as binaries. Thus an OpenVINO tookit user has no way to build this module, as his OpenCV is already built.

  2. Half of this code is a reimplementation of Model Downloader/Converter. This is extremely fragile. The only supported way to download/convert/query models is by running the tools in tools/downloader. Anything else is liable to break as soon as the format of the config changes.

    This code, from what I can see, is already non-functional for models with regex-based postprocessing and PyTorch models. And it's going to be completely broken after Split list_topologies.yml into per-model config files #276, and then broken some more by another PR I have planned. And I heard rumors about a planned Caffe model which requires a new kind of post-processing, so that's going to be broken too. And that's just the changes that I can foresee.

    The bottom line is that this is unacceptable. You either need to run Model Downloader or just request that the user supply a directory with everything already downloaded. IMO, the latter option is way simpler.

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 12, 2019

@IRDonch, thanks for review!

I'm confused as to how this is supposed to be used. OMZ is included into the OpenVINO toolkit as source code, while OpenCV is included as binaries. Thus an OpenVINO tookit user has no way to build this module, as his OpenCV is already built.

We can also build it as a part of OpenCV's binaries for OpenVINO. Just adding OPENCV_EXTRA_MODULES_PATH during build time.

Half of this code is a reimplementation of Model Downloader/Converter. This is extremely fragile. The only supported way to download/convert/query models is by running the tools in tools/downloader. Anything else is liable to break as soon as the format of the config changes.

Python code is based on OMZ's downloader and https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/download_models.py. Binaries uses only default Python packages (urllib, zipfile, tarfile, etc.)

This code, from what I can see, is already non-functional for models with regex-based postprocessing and PyTorch models. And it's going to be completely broken after #276, and then broken some more by another PR I have planned. And I heard rumors about a planned Caffe model which requires a new kind of post-processing, so that's going to be broken too. And that's just the changes that I can foresee.

Most of postprocessing doesn't seem actual:

    postprocessing:
      - $type: regex_replace
        file: mtcnn-p.prototxt
        pattern: 'dim: 12'
        replacement: 'dim: 720'
        count: 1
      - $type: regex_replace
        file: mtcnn-p.prototxt
        pattern: 'dim: 12'
        replacement: 'dim: 1280'
        count: 1
    model_optimizer_args:
      - --framework=caffe
      - --data_type=FP32
      - --input_shape=[1,3,720,1280]
      - --input=data
      - --mean_values=data[127.5,127.5,127.5]
      - --scale_values=data[128.0]
      - --output=conv4-2,prob1
      - --input_model=$dl_dir/mtcnn-p.caffemodel
      - --input_proto=$dl_dir/mtcnn-p.prototxt

I believe MO can ignore input dims at prototxt if --input_shape=[1,3,720,1280] specified (I can check it). Haven't found PyTorch models for now.

I wanted to adapt this PR after changes proposed at #276. That shouldn't be a problem.

@IRDonch
Copy link
Copy Markdown

IRDonch commented Aug 13, 2019

We can also build it as a part of OpenCV's binaries for OpenVINO. Just adding OPENCV_EXTRA_MODULES_PATH during build time.

This seems impractical. It means that the OpenCV team would have to rebuild their binaries after every update to the model configuration file(s). From past experience I can say the models tend to get updated close to the time of the release due to last-minute Model Optimizer bugfixes, so the chances of OpenCV shipping with an out-of-sync module are quite high.

Python code is based on OMZ's downloader and https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/download_models.py. Binaries uses only default Python packages (urllib, zipfile, tarfile, etc.)

I can see that, but it does nothing to address my concern. Also, it's not entirely true - when you're running Model Optimizer, you depend on all of its dependencies.

I believe MO can ignore input dims at prototxt if --input_shape=[1,3,720,1280] specified (I can check it).

That's good, but I know at least one regex-based fix that cannot be skipped - the one in googlenet-v2. In that case, the original prototxt file is actually ill-formed, and we have to patch it to make it work.

Haven't found PyTorch models for now.

They were merged recently. You might want to rebase.

I wanted to adapt this PR after changes proposed at #276. That shouldn't be a problem.

I'm sure you can adapt to that specific change, but the problem is that you have to. Any new feature in the downloader/converter would require you (or someone else) to adapt the module to it. That's not sustainable.

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 13, 2019

@IRDonch, Thanks!

I agree that adding new module is a kind of overhead. There is another one option is to add it to regular OpenCV distribution. However the name of the package will be a bit different:

from cv2.dnn.open_model_zoo import ...

Or

from cv2.dnn.zoo import ...

This way we can use OMZ's topologies as optional ones and refactored https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/download_models.py as a base.

We can start with it and check it's stability first.

@vladimir-dudnik
Copy link
Copy Markdown
Contributor

vladimir-dudnik commented Aug 13, 2019

@IRDonch

I'm sure you can adapt to that specific change, but the problem is that you have to. Any new feature in the downloader/converter would require you (or someone else) to adapt the module to it. That's not sustainable.

Can we rely on downloader/converter API to minimize needs of changes in case of any new features in them?

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 13, 2019

@vladimir-dudnik, Proposed changes use pure Python to download files by URL. The module depends only on list_topologies.yml (or set of them after #276) and source code of some demos (for now it's text_recognition and human_pose_estimation).

@dkurt dkurt force-pushed the py_open_model_zoo branch from 810d387 to 85b2d34 Compare August 13, 2019 20:35
@dkurt dkurt force-pushed the py_open_model_zoo branch from 85b2d34 to f7e8462 Compare August 15, 2019 12:38
@IRDonch
Copy link
Copy Markdown

IRDonch commented Aug 15, 2019

Can we rely on downloader/converter API to minimize needs of changes in case of any new features in them?

That's what I'm suggesting...

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 15, 2019

@IRDonch, I'd like to propose the following solution: the package is still generated by OMZ structure (intel/ and public/ subfolders). For every model it's name is preserved in any way. In case of success - YAML is parser as well.

Then, at download() we will use downloader.py as a first priority tool for downloading (using the name of model we have). In case of failed download.py command (in example, when OpenCV is compiled with OMZ without OpenVINO and script has not been found) - try to download by existing code.

@dkurt
Copy link
Copy Markdown
Contributor Author

dkurt commented Aug 15, 2019

On the other hand - there is a lightweight solution with just Python module which can only download and convert models without demos.

I'll propose a separate PR with it.

Copy link
Copy Markdown

@mmphego mmphego left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions
Overral great PR can't wait for it to be merged.

Less is more!!!

@@ -0,0 +1,108 @@
# Open Model Zoo

This is OpenCV module which let you have interactive Open Model Zoo in Python.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be reworded as:

Suggested change
This is OpenCV module which let you have interactive Open Model Zoo in Python.
This is OpenCV module which lets you interact Open Model Zoo in Python.

```


If you already have modules such opencv_contrib, you can combine it. In example,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you already have modules such opencv_contrib, you can combine it. In example,
If you already have modules such `opencv_contrib`, you can combine it. In example,

topology = squeezenet1_0()
```

To infer network you can use as just paths downloaded files:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To infer network you can use as just paths downloaded files:
To infer a network you can just use paths to the downloaded files:

Comment on lines +80 to +82
Some of networks may have pretty complicated pre- or post- processing procedures.
Another models can be combined to solve interesting problems. For these kind of
topologies you can use ready Algorithms. In example, to recognize text:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Some of networks may have pretty complicated pre- or post- processing procedures.
Another models can be combined to solve interesting problems. For these kind of
topologies you can use ready Algorithms. In example, to recognize text:
Some networks may have pretty complicated pre- or post-processing procedures.
Other models can be combined to solve interesting problems. For this kind of
topologies you can use ready Algorithms. This example shows how to recognize text:

if len(files) > 1:
config['model_url'], config['model_sha256'], config['model_path'] = getSource(files[1])

s = ', '.join(['{"%s", "%s"}' % (key, value) for key, value in config.items()])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to cast into a list.

Suggested change
s = ', '.join(['{"%s", "%s"}' % (key, value) for key, value in config.items()])
s = ', '.join('{"%s", "%s"}' % (key, value) for key, value in config.items())

@dkurt dkurt closed this Jan 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants