From 6ae33f6447fdb21309171a77a05f2aa1ff5d4101 Mon Sep 17 00:00:00 2001 From: MRXLT Date: Tue, 3 Mar 2020 17:28:11 +0800 Subject: [PATCH] add imagenet demo --- .../imagenet/image_classifcation_service.py | 119 ++++++++++++++++++ python/examples/imagenet/image_http_client.py | 35 ++++++ python/examples/imagenet/image_server.py | 45 +++++++ 3 files changed, 199 insertions(+) create mode 100644 python/examples/imagenet/image_classifcation_service.py create mode 100644 python/examples/imagenet/image_http_client.py create mode 100644 python/examples/imagenet/image_server.py diff --git a/python/examples/imagenet/image_classifcation_service.py b/python/examples/imagenet/image_classifcation_service.py new file mode 100644 index 00000000..f9263a4b --- /dev/null +++ b/python/examples/imagenet/image_classifcation_service.py @@ -0,0 +1,119 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from paddle_serving_server.plugin_service import PluginService +import sys +import cv2 +import base64 +from PIL import Image +from StringIO import StringIO +import numpy as np +from image_server import start_serving + + +class ImageService(PluginService): + def set_param(self): + self.image_mean = [0.485, 0.456, 0.406] + self.image_std = [0.229, 0.224, 0.225] + self.image_shape = [3, 224, 224] + self.resize_short_size = 256 + self.interpolation = None + + def resize_short(self, img, target_size, interpolation=None): + """resize image + + Args: + img: image data + target_size: resize short target size + interpolation: interpolation mode + + Returns: + resized image data + """ + percent = float(target_size) / min(img.shape[0], img.shape[1]) + resized_width = int(round(img.shape[1] * percent)) + resized_height = int(round(img.shape[0] * percent)) + if interpolation: + resized = cv2.resize( + img, (resized_width, resized_height), + interpolation=interpolation) + else: + resized = cv2.resize(img, (resized_width, resized_height)) + return resized + + def crop_image(self, img, target_size, center): + """crop image + + Args: + img: images data + target_size: crop target size + center: crop mode + + Returns: + img: cropped image data + """ + height, width = img.shape[:2] + size = target_size + if center == True: + w_start = (width - size) // 2 + h_start = (height - size) // 2 + else: + w_start = np.random.randint(0, width - size + 1) + h_start = np.random.randint(0, height - size + 1) + w_end = w_start + size + h_end = h_start + size + img = img[h_start:h_end, w_start:w_end, :] + return img + + def process_image(self, sample): + """ process_image """ + mean = self.image_mean + std = self.image_std + crop_size = self.image_shape[1] + + data = np.fromstring(sample, np.uint8) + img = cv2.imdecode(data, cv2.IMREAD_COLOR) + + if img is None: + print("img is None, pass it.") + return None + + if crop_size > 0: + target_size = self.resize_short_size + img = self.resize_short( + img, target_size, interpolation=self.interpolation) + img = self.crop_image(img, target_size=crop_size, center=True) + + img = img[:, :, ::-1] + + img = img.astype('float32').transpose((2, 0, 1)) / 255 + img_mean = np.array(mean).reshape((3, 1, 1)) + img_std = np.array(std).reshape((3, 1, 1)) + img -= img_mean + img /= img_std + return img + + def preprocess(self, feed={}, fetch=[]): + self.set_param() + if "image" not in feed: + raise ("feed data error!") + sample = base64.b64decode(feed["image"]) + img = self.process_image(sample) + res_feed = {} + res_feed["image"] = img.reshape(-1) + return res_feed, fetch + + +image_service = ImageService(name="image", model=sys.argv[1], port=9291) +image_service.start_service() diff --git a/python/examples/imagenet/image_http_client.py b/python/examples/imagenet/image_http_client.py new file mode 100644 index 00000000..00d8900c --- /dev/null +++ b/python/examples/imagenet/image_http_client.py @@ -0,0 +1,35 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import requests +import base64 +import sys +import cv2 +import json +import numpy as np + +image = open("./to_longteng/n01440764/n01440764_12362.JPEG").read() +image = base64.b64encode(image) + +req = {} +req["image"] = image +req["fetch"] = ["score"] + +req = json.dumps(req) +url = "http://127.0.0.1:9291/image/prediction" +headers = {"Content-Type": "application/json"} +r = requests.post(url, data=req, headers=headers) +score = r.json()["score"] +score = np.array(score) +print("max score : {} class {}".format(np.max(score), np.argmax(score))) diff --git a/python/examples/imagenet/image_server.py b/python/examples/imagenet/image_server.py new file mode 100644 index 00000000..54a6eb55 --- /dev/null +++ b/python/examples/imagenet/image_server.py @@ -0,0 +1,45 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys +from paddle_serving_server import OpMaker +from paddle_serving_server import OpSeqMaker +from paddle_serving_server import Server + + +def start_serving(): + op_maker = OpMaker() + + read_op = op_maker.create('general_reader') + general_infer_op = op_maker.create('general_infer') + general_response_op = op_maker.create('general_response') + + op_seq_maker = OpSeqMaker() + op_seq_maker.add_op(read_op) + op_seq_maker.add_op(general_infer_op) + op_seq_maker.add_op(general_response_op) + + server = Server() + server.set_op_sequence(op_seq_maker.get_op_sequence()) + server.set_num_threads(24) + + server.load_model_config(sys.argv[1]) + port = int(sys.argv[2]) + server.prepare_server(workdir="work_dir1", port=port, device="cpu") + server.run_server() + + +if __name__ == "__main__": + start_serving() -- GitLab