forked from cortexlabs/cortex
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpredictor.py
98 lines (75 loc) · 2.85 KB
/
predictor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# WARNING: you are on the master branch, please refer to the examples on the branch that matches your `cortex version`
import numpy as np
import cv2, requests
from scipy.special import softmax
def get_url_image(url_image):
"""
Get numpy image from URL image.
"""
resp = requests.get(url_image, stream=True).raw
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
return image
def image_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
"""
Resize a numpy image.
"""
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
# calculate the ratio of the height and construct the dimensions
r = height / float(h)
dim = (int(w * r), height)
else:
# calculate the ratio of the width and construct the dimensions
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation=inter)
return resized
def preprocess(img_data):
"""
Normalize input for inference.
"""
# move pixel color dimension to position 0
img = np.moveaxis(img_data, 2, 0)
mean_vec = np.array([0.485, 0.456, 0.406])
stddev_vec = np.array([0.229, 0.224, 0.225])
norm_img_data = np.zeros(img.shape).astype("float32")
for i in range(img.shape[0]):
# for each pixel in each channel, divide the value by 255 to get value between [0, 1] and then normalize
norm_img_data[i, :, :] = (img[i, :, :] / 255 - mean_vec[i]) / stddev_vec[i]
# extend to batch size of 1
norm_img_data = norm_img_data[np.newaxis, ...]
return norm_img_data
def postprocess(results):
"""
Eliminates all dimensions of size 1, softmaxes the input and then returns the index of the element with the highest value.
"""
squeezed = np.squeeze(results)
maxed = softmax(squeezed)
result = np.argmax(maxed)
return result
class ONNXPredictor:
def __init__(self, onnx_client, config):
# onnx client
self.client = onnx_client
# for image classifiers
classes = requests.get(config["image-classifier-classes"]).json()
self.image_classes = [classes[str(k)][1] for k in range(len(classes))]
self.resize_value = config["image-resize"]
def predict(self, payload, query_params):
# get request params
model_name = query_params["model"]
img_url = payload["url"]
# process the input
img = get_url_image(img_url)
img = image_resize(img, height=self.resize_value)
img = preprocess(img)
# predict
results = self.client.predict(img, model_name)[0]
# interpret result
result = postprocess(results)
predicted_label = self.image_classes[result]
return {"label": predicted_label}