百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

[深度学习] ncnn安装和调用基础教程

connygpt 2024-09-29 11:04 13 浏览

1 介绍

ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台,但是通常都需要protobuf和opencv。ncnn目前已在腾讯多款应用中使用,如 QQ,Qzone,微信,天天P图等。ncnn主要基于C++和caffe,ncnn项目地址见:

?https://github.com/Tencent/ncnn??

本文主要介绍ncnn在Ubuntu 18和Windows10下安装和使用。ncnn实测win10和Ubuntu18下C++调用squeezenet进行分类越比opencv dnn模块调用squeeznet快3到5倍。

ncnn常见的主流系统平台和常见硬件平台都支持,包括树莓派。

其他平台安装教程见:

??https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-windows-x64-using-visual-studio-community-2017??

2 Ubuntu 18下ncnn安装和使用

2.1 Ubuntu 18下ncnn编译安装

ncnn在linux平台需要protobuf和较低的gcc版本支持(根据评论区baiyu33的回复,最新ncnn版本在gcc/g++ 7.5环境,不需要降级为4.8.5,就可以编译安装protobuf 2.6.1和ncnn,2020年7月7日更新),如果你的系统可以运行caffe,可以跳过第一第二步,直接第三步。第一第二步具体安装protobuf见:


(1)将gcc、g++降级为4.8.5版本(最新版本ncnn可以跳过该阶段)。

(2)安装protobuf

(3)编译源码

先下载源码

Bash
git clone https://github.com/Tencent/ncnn

然后进入ncnn安装即可

Bash
cd ncnn

mkdir build

cd build

cmake ..

make –j12 

make install

2.2 Ubuntu 18下ncnn使用

(1) 模型更新

ncnn对caffe模型支持度比其他平台模型支持度更高。所以一般都是将caffe的模型转为ncnn格式。对于比较老的caffe模型需要将其转换为最新的caffe模型(相对来说),不过一般都不需要。以alexnet为例

alexnet 的 deploy.prototxt 可以在这里下载:

??https://github.com/BVLC/caffe/tree/master/models/bvlc_alexnet??

alexnet 的 caffemodel 可以在这里下载 :

??http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel??

caffe自带了工具可以把老版本的caffe 网络和模型转换为新版(ncnn的工具只认识新版),转换方法为将你需要转换的prototxt和caffemodel放在你电脑的caffe/build/tools目录下,然后终端进入caffe/build/tools,执行命令:.

./upgrade_net_proto_text old_deploy.prototxt new_deploy.prototxt
./upgrade_net_proto_binary old.caffemodel new.caffemodel

执行完成之后你就可以在caffe/build/tools下找到你的new_deploy.prototxt和new.caffemodel文件了。注意完成之后打开你的new_deploy.prototxt文件看一下,因为一般每次只需要做一个数据样本的识别,所以如果第一个 dim 不为1,要将其设为

layer {

  name: "data"

  type: "Input"

  top: "data"

  input_param { shape: { dim: 1 dim: 3 dim: 227 dim: 227 } }

}

(2)模型转换

模型转换具体使用见:

new.caffemodel文件后,需要将prototxt转换为ncnn支持的param文件,caffemodel转换为bin文件。Ncnn中使用 caffe2ncnn 工具转换为ncnn的网络描述和模型。将上面转化的new_deploy.prototxt和new.caffemodel放到ncnn/build/tools/caffe下。然后命令行输入以下命令:

./caffe2ncnn new_deploy.prototxt new.caffemodel ncnn.param ncnn.bin

或者在以下网站转换模型:

??https://convertmodel.com/?tdsourcetag=s_pcqq_aiomsg??

(3)运用模型分类

上面提到的是alexnet,在实际本文使用的是squeezenet。ncnn调用模型的一般过程都是参考ncnn/examples/下各个示例cpp文件,选择自己的模型,然后根据该目录下的CMakeLists.txt文件修改参数。本文就不修改参数了,直接选用squeezenet.cpp使用。

然后打开ncnn根目录下的CMakeLists.txt文件,将编译examples语句的注释打开(默认是被注释掉的),如图:

终端进入ncnn/build后执行:

make

然后把所获得ncnn参数和模型文件复制到ncnn/build/examples目录下,本文所用的squeezenet的ncnn文件在ncnn/examples中有提供。将模型.param和.bin文件复制到ncnn/build/examples目录下,然后终端cd到ncnn/build/examples,执行:

./squeezenet imagepath

Imagepath为图像路径。就可以得到结果。

具体调用代码直接参考ncnn/examples中的示例cpp文件,但是使用时最好使用examples所提到的模型。

(4)ncnn工程使用

如果想建立工程,需要自己新建一个目录然后编写你自己的cpp文件。比如使用ncnn/examples/squeezenet.cpp,将其放入本机任意路径新的文件夹。对于ncnn编译,需要添加opencv和openmp,编写如下CMakeLists.txt进行编译,然后cmake .就可以在当前目录运行生成的可执行文件ncnnTest。

# 设置cmake版本
cmake_minimum_required(VERSION 3.2)

# ncnn工程
project(ncnnTest)

# 调用opencv
find_package(OpenCV REQUIRED)
# 调用openmp
FIND_PACKAGE( OpenMP REQUIRED)  
if(OPENMP_FOUND)  
    message("OPENMP FOUND")  
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")  
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")  
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")  
endif()  

# 包含ncnn的头文件
include_directories(/home/user/ncnn/build/install/include/ncnn)
# 包含ncnn的链接文件
link_directories(/home/user/ncnn/build/install/lib)
# 生成可执行文件
add_executable(ncnnTest squeezenet.cpp)
# 链接ncnn静态链接库
target_link_libraries(ncnnTest ncnn ${OpenCV_LIBS} /home/user/ncnn/build/install/lib/libncnn.a)

3 Windows 10下ncnn安装和使用

Win10下安装和ncnn最好都基于visual studio2015以上平台,本文用的vs2017。

3.1 Windows 10下ncnn编译安装

(1)protobuf编译

Win10下需要首先编译ncnn所使用到的protobuf库。Protobuf3.4.0下载路径为:??https://github.com/google/protobuf/archive/v3.4.0.zip??

然后选择vs2017自带的命令提示符工具,对于命令提示符工具选择,用于后期可能会用到opencv或者其他软件包。需要确定是x86还是x64平台,本文由于用的x64平台,选择适用于vs2017的x64本机工具。如下所示:

特别要注意的在编译文件前,一定要确定命令工具所使用的是x64还是x86。

protobuf编译步骤为:

cd <protobuf-root-dir>

mkdir build-vs2017

cd build-vs2017

cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ../cmake

nmake

nmake install

上面protobuf-root-dir为你的protobuf文件路径,比如我的是D:/packages/protobuf-3.4.0,文件路径最好纯英文,protobuf设置的release格式。

(2)ncnn编译

下载ncnn源码,??https://github.com/Tencent/ncnn?? 然后用上面提到的开发工具进入ncnn安装即可,具体步骤如下:

cd <ncnn-root-dir>

mkdir build-vs2017

cd build-vs2017

cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=<protobuf-root-dir>/build-vs2017/install/include -DProtobuf_LIBRARIES=<protobuf-root-dir>/build-vs2017/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=<protobuf-root-dir>/build-vs2017/install/bin/protoc.exe -DNCNN_VULKAN=OFF ..

nmake

nmake install

注意<protobuf-root-dir>要替换为你的protobuf文件绝对路径,比如我的是D:/packages/protobuf-3.4.0。DCMAKE_BUILD_TYPE=Release确定编译的是release文件。

3.2 Windows 10下ncnn使用

ncnn使用类似opencv在windows下的使用。打开vs2017建立工程文件。项目-属性-VC++目录。设置配置文件,VC++目录在包含目录下输入以下路径,调用opencv,ncnn,protobuf头文件。

d:\opencv\build\include\opencv

d:\opencv\build\include

d:\opencv\build\include\opencv2

d:\packages\ncnn\build-vs2017\install\include

d:\packages\ncnn\build-vs2017\install\include\ncnn

d:\packages\protobuf-3.4.0\build-vs2017\install\include

d:\packages\protobuf-3.4.0\build-vs2017\install\include\google

具体如图所示:

接着配置库目录,输入以下路径配置链接文件

d:\opencv\build\x64\vc15\lib

d:\packages\ncnn\build-vs2017\install\lib

d:\packages\protobuf-3.4.0\build-vs2017\install\lib

但是额外要配置配置Windows运行库目录,主要是要protobuf配置文件:

d:\packages\protobuf-3.4.0\build-vs2017\install\bin

最后链接器-输入-附加依赖项配置附加依赖项。Protobuf相关依赖项已经调用了其动态库,就不需要再调用了。

opencv_world341.lib

ncnn.lib

这样ncnn就配置好了。输入代码,直接ncnn/examples中选用一个示例调用cpp就行了。但是只能在release x64下调用ncnn,具体编译ncnn时所选择的编译模式。比如squeezenet.cpp,直接复制过来,设置param和bin文件路径就行了。其他模型依葫芦画瓢。

// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#include <stdio.h>
#include <algorithm>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

// linux平台调用
// #include "platform.h"
// #include "net.h"

// windows平台调用
#include <net.h>
#include <platform.h>

#if NCNN_VULKAN
#include "gpu.h"
#endif // NCNN_VULKAN

static int detect_squeezenet(const cv::Mat& bgr, std::vector<float>& cls_scores)
{
    ncnn::Net squeezenet;

#if NCNN_VULKAN
    squeezenet.opt.use_vulkan_compute = true;
#endif // NCNN_VULKAN
    
    // squeezenet的ncnn模型文件路径
    squeezenet.load_param("squeezenet_v1.1.param");
    squeezenet.load_model("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()
{
    String imagepath = "./image/cat.jpg";
    cv::Mat m = cv::imread(imagepath);
    if (m.empty())
    {
        fprintf(stderr, "cv::imread %s failed\n", imagepath);
        return -1;
    }

#if NCNN_VULKAN
    ncnn::create_gpu_instance();
#endif // NCNN_VULKAN

    std::vector<float> cls_scores;
    detect_squeezenet(m, cls_scores);

#if NCNN_VULKAN
    ncnn::destroy_gpu_instance();
#endif // NCNN_VULKAN

    print_topk(cls_scores, 3);

    return 0;
}

4 参考

  1. ??https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-linux-x86??
  2. ??https://github.com/Tencent/ncnn/wiki/ncnn??

相关推荐

vue3 组件初始化流程

学习完成响应式系统后,咋们来看看vue3组件的初始化流程既然是看vue组件的初始化流程,咋们先来创建基本的代码,跑跑流程(在app.vue中写入以下内容,来跑流程)import{h,ref}...

Context的典型使用场景

获取应用文件路径基类Context提供了获取应用文件路径的能力,ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionCon...

web技术分享|AudioContext 实现音频可视化

要实现音频可视化,实现一些炫酷的效果需要借助WebAudioAPI提供的一些方法AudioContext。AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个...

2023-03-21:音视频解混合(demuxer)为MP3和H264,用go语言编写

2023-03-21:音视频解混合(demuxer)为MP3和H264,用go语言编写。答案2023-03-21:#步骤1:安装github.com/moonfdd/ffmpeg-gogoget...

如何在微信小程序中加入音频或视频?

要在微信小程序中加入音频或视频,可以使用以下步骤:1.在小程序页面中引入wx.createInnerAudioContext()或wx.createVideoContext()方法。2.创建音频或...

使用RKE的方式快速部署K8S集群

RKE是一款经过CNCF认证的开源Kubernetes发行版,可以在Docker容器内运行。它通过删除大部分主机依赖项,并为部署、升级和回滚、节点扩容提供一个稳定的路径,从而解决了Kubernetes...

Rancher(k8s)的持久存储卷Volumes(PV/PVC)的使用方法

1.介绍1.1介绍在上一节课里面福哥带着大家学会了使用k8s的负载均衡LoadBalancing(LB)发布集群内部的服务的方法,今天我们要讲讲k8s的持久存储卷Volumes(PVC)的使用方...

基于 Sealos 的镜像构建能力,快速部署自定义 k8s 集群

Sealos是一个快速构建高可用k8s集群的命令行工具,该工具部署时会在第一个k8smaster节点部署registry服务(sealos.hub),该域名通过hosts解析到第一...

Docker、Containerd、RunC分别是什么

什么是RunC上一遍文章《真正运行容器的工具:深入了解runc和OCI规范》已经讲清楚了Runc与OCI。这里再讲解一下概念。Docker、Google、CoreOS和其他供应商创建了开放容...

偷偷爆料下Docker学习,看这一篇就够了!十分推荐!!

一.什么是容器?生活中常将一个能用来承载物料的装置称之为容器,比如碗、盘子,杯子等,容器内可放入各种各样的物料,每一个容器都相互独立,不相互干扰。而我们计算机领域所说的容器通常是指一个包含了完整的运...

Docker网络优化方案,你认为哪种将引爆未来?

ICT架构师技术交流微信号分析和交流ICT行业最前沿技术,分享更多存储、服务器、数据中心、网络、软件定义和虚拟化等相关知识,旨在知识交流、开放共享和共同进步。上一篇文章Docker原生网络和实现原...

Docker容器和存储系统 云舒网络

江松:1986开始接触到苹果电脑,不是MacBook,是APPLEII.用Basic编程序。1999年去欧洲爱尔兰做存储,从并行SCSI协议开始做,到FC1G,4G,8G。2009年回国后进...

基于docker的跨主机WEB容器管理

前言由于我们的一部分服务器,分布在不同的公共网络环境。而且,这些服务器程序,发布都使用了docker,但并没有使用k8s这样的工具。处于离散的管理状态。也考虑过rancher这样的工具,但对于我们来说...

Kubernetes(k8s)docker 和 Containerd 区别

Kubernetes(k8s)、Docker和Containerd都是容器技术领域的重要工具,但它们各自有不同的角色和功能。Docker:Docker是一个开源的容器化平台,它允许开发者将应...

从 Docker 快刀到 K8s 剑法:程序员的云原生武功秘籍

前言在当今云计算的浪潮中,Docker和Kubernetes(K8s)已成为每位程序员必备的核心工具。Docker,如同一把锐利的快刀,能够迅速、简洁地将应用及其依赖封装成镜像,实现便捷的打包与发...