-# Run PaddlePaddle model by OpenCV
+# Run PaddlePaddle model using OpenCV
-This tutorial shows how to run PaddlePaddle model by opencv.
+These two demonstrations show how to inference PaddlePaddle model using OpenCV.
## Environment Setup
pip install paddle2onnx
```
-## Run PaddlePaddle model demo
+## 1. Run PaddlePaddle ResNet50 using OpenCV
-Run the example code as below,
+### Run PaddlePaddle model demo
+
+Run the code sample as follows:
```shell
python paddle_resnet50.py
```
-there are 3 part of this execution
+There are three parts to the process:
+
+1. Export PaddlePaddle ResNet50 model to onnx format.
+2. Use `cv2.dnn.readNetFromONNX` to load the model file.
+3. Preprocess image file and do the inference.
+
+## 2. Run PaddleSeg Portrait Segmentation using OpenCV
+
+### Convert to ONNX Model
+
+#### 1. Get Paddle Inference model
+
+For more details, please refer to [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.1/contrib/HumanSeg/README.md).
+
+```shell
+wget https://x2paddle.bj.bcebos.com/inference/models/humanseg_hrnet18_small_v1.zip
+unzip humanseg_hrnet18_small_v1.zip
+```
+
+Notes:
+
+* The exported model must have a fixed input shape, as dynamic is not supported at this moment.
+
+#### 2. Convert to ONNX model using paddle2onnx
+
+To convert the model, use the following command:
+
+```
+paddle2onnx --model_dir humanseg_hrnet18_small_v1 \
+ --model_filename model.pdmodel \
+ --params_filename model.pdiparams \
+ --opset_version 11 \
+ --save_file humanseg_hrnet18_tiny.onnx
+```
+
+The converted model can be found in the current directory by the name `humanseg_hrnet18_tiny.onnx` .
+
+### Run PaddleSeg Portrait Segmentation demo
+
+Run the code sample as follows:
+
+```shell
+python paddle_humanseg.py
+```
+
+There are three parts to the process:
+
+1. Use `cv2.dnn.readNetFromONNX` to load the model file.
+2. Preprocess image file and do inference.
+3. Postprocess image file and visualize.
+
+The resulting file can be found at `data/result_test_human.jpg` .
+
+### Portrait segmentation visualization
-- 1. Export PaddlePaddle ResNet50 model to onnx format;
-- 2. Use `cv2.dnn.readNetFromONNX` load model file;
-- 3. Preprocess image file and do inference.
+<img src="../../../../data/messi5.jpg" width="50%" height="50%"><img src="./data/result_test_human.jpg" width="50%" height="50%">
--- /dev/null
+import os
+import paddlehub.vision.transforms as T
+import numpy as np
+import cv2 as cv
+
+
+def get_color_map_list(num_classes):
+ """
+ Returns the color map for visualizing the segmentation mask,
+ which can support arbitrary number of classes.
+
+ Args:
+ num_classes (int): Number of classes.
+
+ Returns:
+ (list). The color map.
+ """
+
+ num_classes += 1
+ 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[3:]
+ return color_map
+
+
+def visualize(image, result, save_dir=None, weight=0.6):
+ """
+ Convert predict result to color image, and save added image.
+
+ Args:
+ image (str): The path of origin image.
+ result (np.ndarray): The predict result of image.
+ save_dir (str): The directory for saving visual image. Default: None.
+ weight (float): The image weight of visual image, and the result weight is (1 - weight). Default: 0.6
+
+ Returns:
+ vis_result (np.ndarray): If `save_dir` is None, return the visualized result.
+ """
+
+ color_map = get_color_map_list(256)
+ color_map = [color_map[i:i + 3] for i in range(0, len(color_map), 3)]
+ color_map = np.array(color_map).astype("uint8")
+ # Use OpenCV LUT for color mapping
+ c1 = cv.LUT(result, color_map[:, 0])
+ c2 = cv.LUT(result, color_map[:, 1])
+ c3 = cv.LUT(result, color_map[:, 2])
+ pseudo_img = np.dstack((c1, c2, c3))
+
+ im = cv.imread(image)
+ vis_result = cv.addWeighted(im, weight, pseudo_img, 1 - weight, 0)
+
+ if save_dir is not None:
+ if not os.path.exists(save_dir):
+ os.makedirs(save_dir)
+ image_name = os.path.split(image)[-1]
+ out_path = os.path.join(save_dir, image_name)
+ cv.imwrite(out_path, vis_result)
+ else:
+ return vis_result
+
+
+def preprocess(image_path):
+ ''' preprocess input image file to np.ndarray
+
+ Args:
+ image_path(str): Path of input image file
+
+ Returns:
+ ProcessedImage(numpy.ndarray): A numpy.ndarray
+ variable which shape is (1, 3, 192, 192)
+ '''
+ transforms = T.Compose([
+ T.Resize((192, 192)),
+ T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
+ ],
+ to_rgb=True)
+ return np.expand_dims(transforms(image_path), axis=0)
+
+
+if __name__ == '__main__':
+ img_path = "../../../../data/messi5.jpg"
+ # load PPSeg Model use cv.dnn
+ net = cv.dnn.readNetFromONNX('humanseg_hrnet18_tiny.onnx')
+ # read and preprocess image file
+ im = preprocess(img_path)
+ # inference
+ net.setInput(im)
+ result = net.forward(['save_infer_model/scale_0.tmp_1'])
+ # post process
+ image = cv.imread(img_path)
+ r, c, _ = image.shape
+ result = np.argmax(result[0], axis=1).astype(np.uint8)
+ result = cv.resize(result[0, :, :],
+ dsize=(c, r),
+ interpolation=cv.INTER_NEAREST)
+
+ print("grid_image.shape is: ", result.shape)
+ folder_path = "data"
+ if not os.path.exists(folder_path):
+ os.makedirs(folder_path)
+ file_path = os.path.join(folder_path, '%s.jpg' % "result_test_human")
+ result_color = visualize(img_path, result)
+ cv.imwrite(file_path, result_color)
+ print('%s saved' % file_path)
variable which shape is (1, 3, 224, 224)
'''
transforms = T.Compose([
- T.Resize((256, 256)),
- T.CenterCrop(224),
- T.Normalize(mean=[0.485, 0.456, 0.406],
- std=[0.229, 0.224, 0.225])],
- to_rgb=True)
+ T.Resize((256, 256)),
+ T.CenterCrop(224),
+ T.Normalize(mean=[0.485, 0.456, 0.406],
+ std=[0.229, 0.224, 0.225])],
+ to_rgb=True)
return np.expand_dims(transforms(image_path), axis=0)
-def export_onnx_mobilenetv2(save_path):
+def export_onnx_resnet50(save_path):
''' export PaddlePaddle model to ONNX format
Args:
'''
model = hub.Module(name="resnet50_vd_imagenet_ssld")
input_spec = paddle.static.InputSpec(
- [1, 3, 224, 224], "float32", "image")
+ [1, 3, 224, 224], "float32", "image")
paddle.onnx.export(model, save_path,
input_spec=[input_spec],
opset_version=10)
save_path = './resnet50'
image_file = './data/cat.jpg'
labels = open('./data/labels.txt').read().strip().split('\n')
- model = export_onnx_mobilenetv2(save_path)
+ model = export_onnx_resnet50(save_path)
- # load mobilenetv2 use cv.dnn
+ # load resnet50 use cv.dnn
net = cv.dnn.readNetFromONNX(save_path + '.onnx')
# read and preprocess image file
im = preprocess(image_file)