6.3. Python编程详解

BM1688/CV186AH SOPHONSDK通过SAIL库向用户提供Python编程接口

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

关于sail接口的详细信息,请阅读doc目录下的《sophon-sail_zh》。

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

  • 加载模型

  • 预处理

  • 推理

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. 预处理

 1class PreProcess:
 2    def __init__(self, width, height, batch_size, img_dtype, input_scale=None):
 3
 4        self.std = np.array([255., 255., 255.], dtype=np.float32)
 5        self.batch_size = batch_size
 6        self.input_scale = float(1.0) if input_scale is None else input_scale
 7        self.img_dtype = img_dtype
 8
 9        self.width = width
10        self.height = height
11        self.use_resize_padding = True
12        self.use_vpp = False
13        ...
14
15    def resize(self, img, handle, bmcv):
16
17        if self.use_resize_padding:
18            img_w = img.width()
19            img_h = img.height()
20            r_w = self.width / img_w
21            r_h = self.height / img_h
22
23            if r_h > r_w:
24                tw = self.width
25                th = int(r_w * img_h)
26                tx1 = tx2 = 0
27                ty1 = int((self.height - th) / 2)
28                ty2 = self.height - th - ty1
29
30            else:
31                tw = int(r_h * img_w)
32                th = self.height
33                tx1 = int((self.width - tw) / 2)
34                tx2 = self.width - tw - tx1
35                ty1 = ty2 = 0
36
37            ratio = (min(r_w, r_h), min(r_w, r_h))
38            txy = (tx1, ty1)
39            attr = sail.PaddingAtrr()
40            attr.set_stx(tx1)
41            attr.set_sty(ty1)
42            attr.set_w(tw)
43            attr.set_h(th)
44            attr.set_r(114)
45            attr.set_g(114)
46            attr.set_b(114)
47
48            tmp_planar_img = sail.BMImage(handle, img.height(), img.width(),
49                                      sail.Format.FORMAT_RGB_PLANAR, sail.DATA_TYPE_EXT_1N_BYTE)
50            bmcv.convert_format(img, tmp_planar_img)
51            preprocess_fn = bmcv.vpp_crop_and_resize_padding if self.use_vpp else bmcv.crop_and_resize_padding
52            resized_img_rgb = preprocess_fn(tmp_planar_img,
53                                        0, 0, img.width(), img.height(),
54                                        self.width, self.height, attr)
55        else:
56            r_w = self.width / img.width()
57            r_h = self.height / img.height()
58            ratio = (r_w, r_h)
59            txy = (0, 0)
60            tmp_planar_img = sail.BMImage(handle, img.height(), img.width(),
61                                        sail.Format.FORMAT_RGB_PLANAR, sail.DATA_TYPE_EXT_1N_BYTE)
62            bmcv.convert_format(img, tmp_planar_img)
63            preprocess_fn = bmcv.vpp_resize if self.use_vpp else bmcv.resize
64            resized_img_rgb = preprocess_fn(tmp_planar_img, self.width, self.height)
65        return resized_img_rgb, ratio, txy
66
67    ...
68
69    def norm_batch(self, resized_images, handle, bmcv):
70
71        bm_array = eval('sail.BMImageArray{}D'.format(self.batch_size))
72
73        preprocessed_imgs = bm_array(handle,
74                                 self.height,
75                                 self.width,
76                                 sail.FORMAT_RGB_PLANAR,
77                                 self.img_dtype)
78
79        a = 1 / self.std
80        b = (0, 0, 0)
81        alpha_beta = tuple([(ia * self.input_scale, ib * self.input_scale) for ia, ib in zip(a, b)])
82
83        # do convert_to
84        bmcv.convert_to(resized_images, preprocessed_imgs, alpha_beta)
85        return preprocessed_imgs

6.3.3. 推理

 1class SophonInference:
 2    def __init__(self, **kwargs):
 3
 4        ...
 5
 6        self.io_mode = sail.IOMode.SYSIO
 7        self.engine = sail.Engine(self.model_path, self.device_id, self.io_mode)
 8        self.handle = self.engine.get_handle()
 9        self.graph_name = self.engine.get_graph_names()[0]
10        self.bmcv = sail.Bmcv(self.handle)
11
12        ...
13
14        input_names = self.engine.get_input_names(self.graph_name)
15        for input_name in input_names:
16
17            input_shape = self.engine.get_input_shape(self.graph_name, input_name)
18            input_dtype = self.engine.get_input_dtype(self.graph_name, input_name)
19            input_scale = self.engine.get_input_scale(self.graph_name, input_name)
20            ...
21            if self.input_mode:
22                input = sail.Tensor(self.handle, input_shape, input_dtype, True, True)
23            ...
24            input_tensors[input_name] = input
25            ...
26
27        output_names = self.engine.get_output_names(self.graph_name)
28
29        for output_name in output_names:
30
31            output_shape = self.engine.get_output_shape(self.graph_name, output_name)
32            output_dtype = self.engine.get_output_dtype(self.graph_name, output_name)
33            output_scale = self.engine.get_output_scale(self.graph_name, output_name)
34            ...
35            if self.input_mode:
36                output = sail.Tensor(self.handle, output_shape, output_dtype, True, True)
37            ...
38            output_tensors[output_name] = output
39            ...
40    def infer_bmimage(self, input_data):
41        self.get_input_feed(self.input_names, input_data)
42
43        #inference
44        self.engine.process(self.graph_name, self.input_tensors, self.output_tensors)
45        outputs_dict = OrderedDict()
46        for name in self.output_names:
47            outputs_dict[name] = self.output_tensors[name].asnumpy().copy() * self.output_scales[name]
48        return outputs_dict