# Ubuntu 建立 ncnn 模型環境
### 先取得需轉換好的模型權重從 pth 到 onnx
https://docs.microsoft.com/zh-cn/windows/ai/windows-ml/tutorials/pytorch-convert-model
```python=
# Export the model
# torch_out = torch.onnx._export(model, # model being run
# x.to(device), # model input (or a tuple for multiple
# f='Magface.onnx',
# export_params=True,
# verbose=True,
# opset_version=11)
onnx_model = load_model("Magface.onnx")
trans_model = float16_converter.convert_float_to_float16(onnx_model, keep_io_types=True)
save_model(trans_model, "Magface_fp16.onnx")
```
### 建立 ncnn 編譯環境:
1. 先下載環境建置文件
https://github.com/BoshiLee/dockerfiles/tree/main/ncnn_python_ubuntu
2. 完成 TODO 事項
### 簡化 onnx 模型:
簡化非必要的 onnx 模型參數,也可以讓後續轉換更順利
* 參考Git 安裝過程
https://github.com/daquexian/onnx-simplifier
安裝好後可下:
```bash=
onnxsim onnx_models/v5s-p6_wider_face.onnx onnx_models/v5s-p6_wider_face_sim.onnx
```
### 將 onnx 編譯成 ncnn
```bash=
cd tools/onnx
./onnx example.onnx example.parm example.bin
```
或者使用模型轉換網站:
[省去编译转换工具的时间开箱即用,一键转换](https://www.convertmodel.com/#input=onnx&output=onnx)
### 導入模型
1. 建立CMake 專案:
```
cmake_minimum_required(VERSION 2.8)
project(yolo_ncnn)
# ncnn
set(ncnn_install_dir "/home/app/ncnn/build/install")
set(ncnn_DIR "${ncnn_install_dir}/lib/cmake/ncnn")
find_package(ncnn REQUIRED)
# open cv
find_package( OpenCV REQUIRED )
add_executable(yolo_ncnn main.cpp)
if(ncnn_FOUND)
message(STATUS "ncnn library: ${ncnn_INSTALL_PATH}")
message(STATUS " version: ${ncnn_VERSION}")
message(STATUS " libraries: ${ncnn_LIBS}")
message(STATUS " include path: ${ncnn_INCLUDE_DIRS}")
target_link_libraries(yolo_ncnn ncnn)
endif()
if(OpenCV_FOUND)
message(STATUS "OpenCV library: ${OpenCV_INSTALL_PATH}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_link_libraries(yolo_ncnn ${OpenCV_LIBS} )
endif()
```
2. 建立載入模型範例程式
```C++
//
// Created by boshi on 2022/6/6.
//
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "headers/net.h"
int main()
{
cv::Mat img = cv::imread("face.jpg", cv::IMREAD_GRAYSCALE);
int w = img.cols;
int h = img.rows;
// subtract 128, norm to -1 ~ 1
ncnn::Mat in = ncnn::Mat::from_pixels_resize(img.data, ncnn::Mat::PIXEL_GRAY, w, h, 60, 60);
float mean[1] = { 128.f };
float norm[1] = { 1/128.f };
in.substract_mean_normalize(mean, norm);
ncnn::Net net;
net.load_param("models/model.param");
net.load_model("models/model.bin");
ncnn::Extractor ex = net.create_extractor();
ex.set_light_mode(true);
ex.set_num_threads(4);
// 這裡要修改成模型輸入的名稱,請找 model.param 的 input layer 是什麼名稱
ex.input("images", in);
ncnn::Mat feat;
ex.extract("output", feat);
printf("x = %d\n", feat);
return 0;
}
```
[參考專案 Git](https://github.com/BoshiLee/yolov5s_ncnn_test)
### 編譯專案
```bash=
cmake .
make
```
### 執行專案
```bash=
./yolo_ncnn
```