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

ops/2024/10/16 0:00:19/

✨博客主页:王乐予🎈
✨年轻人要:Living for the moment(活在当下)!💪
🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】

目录

  • 😺一、引言
  • 😺二、编译 OpenCV
    • 🐶2.1 安装各种依赖
    • 🐶2.2 下载 OpenCV 和 OpenCV-Contrib
    • 🐶2.3 进入 opencv 目录并新建 build 文件夹
    • 🐶2.4 使用 CMake 生成构建脚本
    • 🐶2.5 编译并安装 OpenCV
    • 🐶2.6 配置环境
      • 🦄2.6.1 配置环境变量 PKG_CONFIG_PATH
      • 🦄2.6.2 配置 OpenCV 动态库环境
      • 🦄2.6.3 配置 bash.bashrc
  • 😺三、下载 NCNN
  • 😺四、CLion 工程
    • 🐶4.1 编写 CMakeLists.txt
    • 🐶4.2 编写 main.cpp
  • 😺五、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 安装各种依赖

更新环境:

sudo apt-get update
sudo apt-get upgrade

安装编译器和构建工具等,若已安装,跳过即可:

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

安装各种依赖库:

 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-devsudo apt-get install python-dev python-numpysudo apt-get install libgstreamer-plugins-base1.0-dev libgstreamer1.0-devsudo apt-get install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper1 libjasper-dev libdc1394-22-dev libopenexr-dev libwebp-devsudo apt-get install libatlas-base-dev gfortran sudo apt-get install ffmpeg

安装依赖库libjasper1libjasper-dev时,若报错E:Unable to locate package libjasper-dev ,可以命令行执行以下命令,然后再安装

 sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"            # 国内可能需要换国内的镜像sudo apt-get update 

🐶2.2 下载 OpenCV 和 OpenCV-Contrib

git clone https://github.com/opencv/opencv	# 默认安装最新的版本
git clone https://github.com/opencv/opencv_contrib

下载结束后进行解压:

unzip opencv.zip
unzip opencv_contrib.zip

解压完后的 opencv_contrib 放在 opencv 文件夹里面。

我的 opencv 所在的目录是:/home/***/opencv(***是用户名)

opencv__build__77">🐶2.3 进入 opencv 目录并新建 build 文件夹

mkdir -p build && cd build

🐶2.4 使用 CMake 生成构建脚本

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 目录下执行:

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的脚本文件:

sudo gedit /etc/profile.d/pkgconfig.sh
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/profile.d/pkgconfig.sh 

pkgconfig.sh文件中添加下面一行语句,保存后关闭:

export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

刷新环境变量,使之生效:

source /etc/profile

🦄2.6.2 配置 OpenCV 动态库环境

我们需要将 OpenCV 的libs的安装目录添加到动态库加载配置文件中,这样在编译时,才能找到 OpenCV 的各种库文件

sudo gedit /etc/ld.so.conf
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/ld.so.conf

在文件夹中添加下面内容:

include /etc/ld.so.conf.d/*.conf
/usr/local/lib

刷新动态库环境:

sudo ldconfig

🦄2.6.3 配置 bash.bashrc

打开bash.bashrc文件:

sudo gedit /etc/bash.bashrc 
# 如果gedit无法使用,也可以使用 touch 命令:sudo touch /etc/bash.bashrc

添加下面内容:

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH

保存并关闭文件,激活bash.bashrc

source /etc/bash.bashrc

NCNN_152">😺三、下载 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__158">😺四、CLion 工程

CLion 中创建一个工程,我命名为 ncnn_demo

在工程中创建了一个 assets 文件夹,存放与 squeezenet 相关的文件。

assets下一共有三个文件,分别是:squeezenet_v1.1.paramsqueezenet_v1.1.binsynset_words.txt

🐶4.1 编写 CMakeLists.txt

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

#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 indexint 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 scorefor (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 放到下面的目录下:

/damn/wxr/clionproject/all_lib/opencv-mobile-4.10.0-ubuntu-2004

重新编写CmakeList.txt,如下:

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)

http://www.ppmy.cn/ops/126180.html

相关文章

P1001 | 禾木切西瓜

P1001 | 禾木切西瓜 题目描述 酷热的夏天&#xff0c;禾木从冰箱中拿出一只西瓜&#xff0c;想要将它一分为二&#xff0c;用勺子舀着吃&#xff0c;但作为一个资深的吃货&#xff0c;禾木认为一只好西瓜&#xff0c;一分为二后&#xff0c;两部分的重量都应该为偶数。 例如一…

在 Jupyter Notebook 中,无法看到特定 Conda 环境的内核

问题概述 在 Jupyter Notebook 中&#xff0c;无法看到特定 Conda 环境的内核&#xff0c;导致无法在该环境下运行代码。这通常是由于内核未正确注册到 Jupyter 所致。 常见原因 未安装 ipykernel&#xff1a;每个 Conda 环境需要安装 ipykernel 才能作为 Jupyter 内核使用。…

【鱼类识别】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面+TensorFlow

一、介绍 鱼类识别系统。使用Python作为主要编程语言开发&#xff0c;通过收集常见的30种鱼类&#xff08;‘墨鱼’, ‘多宝鱼’, ‘带鱼’, ‘石斑鱼’, ‘秋刀鱼’, ‘章鱼’, ‘红鱼’, ‘罗非鱼’, ‘胖头鱼’, ‘草鱼’, ‘银鱼’, ‘青鱼’, ‘马头鱼’, ‘鱿鱼’, ‘鲇…

面试22222

好的&#xff0c;我会逐步解释这些面试问题&#xff0c;并给出一些应答建议。我们先从第一个问题开始&#xff1a; 1. 介绍一下你的学术背景和工作经验&#xff0c;以及为什么对生物信息学感兴趣。 回答思路&#xff1a; 首先简单概述你的学术背景&#xff0c;比如你的专业、…

怎么快速定位bug?怎么编写测试用例?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xff0c;那么在…

DAY7 继承多态

继承 目的 提高代码的重用性&#xff0c;减少一些重复代码的书写 权限修饰符 就是是用来限制类中的成员&#xff08;成员变量、成员方法、构造器&#xff09;能够被访问的范围。 private 只能本类 缺省 本类、同一个包中的类 protected 本类&#xff0c;同一个包中的类、子…

【部署篇】Redis-01介绍‌

一、Redis介绍‌ 1、什么是Redis&#xff1f; ‌Redis&#xff0c;英文全称是Remote Dictionary Server&#xff08;远程字典服务&#xff09;&#xff0c;Redis是一个开源的、使用‌ANSI C语言编写的‌Key-Value存储系统&#xff0c;支持网络、可基于内存亦可持久化。‌ 它提…

【Qt】继承自QItemDelegate的代理类是如何工作的?

在 Qt 中&#xff0c;继承自QItemDelegate的代理类主要使用createEditor 和 setEditorData 方法&#xff1a; 创建编辑器&#xff1a;当用户开始编辑一个项时&#xff08;例如通过双击一个单元格或者通过其他方式触发编辑&#xff09;&#xff0c;视图会调用委托的 createEdit…