diff --git a/deploy/paddle-serving/README.md b/deploy/paddle-serving/README.md index 8a62097474651a390db65a387ffc8c102bc0baa7..5faea824f16e741b8c2fc3767f055e3fcfcae0f3 100644 --- a/deploy/paddle-serving/README.md +++ b/deploy/paddle-serving/README.md @@ -6,7 +6,7 @@ PaddleServing是Paddle的在线预测服务框架,可以快速部署训练好 ## 2.安装Paddle Serving -目前PaddleServing的正式版本为0.3.2版本,本文中的示例需要develop版本的paddle_serving_app,请从[链接](https://github.com/PaddlePaddle/Serving/blob/develop/doc/LATEST_PACKAGES.md#app)中下载并安装。 +目前PaddleServing的正式版本为0.3.2版本。 服务端安装: @@ -47,41 +47,18 @@ python pdseg/export_serving_model.py --cfg configs/unet_optic.yaml TEST.TEST_MOD `freeze_model/serving_server`目录下包含了模型文件和serving server端配置文件,`freeze_model/serving_client`目录下包含了serving client端配置文件。 +分别将serving_server和serving_client复制到server和client启动的路径下。 + ## 4.部署预测服务 ```shell -python -m paddle_serving_server.serve --model unet_model/ --port 9494 # CPU -python -m paddle_serving_server_gpu.serve --model unet_model --port 9494 --gpu_ids 0 #GPU +python -m paddle_serving_server.serve --model serving_server/ --port 9494 # CPU +python -m paddle_serving_server_gpu.serve --model serving_server --port 9494 --gpu_ids 0 #GPU ``` ## 5.执行预测 - -```python -#seg_client.py -from paddle_serving_client import Client -from paddle_serving_app.reader import Sequential, File2Image, Resize, Transpose, BGR2RGB, SegPostprocess, Normalize, Div -import sys -import cv2 - -client = Client() -client.load_client_config("unet_client/serving_client_conf.prototxt") -client.connect(["127.0.0.1:9494"]) - -preprocess = Sequential([ - File2Image(), Resize( - (512, 512), interpolation=cv2.INTER_LINEAR), Div(255.0), - Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], False), Transpose((2, 0, 1)) -]) - -postprocess = SegPostprocess(2) - -filename = "N0060.jpg" -im = preprocess(filename) -fetch_map = client.predict(feed={"image": im}, fetch=["transpose_1.tmp_0"]) -fetch_map["filename"] = filename -postprocess(fetch_map) +```shell +python seg_client.py ../../dataset/optic_disc_seg/JPEGImages/N0060.jpg ``` - -脚本执行之后,当前目录下生成处理后的图片。 - -完整的部署示例请参考PaddleServing的[unet示例](https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/unet_for_image_seg)。 +脚本执行之后,会在输入图片所在的目录下生成处理后的图片 +示例中为`../../dataset/optic_disc_seg/JPEGImages/N0060_jpg_mask.png`和`../../dataset/optic_disc_seg/JPEGImages/N0060_jpg_result.png` diff --git a/deploy/paddle-serving/postprocess.py b/deploy/paddle-serving/postprocess.py new file mode 100644 index 0000000000000000000000000000000000000000..6e77879d4d1a4a756210facb9e9e8d7a2dba6c7b --- /dev/null +++ b/deploy/paddle-serving/postprocess.py @@ -0,0 +1,58 @@ +import cv2 +import numpy as np + + +def generate_colormap(num_classes): + color_map = num_classes * [0, 0, 0] + for i in range(0, num_classes): + j = 0 + lab = i + while lab: + color_map[i * 3] |= (((lab >> 0) & 1) << (7 - j)) + color_map[i * 3 + 1] |= (((lab >> 1) & 1) << (7 - j)) + color_map[i * 3 + 2] |= (((lab >> 2) & 1) << (7 - j)) + j += 1 + lab >>= 3 + color_map = [color_map[i:i + 3] for i in range(0, len(color_map), 3)] + return color_map + + +class SegPostprocess(object): + def __init__(self, class_num): + self.class_num = class_num + + def __call__(self, image_with_result): + if "filename" not in image_with_result: + raise ("filename should be specified in postprocess") + img_name = image_with_result["filename"] + ori_img = cv2.imread(img_name, -1) + ori_shape = ori_img.shape + mask = None + for key in image_with_result: + if ".lod" in key or "filename" in key: + continue + mask = image_with_result[key][0] + if mask is None: + raise ("segment mask should be specified in postprocess") + mask = np.argmax(mask, axis=0) + mask = mask.astype("uint8") + mask_png = mask + score_png = mask_png[:, :, np.newaxis] + score_png = np.concatenate([score_png] * 3, axis=2) + + color_map = generate_colormap(self.class_num) + for i in range(score_png.shape[0]): + for j in range(score_png.shape[1]): + score_png[i, j] = color_map[score_png[i, j, 0]] + ext_pos = img_name.rfind(".") + img_name_fix = img_name[:ext_pos] + "_" + img_name[ext_pos + 1:] + mask_save_name = img_name_fix + "_mask.png" + cv2.imwrite(mask_save_name, mask_png, [cv2.CV_8UC1]) + vis_result_name = img_name_fix + "_result.png" + result_png = score_png + + result_png = cv2.resize(result_png, (ori_shape[1], ori_shape[0]), + fx=0, + fy=0, + interpolation=cv2.INTER_CUBIC) + cv2.imwrite(vis_result_name, result_png, [cv2.CV_8UC1]) diff --git a/deploy/paddle-serving/seg_client.py b/deploy/paddle-serving/seg_client.py new file mode 100644 index 0000000000000000000000000000000000000000..cf90a8ab56fcf4c75ef09fd84958545598785d68 --- /dev/null +++ b/deploy/paddle-serving/seg_client.py @@ -0,0 +1,25 @@ +from paddle_serving_client import Client +from paddle_serving_app.reader import Sequential, File2Image, Resize, Transpose, BGR2RGB, Normalize, Div +import sys +import cv2 +from postprocess import SegPostprocess + +client = Client() +client.load_client_config("serving_client/serving_client_conf.prototxt") +client.connect(["127.0.0.1:9494"]) + +preprocess = Sequential([ + File2Image(), + Resize((512, 512), interpolation=cv2.INTER_LINEAR), + Div(255.0), + Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], False), + Transpose((2, 0, 1)) +]) + +postprocess = SegPostprocess(2) + +filename = sys.argv[1] +im = preprocess(filename) +fetch_map = client.predict(feed={"image": im}, fetch=["transpose_1.tmp_0"]) +fetch_map["filename"] = filename +postprocess(fetch_map)