Teach you how to deploy FreeYOLO

Author: Kissrabbit
Original link: https://zhuanlan.zhihu.com/p/578830729

This chapter will explain how to convert the weight file trained by torch into an ONNX file, and how to deploy it back to the OpenVINO、TensorRTetc. framework. The author will take my own FreeYOLO project as an example to complete the content of this chapter. The relevant code is as follows:
https://link.zhihu.com/?target=https%3A//github.com/yjh0410/What
insert image description here
is FreeYOLO FreeYOLO? This is an amateur target detection project of the author. The YOLO detector combined with the YOLOXnetwork structure version of SimOTAand is currently the only amateur project that the author is maintaining. Interested readers can click on another article to learn about this FreeYOLO project, our follow-up content is to explain the relevant deployment on the basis of this project. Therefore, in order to facilitate the study of subsequent content, readers are recommended to download the author's FreeYOLO project and complete the configuration of the relevant environment according to the files given in the project.YOLOv7anchor-freerequirements.txt

When studying this part of the content, the author fully draws on many related operations and code implementations of the YOLOX project. Therefore, I am very grateful to Megvii for the open source YOLOX work, and I am very grateful to the YOLOX team for the open source multi-platform deployment code.

1. ONNX deployment

1.1 Convert PyTorch model to ONNX

Before starting this part of the work, let's install some necessary libraries to complete the follow-up operations:

pip install onnxruntime
pip install onnxsim

For the second onnxsimlibrary, it is optional and only applicable to onnx files obtained by simplifying onnxruntime conversion. At least make sure you have the onnxruntime library installed, otherwise you won't be able to .pthconvert pytorch's weight files to ONNXthe format.

cd <FreeYOLO_dir>
cd tools/

First of all, readers can open the tools folder of the FreeYOLO project, and you can see a export_onnx.pyfile named . Among them, the code for converting ONNX files is written. We mainly look at the main() function. First, we build the FreeYOLO model:

@logger.catch
def main():
    args = make_parser().parse_args()
    logger.info("args value: {}".format(args))
    device = torch.device('cpu')

    # config
    cfg = build_config(args)

    # build model
    model = build_model(args=args, 
                        cfg=cfg,
                        device=device, 
                        num_classes=80, 
                        trainable=False)

Then, load the trained COCO weights, and readers can READMEdownload the corresponding weight files from the files in the project. Suppose we have downloaded FreeYOLO-Tinythe weight file of the modelyolo_free_tiny.pth

# load trained weight
 model = load_weight(model=model, path_to_ckpt=args.weight)
 model = model.to(device).eval()

 # replace nn.SiLU with SiLU
 model = replace_module(model, nn.SiLU, SiLU)

Then, we can convert it to ONNX format:

logger.info("loading checkpoint done.")
dummy_input = torch.randn(args.batch_size, 3, cfg['test_size'], cfg['test_size'])

# save onnx file
save_path = os.path.join(args.save_dir, str(args.opset))
os.makedirs(save_path, exist_ok=True)
output_name = os.path.join(save_path, args.output_name)

torch.onnx._export(
    model,
    dummy_input,
    output_name,
    input_names=[args.input],
    output_names=[args.output],
    dynamic_axes={
    
    args.input: {
    
    0: 'batch'},
                  args.output: {
    
    0: 'batch'}} if args.dynamic else None,
    opset_version=args.opset,
)

logger.info("generated onnx model named {}".format(output_name))

Among them, args.save_dirit is the path to save the converted file, such as weights/onnx/; args.output_namethe name of the output file, such as yolo_free_large.onnx; args.opset is the opset version number of ONNX. If you do not plan to gradually convert the ONNX format to OpenVINOXML format, The default is used here 11, otherwise, we need to manually pass in –opset 10 to set the version number of opset when running, so that it can be converted to the OpenVINO XMLformat later.

Please note that before conversion, we need to set a variable named dummy_input, which is used to store the size of the test image. When using the model in ONNX format for inference, the size of the input image must be kept with the size set here. unanimous. For example, here we set it dummy_input = torch.randn(args.batch_size,3, 416, 416), then in the subsequent reasoning, a 416x416 image must be given instead of other sizes, otherwise an error will be reported.

In addition, if we have installed the onnxsim library and args.no_onnxsim is False, the code will further simplify the converted ONNX format. However, the author does not understand the advantages of this simplified ONNX format for the time being, so I won’t introduce it here.

The code to convert the ONNX format is very simple, and finally the reader can complete the conversion through the following command:

python3 export_onnx.py --output-name yolo_free_tiny.onnx -n yolo_free_tiny --weight ../weight/coco/yolo_free_tiny/yolo_free_tiny.pth --no_decode

Among them, --no_decodeit means that we do not do post-processing in the reasoning stage, because post-processing will include some 非pytorchoperations, and errors will be reported. We need to write post-processing code externally, which we will talk about in the follow-up content. Here, we You only need to let the model do forward reasoning without post-processing operations, and readers can models/yolo_free/yolo_free.py see the corresponding processing in the model file.

if self.no_decode:
    # no post process
    obj_preds = torch.cat(all_obj_preds, dim=0)
    cls_preds = torch.cat(all_cls_preds, dim=0)
    reg_preds = torch.cat(all_reg_preds, dim=0)
    # [n_anchors_all, 4 + 1 + C]
    outputs = torch.cat([reg_preds, obj_preds.sigmoid(), cls_preds.sigmoid()], dim=-1)

    return outputs

When running the upper-end command, if it goes well, we will see the output information as shown in the figure:

insert image description here
weights/onnx/11/So far, we have successfully converted the trained weights into ONNX format, and readers can find the converted files under the project folder.

1.2 Python-based ONNX reasoning

After completing the above conversion, we can use the model file in ONNX format for inference. Ask the reader to open the project deployment/ONNXRuntime/文件夹, you can see a onnx_inference.pyfile and a READMEfile.

cd <FreeYOLO_dir>/
cd deployment/ONNXRuntime/

Let's take a look at onnx_inference.pythe command line parameters of the file for our subsequent use, as follows:

def make_parser():
    parser = argparse.ArgumentParser("onnxruntime inference sample")
    parser.add_argument("--model", type=str, default="../../weights/onnx/11/yolo_free_tiny.onnx",
                        help="Input your onnx model.")
    parser.add_argument("-i", "--image_path", type=str, default='../test_image.jpg',
                        help="Path to your input image.")
    parser.add_argument("-o", "--output_dir", type=str, default='../../det_results/onnx/',
                        help="Path to your output directory.")
    parser.add_argument("-s", "--score_thr", type=float, default=0.3,
                        help="Score threshould to filter the result.")
    parser.add_argument("-size", "--img_size", type=int, default=640,
                        help="Specify an input shape for inference.")
    return parser

Among them, --modelit is the storage path of our converted ONNX file; --image_pathit is the reading path of the test picture; –output_dir is the storage path of the test result; --score_thrit is the confidence threshold, the default is 0.3; –img_size is the size of the test picture, because Before converting the ONNX format, we manually set a size, which must be consistent with this setting value.

Next, we look at the core code. First, for the reasoning behind, we prepare some necessary variables:

if __name__ == '__main__':
    args = make_parser().parse_args()

    # class color for better visualization
    np.random.seed(0)
    class_colors = [(np.random.randint(255),
                     np.random.randint(255),
                     np.random.randint(255)) for _ in range(80)]

    # preprocessor
    prepocess = PreProcessor(img_size=args.img_size)

    # postprocessor
    postprocess = PostProcessor(
        img_size=args.img_size, strides=[8, 16, 32],
        num_classes=80, conf_thresh=args.score_thr, nms_thresh=0.5)

Among them, class_colorfor the sake of good visualization, different types of boxes have different colors, which is easy to distinguish; preprocessit is used to preprocess the read images, and readers can utils/pre_process.pyfind the definition of this class in the file:

# designed for demo

import numpy as np
import cv2


class PreProcessor(object):
    def __init__(self, img_size):
        self.img_size = img_size
        self.input_size = [img_size, img_size]

    def __call__(self, image, swap=(2, 0, 1)):
        """
        Input:
            image: (ndarray) [H, W, 3] or [H, W]
            formar: color format
        """
        if len(image.shape) == 3:
            padded_img = np.ones((self.input_size[0], self.input_size[1], 3), np.float32) * 114.
        else:
            padded_img = np.ones(self.input_size, np.float32) * 114.
        # resize
        orig_h, orig_w = image.shape[:2]
        r = min(self.input_size[0] / orig_h, self.input_size[1] / orig_w)
        resize_size = (int(orig_w * r), int(orig_h * r))
        if r != 1:
            resized_img = cv2.resize(image, resize_size, interpolation=cv2.INTER_LINEAR)
        else:
            resized_img = image

        # pad
        padded_img[:resize_size[1], :resize_size[0]] = resized_img

        # [H, W, C] -> [C, H, W]
        padded_img = padded_img.transpose(swap)
        padded_img = np.ascontiguousarray(padded_img, dtype=np.float32)

        return padded_img, r

注意, here we no longer need to normalize the image read by opencv, convert BGR to RGB format, etc. as before. The author's FreeYOLO项目中的预处理代码也取消了这些操作. From the recent YOLOv5, YOLOX and YOLOv7, we can no longer see these operations, and directly use the images read by opencv for 大epoch、多种数据增强的training 归一化就显得不必要了. Moreover, when C++ is deployed, the corresponding code is also saved, which is also very convenient.

In addition, in addition to preprocessing, we also need to do 后处理operations. Readers can utils/post_process.pydefine postprocess in the file. This class is used for postprocessing, including 解算边界框、阈值筛选和NMS处理:

# designed for demo

import numpy as np
from .nms import multiclass_nms


class PostProcessor(object):
    def __init__(self, img_size, strides, num_classes, conf_thresh=0.15, nms_thresh=0.5):
        self.img_size = img_size
        self.num_classes = num_classes
        self.conf_thresh = conf_thresh
        self.nms_thresh = nms_thresh
        self.strides = strides

        # generate anchors
        self.anchors, self.expand_strides = self.generate_anchors()


    def generate_anchors(self):
        """
            fmp_size: (List) [H, W]
        """
        all_anchors = []
        all_expand_strides = []
        for stride in self.strides:
            # generate grid cells
            fmp_h, fmp_w = self.img_size // stride, self.img_size // stride
            anchor_x, anchor_y = np.meshgrid(np.arange(fmp_w), np.arange(fmp_h))
            # [H, W, 2]
            anchor_xy = np.stack([anchor_x, anchor_y], axis=-1)
            shape = anchor_xy.shape[:2]
            # [H, W, 2] -> [HW, 2]
            anchor_xy = (anchor_xy.reshape(-1, 2) + 0.5) * stride
            all_anchors.append(anchor_xy)

            # expanded stride
            strides = np.full((*shape, 1), stride)
            all_expand_strides.append(strides.reshape(-1, 1))

        anchors = np.concatenate(all_anchors, axis=0)
        expand_strides = np.concatenate(all_expand_strides, axis=0)

        return anchors, expand_strides


    def decode_boxes(self, anchors, pred_regs):
        """
            anchors:  (List[Tensor]) [1, M, 2] or [M, 2]
            pred_reg: (List[Tensor]) [B, M, 4] or [B, M, 4]
        """
        # center of bbox
        pred_ctr_xy = anchors[..., :2] + pred_regs[..., :2] * self.expand_strides
        # size of bbox
        pred_box_wh = np.exp(pred_regs[..., 2:]) * self.expand_strides

        pred_x1y1 = pred_ctr_xy - 0.5 * pred_box_wh
        pred_x2y2 = pred_ctr_xy + 0.5 * pred_box_wh
        pred_box = np.concatenate([pred_x1y1, pred_x2y2], axis=-1)

        return pred_box


    def __call__(self, predictions):
        """
        Input:
            predictions: (ndarray) [n_anchors_all, 4+1+C]
        """
        reg_preds = predictions[..., :4]
        obj_preds = predictions[..., 4:5]
        cls_preds = predictions[..., 5:]
        scores = np.sqrt(obj_preds * cls_preds)

        # scores & labels
        labels = np.argmax(scores, axis=1)                      # [M,]
        scores = scores[(np.arange(scores.shape[0]), labels)]   # [M,]

        # bboxes
        bboxes = self.decode_boxes(self.anchors, reg_preds)     # [M, 4]    

        # thresh
        keep = np.where(scores > self.conf_thresh)
        scores = scores[keep]
        labels = labels[keep]
        bboxes = bboxes[keep]

        # nms
        scores, labels, bboxes = multiclass_nms(
            scores, labels, bboxes, self.nms_thresh, self.num_classes, True)

        return bboxes, scores, labels

With these tools in place, we can use the ONNX model for inference. First, we use OpenCVthe library to read the test image test_image.jpgand then preprocess it:

# read an image
input_shape = tuple([args.img_size, args.img_size])
origin_img = cv2.imread(args.image_path)

# preprocess
x, ratio = prepocess(origin_img)

Then hand it over to the ONNX model for reasoning, and get the output variable output:

t0 = time.time()
# inference
session = onnxruntime.InferenceSession(args.model)

ort_inputs = {
    
    session.get_inputs()[0].name: x[None, :, :, :]}
output = session.run(None, ort_inputs)
print("inference time: {:.1f} ms".format((time.time() - t0)*100))

Among them, output[0]is the output of FreeYOLO, we post-process it, and get three processing results of bounding box, score and category:

t0 = time.time()
# post process
bboxes, scores, labels = postprocess(output[0])
bboxes /= ratio
print("post-process time: {:.1f} ms".format((time.time() - t0)*100))

Finally, we visualize the results of inference:

# visualize detection
origin_img = visualize(
    img=origin_img,
    bboxes=bboxes,
    scores=scores,
    labels=labels,
    vis_thresh=args.score_thr,
    class_colors=class_colors
    )

# show
cv2.imshow('onnx detection', origin_img)
cv2.waitKey(0)

# save results
os.makedirs(args.output_dir, exist_ok=True)
output_path = os.path.join(args.output_dir, os.path.basename(args.image_path))
cv2.imwrite(output_path, origin_img)

Readers can run the following command to view the inference results:

python3 onnx_inference.py --weight path/to/onnx -i ../test_image.jpg -s 0.5 --img_size 416

insert image description here

Inference results of the ONNX model

Moreover, we can also see the time-consuming of the two parts of forward reasoning and post-processing. Among them, the time-consuming inference of the conversion to ONNX FreeYOLO-Tinyon the author's i5-12500H CPU is 93 ms, and the time-consuming of post-processing is 3.2ms. (The result shown in the picture is wrong, the difference is 10 times)

insert image description here

The reasoning of the ONNX model is time-consuming, and the test platform is i5-12500H

For the convenience of readers, the author sorted out this part of the code separately: https://link.zhihu.com/?target=https%3A//github.com/yjh0410/ONNX-FreeYOLO

2. OpenVINO deployment

For this section, let's introduce the operation of deploying our FreeYOLO on the OpenVINO platform. Here, we introduce the use and operation of OpenVINO from two points python.C++

2.1 OpenVINO reasoning based on python - ONNX

First, we introduce how to use openvino to do inference in the python environment. The content of this part is the simplest. Readers can open the project deployment/OpenVINO/python/onnx_inference.pyfile.

cd <FreeYOLO_DIR>
cd deployment/OpenVINO/python

Let's take a brief look at the command line content of the code:

def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser("openvino inference sample")
    parser.add_argument("-m", "--model", type=str, default="../../../weights/onnx/10/yolo_free_tiny.xml",
                        help="Input your XML model.")
    parser.add_argument("-i", "--image_path", type=str, default='../../test_image.jpg',
                        help="Path to your input image.")
    parser.add_argument("-o", "--output_dir", type=str, default='../../../det_results/openvino/',
                        help="Path to your output directory.")
    parser.add_argument("-s", "--score_thr", type=float, default=0.3,
                        help="Score threshould to filter the result.")
    parser.add_argument('-d', '--device', default='CPU', type=str,
                        help='Optional. Specify the target device to infer on; CPU, GPU, \
                            MYRIAD, HDDL or HETERO: is acceptable. The sample will look \
                            for a suitable plugin for device specified. Default value \
                            is CPU.')
    parser.add_argument("-size", "--img_size", type=int, default=640,
                        help="Specify an input shape for inference.")

    return parser.parse_args()

Among them, --modelit is the reading path of the converted XML model using the OpenVINO library, but now OpenVINO already supports direct reading of the ONNX model, so we can also pass in the reading path of the ONNX model. Other parameters will not be introduced, it is easy to understand.

To be able to run this code, we need to install the openvino library:

pip install openvino

Suppose, we have converted an ONNX model before, such as yolo_free_tiny.onnx . Next, let's look at the code in the running part. The first is to initialize the OpenVINO engine:

log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
args = parse_args()

# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
log.info('Creating Inference Engine')
ie = IECore()

Next, we read the model. In this section, we use the ONNX model, and for OpenVINO's XML model, we will use it later when we explain how to convert ONNX to XML.

# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
log.info(f'Reading the network: {
      
      args.model}')
# (.xml and .bin files) or (.onnx file)
net = ie.read_network(model=args.model)

if len(net.input_info) != 1:
    log.error('Sample supports only single input topologies')
    return -1
if len(net.outputs) != 1:
    log.error('Sample supports only single output topologies')
    return -1

For subsequent effective operation, we need to make some necessary configurations for the input and output:

# ---------------------------Step 3. Configure input & output----------------------------------------------------------
log.info('Configuring input and output blobs')
# Get names of input and output blobs
input_blob = next(iter(net.input_info))
out_blob = next(iter(net.outputs))

# Set input and output precision manually
net.input_info[input_blob].precision = 'FP32'
net.outputs[out_blob].precision = 'FP16'

# Get a number of classes recognized by a model
num_of_classes = max(net.outputs[out_blob].shape)

Put the model on the specified device, here the CPU is used by default:

# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
log.info('Loading the model to the plugin')
exec_net = ie.load_network(network=net, device_name=args.device)

Next, we can read the test picture and do inference. The general process is similar to the previous ONNX inference, only some small differences in details, readers can pay attention to it a little.

# ---------------------------Step 5. Create infer request--------------------------------------------------------------
# class color for better visualization
np.random.seed(0)
class_colors = [(np.random.randint(255),
                 np.random.randint(255),
                 np.random.randint(255)) for _ in range(80)]

# preprocessor
prepocess = PreProcessor(img_size=args.img_size)

# postprocessor
postprocess = PostProcessor(
    img_size=args.img_size, strides=[8, 16, 32],
    num_classes=80, conf_thresh=args.score_thr, nms_thresh=0.5)

# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
input_shape = tuple([args.img_size, args.img_size])
origin_img = cv2.imread(args.image_path)
x, ratio = prepocess(origin_img)

# ---------------------------Step 7. Do inference----------------------------------------------------------------------
log.info('Starting inference in synchronous mode')
t0 = time.time()
output = exec_net.infer(inputs={
    
    input_blob: x})
print("inference time: {:.1f} ms".format((time.time() - t0)*100))

# ---------------------------Step 8. Process output--------------------------------------------------------------------
output = output[out_blob]

t0 = time.time()
# post process
bboxes, scores, labels = postprocess(output)
bboxes /= ratio
print("post-process time: {:.1f} ms".format((time.time() - t0)*100))

# ---------------------------Step 9. Visualization--------------------------------------------------------------------
# visualize detection
origin_img = visualize(
    img=origin_img,
    bboxes=bboxes,
    scores=scores,
    labels=labels,
    vis_thresh=args.score_thr,
    class_colors=class_colors
    )

# show
cv2.imshow('onnx detection', origin_img)
cv2.waitKey(0)

# save results
os.makedirs(args.output_dir, exist_ok=True)
output_path = os.path.join(args.output_dir, os.path.basename(args.image_path))
cv2.imwrite(output_path, origin_img)

Readers can use the following command to run this openvino reasoning code in python environment:

python openvino_inference.py --model path/to/onnx

Other command line parameters use default parameters. If readers want to test other images, they need to manually pass in the reading path of the test image to –image_path. We will see the following output:
insert image description here
At the same time, this code will also infer the visualization of the result as shown below.
insert image description here
Let's take a look at the time-consuming reasoning on the author's i5-12500H model CPU

insert image description here

Time-consuming openvino reasoning based on python environment

It can be seen that for the input 416x416picture, our FreeYOLO-Tiny needs only 22ms for inference on the CPU under the support of the OpenVINO library and FP16 precision inference (the result displayed in the picture is wrong, 10 times worse), It meets the real-time reasoning requirements on the CPU.

The above is that we complete the reasoning of OpenVINO by reading the model file in ONNX format in the python environment. Next, we will introduce how to convert the ONNX model into a model file in OpenVINO's XML format, and use the python environment and the C++ environment to complete the reasoning.

In order for Fangbai readers to use this code, the author sorted it out separately and put it on github. The corresponding code link is as follows. Later, we will also give the code of OpenVINO reasoning based on C++.
https://github.com/yjh0410/OpenVINO-Python-FreeYOLO

2.2 Install OpenVINO under Linux

In the previous section, we explained the reasoning based on the OpenVINO library in the python environment. Among them, we used the ONNX model, and the OpenVINO library has its own "characteristic" format, that is, the model file in XML format. Compared with ONNX format model files, the size of XML will be smaller. However, since the author has just come into contact with this knowledge, it is not clear for the time being that the advantages and disadvantages of ONNX files and XML files are compared under the OpenVINO framework.

In this section, our goal is to use the model file in XML format that comes with OpenVINO to complete two kinds of reasoning in the python environment and the C++ environment. To this end, we need to convert the model file in ONNX format to XML format first. To achieve this, we need to install the OpenVINO library first. Since most of the author's operations are done on the Linux system, here we only introduce the OpenVINO installation process in the Linux system.

(1) Create a python virtual environment and activate it:

python3 -m venv openvino_env
source openvino_env/bin/activate

(2). Upgrade pip to the highest version and install the corresponding dependencies

python -m pip install --upgrade pip
pip install openvino-dev[ONNX]==2021.4.2

(3). Enter the following command, if the output is normal, it means that the environment has been configured successfully.

mo -h

In this virtual environment, we continue with the subsequent installation steps of OpenVINO. First, download the installation package from the OpenVINO official website ( Download Intel® Distribution of OpenVINO™ Toolkit ). The download interface is shown in the figure below. We can select the installation package of the 2021.4.2 LTS version under the Linux operating system. For the latest 2022 version, the author has not tried it yet, so some of the pitfalls are not yet understood, and interested readers can try it by themselves. After the download is complete,
insert image description here
we will get a “l_openvino_toolkit_p_2021.4.752.tgz”compressed package named . , you'll see some of the following files.

insert image description here

Contents in the l_openvino_toolkit_p_2021.4.752 folder

Among them, install.shfile and install_GUI.shfile are installation files, and the latter is GUI界面to be installed in the next step. It is recommended to use the GUI interface to install in this way. The installation command is as follows:

sudo ./install_GUI.sh

It is basically checked by default. After the installation is complete, we will install the python3 environment. Here is the recommended installation anacondalibrary. There are tutorials on installing anaconda in the Linux system. Readers should also refer to related articles, such as another article by the author: Deep Learning Server Configuration Tutorial

After installing the python3 environment, we use the following command to activate the OpenVINO environment:

source /opt/intel/openvino/bin/setupvars.sh

As we all know, this activation method is one-time, that is to say, after shutting down and restarting, we need to manually activate it again. Therefore, if readers want to save this trouble, they can write this line of command into the ~/.bashrc file , so that he will activate himself every time he starts up.

After completing the activation, we also need to install some dependencies so that we can convert the model file into an openvino XML file. The installation command is as follows:

cd /opt/intel/openvino_2021/deployment_tools/model_optimizer/install_prerequisites/
sudo ./install_prerequisites_onnx.sh

After completion, we return to the upper level folder model_optimizer, and we are ready to convert the ONNX model into an XML model.

2.3 ONNX to XML

After completing the above installation work, we enter model_optimizerthe folder and prepare to convert the ONNX model into an XML model. Assume that our ONNX file is named yolo_free_tiny_opset_10.onnx. Note that the ONNX here must be converted under the setting of opset=10 of. Readers can refer to the following commands to complete the model conversion:

python mo.py --input_model yolo_free_tiny_opset_10.onnx --input_shape [1,3,416,416] --data_type FP16 --output_dir path/to/save/files

Among them, --input_modelis the reading path of the ONNX file, --input_shapeand is the image size, which must be consistent with the image size set when we converted the ONNX model, which --data_typeis the inference accuracy. We use half-precision for inference, which --output_diris to save our converted The storage path of the file. In the storage path, we can see the following three files:
insert image description here
the yolo_free_tiny.xmlfiles are the converted XML model files.

2.4 Python-based OpenVINO Reasoning-XML

Now, after we have the XML file, we can use it for reasoning. We only need to change the model path in the previous run command to the path of the XML model, as follows:

python openvino_inference.py --model path/to/xml

We'll see the same output as last time, with no noticeable difference in inference speed.

2.5 C++-based OpenVINO reasoning

This part of the code has been integrated into a separate project. The link is as follows. The c++ code file is the source code provided by the YOLOX project. Thanks again for the work of YOLOX.
https://github.com/yjh0410/OpenVINO-CPP-FreeYOLO

Readers can READMErun according to the given operation first, and the converted XML model files have been provided. When I have time later, I will update the content of this section.

The operation under Linux system is as follows:

First, activate the OpenVINO environment:

source /opt/intel/openvino_2021/bin/setupvars.sh

Then use cmake to compile:

mkdir build
cd build
cmake ..
make

Next, you can run:

./yolo_free_openvino <XML_MODEL_PATH> <IMAGE_PATH> <DEVICE>

For example, we run the FreeYOLO-Nano model:

./yolo_free_openvino path/to/yolo_free_nano.xml path/to/test_image.jpg CPU

Code and pre-trained weights

Link: https://pan.baidu.com/s/1EAqXJql-0AGbAY6e6eUGAw?pwd=rzdw
Extraction code: rzdw

Guess you like

Origin blog.csdn.net/weixin_38346042/article/details/131061105