RKNN モデル トレーニング変換の展開

1. 背景

人数カウントのモバイル版を作ったのですが、明らかにデータセットが足りず、ハードウェアに他のデバイスを搭載する必要があるため、実環境で実装することはできません。そのため、Android 産業用コンピューターを使用していますが、推論は速度は非常に遅く、500 ミリ秒近くです。3568 産業用コンピューターなどの CPU に変更することをお勧めします。速度も 150 ミリ秒程度ですが、Firefly 関連のドキュメント、Rockchip を見つけ、NPU を使用して計算を行うことができます始めましょう.

2. まずはNPUをサクッと体験

ROC-RK3568-PC ボードはサブ フラグシップで、3588 のパフォーマンスが高くなり、現在 3568 を開発に使用しています。

rknn-toolkitは主に RK1808/RK1806/RV1109/RV1126 用で、必要なライブラリアドレスrknpuに対応しているため、これを無視して次のツールを使用してください

rknn-toolkit2は主に RK3566/RK3568/RK3588/RK3588S/RV1103/RV1106 用で、必要なライブラリ アドレスrknpu2に対応しています。

使用説明書は、NPU の使用を参照できます。

  1. rknpu2をダウンロードし、対応するディレクトリに so ライブラリをインポートします.これは、NPU 機能を簡単にテストするためのものです.後で、Android 用のプロジェクトの jnilib の下に配置されます.
adb root && adb remount
adb push rknpu2_1.4.0/runtime/RK356X/Android/librknn_api/arm64-v8a/* /vendor/lib64
adb push rknpu2_1.4.0/runtime/RK356X/Android/librknn_api/arm64-v8a/* /vendor/lib
  1. デモを ROC-RK3568-PC に入れ、次のようにデモを実行します。
:/ # cd /data/rknn_ssd_demo_Android/    (Linux 系统使用 rknn_ssd_demo_Linux 即可)
:/data/rknn_ssd_demo_Android # chmod 777 rknn_ssd_demo
:/data/rknn_ssd_demo_Android # export LD_LIBRARY_PATH=./lib
:/data/rknn_ssd_demo_Android # ./rknn_ssd_demo model/RK356X/ssd_inception_v2.rknn model/road.bmp (Linux 为 bus.jpg)
Loading model ...
rknn_init ...
model input num: 1, output num: 2
input tensors:
  index=0, name=Preprocessor/sub:0, n_dims=4, dims=[1, 300, 300, 3], n_elems=270000, size=270000, fmt=NHWC, type=UINT8, qnt_type=AFFINE, zp=0, scale=0.007812
output tensors:
  index=0, name=concat:0, n_dims=4, dims=[1, 1917, 1, 4], n_elems=7668, size=30672, fmt=NHWC, type=FP32, qnt_type=AFFINE, zp=53, scale=0.089455
  index=1, name=concat_1:0, n_dims=4, dims=[1, 1917, 91, 1], n_elems=174447, size=697788, fmt=NHWC, type=FP32, qnt_type=AFFINE, zp=53, scale=0.143593
rknn_run
loadLabelName
ssd - loadLabelName ./model/coco_labels_list.txt
loadBoxPriors
person @ (13 125 59 212) 0.984696
person @ (110 119 152 197) 0.969119
bicycle @ (171 165 278 234) 0.969119
person @ (206 113 256 216) 0.964519
car @ (146 133 216 170) 0.959264
person @ (49 133 58 156) 0.606060
person @ (83 134 92 158) 0.606060
person @ (96 135 106 162) 0.464163

これで体験は終了です。次に、モデル変換環境をセットアップします。

3. RKNN モデル変換

  1. rknn-toolkit2をダウンロードします。RKNN
    -Toolkit2 の現在のバージョンはシステム Ubuntu に適しています。Docker を使用することをお勧めします。デュアル システムをインストールしましたが、切り替えるのが面倒です。Ubuntu 18.04 python 3.6 / Ubuntu 20.04 python 3.8である必要があります
    。1 つだけを選択できます。1 つだけを選択できます。1 つだけを選択できます。
  2. システムをインストールしたら、18.04 を例に、必要な Python 環境をインストールします。
#Python3.6
cat doc/requirements_cp36-1.3.0.txt
numpy==1.16.6
onnx==1.7.0
onnxoptimizer==0.1.0
onnxruntime==1.6.0
tensorflow==1.14.0
tensorboard==1.14.0
protobuf==3.12.0
torch==1.6.0
torchvision==0.7.0
psutil==5.6.2
ruamel.yaml==0.15.81
scipy==1.2.1
tqdm==4.27.0
requests==2.21.0
opencv-python==4.4.0.46
PuLP==2.4
scikit_image==0.17.2
# if install bfloat16 failed, please install numpy manually first. "pip install numpy==1.16.6"
bfloat16==1.1
flatbuffers==1.12
  1. Python3.6 を例にとると、システムには同時に複数のバージョンの Python 環境が存在する可能性があるため、virtualenv を使用して Python 環境を管理することをお勧めします。
# 1)安装virtualenv 环境、Python3.6 和 pip3
sudo apt-get install virtualenv \
sudo apt-get install python3 python3-dev python3-pip
# 2)安装相关依赖
sudo apt-get install libxslt1-dev zlib1g zlib1g-dev libglib2.0-0 libsm6 \
libgl1-mesa-glx libprotobuf-dev gcc
# 3)使用 virtualenv 管理 Python 环境并安装 Python 依赖,Python3.6用requirements_cp36-1.3.0.txt
virtualenv -p /usr/bin/python3 venv
source venv/bin/activate
pip3 install -r doc/requirements_cp36-*.txt
# 4)安装 RKNN-Toolkit2,如rknn_toolkit2-1.3.0_11912b58-cp36-cp36m-linux_x86_64.whl
sudo pip3 install packages/rknn_toolkit2*cp36*.whl
# 5)检查RKNN-Toolkit2是否安装成功,可按ctrl+d组合键退出
(venv) firefly@T-chip:~/rknn-toolkit2$ python3
>>> from rknn.api import RKNN
>>>
  1. 変換にはrknn-toolkit2 を使用せず、yolov5 モデルを使用しています. yolo モデルは、公式に推奨されているrknn_model_zooを使用し、モデルのトレーニングには airockchip を改造した yolov5/yolov7/YOLOX ウェアハウスを使用し、対応する onnx をエクスポートすることで、入力と出力のデモと比較して一貫性を保つことができます。下図のように、左がサポートされている変換モデルの構造体、右が公式yolov5の構造体ですが、右のものではなく、左のものを取得する必要があります。ただし、モデルの構造を十分に理解し、出力を正しく処理できる場合を除きます


  2. airockchip 変更yolov5モデル トレーニング、ヘッド データ セットを使用し、体重も彼が提供するyolov5s_relu.ptを使用できます。
  3. onnx モデルのエクスポート
导出模型时 python export.py --rknpu {rk_platform} 即可导出优化模型
(rk_platform支持 rk1808, rv1109, rv1126, rk3399pro, rk3566, rk3568, rk3588, rv1103, rv1106)
  1. モデル変換リファレンスrknn_model_zoo/models/CV/object_detection/yolo/RKNN_model_convert
  2. 推論テストリファレンスrknn_model_zoo/models/CV/object_detection/yolo/RKNN_python_demo

4. Android での RKNN モデルの使用

方法 1. rknn_yolov5_android_apk_demoを使用する. 画像入力時、データ処理に対応する rga ライブラリが不足している. 私のボードの基盤となるドライバーは Lenovo によって変更されるべきである. 統合してほしい.

方法 2. RK356X NPU Demoを使用して上記のデモと比較します. 画像入力は direct_texture によって処理されたデータのみを使用します. 後処理関数を変更するだけです. rknn_yolo_demo を参照してください.シグモイド処理が使用されていないことがわかります. .

static int process_i8(int8_t *input, int *anchor, int grid_h, int grid_w, int height,
           int width, int stride,
           std::vector<float> &boxes, std::vector<float> &boxScores, std::vector<int> &classId,
           float threshold, int32_t zp, float scale) {
    int validCount = 0;
    int grid_len = grid_h * grid_w;
    float thres = threshold;
    auto thres_i8 = qnt_f32_to_affine(thres, zp, scale);
    // puts("==================================");
    // printf("threash %f\n", thres);
    // printf("thres_i8 %u\n", thres_i8);
    // printf("scale %f\n", scale);
    // printf("zp %d\n", zp);
    // puts("==================================");

    //printf("it goes here: file %s, at line %d\n", __FILE__, __LINE__);
    for (int a = 0; a < 3; a++) {
        for (int i = 0; i < grid_h; i++) {

            for (int j = 0; j < grid_w; j++) {

                int8_t box_confidence = input[(YOLOV5_PROP_BOX_SIZE * a + 4) * grid_len +
                                              i * grid_w + j];
                //printf("The box confidence in i8: %d\n", box_confidence);
                if (box_confidence >= thres_i8) {
                    // printf("box_conf %u, thres_i8 %u\n", box_confidence, thres_i8);
                    int offset = (YOLOV5_PROP_BOX_SIZE * a) * grid_len + i * grid_w + j;
                    int8_t *in_ptr = input + offset;

                    int8_t maxClassProbs = in_ptr[5 * grid_len];
                    int maxClassId = 0;
                    for (int k = 1; k < YOLOV5_OBJ_CLASS_NUM; ++k) {
                        int8_t prob = in_ptr[(5 + k) * grid_len];
                        if (prob > maxClassProbs) {
                            maxClassId = k;
                            maxClassProbs = prob;
                        }
                    }

                    float box_conf_f32 = deqnt_affine_to_f32(box_confidence, zp, scale);
                    float class_prob_f32 = deqnt_affine_to_f32(maxClassProbs, zp, scale);
                    float limit_score = box_conf_f32 * class_prob_f32;
//                    LOGI("limit score: %f\n", limit_score);
                    if (limit_score > YOLOV5_CONF_THRESHOLD) {
                        float box_x, box_y, box_w, box_h;

                        box_x = deqnt_affine_to_f32(*in_ptr, zp, scale) * 2.0 - 0.5;
                        box_y = deqnt_affine_to_f32(in_ptr[grid_len], zp, scale) * 2.0 - 0.5;
                        box_w = deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale) * 2.0;
                        box_h = deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale) * 2.0;
                        box_w = box_w * box_w;
                        box_h = box_h * box_h;

                        box_x = (box_x + j) * (float) stride;
                        box_y = (box_y + i) * (float) stride;
                        box_w *= (float) anchor[a * 2];
                        box_h *= (float) anchor[a * 2 + 1];
                        box_x -= (box_w / 2.0);
                        box_y -= (box_h / 2.0);

                        boxes.push_back(box_x);
                        boxes.push_back(box_y);
                        boxes.push_back(box_w);
                        boxes.push_back(box_h);
                        boxScores.push_back(box_conf_f32 * class_prob_f32);
                        classId.push_back(maxClassId);
                        validCount++;
                    }
                }
            }
        }
    }
    return validCount;
}

発生した問題

  1. rknn-toolkit2/examples/onnx/yolov5/ この変換を使用することも可能ですが、一連の training-export-conversion-test パッケージが含まれているため、YOLO モデルは rknn_model_zoo を使用して変換するのが最適です
  2. 推論結果で画面がぼやける問題は、モデル結果にシグモイド処理がなく、テスト メソッドが使用されているため、シグモイド関数が原因であり、上記の手順 8 を確認して、関連する関数を削除できます。
  3. モデル変換を行う場合は、rknn-server を起動する必要があります 詳細はrknpu2/rknn_server_proxyを参照してください
  4. カメラデータをビットマップに直接変換し、入力として cv Mat を試みますが、効果がなく失敗します。

要約する

すべてを試してください

その他の AI ライブラリ。
TensorflowLite
Tencent TNN
Xiaomi Mace
Ali MNN
コンピュータ ビジョン学習ビデオ。北京郵電大学の Lu Peng が教える
コンピュータ ビジョンとディープ ラーニングを強くお勧めします。

おすすめ

転載: blog.csdn.net/weixin_43141131/article/details/128407827