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、TensorRT
etc. 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
is FreeYOLO FreeYOLO
? This is an amateur target detection project of the author. The YOLO detector combined with the YOLOX
network structure version of SimOTA
and 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.YOLOv7
anchor-free
requirements.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 onnxsim
library, 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 .pth
convert pytorch's weight files to ONNX
the 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.py
file 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 README
download the corresponding weight files from the files in the project. Suppose we have downloaded FreeYOLO-Tiny
the 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_dir
it is the path to save the converted file, such as weights/onnx/
; args.output_name
the 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 OpenVINO
XML 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 XML
format 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_decode
it means that we do not do post-processing in the reasoning stage, because post-processing will include some 非pytorch
operations, 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:
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.py
file and a README
file.
cd <FreeYOLO_dir>/
cd deployment/ONNXRuntime/
Let's take a look at onnx_inference.py
the 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, --model
it is the storage path of our converted ONNX file; --image_path
it is the reading path of the test picture; –output_dir is the storage path of the test result; --score_thr
it 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_color
for the sake of good visualization, different types of boxes have different colors, which is easy to distinguish; preprocess
it is used to preprocess the read images, and readers can utils/pre_process.py
find 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.py
define 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 OpenCV
the library to read the test image test_image.jpg
and 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
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-Tiny
on 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)
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.py
file.
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, --model
it 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:
At the same time, this code will also infer the visualization of the result as shown below.
Let's take a look at the time-consuming reasoning on the author's i5-12500H model CPU
It can be seen that for the input 416x416
picture, 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,
we will get a “l_openvino_toolkit_p_2021.4.752.tgz”
compressed package named . , you'll see some of the following files.
Among them, install.sh
file and install_GUI.sh
file 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 anaconda
library. 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_optimizer
the 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_model
is the reading path of the ONNX file, --input_shape
and is the image size, which must be consistent with the image size set when we converted the ONNX model, which --data_type
is the inference accuracy. We use half-precision for inference, which --output_dir
is to save our converted The storage path of the file. In the storage path, we can see the following three files:
the yolo_free_tiny.xml
files 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 README
run 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