FreeYOLO の導入方法を教えます

著者: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 プロジェクトをダウンロードし、プロジェクト内で提供されるファイルに従って関連環境の構成を完了することをお勧めします。SimOTAYOLOv7anchor-freerequirements.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 バージョン番号です。形式をOpenVINOXML 形式に変更します。ここではデフォルトが使用されます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.pyREADME

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

ここに画像の説明を挿入

ONNX モデルの推論結果

FreeYOLO-Tinyまた、前方推論と後処理の 2 つの部分に時間がかかることもわかります。このうち、筆者の i5-12500H CPU でのONNX への変換の推論には時間がかかり93 ms、後処理はございます3.2ms(写真の結果は間違っており、10倍の差があります)

ここに画像の説明を挿入

ONNX モデルの推論には時間がかかり、テスト プラットフォームは i5-12500H です

読者の便宜のために、作成者はコードのこの部分を個別に整理しました: https://link.zhihu.com/?target=https%3A//github.com/yjh0410/ONNX-FreeYOLO

2. OpenVINOの導入

このセクションでは、FreeYOLO を OpenVINO プラットフォームにデプロイする操作を紹介します。ここではOpenVINOの使い方と操作方法を2つのポイントから紹介しますpythonC++

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()

このうち、--modelOpenVINOライブラリを利用して変換した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 に関する時間のかかる推論を見てみましょう

ここに画像の説明を挿入

Python 環境に基づいた時間のかかる openvino 推論

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”。次のファイルのいくつかが表示されます。

ここに画像の説明を挿入

l_openvino_toolkit_p_2021.4.752 フォルダーの内容

このうち、install.shfile とinstall_GUI.shfile はインストール ファイルであり、後者は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_modelONNX ファイルの読み取りパス--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

おすすめ

転載: blog.csdn.net/weixin_38346042/article/details/131061105