1. 배경
사람 수 세는 모바일 버전을 만들었지만 데이터 세트가 충분하지 않고 하드웨어에 다른 장치를 장착해야 하기 때문에 실제 환경에서 구현할 수 없는 것은 분명합니다. 그래서 Android 산업용 컴퓨터를 사용하지만 추론은 속도는 매우 느리고 500ms에 가깝습니다. 3568 산업용 컴퓨터 등과 같은 CPU를 변경하는 것이 좋습니다. 속도도 약 150ms이지만 Firefly 관련 문서를 찾았습니다 . Rockchip , NPU를 사용하여 계산을 할 수 있습니다. 시작하겠습니다. .
2. NPU를 먼저 빠르게 경험해보세요.
ROC-RK3568-PC 보드는 하위 플래그쉽이며 3588 성능은 더 높을 것이며 현재 개발을 위해 3568을 사용합니다.
rknn-toolkit은 주로 필요한 라이브러리 주소 rknpu 에 해당하는 RK1808/RK1806/RV1109/RV1126용 이므로 이를 무시하고 다음 도구를 사용하십시오 .
rknn-toolkit2는 주로 필요한 라이브러리 주소 rknpu2 에 해당하는 RK3566/RK3568/RK3588/RK3588S/RV1103/RV1106용입니다 .
사용 지침은 NPU 사용을 참조할 수 있습니다 .
- 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
- 데모를 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 모델 변환
- rknn-toolkit2 다운로드 ,
RKNN-Toolkit2의 현재 버전은 Ubuntu 시스템에 적합합니다. Docker를 사용하는 것이 좋습니다. 이중 시스템을 설치했으며 전환이 불편합니다. Ubuntu 18.04 python 3.6 / Ubuntu 20.04 python 3.8 이어야 합니다
. 하나만 선택할 수 있습니다. 하나만 선택할 수 있습니다. 하나만 선택할 수 있습니다. - 시스템을 설치한 후 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
- 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
>>>
- 나는 yolov5 모델을 사용하고, 변환을 위해 rknn -toolkit2 를 사용하지 않는다. 입력 및 출력 데모와 비교하여 일관성을 유지할 수 있습니다. 아래 그림과 같이 왼쪽이 지원되는 변환 모델 구조이고, 오른쪽이 공식 yolov5 이므로 오른쪽이 아닌 왼쪽을 가져와야 합니다. 모델 구조를 잘 이해하고 출력을 올바르게 처리할 수 있는 경우가 아니면 .
- airockchip 수정 yolov5 모델 교육, 헤드 데이터 세트 , 체중을 사용하여 그가 제공한 yolov5s_relu.pt를 사용할 수도 있습니다 .
- onnx 모델 내보내기
导出模型时 python export.py --rknpu {rk_platform} 即可导出优化模型
(rk_platform支持 rk1808, rv1109, rv1126, rk3399pro, rk3566, rk3568, rk3588, rv1103, rv1106)
- 모델 변환 참조 rknn_model_zoo/models/CV/object_detection/yolo/RKNN_model_convert
- 추론 테스트 참조 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;
}
발생한 문제
- rknn-toolkit2/examples/onnx/yolov5/ 이 변환을 사용할 수도 있지만 YOLO 모델은 일련의 training-export-conversion-test 패키지가 포함되어 있기 때문에 rknn_model_zoo 를 사용하여 변환하는 것이 가장 좋습니다.
- 추론 결과의 흐릿한 화면 문제는 시그모이드 함수에 의해 발생합니다. 모델 결과에 시그모이드 처리가 없고 귀하의 테스트 방법이 사용되기 때문에 위의 8단계를 확인하고 관련 기능을 제거할 수 있습니다.
- 모델 변환을 할 때 rknn-server를 시작해야 합니다.자세한 내용은 rknpu2/rknn_server_proxy를 참조하십시오.
- 카메라 데이터를 입력으로 비트맵 및 cv Mat로 직접 변환하려고 시도하지만 효과가 없고 실패합니다.
요약하다
모든 것을 시도하십시오 .
다른 AI 라이브러리.
TensorflowLite
Tencent TNN
Xiaomi Mace
Ali MNN
컴퓨터 비전 학습 비디오, Beijing University of Posts and Telecommunications의 Lu Peng이 가르치는
컴퓨터 비전 및 딥 러닝을 적극 권장합니다.