Skip to content

Commit 3c4e2fc

Browse files
committed
Add pages for json inference and image inference
1 parent 0282d2e commit 3c4e2fc

File tree

7 files changed

+273
-81
lines changed

7 files changed

+273
-81
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
import json
5+
import requests
6+
from PIL import Image
7+
import numpy as np
8+
9+
10+
def predict_image(image_file_path):
11+
endpoint = "http://127.0.0.1:8500"
12+
13+
img = Image.open(image_file_path)
14+
img = img.convert('RGB')
15+
img.load()
16+
image_ndarray = np.asarray(img, dtype="int32")
17+
# Shape is [48, 400, 3] -> [400, 48, 3]
18+
image_ndarray = image_ndarray.transpose((1, 0, 2))
19+
image_array = [image_ndarray.tolist()]
20+
# TODO: Support specified model name
21+
json_data = {"model_name": "default", "data": {"image": image_array}}
22+
23+
result = requests.post(endpoint, json=json_data)
24+
25+
# Shape is [-1, -1]
26+
predict_result = json.loads(result.text)
27+
print("Get predict result:{}".format(predict_result))
28+
29+
return predict_result
30+
31+
32+
def predict_json(json_data):
33+
# TODO: Support for other endpoint
34+
endpoint = "http://127.0.0.1:8500"
35+
36+
result = requests.post(endpoint, json=json_data)
37+
38+
predict_result = json.loads(result.text)
39+
print("Get predict result:{}".format(predict_result))
40+
41+
return predict_result
42+
43+
44+
# TODO: Only support testing with images
45+
def parse_args():
46+
parser = argparse.ArgumentParser(description='Predict image')
47+
parser.add_argument(
48+
'--image', required=False, type=str, default="./0.jpg", help='The image')
49+
args = parser.parse_args()
50+
return args
51+
52+
53+
def main(args):
54+
image_file_path = args.image
55+
predict_image(image_file_path)
56+
57+
58+
if __name__ == "__main__":
59+
main(parse_args())

simple_tensorflow_serving/server.py

+46-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import argparse
44
#import argcomplete
5+
import os
56
import cStringIO
67
import json
78
import logging
@@ -16,6 +17,7 @@
1617
from tensorflow_inference_service import TensorFlowInferenceService
1718
from mxnet_inference_service import MxnetInferenceService
1819
from onnx_inference_service import OnnxInferenceService
20+
import python_predict_client
1921

2022
logging.basicConfig(level=logging.DEBUG)
2123

@@ -151,6 +153,9 @@ def decorated(*decorator_args, **decorator_kwargs):
151153
# Initialize flask application
152154
application = Flask(__name__, template_folder='templates')
153155

156+
UPLOAD_FOLDER = os.path.basename('static')
157+
application.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
158+
154159
# Example: {"default": TensorFlowInferenceService}
155160
model_name_service_map = {}
156161

@@ -271,9 +276,49 @@ def inference():
271276
return jsonify(json.loads(json.dumps(result, cls=NumpyEncoder)))
272277

273278

279+
@application.route('/image_inference', methods=["GET"])
280+
def image_inference():
281+
return render_template('image_inference.html')
282+
283+
284+
@application.route('/run_image_inference', methods=['POST'])
285+
def run_image_inference():
286+
file = request.files['image']
287+
file_path = os.path.join(application.config['UPLOAD_FOLDER'], file.filename)
288+
file.save(file_path)
289+
290+
image_file_path = os.path.join(application.config['UPLOAD_FOLDER'],
291+
file.filename)
292+
predict_result = python_predict_client.predict_image(image_file_path)
293+
294+
return render_template(
295+
'image_inference.html',
296+
image_file_path=image_file_path,
297+
predict_result=predict_result)
298+
299+
300+
@application.route('/json_inference', methods=["GET"])
301+
def json_inference():
302+
return render_template('json_inference.html')
303+
304+
305+
@application.route('/run_json_inference', methods=['POST'])
306+
def run_json_inference():
307+
json_data_string = request.form["json_data"]
308+
json_data = json.loads(json_data_string)
309+
model_name = request.form["model_name"]
310+
311+
request_json_data = {"model_name": model_name, "data": json_data}
312+
313+
predict_result = python_predict_client.predict_json(request_json_data)
314+
315+
return render_template('json_inference.html', predict_result=predict_result)
316+
317+
274318
def main():
275319
# Start the HTTP server
276-
application.run(host=args.host, port=args.port)
320+
# Support multi-thread for json inference and image inference
321+
application.run(host=args.host, port=args.port, threaded=True)
277322

278323

279324
if __name__ == "__main__":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<br/>
2+
<footer class="footer" id="footer">
3+
<div style='margin:0px 0px auto auto' class="footer-copyright text-center rgba-black-light">
4+
<div class="container-fluid">
5+
<small>Copyright © 2018</small>
6+
</div>
7+
</div>
8+
</footer> <!-- end of footer -->
9+
10+
</div> <!-- End of container -->
11+
12+
</body>
13+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
5+
<!--[if IE]>
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7+
<![endif]-->
8+
<meta charset="utf-8">
9+
<title>Simple TensorFlow Serving</title>
10+
<meta name="description" content="Once photograph.">
11+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
12+
13+
<link rel="shortcut icon" type="image/png" href="/static/images/favicon.ico"/>
14+
15+
<link rel="stylesheet" href="/static/bootstrap-4.0.0-dist/css/bootstrap.min.css">
16+
17+
<script type="text/javascript" src="/static/jquery/dist/jquery.min.js"></script>
18+
<script type="text/javascript" src="/static/bootstrap-4.0.0-dist/js/bootstrap.min.js"></script>
19+
20+
</head>
21+
<body>
22+
23+
<!-- nav bar -->
24+
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
25+
26+
<div class="navbar-header">
27+
<a class="navbar-brand" href="/">
28+
<img alt="Brand" height="26px" src="/static/images/logo.png">
29+
</a>
30+
</div>
31+
32+
<button class="navbar-toggler" type="button" data-toggle="collapse"
33+
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
34+
aria-expanded="false" aria-label="Toggle navigation">
35+
<span class="navbar-toggler-icon"></span>
36+
</button>
37+
38+
<div class="collapse navbar-collapse" id="navbarSupportedContent">
39+
<ul class="navbar-nav mr-auto">
40+
<li class="nav-item active">
41+
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
42+
</li>
43+
<li class="nav-item dropdown">
44+
<a class="nav-link dropdown-toggle" href="#" id="test_nav" role="button"
45+
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Test</a>
46+
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
47+
<a class="dropdown-item"
48+
href="/json_inference">JSON inference</a>
49+
<a class="dropdown-item"
50+
href="/image_inference">Image inference</a>
51+
</div>
52+
</li>
53+
<li class="nav-item dropdown">
54+
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
55+
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">More</a>
56+
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
57+
<a class="dropdown-item" target="_blank"
58+
href="https://github.com/tobegit3hub/simple_tensorflow_serving">Github</a>
59+
<a class="dropdown-item" target="_blank"
60+
href="https://github.com/tobegit3hub/simple_tensorflow_serving/issues">Issues</a>
61+
<a class="dropdown-item" target="_blank"
62+
href="https://github.com/tobegit3hub/simple_tensorflow_serving/pulls">Pull
63+
requests</a>
64+
</div>
65+
</li>
66+
</ul>
67+
<form class="form-inline my-2 my-lg-0">
68+
<input class="form-control mr-sm-2" type="search" placeholder="Search"
69+
aria-label="Search">
70+
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
71+
</form>
72+
</div>
73+
</nav> <!-- end of nav bar -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{% include "header.html" %}
2+
3+
<br />
4+
<div class="container">
5+
6+
<form action="/run_image_inference" method="post" enctype="multipart/form-data" >
7+
<span class="btn btn-default btn-file">
8+
Browse files<input type="file" name="image">
9+
</span>
10+
11+
<input type="submit" value="Upload image" class="btn btn-primary">
12+
</form>
13+
14+
<h2>Predict image: </h2>
15+
<img src={{ image_file_path }} />
16+
17+
<h2>Predict result: </h2>
18+
<p>{{ predict_result }}</p>
19+
20+
</div>
21+
22+
{% include "footer.html" %}

simple_tensorflow_serving/templates/index.html

+4-80
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,5 @@
1-
<!DOCTYPE html>
2-
<html>
3-
<head>
4-
5-
<!--[if IE]>
6-
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7-
<![endif]-->
8-
<meta charset="utf-8">
9-
<title>Simple TensorFlow Serving</title>
10-
<meta name="description" content="Once photograph.">
11-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
12-
13-
<link rel="shortcut icon" type="image/png" href="/static/images/favicon.ico"/>
14-
15-
<link rel="stylesheet" href="/static/bootstrap-4.0.0-dist/css/bootstrap.min.css">
16-
17-
<script type="text/javascript" src="/static/jquery/dist/jquery.min.js"></script>
18-
<script type="text/javascript" src="/static/bootstrap-4.0.0-dist/js/bootstrap.min.js"></script>
19-
20-
</head>
21-
<body>
22-
23-
<!-- nav bar -->
24-
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
25-
26-
<div class="navbar-header">
27-
<a class="navbar-brand" href="#">
28-
<img alt="Brand" height="26px" src="/static/images/logo.png">
29-
</a>
30-
</div>
31-
32-
<button class="navbar-toggler" type="button" data-toggle="collapse"
33-
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
34-
aria-expanded="false" aria-label="Toggle navigation">
35-
<span class="navbar-toggler-icon"></span>
36-
</button>
37-
38-
<div class="collapse navbar-collapse" id="navbarSupportedContent">
39-
<ul class="navbar-nav mr-auto">
40-
<li class="nav-item active">
41-
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
42-
</li>
43-
<li class="nav-item">
44-
<a class="nav-link" target="_blank"
45-
href="https://github.com/tobegit3hub/simple_tensorflow_serving">Github</a>
46-
</li>
47-
<li class="nav-item dropdown">
48-
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
49-
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">More</a>
50-
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
51-
<a class="dropdown-item" target="_blank"
52-
href="https://github.com/tobegit3hub/simple_tensorflow_serving/issues">Issues</a>
53-
<a class="dropdown-item" target="_blank"
54-
href="https://github.com/tobegit3hub/simple_tensorflow_serving/pulls">Pull
55-
requests</a>
56-
</div>
57-
</li>
58-
</ul>
59-
<form class="form-inline my-2 my-lg-0">
60-
<input class="form-control mr-sm-2" type="search" placeholder="Search"
61-
aria-label="Search">
62-
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
63-
</form>
64-
</div>
65-
</nav> <!-- end of nav bar -->
661

2+
{% include "header.html" %}
673

684
<div class="container">
695

@@ -83,8 +19,8 @@ <h4>Server Status</h4>
8319
<div class="col-md-8">
8420
<div class="progress">
8521
<div class="progress-bar progress-bar-striped progress-bar-animated"
86-
role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"
87-
style="width: 75%"></div>
22+
role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"
23+
style="width: 100%"></div>
8824
</div>
8925
</div>
9026
</div>
@@ -179,16 +115,4 @@ <h4>Graph Signature</h4>
179115
-->
180116

181117

182-
<br/>
183-
<footer class="footer" id="footer">
184-
<div style='margin:0px 0px auto auto' class="footer-copyright text-center rgba-black-light">
185-
<div class="container-fluid">
186-
<small>Copyright © 2018</small>
187-
</div>
188-
</div>
189-
</footer> <!-- end of footer -->
190-
191-
</div> <!-- End of container -->
192-
193-
</body>
194-
</html>
118+
{% include "footer.html" %}

0 commit comments

Comments
 (0)