Skip to content

Commit 0c3f452

Browse files
authored
Merge pull request #167 from CoinCheung/dev
add ncnn demo
2 parents ad67baa + d1989a5 commit 0c3f452

File tree

7 files changed

+206
-4
lines changed

7 files changed

+206
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,4 @@ datasets/coco/val.txt
116116
pretrained/*
117117
dist_train.sh
118118

119+
tvm/

ncnn/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 3.15)
2+
3+
PROJECT(segment)
4+
5+
set(CMAKE_CXX_FLAGS "-std=c++14 -O2")
6+
7+
8+
set (ncnn_DIR ${NCNN_ROOT}/lib/cmake/ncnn)
9+
find_package(OpenCV REQUIRED)
10+
find_package(ncnn REQUIRED)
11+
12+
13+
add_executable(segment segment.cpp)
14+
target_include_directories(segment PUBLIC ${OpenCV_INCLUDE_DIRS})
15+
target_link_libraries(segment ${OpenCV_LIBRARIES} ncnn)

ncnn/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
### My platform
3+
4+
* ubuntu 18.04
5+
* Intel(R) Xeon(R) Gold 6240 CPU @ 2.60GHz
6+
* cmake 3.17.1
7+
* opencv built from source
8+
9+
### NOTE
10+
11+
Though this demo runs on x86 platform, you can also use it on mobile platforms. NCNN is better optimized on mobile platforms.
12+
13+
14+
### Install ncnn
15+
16+
1. dependencies
17+
```
18+
$ python -m pip install onnx-simplifier
19+
```
20+
21+
2. build ncnn
22+
Just following the ncnn official tutoral: [build-for-linux](https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-linux) to install ncnn:
23+
24+
1) dependencies
25+
```
26+
# apt install build-essential git libprotobuf-dev protobuf-compiler
27+
```
28+
29+
2) (optional) install vulkan
30+
31+
3) install opencv from source
32+
33+
4) build
34+
```
35+
## I am using commit 9391fae741a1fb8d58cdfdc92878a5e9800f8567, and I have not tested over newer commits
36+
$ git clone https://github.com/Tencent/ncnn.git
37+
$ $cd ncnn
38+
$ git submodule update --init
39+
$ mkdir -p build
40+
$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/host.gcc.toolchain.cmake ..
41+
$ make -j
42+
$ make install
43+
```
44+
45+
### convert model, build and run the demo
46+
47+
1. convert pytorch model to ncnn model via onnx
48+
```
49+
$ cd BiSeNet/
50+
$ python tools/export_onnx.py --aux-mode eval --config configs/bisenetv2_city.py --weight-path /path/to/your/model.pth --outpath ./model_v2.onnx
51+
$ python -m onnxsim model_v2.onnx model_v2_sim.onnx
52+
$ /path/to/ncnn/build/tools/onnx/onnx2ncnn model_v2_sim.onnx model_v2_sim.param model_v2_sim.bin
53+
$ mv model_v2_sim.param ncnn/models
54+
$ mv model_v2_sim.bin ncnn/models
55+
```
56+
57+
2. compile demo code
58+
```
59+
cd ncnn/build
60+
cmake .. -DNCNN_ROOT=/path/to/ncnn/build/install
61+
make
62+
```
63+
64+
3. run demo
65+
```
66+
./segment
67+
```

ncnn/segment.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
2+
#include "net.h"
3+
#include "mat.h"
4+
5+
#include <opencv2/core/core.hpp>
6+
#include <opencv2/highgui/highgui.hpp>
7+
#include <opencv2/imgproc/imgproc.hpp>
8+
9+
#include <iostream>
10+
#include <random>
11+
#include <algorithm>
12+
#include <stdio.h>
13+
#include <vector>
14+
15+
16+
using std::string;
17+
using std::vector;
18+
using cv::Mat;
19+
20+
21+
vector<vector<uint8_t>> get_color_map();
22+
void inference();
23+
24+
25+
int main(int argc, char** argv) {
26+
inference();
27+
return 0;
28+
}
29+
30+
31+
void inference() {
32+
bool use_fp16 = false;
33+
// load model
34+
ncnn::Net mod;
35+
#if NCNN_VULKAN
36+
int gpu_count = ncnn::get_gpu_count();
37+
if (gpu_count <= 0) {
38+
fprintf(stderr, "we do not have gpu device\n");
39+
return;
40+
}
41+
mod.opt.use_vulkan_compute = 1;
42+
mod.set_vulkan_device(1);
43+
#endif
44+
mod.load_param("../models/model_v2_sim.param");
45+
mod.load_model("../models/model_v2_sim.bin");
46+
mod.opt.use_fp16_packed = use_fp16;
47+
mod.opt.use_fp16_storage = use_fp16;
48+
mod.opt.use_fp16_arithmetic = use_fp16;
49+
50+
// load image, and copy to ncnn mat
51+
int oH{1024}, oW{2048}, n_classes{19};
52+
float mean[3] = {0.3257f, 0.3690f, 0.3223f};
53+
float var[3] = {0.2112f, 0.2148f, 0.2115f};
54+
cv::Mat im = cv::imread("../../example.png");
55+
if (im.empty()) {
56+
fprintf(stderr, "cv::imread failed\n");
57+
return;
58+
}
59+
ncnn::Mat inp = ncnn::Mat::from_pixels_resize(
60+
im.data, ncnn::Mat::PIXEL_BGR, im.cols, im.rows, oW, oH);
61+
for (float &el : mean) el *= 255.;
62+
for (float &el : var) el = 1. / (255. * el);
63+
inp.substract_mean_normalize(mean, var);
64+
65+
// set input, run, get output
66+
ncnn::Extractor ex = mod.create_extractor();
67+
// ex.set_num_threads(1);
68+
#if NCNN_VULKAN
69+
ex.set_vulkan_compute(true);
70+
#endif
71+
72+
ex.input("input_image", inp);
73+
ncnn::Mat out;
74+
ex.extract("preds", out); // output is nchw, as onnx, where here n=1
75+
76+
// generate colorful output, and dump
77+
vector<vector<uint8_t>> color_map = get_color_map();
78+
Mat pred(cv::Size(oW, oH), CV_8UC3);
79+
for (int i{0}; i < oH; ++i) {
80+
uint8_t *ptr = pred.ptr<uint8_t>(i);
81+
for (int j{0}; j < oW; ++j) {
82+
// compute argmax
83+
int idx, offset, argmax{0};
84+
float max;
85+
idx = i * oW + j;
86+
offset = oH * oW;
87+
max = out[idx];
88+
for (int k{1}; k < n_classes; ++k) {
89+
idx += offset;
90+
if (max < out[idx]) {
91+
max = out[idx];
92+
argmax = k;
93+
}
94+
}
95+
// color the result
96+
ptr[0] = color_map[argmax][0];
97+
ptr[1] = color_map[argmax][1];
98+
ptr[2] = color_map[argmax][2];
99+
ptr += 3;
100+
}
101+
}
102+
cv::imwrite("out.png", pred);
103+
104+
}
105+
106+
107+
vector<vector<uint8_t>> get_color_map() {
108+
vector<vector<uint8_t>> color_map(256, vector<uint8_t>(3));
109+
std::minstd_rand rand_eng(123);
110+
std::uniform_int_distribution<uint8_t> u(0, 255);
111+
for (int i{0}; i < 256; ++i) {
112+
for (int j{0}; j < 3; ++j) {
113+
color_map[i][j] = u(rand_eng);
114+
}
115+
}
116+
return color_map;
117+
}

tools/export_libtorch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
if cfg.use_sync_bn: cfg.use_sync_bn = False
2626

2727
net = model_factory[cfg.model_type](cfg.n_cats, aux_mode='pred')
28-
net.load_state_dict(torch.load(args.weight_pth), strict=False)
28+
net.load_state_dict(torch.load(args.weight_pth, map_location='cpu'), strict=False)
2929
net.eval()
3030

3131

tools/export_onnx.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@
1818
default='model_final.pth')
1919
parse.add_argument('--outpath', dest='out_pth', type=str,
2020
default='model.onnx')
21+
parse.add_argument('--aux-mode', dest='aux_mode', type=str,
22+
default='pred')
2123
args = parse.parse_args()
2224

2325

2426
cfg = set_cfg_from_file(args.config)
2527
if cfg.use_sync_bn: cfg.use_sync_bn = False
2628

27-
net = model_factory[cfg.model_type](cfg.n_cats, aux_mode='pred')
28-
net.load_state_dict(torch.load(args.weight_pth), strict=False)
29+
net = model_factory[cfg.model_type](cfg.n_cats, aux_mode=args.aux_mode)
30+
net.load_state_dict(torch.load(args.weight_pth, map_location='cpu'), strict=False)
2931
net.eval()
3032

3133

tools/train.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def train():
200200

201201
logger.info('\nevaluating the final model')
202202
torch.cuda.empty_cache()
203-
heads, mious = eval_model(cfg, net)
203+
heads, mious = eval_model(cfg, net.module)
204204
logger.info(tabulate([mious, ], headers=heads, tablefmt='orgtbl'))
205205

206206
return

0 commit comments

Comments
 (0)