著者:Kissrabbit
元のリンク:https ://zhuanlan.zhihu.com/p/578830729
この章では、torch によってトレーニングされたウェイト ファイルを ONNX ファイルに変換する方法と、それを etc. フレームワークにデプロイし直す方法について説明しますOpenVINO、TensorRT
。著者は、この章の内容を完了するために、私自身の FreeYOLO プロジェクトを例として取り上げます。関連するコードは次のとおりです:
https://link.zhihu.com/?target=https%3A//github.com/yjh0410/
FreeYOLOとは何FreeYOLO
ですか?これは著者のアマチュア ターゲット検出プロジェクトです。YOLO 検出器は、と組み合わせられており構造バージョンYOLOX
ネットワーク したがって、その後のコンテンツの学習を容易にするために、読者は著者の FreeYOLO プロジェクトをダウンロードし、プロジェクト内で提供されるファイルに従って関連環境の構成を完了することをお勧めします。SimOTA
YOLOv7
anchor-free
requirements.txt
コンテンツのこの部分を研究する際、著者は YOLOX プロジェクトの多くの関連操作とコード実装を十分に活用しています。したがって、オープンソース YOLOX の取り組みについて Megvii に非常に感謝しており、また、オープンソースのマルチプラットフォーム展開コード。
1.ONNX の展開
1.1 PyTorch モデルを ONNX に変換する
作業のこの部分を開始する前に、後続の操作を完了するために必要なライブラリをいくつかインストールしましょう。
pip install onnxruntime
pip install onnxsim
2 番目のonnxsim
ライブラリの場合、これはオプションであり、onnxruntime 変換を簡素化することによって取得された onnx ファイルにのみ適用されます。.pth
少なくとも onnxruntime ライブラリがインストールされていることを確認してください。そうしないと、pytorch の重みファイルをその形式に変換できませんONNX
。
cd <FreeYOLO_dir>
cd tools/
まず、FreeYOLO プロジェクトの tools フォルダーを開くと、export_onnx.py
というファイルがあり、その中に ONNX ファイルを変換するためのコードが書かれています。主に main() 関数を見ていきます。まず、FreeYOLO モデルを構築します。
@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)
次に、トレーニング済みの COCO 重みをロードすると、リーダーはREADME
プロジェクト内のファイルから対応する重みファイルをダウンロードできます。FreeYOLO-Tiny
モデルの重みファイルをダウンロードしたとします。yolo_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)
次に、それを ONNX 形式に変換できます。
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))
このうち、args.save_dir
変換されたファイルを保存するパス (例: yolo_free_large.onnx) weights/onnx/
、args.output_name
出力ファイルの名前 (yolo_free_large.onnx など)、args.opset は ONNX の opset バージョン番号です。形式をOpenVINO
XML 形式に変更します。ここではデフォルトが使用されます11
。それ以外の場合は、後で OpenVINO 形式に変換できるように、実行時に opset のバージョン番号を設定するために –opset 10 を手動で渡す必要がありますXML
。
変換する前に、テスト画像のサイズを保存するために使用される dummy_input という名前の変数を設定する必要があることに注意してください。推論に ONNX 形式のモデルを使用する場合、入力画像のサイズは設定されたサイズを維持する必要がありますここで全会一致です。たとえば、ここではこれを設定しますdummy_input = torch.randn(args.batch_size,3, 416, 416)
。その後の推論では、他のサイズではなく 416x416 の画像を指定する必要があります。指定しないとエラーが報告されます。
さらに、onnxsim ライブラリをインストールしており、args.no_onnxsim が False の場合、コードは変換された ONNX 形式をさらに簡素化します。ただし、この簡易ONNX形式の利点は今のところ筆者には理解できていないので、ここでは紹介しません。
ONNX 形式を変換するコードは非常に単純で、最終的にリーダーは次のコマンドを使用して変換を完了できます。
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
このうち、--no_decode
後処理には何らかの非pytorch
操作が含まれ、エラーが報告されるため、推論段階では後処理を行わないことを意味します。後処理コードを外部に記述する必要があります。これについては、次の章で説明します。ここでは、後処理操作を行わずにモデルに前進推論を実行させるだけでよく、読者はmodels/yolo_free/yolo_free.py
モデル ファイル内の対応する処理を確認できます。
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
上位コマンドを実行すると、正常に実行されると、図に示すような出力情報が表示されます。
weights/onnx/11/
これまでのところ、トレーニングされた重みを ONNX 形式に変換することに成功しており、読者は変換されたファイルをプロジェクトフォルダーで見つけることができます。
1.2 Python ベースの ONNX 推論
上記の変換が完了すると、ONNX 形式のモデル ファイルを推論に使用できるようになります。読者にプロジェクトを開いてもらいます。ファイルとファイルdeployment/ONNXRuntime/文件夹
が表示されます。onnx_inference.py
README
cd <FreeYOLO_dir>/
cd deployment/ONNXRuntime/
onnx_inference.py
次のように、後で使用するためにファイルのコマンド ライン パラメーターを見てみましょう。
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
その中で、--model
これは変換された ONNX ファイルのストレージ パス、--image_path
テスト画像の読み取りパス、-output_dir はテスト結果のストレージ パス、--score_thr
信頼性のしきい値、デフォルトは 0.3、-img_size はテスト画像のサイズ。ONNX 形式を変換する前に、手動でサイズを設定します。この設定値と一致する必要があります。
次に、コアコードを見ていきます。まず、その理由を説明するために、必要な変数をいくつか準備します。
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)
その中で、class_color
視覚的にわかりやすくするために、さまざまな種類のボックスには異なる色が付けられており、簡単に区別できます。これはpreprocess
読み取られた画像の前処理に使用され、読者はutils/pre_process.py
ファイル内でこのクラスの定義を見つけることができます。
# 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
注意
, ここでは、以前のように、opencv で読み込んだ画像を正規化したり、BGR を RGB 形式に変換したりする必要がなくなりました。著者のFreeYOLO项目中的预处理代码也取消了这些操作
. 最近の YOLOv5、YOLOX、YOLOv7 からはこれらの操作が見られなくなり、opencv で読み込んだ画像を直接大epoch、多种数据增强的
トレーニングに使用するようになりました归一化就显得不必要了
。また、C++ をデプロイすると、対応するコードも保存されるので、これも非常に便利です。
さらに、前処理に加えて、后处理
操作も行う必要があります。リーダーはutils/post_process.py
ファイル内で後処理を定義できます。このクラスは、次のような後処理に使用されます解算边界框、阈值筛选和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
これらのツールを導入すると、ONNX モデルを推論に使用できます。まず、OpenCV
ライブラリを使用してテスト イメージを読み取りtest_image.jpg
、前処理します。
# 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)
次に、推論のためにそれを ONNX モデルに渡し、出力変数の出力を取得します。
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))
その中にはoutput[0]
FreeYOLO の出力があり、それを後処理して、バウンディング ボックス、スコア、カテゴリの 3 つの処理結果を取得します。
t0 = time.time()
# post process
bboxes, scores, labels = postprocess(output[0])
bboxes /= ratio
print("post-process time: {:.1f} ms".format((time.time() - t0)*100))
最後に、推論の結果を視覚化します。
# 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)
読者は次のコマンドを実行して推論結果を表示できます。
python3 onnx_inference.py --weight path/to/onnx -i ../test_image.jpg -s 0.5 --img_size 416
FreeYOLO-Tiny
また、前方推論と後処理の 2 つの部分に時間がかかることもわかります。このうち、筆者の i5-12500H CPU でのONNX への変換の推論には時間がかかり93 ms
、後処理はございます3.2ms
。(写真の結果は間違っており、10倍の差があります)
読者の便宜のために、作成者はコードのこの部分を個別に整理しました: https://link.zhihu.com/?target=https%3A//github.com/yjh0410/ONNX-FreeYOLO
2. OpenVINOの導入
このセクションでは、FreeYOLO を OpenVINO プラットフォームにデプロイする操作を紹介します。ここではOpenVINOの使い方と操作方法を2つのポイントから紹介しますpython
。C++
2.1 Python に基づく OpenVINO 推論 - ONNX
まず、openvino を使って Python 環境で推論を行う方法を紹介しますが、この部分の内容は最も単純で、読者はプロジェクトdeployment/OpenVINO/python/onnx_inference.py
ファイルを開くことができます。
cd <FreeYOLO_DIR>
cd deployment/OpenVINO/python
コードのコマンドラインの内容を簡単に見てみましょう。
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()
このうち、--model
OpenVINOライブラリを利用して変換したXMLモデルの読み込みパスですが、現在OpenVINOはすでにONNXモデルの直接読み込みをサポートしているため、ONNXモデルの読み込みパスを渡すこともできます。他のパラメータは紹介しませんが、理解するのは簡単です。
このコードを実行できるようにするには、openvino ライブラリをインストールする必要があります。
pip install openvino
以前に などの ONNX モデルを変換したとしますyolo_free_tiny.onnx
。次に、実行部分のコードを見てみましょう。1 つ目は、OpenVINO エンジンを初期化することです。
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()
このセクションでは ONNX モデルを使用しますが、OpenVINO の XML モデルについては、後で ONNX を 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
その後の効果的な動作のために、入力と出力に必要な構成をいくつか行う必要があります。
# ---------------------------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)
指定したデバイスにモデルを配置します。ここでは CPU がデフォルトで使用されます。
# ---------------------------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)
次に、テスト画像を読み取って推論を行うことができますが、全体的なプロセスは以前の ONNX 推論と似ていますが、細部にいくつかの小さな違いがあるだけで、読者はそれに少し注目していただけます。
# ---------------------------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)
読者は次のコマンドを使用して、この openvino 推論コードを Python 環境で実行できます。
python openvino_inference.py --model path/to/onnx
他のコマンドラインパラメータはデフォルトパラメータを使用します。リーダーが他のイメージをテストしたい場合は、テスト イメージの読み取りパスを –image_path に手動で渡す必要があります。次の出力が表示されます。
同時に、このコードは、以下に示すように結果の視覚化も推論します。
著者の i5-12500H モデル CPU に関する時間のかかる推論を見てみましょう
416x416
入力画像の場合、OpenVINO ライブラリと FP16 精度推論のサポートの下、FreeYOLO-Tiny は CPU での推論にわずか 22ms しか必要としないことがわかります (画像に表示される結果は間違っており、10 倍悪い) 。CPU 上のリアルタイム推論要件。
以上でPython環境でONNX形式のモデルファイルを読み込むことでOpenVINOの推論が完了しました。次に、ONNX モデルを OpenVINO の XML 形式のモデル ファイルに変換し、Python 環境と C++ 環境を使用して推論を完了する方法を紹介します。
Fangbai の読者がこのコードを使用できるように、作者が別途整理して github に置きました。対応するコードのリンクは次のとおりです。後で、C++ に基づいた OpenVINO 推論のコードも示します。
https://github.com/yjh0410/OpenVINO-Python-FreeYOLO
2.2 Linux に OpenVINO をインストールする
前節ではPython環境のOpenVINOライブラリをベースに推論を説明しましたが、その中でもONNXモデルを使用しましたが、OpenVINOライブラリはXML形式のモデルファイルという独自の「特徴」のある形式を持っています。ONNX 形式のモデル ファイルに比べて XML のサイズは小さくなりますが、筆者はまだこの知識に触れたばかりなので、ONNX ファイルと XML ファイルの利点と欠点を比較することは今のところ明確ではありません。 OpenVINO フレームワークの下で。
このセクションでは、OpenVINO に付属する XML 形式のモデル ファイルを使用して、Python 環境と C++ 環境で 2 種類の推論を完了することを目標とします。そのためには、まず ONNX 形式のモデル ファイルを XML 形式に変換する必要があり、これを行うには、まず OpenVINO ライブラリをインストールする必要があります。著者の操作のほとんどは Linux システム上で行われるため、ここでは Linux システムでの OpenVINO インストール プロセスのみを紹介します。
(1) Python 仮想環境を作成し、アクティブ化します。
python3 -m venv openvino_env
source openvino_env/bin/activate
(2). pip を最新バージョンにアップグレードし、対応する依存関係をインストールします。
python -m pip install --upgrade pip
pip install openvino-dev[ONNX]==2021.4.2
(3). 以下のコマンドを入力し、出力が正常であれば環境構築は成功です。
mo -h
この仮想環境では、後続の OpenVINO のインストール手順を続行します。まず、 OpenVINO 公式 Web サイト (「OpenVINO™ Toolkit のインテル® ディストリビューションをダウンロード」) からインストール パッケージをダウンロードします。ダウンロード インターフェイスは次の図に示されています。Linux オペレーティング システムでは、2021.4.2 LTS バージョンのインストール パッケージを選択できます。 。最新の 2022 バージョンについては、作者はまだ試していないため、いくつかの落とし穴がまだ理解されていませんが、興味のある読者はご自身で試してみてください。ダウンロードが完了すると、 という名前の圧縮パッケージが提供され
ます“l_openvino_toolkit_p_2021.4.752.tgz”
。次のファイルのいくつかが表示されます。
このうち、install.sh
file とinstall_GUI.sh
file はインストール ファイルであり、後者はGUI界面
次の手順でインストールされます。この方法でインストールするには GUI インターフェイスを使用することをお勧めします。インストール コマンドは次のとおりです。
sudo ./install_GUI.sh
基本的にはデフォルトでチェックが入っています。インストールが完了したら、python3 環境をインストールします。推奨されるインストールanaconda
ライブラリは次のとおりです。Linux システムに anaconda をインストールするためのチュートリアルがあります。読者は、著者による別の記事などの関連記事も参照してください: Deep Learning Server構成チュートリアル
python3 環境をインストールした後、次のコマンドを使用して OpenVINO 環境をアクティブにします。
source /opt/intel/openvino/bin/setupvars.sh
ご存知のとおり、このアクティブ化方法は 1 回限りです。つまり、シャットダウンして再起動した後、手動で再度アクティブ化する必要があります。したがって、読者がこの手間を省きたい場合は、このコマンド行を次のコマンド行に書き込むことができます。 ~/.bashrc ファイルに保存し、起動するたびに自分自身をアクティブ化します。
アクティベーションが完了したら、モデル ファイルを openvino XML ファイルに変換できるように、いくつかの依存関係をインストールする必要もあります。インストールコマンドは以下のとおりです。
cd /opt/intel/openvino_2021/deployment_tools/model_optimizer/install_prerequisites/
sudo ./install_prerequisites_onnx.sh
完了後、上位レベルのフォルダー model_optimizer に戻り、ONNX モデルを XML モデルに変換する準備が整います。
2.3 ONNX から XML へ
上記のインストール作業が完了したら、model_optimizer
フォルダーに入り、ONNX モデルを XML モデルに変換する準備をします。ONNX ファイルの名前は であるとします。yolo_free_tiny_opset_10.onnx
ここでの ONNX は、opset=10 の設定で変換する必要があることに注意してください。読者は次のコマンドを参照してモデル変換を完了できます。
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
その中には、--input_model
ONNX ファイルの読み取りパス--input_shape
と画像サイズ (ONNX モデルを変換したときに設定した画像サイズと一致する必要があります) (--data_type
推論精度) があり、推論には半精度を使用します--output_dir
。変換されたファイルのストレージパスを保存します。ストレージ パスには、次の 3 つのファイルが表示されます。
これらのyolo_free_tiny.xml
ファイルは、変換された XML モデル ファイルです。
2.4 Python ベースの OpenVINO 推論 XML
XML ファイルを取得したら、それを推論に使用できます。次のように、前の実行コマンドのモデル パスを XML モデルのパスに変更するだけです。
python openvino_inference.py --model path/to/xml
前回と同じ出力が表示されますが、推論速度に目立った違いはありません。
2.5 C++ ベースの OpenVINO 推論
コードのこの部分は別のプロジェクトに統合されています。リンクは次のとおりです。C++ コード ファイルは、YOLOX プロジェクトによって提供されるソース コードです。YOLOX の取り組みに改めて感謝します。
https://github.com/yjh0410/OpenVINO-CPP-FreeYOLO
リーダーは、README
最初に指定された操作に従って実行でき、変換された XML モデル ファイルが提供されます。後で時間があるときに、このセクションの内容を更新します。
Linux システムでの操作は次のとおりです。
まず、OpenVINO 環境をアクティブ化します。
source /opt/intel/openvino_2021/bin/setupvars.sh
次に、cmake を使用してコンパイルします。
mkdir build
cd build
cmake ..
make
次に、以下を実行できます。
./yolo_free_openvino <XML_MODEL_PATH> <IMAGE_PATH> <DEVICE>
たとえば、FreeYOLO-Nano モデルを実行します。
./yolo_free_openvino path/to/yolo_free_nano.xml path/to/test_image.jpg CPU
コードと事前トレーニングされた重み
リンク: https://pan.baidu.com/s/1EAqXJql-0AGbAY6e6eUGAw?pwd=rzdw
抽出コード: rzdw