✨博客主页:王乐予🎈
✨年轻人要:Living for the moment(活在当下)!💪
🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】
目录
- 😺一、引言
- [😺二、编译 OpenCV](#😺二、编译 OpenCV)
-
- [🐶2.1 安装各种依赖](#🐶2.1 安装各种依赖)
- [🐶2.2 下载 OpenCV 和 OpenCV-Contrib](#🐶2.2 下载 OpenCV 和 OpenCV-Contrib)
- [🐶2.3 进入 opencv 目录并新建 build 文件夹](#🐶2.3 进入 opencv 目录并新建 build 文件夹)
- [🐶2.4 使用 CMake 生成构建脚本](#🐶2.4 使用 CMake 生成构建脚本)
- [🐶2.5 编译并安装 OpenCV](#🐶2.5 编译并安装 OpenCV)
- [🐶2.6 配置环境](#🐶2.6 配置环境)
-
- [🦄2.6.1 配置环境变量 PKG_CONFIG_PATH](#🦄2.6.1 配置环境变量 PKG_CONFIG_PATH)
- [🦄2.6.2 配置 OpenCV 动态库环境](#🦄2.6.2 配置 OpenCV 动态库环境)
- [🦄2.6.3 配置 bash.bashrc](#🦄2.6.3 配置 bash.bashrc)
- [😺三、下载 NCNN](#😺三、下载 NCNN)
- [😺四、CLion 工程](#😺四、CLion 工程)
-
- [🐶4.1 编写 CMakeLists.txt](#🐶4.1 编写 CMakeLists.txt)
- [🐶4.2 编写 main.cpp](#🐶4.2 编写 main.cpp)
- [😺五、OpenCV-Mobile 替换 OpenCV](#😺五、OpenCV-Mobile 替换 OpenCV)
😺一、引言
最近在用腾讯的 ncnn 框架做模型推理,想着在 ubuntu 上编译一下。于是就有了这篇记录。
NCNN:https://github.com/Tencent/ncnn/
OpenCV:https://github.com/opencv/opencv
OpenCV-Contrib:https://github.com/opencv/opencv_contrib
😺二、编译 OpenCV
NCNN 会用到 OpenCV 读取图片,因此首先要编译 OpenCV。
在 Ubuntu 上编译 OpenCV ,网上有非常多的教程,我参考的是下面的几个:
ubuntu20.04配置opencv4.5.5+opencv_contrib4.5.5+Vscode配置
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
Ubuntu20.04安装OpenCV并在vsCode中配置
我是用 CLion 开发做 C++ 开发的,因此编译完 OpenCV 就可以结束了,不用对 VSCode 进行配置。
我这里用的是最新的 OpenCV (4.10.0)。可能存在一些版本问题,但影响不大,NCNN 代码例程用的大多是 OpenCV 的基本操作。
注意:OpenCV-Contrib 要与 OpenCV 同一版本。
🐶2.1 安装各种依赖
更新环境:
bash
sudo apt-get update
sudo apt-get upgrade
安装编译器和构建工具等,若已安装,跳过即可:
bash
sudo apt-get install -y g++ # Ubuntu自带gcc
sudo apt-get install -y cmake
sudo apt-get install -y make
sudo apt-get install -y wget
sudo apt-get install -y unzip
sudo apt-get install -y git
安装各种依赖库:
bash
sudo apt-get install build-essential pkg-config
sudo apt-get install libgtk2.0-dev libgtk-3-dev libglib2.0-dev libavcodec-dev libavformat-dev libswscale-dev libavutil-dev libv4l-dev liblapacke-dev libxvidcore-dev libx264-dev
sudo apt-get install python-dev python-numpy
sudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev
sudo apt-get install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper1 libjasper-dev libdc1394-22-dev libopenexr-dev libwebp-dev
sudo apt-get install libatlas-base-dev gfortran
sudo apt-get install ffmpeg
安装依赖库libjasper1
和libjasper-dev
时,若报错E:Unable to locate package libjasper-dev
,可以命令行执行以下命令,然后再安装
bash
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main" # 国内可能需要换国内的镜像
sudo apt-get update
🐶2.2 下载 OpenCV 和 OpenCV-Contrib
bash
git clone https://github.com/opencv/opencv # 默认安装最新的版本
git clone https://github.com/opencv/opencv_contrib
下载结束后进行解压:
bash
unzip opencv.zip
unzip opencv_contrib.zip
解压完后的 opencv_contrib 放在 opencv 文件夹里面。
我的 opencv 所在的目录是:/home/***/opencv
(***是用户名)
🐶2.3 进入 opencv 目录并新建 build 文件夹
bash
mkdir -p build && cd build
🐶2.4 使用 CMake 生成构建脚本
bash
sudo cmake -D CMAKE_BUILD_TYPE=Release -D OPENCV_GENERATE_PKGCONFIG=ON -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=/home/***/opencv/opencv_contrib/modules -D OPENCV_ENABLE_NONFREE=ON ..
🐶2.5 编译并安装 OpenCV
在 build 目录下执行:
bash
sudo make -j8 # 编译
sudo make install # 安装
🐶2.6 配置环境
🦄2.6.1 配置环境变量 PKG_CONFIG_PATH
前面进行 cmake 时,已经生成了opencv4.pc
配置文件,该文件的安装路径为:/usr/local/lib/pkgconfig/opencv4.pc
我们需要将opencv4.pc
的路径添加到环境变量PKG_CONFIG_PATH
中,创建一个名为pkgconfig.sh
的脚本文件:
bash
sudo gedit /etc/profile.d/pkgconfig.sh
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/profile.d/pkgconfig.sh
在pkgconfig.sh
文件中添加下面一行语句,保存后关闭:
bash
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
刷新环境变量,使之生效:
bash
source /etc/profile
🦄2.6.2 配置 OpenCV 动态库环境
我们需要将 OpenCV 的libs
的安装目录添加到动态库加载配置文件中,这样在编译时,才能找到 OpenCV 的各种库文件
bash
sudo gedit /etc/ld.so.conf
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/ld.so.conf
在文件夹中添加下面内容:
bash
include /etc/ld.so.conf.d/*.conf
/usr/local/lib
刷新动态库环境:
bash
sudo ldconfig
🦄2.6.3 配置 bash.bashrc
打开bash.bashrc
文件:
bash
sudo gedit /etc/bash.bashrc
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/bash.bashrc
添加下面内容:
bash
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
保存并关闭文件,激活bash.bashrc
bash
source /etc/bash.bashrc
😺三、下载 NCNN
NCNN-GitHub有现成的,所以我就没有编译,用的是下面版本:
https://github.com/Tencent/ncnn/releases/download/20240820/ncnn-20240820-ubuntu-2004-shared.zip
存放的目录是:/damn/***/clionproject/all_lib/ncnn-official/ncnn-20240820-ubuntu-2004-shared
😺四、CLion 工程
在 CLion 中创建一个工程,我命名为 ncnn_demo
在工程中创建了一个 assets 文件夹,存放与 squeezenet 相关的文件。
assets下一共有三个文件,分别是:squeezenet_v1.1.param
、squeezenet_v1.1.bin
、synset_words.txt
🐶4.1 编写 CMakeLists.txt
bash
cmake_minimum_required(VERSION 3.29)
project(ncnn_demo)
set(CMAKE_CXX_STANDARD 20)
# 设置opencv路径
set(OpenCV_DIR "/usr/local")
find_package(OpenCV REQUIRED)
# 设置ncnn路径
set(NCNN_INCLUDE_DIRS "/damn/***/clionproject/all_lib/ncnn-official/ncnn-20240820-ubuntu-2004-shared/include/ncnn")
set(ncnn_DIR "/damn/***/clionproject/all_lib/ncnn-official/ncnn-20240820-ubuntu-2004-shared/lib/cmake/ncnn")
find_package(ncnn REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS} ${NCNN_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ncnn)
因为之前不太懂CMakeLists.txt怎么写,所以这部分花了点时间。需要注意的有以下几点:
- OpenCV_DIR 和之前配置 opencv 时一样,/usr/local 下有 include 和 lib 等文件夹。
- include 文件夹下有 opencv4 文件夹,opencv4 文件夹下有 opencv2 文件夹,opencv2 文件夹中有 opencv 的库文件;
- lib 文件夹下有大量 opencv 的动态库。
- NCNN 的配置需要包含 include 库文件目录和 lib 动态链接库目录。
🐶4.2 编写 main.cpp
cpp
#include "iostream"
#include <vector>
#include <opencv4/opencv2/core/core.hpp>
#include <opencv4/opencv2/highgui/highgui.hpp>
#include "mat.h"
#include "net.h"
static int detect_squeezenet(const cv::Mat& bgr, std::vector<float>& cls_scores)
{
ncnn::Net squeezenet;
# squeezenet.opt.use_vulkan_compute = true;
squeezenet.load_param("/damn/***/clionproject/ncnn_demo/assets/squeezenet_v1.1.param");
squeezenet.load_model("/damn/***/clionproject/ncnn_demo/assets/squeezenet_v1.1.bin");
ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows, 227, 227);
const float mean_vals[3] = {104.f, 117.f, 123.f};
in.substract_mean_normalize(mean_vals, 0);
ncnn::Extractor ex = squeezenet.create_extractor();
ex.input("data", in);
ncnn::Mat out;
ex.extract("prob", out);
cls_scores.resize(out.w);
for (int j = 0; j < out.w; j++)
{
cls_scores[j] = out[j];
}
return 0;
}
static int print_topk(const std::vector<float>& cls_scores, int topk)
{
// partial sort topk with index
int size = cls_scores.size();
std::vector< std::pair<float, int> > vec;
vec.resize(size);
for (int i = 0; i<size; i++)
{
vec[i] = std::make_pair(cls_scores[i], i);
}
std::partial_sort(vec.begin(), vec.begin() + topk, vec.end(),
std::greater< std::pair<float, int> >());
// print topk and score
for (int i = 0; i<topk; i++)
{
float score = vec[i].first;
int index = vec[i].second;
fprintf(stderr, "%d = %f\n", index, score);
}
return 0;
}
int main()
{
std::string imagepath = "/damn/***/clionproject/ncnn_demo/0.jpg";
cv::Mat m = cv::imread(imagepath);
if (m.empty())
{
std::cout << "cv::imread " << imagepath << " failed\n" << std::endl;
return -1;
}
std::vector<float> cls_scores;
detect_squeezenet(m, cls_scores);
print_topk(cls_scores, 3);
return 0;
}
代码运行结果:
😺五、OpenCV-Mobile 替换 OpenCV
使用 opencv-mobile。
我直接下载的预编译包。
将解压后的 opencv-mobile 放到下面的目录下:
bash
/damn/wxr/clionproject/all_lib/opencv-mobile-4.10.0-ubuntu-2004
重新编写CmakeList.txt
,如下:
bash
cmake_minimum_required(VERSION 3.29)
project(ncnn_demo)
set(CMAKE_CXX_STANDARD 20)
# 设置opencv路径
set(OpenCV_INCLUDE_DIRS "/damn/wxr/clionproject/all_lib/opencv-mobile-4.10.0-ubuntu-2004/include/opencv4")
set(OpenCV_DIR "/damn/wxr/clionproject/all_lib/opencv-mobile-4.10.0-ubuntu-2004/lib/cmake/opencv4")
find_package(OpenCV REQUIRED)
# 设置ncnn路径
set(NCNN_INCLUDE_DIRS "/damn/wxr/clionproject/all_lib/ncnn-official/ncnn-20240820-ubuntu-2004-shared/include/ncnn")
set(ncnn_DIR "/damn/wxr/clionproject/all_lib/ncnn-official/ncnn-20240820-ubuntu-2004-shared/lib/cmake/ncnn")
find_package(ncnn REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS} ${NCNN_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ncnn)