NCNN 记录1:Ubuntu+CLion+OpenCV+NCNN+Squeezenet 从源码编译到代码输出全流程记录

✨博客主页:王乐予🎈

✨年轻人要: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

安装依赖库libjasper1libjasper-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.paramsqueezenet_v1.1.binsynset_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。

https://github.com/nihui/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)
相关推荐
机器视觉知识推荐、就业指导1 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
朝九晚五ฺ1 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream1 小时前
Linux的桌面
linux
xiaozhiwise2 小时前
Makefile 之 自动化变量
linux
Yang.993 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王3 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_3 小时前
C++自己写类 和 运算符重载函数
c++
如若1233 小时前
主要用于图像的颜色提取、替换以及区域修改
人工智能·opencv·计算机视觉
六月的翅膀3 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++