6.3. Python编程详解

SOPHONSDK通过SAIL库向用户提供Python编程接口。

这个章节将会选取 YOLOV5 检测算法作为示例, 来介绍python接口编程,样例代码路径位于sophon-demo/sample/YOLOV5

其他sail关于接口的更详细的信息,请阅读《 SOPHON-SAIL用户手册 》。

本章主要介绍以下三点内容:

  • 加载模型

  • 预处理

  • 推理

6.3.1. 加载模型

1import sophon.sail as sail
2
3...
4
5engine = sail.Engine(model_path, device_id, io_mode)
6
7...

6.3.2. 预处理

 1def preprocess(self, ori_img):
 2    """
 3    pre-processing
 4    Args:
 5        img: numpy.ndarray -- (h,w,3)
 6
 7    Returns: (3,h,w) numpy.ndarray after pre-processing
 8
 9    """
10    letterbox_img, ratio, (tx1, ty1) = self.letterbox(
11        ori_img,
12        new_shape=(self.net_h, self.net_w),
13        color=(114, 114, 114),
14        auto=False,
15        scaleFill=False,
16        scaleup=True,
17        stride=32
18    )
19
20    img = letterbox_img.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
21    img = img.astype(np.float32)
22    # input_data = np.expand_dims(input_data, 0)
23    img = np.ascontiguousarray(img / 255.0)
24    return img, ratio, (tx1, ty1)
25
26def letterbox(self, im, new_shape=(640, 640), color=(114, 114, 114), auto=False, scaleFill=False, scaleup=True, stride=32):
27    # Resize and pad image while meeting stride-multiple constraints
28    shape = im.shape[:2]  # current shape [height, width]
29    if isinstance(new_shape, int):
30        new_shape = (new_shape, new_shape)
31
32    # Scale ratio (new / old)
33    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
34    if not scaleup:  # only scale down, do not scale up (for better val mAP)
35        r = min(r, 1.0)
36
37    # Compute padding
38    ratio = r, r  # width, height ratios
39    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
40    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
41    if auto:  # minimum rectangle
42        dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding
43    elif scaleFill:  # stretch
44        dw, dh = 0.0, 0.0
45        new_unpad = (new_shape[1], new_shape[0])
46        ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]  # width, height ratios
47
48    dw /= 2  # divide padding into 2 sides
49    dh /= 2
50
51    if shape[::-1] != new_unpad:  # resize
52        im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
53    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
54    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
55    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
56    return im, ratio, (dw, dh)
57
58    ...

6.3.3. 推理

 1def predict(self, input_img, img_num):
 2        input_data = {self.input_name: input_img}
 3        outputs = self.net.process(self.graph_name, input_data)
 4
 5        if self.use_cpu_opt:
 6            out = {}
 7            for name in outputs.keys():
 8                # outputs_dict[name] = self.output_tensors[name].asnumpy()[:img_num] * self.output_scales[name]
 9                out[name] = sail.Tensor(self.handle, outputs[name])
10        else:
11            # resort
12            out_keys = list(outputs.keys())
13            ord = []
14            for n in self.output_names:
15                for i, k in enumerate(out_keys):
16                    if n == k:
17                        ord.append(i)
18                        break
19            out = [outputs[out_keys[i]][:img_num] for i in ord]
20        return out