前言: 前面復現了centerface,這是一個簡潔,簡單的框架。前面也做了ncnn,android平臺的移植。這裏做Atlas的移植。
1. 開發環境
- ubuntu16.04
- pytorch
- Atlas500
2. pytorch模型訓練
採用上一篇博客的安全帽佩戴數據集進行訓練,採用centerface項目,訓練一個矩形框檢測不帶關鍵點的檢測模型。
- 項目自帶pytorch2onnx腳本
注意: Atlas的deconvolution操作限制group=1,所以需要對mobilenetv2主幹網絡的deconvolution group參數改爲1就ok。
3. pytorch->caffe->om
3.1 pytorch->caffe
Atlas提供了一個omg模型轉換的腳本,只支持caffe,tensorflow的模型。這裏採用pytorch->caffe->om的路線。
這裏可以用兩個項目實現(實測可用)
1.https://github.com/MTlab/onnx2caffe美圖的,onnx到caffe
- https://github.com/xxradon/PytorchToCaffe不需要轉到onnx,支持可以pytorch模型轉caffe
以上兩個項目實測都是可以的
3.2 caffe->om
命令:
omg --framework 0 --model centernet.prototxt --weight centernet.caffemodel --output center_c --insert_op_conf aipp_center.cfg
注意: aipp_center.cfg配置文件參數的設置
aipp_op{
aipp_mode: static
crop: true
input_format : YUV420SP_U8
load_start_pos_h : 0
load_start_pos_w : 0
src_image_size_h : 512
src_image_size_w : 512
csc_switch : true
rbuv_swap_switch:false
matrix_r0c0 : 256
matrix_r0c1 : 454
matrix_r0c2 : 0
matrix_r1c0 : 256
matrix_r1c1 : -88
matrix_r1c2 : -183
matrix_r2c0 : 256
matrix_r2c1 : 0
matrix_r2c2 : 359
input_bias_0 : 0
input_bias_1 : 128
input_bias_2 : 128
mean_chn_0 : 124
mean_chn_1 : 116
mean_chn_2 : 103
var_reci_chn_0 : 0.01712
var_reci_chn_1 : 0.01751
var_reci_chn_2 : 0.01743
}
Atlas的預處理爲: (x - mean_atlas) * var_atlas
,而centerface的預處理爲 (x/255 - mean) / std
,所以 mean_atlas = mean * 255, vat_atlas = 1 / (255 * std)
4. 後處理
這裏用Atlas_samples修改而來。
用Atlas開發,一般只用寫後處理,這裏就沒法展開了。
注意:
- Atlas_samples項目中yolov3和ssd在jpg解碼部分用的對齊方式不一樣。需要將centerface用yolov3的對齊方式。
# 這裏1是yolov3, 2是centerface的推理方式
if (1 == g_modelType || 2 == g_modelType) {
// set crop area:
float rx = (float)(jpegdOutData.imgWidth) / (float)(g_detectInputWidth); // 寬度方向的比例
float ry = (float)(jpegdOutData.imgHeight) / (float)(g_detectInputHeight); // 高度方向比例
int dx = 0;
int dy = 0;
float r;
if (rx > ry) {
dx = 0;
r = rx;
dy = (g_detectInputHeight - jpegdOutData.imgHeight / r) / g_denominator;
} else {
dy = 0;
r = ry;
dx = (g_detectInputWidth - jpegdOutData.imgWidth / r) / g_denominator;
}
outputConfigure->outputArea.leftOffset = ALIGN_UP(dx, ALIGN_16); // align to 16 // 應用開發 P220
outputConfigure->outputArea.rightOffset = CHECK_ODD(g_detectInputWidth - dx);
outputConfigure->outputArea.upOffset = CHECK_EVEN(dy);
outputConfigure->outputArea.downOffset = CHECK_ODD(g_detectInputHeight - dy);
}
- Atlas_samples項目中的後處理固定格式是:預測bbox的(cx, cy, w, h)中心點歸一化,w/h歸一化。
5. 簡單測試
5.1 時間
- 設備端推理時間
需要通過日誌的方式打印。推理+後處理大概10ms左右
[centernet post process] | time:10.000000 ms, end:160000, start:150000, cha:10000
- 這個腳本運行時間
直接在main.cpp
中用printf打印就行
#include<ctime>
using namespace std;
clock_t start,end;
int main(){
start=clock(); //程序開始計時
end=clock(); //程序結束用時
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
}
>>> [Atlas 500] | time use:42.643000
大概在40ms左右
6. 結果可視化
便於檢查,還是對結果進行可視化一下。
這裏採用將打印的結果,copy到python中進行可視化。
import cv2
'''
#0, bbox( 60, 106, 152, 214) confidence: 0.872998 classId is 0
#1, bbox( 379, 35, 462, 133) confidence: 0.717804 classId is 0
#2, bbox( 247, 58, 350, 181) confidence: 0.680454 classId is 1
'''
dict_label = {0:'person', 1:'hat'}
bbox = [[60, 106, 152, 214, 0], [379, 35, 462, 133, 0], [247, 58, 350, 181, 1]]
img_path = './data/demo_data/000009.jpg'
img = cv2.imread(img_path)
for box in bbox:
cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 2)
label = dict_label[box[4]]
cv2.putText(img, label, (box[0], box[1] - 2), 0, float(2) / 3, [0, 0, 0], thickness=1, lineType=cv2.LINE_AA)
cv2.imshow('Atlas500', img)
cv2.waitKey()
其他
- 如果用atlas進行開發,儘量用常規的算子,比如:conv+bn+relu。實測se模塊支持不好(pytorch轉caffe不好轉)
- caffe的模型到om這裏很關鍵,所以能有一個強大的pytorch2caffe的項目(不知道這算不算一個痛點)