任务内容
在做ncnn-yolov8-obb模型安卓端移植的过程中,对开源代码进行调试。为了确认开源代码yolov8-obb.cpp可以移植开发,先对代码进行复现。因此在linux系统下编译yolov8-obb.cpp代码,验证项目中的代码是可运行的。然后再把这个代码中的模型换为自己的缺陷检测模型。
项目代码:https://github.com/FeiGeChuanShu/ncnn-android-yolov8
操作流程
编译安装代码需要的ncnn库
linux安装ncnn库
安装依赖项:
sudo apt install build-essential git cmake libprotobuf-dev protobuf-compiler libomp-dev libvulkan-dev vulkan-tools libopencv-dev
安装依赖的bazel库
需要在服务器上安装代理软件,能够访问bazel官网并下载公钥,然后再apt安装。
bazel安装参考:https://bazel.build/install/ubuntu?hl=zh-cn
安装protobuf
参考官网:https://github.com/protocolbuffers/protobuf/blob/main/src/README.md
源码编译ncnn
git clone https://github.com/Tencent/ncnn.git
cd ncnn
mkdir build && cd build
cmake ..
make -j4
sudo make install
完成编译安装结果。
编译代码,生成可执行文件
- 编译流程:由于对gcc指令不熟,因此采用cmake的方式进行编译。
- 创建cmakelists.txt,将需要include和link的ncnn库,opencv库都添加进去。
- mkdir build & cd build & cmake .. & make
- 生成可执行文件。
- 会遇到的报错问题:
问题一:libncnn.a(simpleomp.cpp.o): undefined reference to symbol 'pthread_getspecific@@GLIBC_2.2.5',
[100%] Linking CXX executable yolov8-obb
/usr/bin/ld: /home/xbang/cpz/env/ncnn/build/install/lib/libncnn.a(simpleomp.cpp.o): undefined reference to symbol 'pthread_getspecific@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/yolov8-obb.dir/build.make:102:yolov8-obb] 错误 1
make[1]: *** [CMakeFiles/Makefile2:76:CMakeFiles/yolov8-obb.dir/all] 错误 2
make: *** [Makefile:84:all] 错误 2
-
- 原因:是ncnn代码中用了多线程,因此在cmake过程中需要指定多线程参数。
- 解决方法:在cmakelists.txt中的add_executable()之前增加:
set(CMAKE_CXX_FLAGS -pthread)
message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
问题二:undefined reference to `omp_get_thread_num'等
编译器在链接过程中找不到 GOMP_parallel 这个符号,还有omp_get_num_threads 和 omp_get_thread_num 等。
/usr/bin/ld: celu.cpp:(.text+0x4d): undefined reference to `omp_get_thread_num'
/usr/bin/ld: /home/xbang/cpz/env/ncnn/build/install/lib/libncnn.a(celu.cpp.o): in function `ncnn::CELU::forward_inplace(ncnn::Mat&, ncnn::Option const&) const':
celu.cpp:(.text+0x180): undefined reference to `GOMP_parallel'
/usr/bin/ld: /home/xbang/cpz/env/ncnn/build/install/lib/libncnn.a(shrink.cpp.o): in function `ncnn::Shrink::forward_inplace(ncnn::Mat&, ncnn::Option const&) const [clone ._omp_fn.0]':
shrink.cpp:(.text+0x66): undefined reference to `omp_get_num_threads'
/usr/bin/ld: shrink.cpp:(.text+0x6d): undefined reference to `omp_get_thread_num'
/usr/bin/ld: /home/xbang/cpz/env/ncnn/build/install/lib/libncnn.a(shrink.cpp.o): in function `ncnn::Shrink::forward_inplace(ncnn::Mat&, ncnn::Option const&) const':
shrink.cpp:(.text+0x3ac): undefined reference to `GOMP_parallel'
collect2: error: ld returned 1 exit status报错了
-
- 原因:GOMP_parallel ,omp_get_num_threads,omp_get_thread_num 都是是 OpenMP 库中的函数或变量。由于ncnn库本身是使用 OpenMP 编译的。因此是ncnn在编译过程对openMP库的设置出了问题。
- 解决方法:在cmakelists.txt中option里设置了OPENMP模式为on启用模式。但是文件中另一处使用OPENMP库时,if判断条件and配合了另一个库SIMPLEOMP默认是off模式,因此我把SIMPLEOMP库的option也设置为on模式。然后再次编译ncnn后就不报这个错误了。
问题三:当安装多个版本的opencv时,如果用gcc方式编译就会因为设置不明白opencv的库文件路径报错。
-
- 解决方法:在cmakelist中可以通过find_package的方式找到路径。
测试代码
将代码中的读取图像参数设为图像绝对路径,模型文件设为绝对路径,然后运行生成的可执行文件,得到测试结果图如下: