galatasaray commited on
Commit
c579946
1 Parent(s): 63c3845

added flash

Browse files
yolov5-flask-master/.github/FUNDING.yml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # These are supported funding model platforms
2
+
3
+ github: robmarkcole
yolov5-flask-master/.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ venv/
2
+ .vscode
3
+ *.pt
4
+ #*.jpg
5
+ static/tmp.jpg
6
+ *.pyc
yolov5-flask-master/Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-slim-buster
2
+
3
+ RUN apt-get update
4
+ RUN apt-get install ffmpeg libsm6 libxext6 -y
5
+
6
+ WORKDIR /app
7
+ ADD . /app
8
+ RUN pip install -r requirements.txt
9
+
10
+ EXPOSE 5000
11
+
12
+ CMD ["python", "restapi.py", "--port=5000"]
yolov5-flask-master/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2020 jzhang533
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
yolov5-flask-master/README.md ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Yolov5 object detection model deployment using flask
2
+ This repo contains example apps for exposing the [yolo5](https://github.com/ultralytics/yolov5) object detection model from [pytorch hub](https://pytorch.org/hub/ultralytics_yolov5/) via a [flask](https://flask.palletsprojects.com/en/1.1.x/) api/app.
3
+
4
+ ## Web app
5
+ Simple app consisting of a form where you can upload an image, and see the inference result of the model in the browser. Run:
6
+
7
+ `$ python3 webapp.py --port 5000`
8
+
9
+ then visit http://localhost:5000/ in your browser:
10
+
11
+ <p align="center">
12
+ <img src="https://github.com/robmarkcole/yolov5-flask/blob/master/docs/app_form.jpg" width="450">
13
+ </p>
14
+
15
+ <p align="center">
16
+ <img src="https://github.com/robmarkcole/yolov5-flask/blob/master/docs/app_result.jpg" width="450">
17
+ </p>
18
+
19
+ ## Rest API
20
+ Simple rest API exposing the model for consumption by another service. Run:
21
+
22
+ `$ python3 restapi.py --port 5000`
23
+
24
+ Then use [curl](https://curl.se/) to perform a request:
25
+
26
+ `$ curl -X POST -F image=@tests/zidane.jpg 'http://localhost:5000/v1/object-detection/yolov5s'`
27
+
28
+ The model inference results are returned:
29
+
30
+ ```
31
+ [{'class': 0,
32
+ 'confidence': 0.8197850585,
33
+ 'name': 'person',
34
+ 'xmax': 1159.1403808594,
35
+ 'xmin': 750.912902832,
36
+ 'ymax': 711.2583007812,
37
+ 'ymin': 44.0350036621},
38
+ {'class': 0,
39
+ 'confidence': 0.5667674541,
40
+ 'name': 'person',
41
+ 'xmax': 1065.5523681641,
42
+ 'xmin': 116.0448303223,
43
+ 'ymax': 713.8904418945,
44
+ 'ymin': 198.4603881836},
45
+ {'class': 27,
46
+ 'confidence': 0.5661227107,
47
+ 'name': 'tie',
48
+ 'xmax': 516.7975463867,
49
+ 'xmin': 416.6880187988,
50
+ 'ymax': 717.0524902344,
51
+ 'ymin': 429.2020568848}]
52
+ ```
53
+
54
+ An example python script to perform inference using [requests](https://docs.python-requests.org/en/master/) is given in `tests/test_request.py`
55
+
56
+ ## Run & Develop locally
57
+ Run locally and dev:
58
+ * `python3 -m venv venv`
59
+ * `source venv/bin/activate`
60
+ * `(venv) $ pip install -r requirements.txt`
61
+ * `(venv) $ python3 webapp.py --port 5000`
62
+
63
+ ## Docker
64
+ The example dockerfile shows how to expose the rest API:
65
+ ```
66
+ # Build
67
+ docker build -t yolov5-flask .
68
+ # Run
69
+ docker run -p 5000:5000 yolov5-flask:latest
70
+ ```
71
+
72
+ ## reference
73
+ - https://github.com/ultralytics/yolov5
74
+ - https://github.com/jzhang533/yolov5-flask (this repo was forked from here)
75
+ - https://github.com/avinassh/pytorch-flask-api-heroku
yolov5-flask-master/docs/app_form.jpg ADDED
yolov5-flask-master/docs/app_result.jpg ADDED
yolov5-flask-master/requirements.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ flask
2
+ requests
3
+ black
4
+
5
+ matplotlib>=3.2.2
6
+ numpy>=1.18.5
7
+ opencv-python>=4.1.2
8
+ Pillow
9
+ PyYAML>=5.3.1
10
+ scipy>=1.4.1
11
+ torch>=1.7.0
12
+ torchvision>=0.8.1
13
+ tqdm>=4.41.0
14
+
15
+ tensorboard>=2.4.1
16
+
17
+ seaborn>=0.11.0
18
+ pandas
19
+
20
+ thop # FLOPs computation
yolov5-flask-master/restapi.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Run a rest API exposing the yolov5s object detection model
3
+ """
4
+ import argparse
5
+ import io
6
+ from PIL import Image
7
+
8
+ import torch
9
+ from flask import Flask, request
10
+
11
+ app = Flask(__name__)
12
+
13
+ DETECTION_URL = "/v1/object-detection/yolov5s"
14
+
15
+
16
+ @app.route(DETECTION_URL, methods=["POST"])
17
+ def predict():
18
+ if not request.method == "POST":
19
+ return
20
+
21
+ if request.files.get("image"):
22
+ image_file = request.files["image"]
23
+ image_bytes = image_file.read()
24
+
25
+ img = Image.open(io.BytesIO(image_bytes))
26
+
27
+ results = model(img, size=640)
28
+ data = results.pandas().xyxy[0].to_json(orient="records")
29
+ return data
30
+
31
+
32
+ if __name__ == "__main__":
33
+ parser = argparse.ArgumentParser(description="Flask api exposing yolov5 model")
34
+ parser.add_argument("--port", default=5000, type=int, help="port number")
35
+ args = parser.parse_args()
36
+
37
+ model = torch.hub.load(
38
+ "ultralytics/yolov5", "yolov5s", pretrained=True, force_reload=True
39
+ ).autoshape() # force_reload = recache latest code
40
+ model.eval()
41
+ app.run(host="0.0.0.0", port=args.port) # debug=True causes Restarting with stat
yolov5-flask-master/static/image0.jpg ADDED
yolov5-flask-master/static/pytorch.png ADDED
yolov5-flask-master/static/style.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html,
2
+ body {
3
+ height: 100%;
4
+ }
5
+
6
+ body {
7
+ display: -ms-flexbox;
8
+ display: flex;
9
+ -ms-flex-align: center;
10
+ align-items: center;
11
+ padding-top: 40px;
12
+ padding-bottom: 40px;
13
+ background-color: #f5f5f5;
14
+ }
15
+
16
+ .form-signin {
17
+ width: 100%;
18
+ max-width: 330px;
19
+ padding: 15px;
20
+ margin: auto;
21
+ }
22
+
23
+ .form-signin .form-control {
24
+ position: relative;
25
+ box-sizing: border-box;
26
+ height: auto;
27
+ padding: 10px;
28
+ font-size: 16px;
29
+ }
yolov5-flask-master/templates/index.html ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
7
+ <style>
8
+ .bd-placeholder-img {
9
+ font-size: 1.125rem;
10
+ text-anchor: middle;
11
+ }
12
+
13
+ @media (min-width: 768px) {
14
+ .bd-placeholder-img-lg {
15
+ font-size: 3.5rem;
16
+ }
17
+ }
18
+ </style>
19
+ <link rel="stylesheet" href="/static/style.css">
20
+
21
+ <title>yolov5 object detection</title>
22
+ </head>
23
+ <body class="text-center">
24
+ <form class="form-signin" method=post enctype=multipart/form-data>
25
+ <img class="mb-4" src="/static/pytorch.png" alt="" width="72">
26
+ <h1 class="h3 mb-3 font-weight-normal">Upload any image</h1>
27
+ <input type="file" name="file" class="form-control-file" id="inputfile">
28
+ <br/>
29
+ <button class="btn btn-lg btn-primary btn-block" type="submit">Upload</button>
30
+ <p class="mt-5 mb-3 text-muted">Built using Pytorch & Flask</p>
31
+ </form>
32
+ <script src="//code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
33
+ <script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
34
+ <script src="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
35
+ <script type="text/javascript">
36
+ $('#inputfile').bind('change', function() {
37
+ let fileSize = this.files[0].size/1024/1024; // this gives in MB
38
+ if (fileSize > 1) {
39
+ $("#inputfile").val(null);
40
+ alert('file is too big. images more than 1MB are not allowed')
41
+ return
42
+ }
43
+
44
+ let ext = $('#inputfile').val().split('.').pop().toLowerCase();
45
+ if($.inArray(ext, ['jpg','jpeg']) == -1) {
46
+ $("#inputfile").val(null);
47
+ alert('only jpeg/jpg files are allowed!');
48
+ }
49
+ });
50
+ </script>
51
+ </body>
52
+ </html>
yolov5-flask-master/tests/test_inference.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import torch
3
+ from PIL import Image
4
+
5
+ # Model
6
+ model = torch.hub.load("ultralytics/yolov5", "yolov5s", pretrained=True, force_reload=True)
7
+
8
+ # img = Image.open("zidane.jpg") # PIL image direct open
9
+
10
+ # Read from bytes as we do in app
11
+ with open("zidane.jpg", "rb") as file:
12
+ img_bytes = file.read()
13
+ img = Image.open(io.BytesIO(img_bytes))
14
+
15
+ results = model(img, size=640) # includes NMS
16
+
17
+ print(results.pandas().xyxy[0])
yolov5-flask-master/tests/test_request.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Perform test request"""
2
+ import pprint
3
+ import requests
4
+
5
+ DETECTION_URL = "http://localhost:5000/v1/object-detection/yolov5s"
6
+ TEST_IMAGE = "zidane.jpg"
7
+
8
+ image_data = open(TEST_IMAGE, "rb").read()
9
+
10
+ response = requests.post(DETECTION_URL, files={"image": image_data}).json()
11
+
12
+ pprint.pprint(response)
yolov5-flask-master/tests/zidane.jpg ADDED
yolov5-flask-master/webapp.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Simple app to upload an image via a web form
3
+ and view the inference results on the image in the browser.
4
+ """
5
+ import argparse
6
+ import io
7
+ import os
8
+ from PIL import Image
9
+
10
+ import torch
11
+ from flask import Flask, render_template, request, redirect
12
+
13
+ app = Flask(__name__)
14
+
15
+
16
+ @app.route("/", methods=["GET", "POST"])
17
+ def predict():
18
+ if request.method == "POST":
19
+ if "file" not in request.files:
20
+ return redirect(request.url)
21
+ file = request.files["file"]
22
+ if not file:
23
+ return
24
+
25
+ img_bytes = file.read()
26
+ img = Image.open(io.BytesIO(img_bytes))
27
+ results = model(img, size=640)
28
+
29
+ # for debugging
30
+ # data = results.pandas().xyxy[0].to_json(orient="records")
31
+ # return data
32
+
33
+ results.render() # updates results.imgs with boxes and labels
34
+ for img in results.imgs:
35
+ img_base64 = Image.fromarray(img)
36
+ img_base64.save("static/image0.jpg", format="JPEG")
37
+ return redirect("static/image0.jpg")
38
+
39
+ return render_template("index.html")
40
+
41
+
42
+ if __name__ == "__main__":
43
+ parser = argparse.ArgumentParser(description="Flask app exposing yolov5 models")
44
+ parser.add_argument("--port", default=5000, type=int, help="port number")
45
+ args = parser.parse_args()
46
+
47
+ model = torch.hub.load('../yolov5', 'custom', path='../saved_model/s1000_best.pt', source='local') # force_reload = recache latest code
48
+ model.eval()
49
+ app.run(host="0.0.0.0", port=args.port) # debug=True causes Restarting with stat
50
+
51
+
52
+ #python3 webapp.py --port 5000
53
+
54
+
55
+ # python webapp.py --port 5000
56
+ # http://localhost:5000/