Sign inSign up

ronhanson/tensorflow-image-resizer

By ronhanson

•Updated over 7 years ago

Image
0

306

ronhanson/tensorflow-image-resizer repository overview

⁠Tensorflow Image Resizer

Project sponsored by Kontron⁠

Project Lead and related articles⁠ by Samuel Cozannet⁠

Code and programming by Ronan Delacroix⁠

⁠What is this ?

This small demo aims to provides a simple dummy web interface allowing to upload images and send them to Tensorflow for prediction.

Also provides an API to upload your image and do Tensorflow prediction using kind of Rest/Json format.

The API actually sends the image to a Tensorflow server set for prediction. The API also resizes original images into different lower resolutions, make the same Tensorflow prediction and create metrics out of results. It returns statistics about timings, performances, accuracy and prediction precision.

The aim is to compare Tensorflow results and processing times when varying image sizes, and/or server kind (CPU, GPU, cores).

This small project is not production grade and is made for Mobile World Congress as a demo.

Read https://medium.com/@samnco/fun-with-kubernetes-tensorflow-serving-4fef8d7502b9⁠ to know more.

⁠Run

⁠Python script usage (dev mode)
bin/tensorflow-image-resizer
⁠Run using gunicorn

First set required ENV variable (see below), then :

gunicorn -b 0.0.0.0:5051 --access-logfile - --error-logfile - tensorflow-image-resizer.web:app

or

bin/tensorflow-image-resizer.sh 
⁠Docker Build and Run
docker build . -t mwc-tensorflow-image-resizer:latest

docker run \
    --env TF_SERVERS="Default CPU Server:tf-serving-server-cpu:9000;GPU Server:tf-serving-server-gpu:9000" \ 
    -p 5051:5051 -t -i \
    mwc-tensorflow-image-resizer:latest

Finally go to http://localhost:5051/⁠

⁠Env variables

  • TF_SERVERS <required> - contains info about TF servers : TF_SERVERS="<server_name>:<server_host>:<server_port>" You can input multiple TF servers (separated with semicolons if there are more than one). Example : TF_SERVERS="My CPU TF Server:192.168.0.3:9000;Someone else GPU TF Server:192.168.1.148:8000".
  • MODEL_NAME - default : 'inception' - Name of the TF Model to use.
  • MODEL_SIGNATURE_NAME - default : 'predict_images' - Signature Name of the TF Model to use.
  • MODEL_INPUT_KEY - default : 'images' - Input key of the TF Model to upload an image to.

Pay attention that your TF server should be accessible on the network of your docker container.

⁠Run the full project with docker-compose

You can use docker-compose and the docker-compose.yaml file to run the full project, both TF server and the client at once.

Copy the docker-compose.yaml in a folder of your choice and simply type :

docker-compose up

Also, you only need to download the TF image inception model and place it in /tmp/model-data:

> mkdir /tmp/model-data
> cd /tmp/model-data
# copy your exported model data here, so that it contains a folder named "1" like this :
> tree
.
└── 1
    ├── saved_model.pb
    └── variables
        ├── variables.data-00000-of-00001
        └── variables.index

⁠API Usage

You can also use this project as an API endpoint to post your image from your own app.

Simply upload your image through a HTTP POST request on /upload url, using file input file field.

Here is an example :

curl  -F "file=@/Users/ronan/Pictures/cat.jpg"   http://localhost:5051/upload

The result is presented as JSON. Dummy result example follows:

{
  "files": [
    {
      "filename": "moi.jpg",
      "filesize": 118707,
      "content_type": "image\/jpeg",
      "server_names": [
        "default",
        "gpu"
      ],
      "sizes": [
        "Orig. 550x636",
        "2048x2048",
        "1024x1024",
        "512x512",
        "256x256",
        "128x128"
      ],
      "derivatives": {
        "Orig. 550x636": {
          "average_duration": 6.6138181686401,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 8.89501953125,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.2884063720703,
                "envelope": 4.5581865310669,
                "tray": 3.6763899326324,
                "packet": 3.4327256679535
              },
              "precision": 100,
              "predict_duration": 0.99241065979004,
              "total_duration": 0.99241065979004
            },
            "default": {
              "results": {
                "comic book": 8.89501953125,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.2884063720703,
                "envelope": 4.5581865310669,
                "tray": 3.6763899326324,
                "packet": 3.4327256679535
              },
              "precision": 100,
              "predict_duration": 12.23522567749,
              "total_duration": 12.23522567749
            }
          },
          "resize_duration": 0,
          "format": "JPEG",
          "average_precision": 100,
          "filesize": 118707,
          "filename": "moi.jpg",
          "image_size": "550x636",
          "resized": "Reference",
          "filesize_percent": 100
        },
        "2048x2048": {
          "average_duration": 1.1133260726929,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 8.8598012924194,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.6930170059204,
                "envelope": 4.5749850273132,
                "tray": 3.6941545009613,
                "puck, hockey puck": 3.4707596302032
              },
              "precision": 81.067491018236,
              "predict_duration": 1.0252320766449,
              "total_duration": 1.1765704154968
            },
            "default": {
              "results": {
                "comic book": 8.8598012924194,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.6930170059204,
                "envelope": 4.5749850273132,
                "tray": 3.6941545009613,
                "puck, hockey puck": 3.4707596302032
              },
              "precision": 81.067491018236,
              "predict_duration": 1.2014200687408,
              "total_duration": 1.3527584075928
            }
          },
          "resize_duration": 0.15133833885193,
          "format": "JPEG",
          "average_precision": 81.067491018236,
          "filesize": 71679,
          "filename": "moi.2048x2048.jpg",
          "image_size": "550x636",
          "resized": "2048x2048",
          "filesize_percent": 60.383128206424
        },
        "1024x1024": {
          "average_duration": 0.89396262168884,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 8.8598012924194,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.6930170059204,
                "envelope": 4.5749850273132,
                "tray": 3.6941545009613,
                "puck, hockey puck": 3.4707596302032
              },
              "precision": 81.067491018236,
              "predict_duration": 0.83424687385559,
              "total_duration": 0.85841846466064
            },
            "default": {
              "results": {
                "comic book": 8.8598012924194,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.6930170059204,
                "envelope": 4.5749850273132,
                "tray": 3.6941545009613,
                "puck, hockey puck": 3.4707596302032
              },
              "precision": 81.067491018236,
              "predict_duration": 0.95367836952209,
              "total_duration": 0.97784996032715
            }
          },
          "resize_duration": 0.024171590805054,
          "format": "JPEG",
          "average_precision": 81.067491018236,
          "filesize": 71679,
          "filename": "moi.1024x1024.jpg",
          "image_size": "550x636",
          "resized": "1024x1024",
          "filesize_percent": 60.383128206424
        },
        "512x512": {
          "average_duration": 0.98880505561829,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 8.9899501800537,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.4078044891357,
                "envelope": 4.4274864196777,
                "tray": 3.9461207389832,
                "puck, hockey puck": 3.2541999816895
              },
              "precision": 81.395449099462,
              "predict_duration": 1.0694222450256,
              "total_duration": 1.2666203975677
            },
            "default": {
              "results": {
                "comic book": 8.9899501800537,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.4078044891357,
                "envelope": 4.4274864196777,
                "tray": 3.9461207389832,
                "puck, hockey puck": 3.2541999816895
              },
              "precision": 81.395449099462,
              "predict_duration": 0.90818786621094,
              "total_duration": 1.1053860187531
            }
          },
          "resize_duration": 0.19719815254211,
          "format": "JPEG",
          "average_precision": 81.395449099462,
          "filesize": 47200,
          "filename": "moi.512x512.jpg",
          "image_size": "442x512",
          "resized": "512x512",
          "filesize_percent": 39.761766365926
        },
        "256x256": {
          "average_duration": 1.4369288682938,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 9.7475137710571,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.5457496643066,
                "jersey, T-shirt, tee shirt": 4.631067276001,
                "tray": 4.5579609870911,
                "envelope": 4.5538229942322
              },
              "precision": 87.314467556298,
              "predict_duration": 0.88055467605591,
              "total_duration": 0.90344023704529
            },
            "default": {
              "results": {
                "comic book": 9.7475137710571,
                "book jacket, dust cover, dust jacket, dust wrapper": 8.5457496643066,
                "jersey, T-shirt, tee shirt": 4.631067276001,
                "tray": 4.5579609870911,
                "envelope": 4.5538229942322
              },
              "precision": 87.314467556298,
              "predict_duration": 1.9933030605316,
              "total_duration": 2.016188621521
            }
          },
          "resize_duration": 0.02288556098938,
          "format": "JPEG",
          "average_precision": 87.314467556298,
          "filesize": 15173,
          "filename": "moi.256x256.jpg",
          "image_size": "221x256",
          "resized": "256x256",
          "filesize_percent": 12.781891548097
        },
        "128x128": {
          "average_duration": 0.8400958776474,
          "predictions": {
            "gpu": {
              "results": {
                "comic book": 9.6742382049561,
                "book jacket, dust cover, dust jacket, dust wrapper": 7.1120657920837,
                "jersey, T-shirt, tee shirt": 5.7149996757507,
                "binder, ring-binder": 5.0224323272705,
                "handkerchief, hankie, hanky, hankey": 4.6893925666809
              },
              "precision": 38.913513118862,
              "predict_duration": 0.82929587364197,
              "total_duration": 0.90497159957886
            },
            "default": {
              "results": {
                "comic book": 9.6742382049561,
                "book jacket, dust cover, dust jacket, dust wrapper": 7.1120657920837,
                "jersey, T-shirt, tee shirt": 5.7149996757507,
                "binder, ring-binder": 5.0224323272705,
                "handkerchief, hankie, hanky, hankey": 4.6893925666809
              },
              "precision": 38.913513118862,
              "predict_duration": 0.85089588165283,
              "total_duration": 0.92657160758972
            }
          },
          "resize_duration": 0.07567572593689,
          "format": "JPEG",
          "average_precision": 38.913513118862,
          "filesize": 4933,
          "filename": "moi.128x128.jpg",
          "image_size": "110x128",
          "resized": "128x128",
          "filesize_percent": 4.1556100314219
        }
      }
    }
  ]
}

⁠Compatibility

This API can be used on Linux or MacOS systems.

Mainly tested on Python 3.5 and 3.6.

⁠Author and Licence

Project url : https://github.com/ronhanson/crypto-miner-webui⁠

Copyright © 2018 Ronan Delacroix⁠

This program is released under MIT Licence. Feel free to use it or part of it anywhere you want.

Tag summary

Content type

Image

Digest

Size

350.5 MB

Last updated

over 7 years ago

docker pull ronhanson/tensorflow-image-resizer