深度学习-服务端训练+android客户端物体识别实战(caffe入门教程+mobilenet+ncnn+android)

文章目录

  • 背景
  • 物体识别简介

  • 自动驾驶

    • 淘宝京东使用物体识别技术
    • 公司业务需求
  • 深度学习简介

  • 深度学习的位置

    • 深度学习概念
    • 深度学习优势
  • 深度学习基础知识

  • 感知机

    • 激活函数
    • 多层感知机
    • 卷积神经网络
  • 卷积层 * 池化层

    • 模型训练
  • 前向传播 * 反向传播与参数优化

  • 深度学习服务端框架

  • tensorFlow

    • keras
    • pytorch
    • Caffe/Caffe2.0
  • caffe框架

  • 为何选择caffe

    • caffe环境搭建
    • caffe基础
  • 数据集 模块概要图 solver(prototxt) 执行者配置 神经网络可视化 caffe中的基础概念

  • blobs layer 神经层 net 神经网络 * forward/backward 前向传播/反向传播

* caffe+mnist数据集+lenet
* caffe+cifar10+caffenet
* caffe+cifar10+mobilenet
* caffe+voc2012+vgg(finetune)+ssd(物体检测模型)
  • 轻量级客户端框架-ncnn

  • ncnn简介

    • ncnn+caffe+mobilenet实战
  • ncnn环境搭建 * 模型转化(caffe格式-> ncnn格式)

    • 源码解析
  • 文件目录 执行流程 重点代码 效果展示 其他工程的效果图

  • 相关学习资料

  • 教学视频

    • 开源项目
    • 参考博客

背景

产品以后的发展需要添加更多科技元素,如下:

  • 人脸识别
  • 物体识别
  • 场景识别

以下以物体识别为重点,使用到了深度学习技术,以下我们将逐一展开。
本次分享的重点是深度学习+caffe+ncnn,其余部分将简单的进行带过。
注:本文主要以有监督的学习为主(分类和回归问题),无监督学习不作为分享范围。

物体识别简介

物体识别(俗称Object detection),是近年来兴起的技术,这也是人工智能的首要目标之一。这是一种完全模拟人眼识别的技术,即使在物体旋转、变色、部分展示等的情况下,同样具备优秀的识别效果。
人工智能目标是:

  • 让机器看世界
  • 让机器听世界
  • 让机器独立思考
    在这里插入图片描述

自动驾驶

在驾驶领域中,引入物体识别技术将大大降低交通事故发生的概率。
在这里插入图片描述
在这里插入图片描述

淘宝京东使用物体识别技术

在这里插入图片描述

公司业务需求

近期产品提出物体识别的相应需求,能识别出家长和老师发送图片中的物体,来开展相应的业务。以下是一张海边游玩的照片。
在这里插入图片描述

深度学习简介

深度学习的位置

在这里插入图片描述
深度学习分别属于人工智能和机器学习的一部分。与深度学习相并行的另外一种机器学习方法,被称之为传统的机器学习(例如svm、逻辑回归)。

深度学习概念

人工神经网络是一个分层的有向图,第一层输入节点接受输入的信息,也称为输入层。来自这些点的数值按照它们输出的弧的权重(wn),进行线性加权(得到G),然后再做一次函数变化f(G),赋给第二层的节点Y。
第二层的节点照此将数值向后传递,直到第三层节点,如此一层层传递,直到最后一层,最后一层又被称为输出层。在模式分类时,一个模式(图像、语音、文字等)的特征值(比如坐标),从输入层开始,按照上面的规则和公式一层层向后传递。最后在输出层,哪个节点的数值最大,输入的模式就被分在了哪一类。
------------------引自《数学之美—Google大脑和人工神经网络》

在这里插入图片描述

在这里插入图片描述

深度学习优势

神经网络与传统的机器学习相比:

  • 能支持更复杂的分类边界
  • 非线性表征更加丰富
  • 准确率会随着数据集的增加而突破传统学习的瓶颈
  • 与svm相比,在大数据集上收敛的更快
  • 轻量级神经网络具备高性能的前向传播,方便部署到移动设备
    在这里插入图片描述

在这里插入图片描述

深度学习基础知识

参考:https://www.cnblogs.com/wj-1314/p/9754072.html

感知机

可以简单的理解为是线性分类。假设训练数据集是线性可分的,感知机学习的目标是求得一个能够将训练数据集正实例点和负实例点完全正确分开的分离超平面。
在这里插入图片描述
感知机重点包含以下两点:

  • 线性加权
  • 依靠损失函数进行权重优化

数学公式略,将在其他博文中进行阐述。

感知机的缺陷:只支持线性分类,对于简单的异或问题也不能进行分类。以下是异或问题中最简单的情况,可以看到无论哪一条直线都不能进行完美的分割。
在这里插入图片描述

激活函数

针对于感知机不能表达非线性的问题,激活函数诞生了。

在人工神经网络中,规定神经元函数只能对输入变量(指向他的节点的值)线性组合后的结果进行一次非线性变换。
这次非线性变化成为“激活函数”
----《数学之美》

为了神经网络的通用性,每一层的非线性变化都选择同一类函数。
激活函数包括:

  • relu
  • sigmoid
  • tanh
  • 等等

激活函数参考博客:https://blog.csdn.net/tyhj_sf/article/details/79932893
在这里插入图片描述

多层感知机

多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构
在这里插入图片描述

  • 输入层,输入特征数据等加工或者没有加工过的原始数据
  • 隐含层,隐含层可以很多,resnet有128层的,就是说的隐含层
  • 输出层,输出最后的计算结果,很多神经网络里面都把输出层定义为概率值

多层感知机等同于全连接层,信息每向下传递一个神经元,都会产生n*n的计算量(计算量会随着输入的维度增大而变得非常恐怖)

卷积神经网络

卷积神经网络是近年发展起来的,并引起广泛重视的一种高效识别方法,20世纪60年代,Hubel和Wiesel在研究猫脑皮层中用于局部敏感和方向选择的神经元时发现其独特的网络结构可以有效地降低反馈神经网络的复杂性,继而提出了卷积神经网络(Convolutional Neural Networks-简称CNN)

参考资料:https://www.cnblogs.com/wj-1314/p/9754072.html

卷积的原理与人眼观察事物极其相似,过程都是边缘 -> 局部 -> 整体。卷积神经网络的核心就是使用多个局部特征来影响分类结果。
在这里插入图片描述
全连接的计算量非常大。而且是以整体来计算,没有进行有效的特征提取,即使权重最终达到了收敛效果,也不能很好的进行预测。
卷积神经网络则不同,每次卷积完毕后,传入下一层的数据大大降低了维度,而且经过卷积,获得了众多局部特征,后面的层对这些特征数据进行训练,将变得既简单又高效。

卷积层

简单来说,卷积层用于特征提取。
在这里插入图片描述
根据卷积核的滑动,获取到一个新的特征数据(Convolved Feature)。这个特征数据不是那么直观,来看一下实物的效果。
在这里插入图片描述
针对于不同的通道(rgb)进行卷积后,会得到边缘轮廓的图。

池化层

池化层用于降低参数,而降低参数的方法当然是删除参数,保留最有效的参数。

一般我们有最大池化和平均池化。

  • 最大池化是现在使用最多的,可以突出局部特征
  • 平均池化则考虑了所有参数,而计算出了平均值

需要注意的是,池化层一般放在卷积层后面。所以池化层池化的是卷积层的输出。

模型训练

本博客重点关注有监督的训练。在训练之前需要有一批标注好的数据,即训练数据。为了能在训练过程中动态的观测模型的准确率,同样也需要一批标注数据(推荐为训练数据/测试数据比例为4/1)

前向传播

在这里插入图片描述
前向传播,即训练数据在神经网络里从输入层到输出层的方向传播一次,最终得到输出层的输出结果,即在每个分类的概率值。

反向传播与参数优化

用数据语言来表达:假设C为一个成本函数(Cost Function),它表示根据人工神经网络的输出值(分类结果概率)和实际训练数据中的输出值之间的差距。现在,训练人工神经网络的问题就变成了一个最优化的问题,说的通俗点就是数学中的“找最大(最小)值”的问题。解决最优化为题的常用方法是梯度下降法(Gradient Descent)
在这里插入图片描述
注:这里存在一个局部最优解的问题,不过已经被证明:在深度神经网络中,即使收敛过程进入了局部最优,最终结果也与全局最优没有明显差异。

深度学习服务端框架

在这里插入图片描述

tensorFlow

2015年11月谷歌(Google)出品,基于Python和C++编写。GitHub上最热,谷歌搜索最多,使用人数最多(笔者也是其中之一),大多数网上招聘工作描述中也提到了它。由于Google在深度学习领域的巨大影响力和强大的推广能力,TensorFlow一经推出就获得了极大的关注,并迅速成为如今用户最多的深度学习框架。2019年3月已发布最新的TensorFlow2.0 版本。

官方网站:https://www.tensorflow.org/
优点:

  • 自带tensorboard可视化工具,能够让用户实时监控观察训练过程在这里插入图片描述
  • 拥有大量的开发者,有详细的说明文档、可查询资料多
  • 支持多GPU、分布式训练,跨平台运行能力强
  • 具备不局限于深度学习的多种用途,还有支持强化学习和其他算法的工具

缺点:

  • 频繁变动的接口。TensorFlow的接口一直处于快速迭代之中,并且没有很好地考虑向后兼容性,这导致现在许多开源代码已经无法在新版的TensorFlow上运行,同时也间接导致了许多基于TensorFlow的第三方框架出现BUG
  • 接口设计过于晦涩难懂,在设计TensorFlow时,创造了图、会话、命名空间、PlaceHolder等诸多抽象概念,对初学者来说较难上手
  • 运行明显比其他框架速度慢

keras

Keras 于2015年3月首次发布,拥有“为人类而不是机器设计的API”,得到Google的支持。它是一个用于快速构建深度学习原型的高层神经网络库,由纯Python编写而成,以TensorFlow,CNTK,Theano和MXNet为底层引擎,提供简单易用的API接口,能够极大地减少一般应用下用户的工作量。
如果你是深度学习的初学者,想要快速入门,建议从Keras开始。
官方网站:https://keras.io

优点:

  • 更简洁,更简单的API
  • 丰富的教程和可重复使用的代码
  • 更多的部署选项(直接并且通过TensorFlow后端),更简单的模型导出

缺点:

  • 过度封装导致丧失灵活性,导致用户在新增操作或是获取底层的数据信息时过于困难
  • 初学者容易依赖于 Keras 的易使用性而忽略底层原理

pytorch

PyTorch于2016年10月发布,是一款专注于直接处理数组表达式的低级API。 前身是 Torch(一个基于 Lua 语言的深度学习库)。Facebook 人工智能研究院对PyTorch提供了强力支持。 PyTorch 支持动态计算图,为更具数学倾向的用户提供了更低层次的方法和更多的灵活性,目前许多新发表的论文都采用PyTorch作为论文实现的工具,成为学术研究的首选解决方案。

如果你是一名科研工作者,倾向于理解你的模型真正在做什么,那么就考虑选择PyTorch。

官方网站:https://pytorch.org/

Caffe/Caffe2.0

Caffe的全称是Convolutional Architecture for Fast Feature Embedding,它是一个清晰、高效的深度学习框架,于2013年底由加州大学伯克利分校开发,核心语言是C++。它支持命令行、Python和MATLAB接口。Caffe的一个重要特色是可以在不编写代码的情况下训练和部署模型。

具体介绍见下文。

caffe框架

为何选择caffe

我们暂时先选择caffe框架作为分享目标,原因如下:

  • 与ncnn的兼容性好(最重点)
  • 不需要写代码就可以实现训练(可以作为深度学习的突破口)
  • 支持python接口,可以丰富编程化实现
  • 丰富的demo实现等

caffe环境搭建

推荐ubuntu系统,参考博客:https://blog.csdn.net/wangjie5540/article/details/97786182
mac系统也可搭建,参考博客:https://blog.csdn.net/wangjie5540/article/details/99571832

caffe使用了众多的依赖库,再加上caffe年久失修,出现编译兼容问题也不奇怪。推荐大家在ubuntu上进行编译,可以驱动gpu,mac的最新14.14不支持n卡,据说需要降到14.13才可以。

caffe基础

针对于神经网络的模型,caffe设计了对应的概念。并且使用caffe来训练模型的过程非常简单,甚至都不用写一行代码,仅仅改改配置文件也同样能直接开始训练(当然,用python去写训练过程的话,会更加的灵活)。

数据集

  • 原始数据,本文主要针对的是图片数据,可能有不同的格式(image格式、bytes格式、lmdb格式等)
  • 标注数据,监督学习,必须进行标注

caffe倾向于先把数据集转化成lmdb或者hdf5格式,然后输入神经网络进行训练。

模块概要图

在这里插入图片描述
概要:

  • 使用数据构建脚本,构建训练数据和测试数据
  • caffe train命令加载solver的prototxt配置
  • solver配置加载神经网络配置
  • 神经网络对接训练数据和测试数据
  • 成千上万次迭代,最终按照solver中的配置策略,周期性生成权重模型文件

solver(prototxt) 执行者配置

超参数配置文件。
超参数的概念如下:

在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果

神经网络可视化

http://ethereon.github.io/netscope/#/editor
下面是对lenet的可视化,可以清楚的看到lenet的全貌。

  • mnist数据输入
  • conv1,第一次卷积层
  • pool1,第一池化层
  • conv2,第二次卷积层
  • pool2,第二次池化层
  • ip1,全连接层(即多层感知机)
  • relu1,激活层
  • ip2,全连接层
  • loss,损失层(同时激发bn反向传播操作)
    在这里插入图片描述

caffe中的基础概念

blobs

  • 对待处理数据带一层封装用于在Caffe中通信传递
  • 也为CPU和GPU间提供同步能力
  • 数学上,是一个N维的C风格的存储数组

总的来说,Caffe使用Blob来交流数据,其是Caffe中标准的数组与统一的内存接口,它是多功能的,在不同的应用场景具有不同的含义,如可以是:batches of images, model parameters, and derivatives for optimization等
作者:沤江一流
链接:https://www.jianshu.com/p/0ac09c3ffec0

layer 神经层

layer是caffe神经网络的基本组成单元。layer包括不同的种类:

  • Data,也就是blob的层
  • Convolution,卷积层
  • Pooling,池化层
  • InnerProduct,全连接
  • SoftmaxWithLoss,激活函数+loss层

不同的层次对应了神经网络中的不通过概念。另外,每种类型的层在caffe的源码中有特定的实现,之后会在其他博客中展开讨论,这里不再赘述。

net 神经网络

net是指神经网络定义,可以认为是layer的总和。在python版本编程中会出现net的概念。

forward/backward 前向传播/反向传播

forward和backward在python编程版本中会出现,手动执行会触发一次前向传播或反向传播(python实现的caffe训练最终的本质是在循环中每次手动触发forward函数,重点看一下本博客的caffe+mnist的python实现注释版)。

caffe+mnist数据集+lenet

参考博客:https://blog.csdn.net/wangjie5540/article/details/98615226
python实现mnist(注释版):https://gitee.com/simple_projects/caffe_learning/blob/master/01-learning-lenet-mine.ipynb

caffe+cifar10+caffenet

非常类似mnist数据集,参考:https://blog.csdn.net/wangjie5540/article/details/98615226

caffe+cifar10+mobilenet

参考:https://github.com/shicai/MobileNet-Caffe.git
shicai的mobilenet提供了预训练模型,可以直接进行数据预测。
在这里插入图片描述
大家肯定想,预训练模型没什么意思,要自己训练才来实际。
参考:https://blog.csdn.net/lwplwf/article/details/82415525,可以使用cifar10进行模型训练。
(ps,作者用cpu训练了几天,最终迭代了19w次,最终准确率在70%,没有达到很好的收敛效果。之后准备好gpu的机器,还会再次训练,以观后效)

注:cifar10的数据集进行模型训练的时候,出现mean的概念(即均值,rgb每个通道上的像素的平均值)。这样做的目的是让个像素的值以0为对称点进行均匀分布,训练过程更容易收敛。有两种获取均值的方法:

  • 以数据集为目标,把每个通道上的像素值全部加和,然后求平均(caffe的cifar10就是使用的这种方法)
  • 直接使用均值(128,128,128),简单暴力。(mobilenet+ssd的训练过程中就是这么做的,最终也能收敛)

以上两种方法,暂时没有证实哪个效果最好。

caffe+voc2012+vgg(finetune)+ssd(物体检测模型)

参考:https://github.com/weiliu89/caffe.git
voc的数据集需要在外网下载,时间要好久好久。。我已经把这些数据都下载完毕,上传到云盘。以下是下载地址:https://download.csdn.net/download/wangjie5540/11598810
由于本次是迁移训练,预训练模型是vggnet,还需要下载vggnet,地址是:https://download.csdn.net/download/wangjie5540/11603902

注:博主用cpu训练跑了两天,还没有跑到第一次的快照地点。如果想自己训练的话,就选gpu的机器吧。

轻量级客户端框架-ncnn

ncnn简介

git地址:https://github.com/Tencent/ncnn
ncnn 是一个为手机端极致优化的高性能神经网络前向计算框架。ncnn 从设计之初深刻考虑手机端的部署和使用。无第三方依赖,跨平台,手机端 cpu 的速度快于目前所有已知的开源框架。基于 ncnn,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能 APP,将 AI 带到你的指尖。ncnn 目前已在腾讯多款应用中使用,如 QQ,Qzone,微信,天天P图等。

支持大部分常用的 CNN 网络

  • Classical CNN: VGG AlexNet GoogleNet Inception …
  • Practical CNN: ResNet DenseNet SENet FPN …
  • Light-weight CNN: SqueezeNet MobileNetV1/V2/V3 ShuffleNetV1/V2 MNasNet …
  • Detection: MTCNN facedetection …
  • Detection: VGG-SSD MobileNet-SSD SqueezeNet-SSD MobileNetV2-SSDLite …
  • Detection: Faster-RCNN R-FCN …
  • Detection: YOLOV2 YOLOV3 MobileNet-YOLOV3 …
  • Segmentation: FCN PSPNet UNet …

ncnn+caffe+mobilenet实战

ncnn环境搭建

先下载release版本的ncnn,我这里现在ncnn-20190611

$ cd <ncnn-root-dir>
$ mkdir -p build-android-armv7
$ cd build-android-armv7$ cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \-DANDROID_PLATFORM=android-14 ..# if you want to enable vulkan, platform api version >= android-24 is needed
$ cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \-DANDROID_PLATFORM=android-24 -DNCNN_VULKAN=ON ..$ make -j4
$ make installpick build-android-armv7/install folder for further jni usage

编译完成后,生成以下文件
在这里插入图片描述
支持库和头文件供android的arm-v7a使用

模型转化(caffe格式-> ncnn格式)

首先需要编译caffe的环境。
参考:
https://blog.csdn.net/wangjie5540/article/details/97786182
https://blog.csdn.net/wangjie5540/article/details/99571832

源码解析

文件目录

├── README.md
├── app
│   ├── build.gradle // android工程配置
│   ├── proguard-rules.pro // 混淆配置
│   └── src
│       ├── androidTest
│       │   └── java
│       │       └── com
│       │           └── ztjy
│       │               └── ncnndemo
│       │                   └── ExampleInstrumentedTest.java
│       ├── main
│       │   ├── AndroidManifest.xml
│       │   ├── assets
│       │   │   ├── mobilenet_v2.bin // mobilenet权重文件
│       │   │   ├── mobilenet_v2.param.bin // 神经网络参数文件
│       │   │   └── synset.txt // 分类索引文件
│       │   ├── cpp
│       │   │   ├── CMakeLists.txt
│       │   │   ├── include // ncnn的头文件
│       │   │   │   ├── allocator.h
│       │   │   │   ├── benchmark.h
│       │   │   │   ├── blob.h
│       │   │   │   ├── caffe.pb.h
│       │   │   │   ├── command.h
│       │   │   │   ├── cpu.h
│       │   │   │   ├── gpu.h
│       │   │   │   ├── layer.h
│       │   │   │   ├── layer_type.h
│       │   │   │   ├── layer_type_enum.h
│       │   │   │   ├── mat.h
│       │   │   │   ├── mobilenet_v2.id.h
│       │   │   │   ├── mobilenet_v2.mem.h
│       │   │   │   ├── modelbin.h
│       │   │   │   ├── net.h
│       │   │   │   ├── opencv.h
│       │   │   │   ├── option.h
│       │   │   │   ├── paramdict.h
│       │   │   │   ├── pipeline.h
│       │   │   │   └── platform.h
│       │   │   ├── jniLibs
│       │   │   │   └── armeabi-v7a
│       │   │   │       └── libncnn.a // ncnn静态库
│       │   │   └── native-lib.cpp
│       │   ├── java
│       │   │   └── com
│       │   │       └── ztjy
│       │   │           └── ncnndemo
│       │   │               ├── MainActivity.java // 主窗体
│       │   │               ├── NcnnJni.java // jni交互文件
│       │   │               └── PhotoUtil.java // 图片工具文类(从相册中取文件)
│       │   └── res
│       │       ├── drawable
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout
│       │       │   └── activity_main.xml
│       │       ├── mipmap-anydpi-v26
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── mipmap-hdpi
│       │       │   ├── ic_launcher.png
│       │       │   └── ic_launcher_round.png
│       │       ├── mipmap-mdpi
│       │       │   ├── ic_launcher.png
│       │       │   └── ic_launcher_round.png
│       │       ├── mipmap-xhdpi
│       │       │   ├── ic_launcher.png
│       │       │   └── ic_launcher_round.png
│       │       ├── mipmap-xxhdpi
│       │       │   ├── ic_launcher.png
│       │       │   └── ic_launcher_round.png
│       │       ├── mipmap-xxxhdpi
│       │       │   ├── ic_launcher.png
│       │       │   └── ic_launcher_round.png
│       │       └── values
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test
│           └── java
│               └── com
│                   └── ztjy
│                       └── ncnndemo
│                           └── ExampleUnitTest.java
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

执行流程

https://www.processon.com/view/link/5d5cfe08e4b08b95b82695bb
在这里插入图片描述

重点代码

java层代码

//  predict imageprivate void predict_image(String image_path) {// picture to float arrayBitmap bmp = PhotoUtil.getScaleBitmap(image_path);Bitmap rgba = bmp.copy(Bitmap.Config.ARGB_8888, true);// resize to 227x227Bitmap input_bmp = Bitmap.createScaledBitmap(rgba, ddims[2], ddims[3], false);try {// Data format conversion takes too long// Log.d("inputData", Arrays.toString(inputData));long start = System.currentTimeMillis();// get predict result(调用jni层代码,进行预测)float[] result = squeezencnn.detect(input_bmp);long end = System.currentTimeMillis();Log.d(TAG, "origin predict result:" + Arrays.toString(result));long time = end - start;Log.d(TAG, String.valueOf(result.length));// show predict result and timeint r = get_max_result(result);Log.d(TAG, r + "");Log.d(TAG, resultLabel.toString());Log.d(TAG, resultLabel.get(r));Log.d(TAG, result[r] + "");Log.d(TAG, time + "");String show_text = "result:" + r + ",name:" + resultLabel.get(r) + "\nprobability:" + result[r] + "\ntime:" + time + "ms";Log.d(TAG, show_text);result_text.setText(show_text);} catch (Exception e) {e.printStackTrace();}}

jni层代码

// public native String Detect(Bitmap bitmap);
JNIEXPORT jfloatArray JNICALL
Java_com_ztjy_ncnndemo_NcnnJni_detect(JNIEnv *env, jobject thiz, jobject bitmap) {// ncnn from bitmapncnn::Mat in;{AndroidBitmapInfo info;// 获取位图信息AndroidBitmap_getInfo(env, bitmap, &info);// 获取位图宽高int width = info.width;int height = info.height;// demo只支持rgba格式的图片if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)return NULL;void *indata;AndroidBitmap_lockPixels(env, bitmap, &indata);// 把像素转换成data,并指定通道顺序in = ncnn::Mat::from_pixels((const unsigned char *) indata, ncnn::Mat::PIXEL_RGBA2BGR,width, height);AndroidBitmap_unlockPixels(env, bitmap);}// ncnn_net// std::vector<float> cls_scores;{// 减去均值和乘上比例(来源与caffe神经网络的配置文件,即prototxt文件)const float mean_vals[3] = {103.94f, 116.78f, 123.68f};const float scale[3] = {0.017f, 0.017f, 0.017f};// 设置均值与标准化参数in.substract_mean_normalize(mean_vals, scale);// 创建ncnn前向传播的结果提取器ncnn::Extractor ex = ncnn_net.create_extractor();// 如果不加密使用ex.input("data", in);ex.input(mobilenet_v2_param_id::BLOB_data, in);ncnn::Mat out;// 如果不加密是使用ex.extract("prob", out);ex.extract(mobilenet_v2_param_id::BLOB_prob, out);int output_size = out.w;jfloat *output[output_size];for (int j = 0; j < out.w; j++) {output[j] = &out[j];}// 获取结果预测结果,并返回给android层jfloatArray jOutputData = env->NewFloatArray(output_size);if (jOutputData == nullptr) return nullptr;env->SetFloatArrayRegion(jOutputData, 0, output_size,reinterpret_cast<const jfloat *>(*output));  // copyreturn jOutputData;}
}

效果展示

caffe+mobilenet分类
在这里插入图片描述

其他工程的效果图

https://github.com/chehongshu/ncnnforandroid_objectiondetection_Mobilenetssd.git
ncnn+mobilenet-ssd
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关学习资料

教学视频

唐宇迪-深度学习Caffe框架入门视频课程:https://edu.csdn.net/course/detail/3506
会写代码的好厨师-Caffe实战入门:https://www.imooc.com/learn/1040

开源项目

caffe官网:https://github.com/BVLC/caffe
ncnn:https://github.com/Tencent/ncnn.git
ncnn+mobilenet-ssd:https://github.com/chehongshu/ncnnforandroid_objectiondetection_Mobilenetssd
shicai_mobilenet:https://github.com/shicai/MobileNet-Caffe.git
weiliu89:https://github.com/weiliu89/caffe.git(需要check_out到ssd分支)

参考博客

在Android手机上使用腾讯的ncnn实现图像分类:
https://blog.csdn.net/qq_33200967/article/details/82421089

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547748.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java数组怎么倒循环_java – 用于数组倒计时的反向循环

我收到错误..Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10at Reverse.main(Reverse.java:20).语法没有错,所以我不确定为什么编译时会出错&#xff1f;public class Reverse {public static void main(String [] args){int i, j;System…

解压zip,解决中文乱码

Project p new Project(); Expand e new Expand(); e.setProject(p); e.setSrc(file); e.setOverwrite(false); e.setDest(new File(savepath)); /* * * ant下的zip工具默认压缩编码为UTF-8编码&#xff0c; …

二维码的生成(可设置大小)以及插件下载地址

本文写的二维码生成是基于jQuery和jquery.qrcode.min.js插件的&#xff0c;本文将介绍两种方法和方式&#xff0c;仅供朋友选择和取舍。本文最下面附有插件的下载地址&#xff01; 方式1&#xff1a; 基于jquery.qrcode.min.js插件生成&#xff0c;代码如下&#xff1a; <h…

java+包装类,装箱和拆箱_Java包装类,装箱和拆箱详解

下面要给大家讲到的就是Java内置包装类方面的知识&#xff0c;这章主要会讲到Java包装类装箱和拆箱方面的知识&#xff0c;一起来了解一下。Java为每种基本数据类型分别设计了对应的类&#xff0c;这就被叫做是包装类(WrapperClasses)&#xff0c;当然&#xff0c;也有的地方叫…

AI换声,只需5秒音源,这个网络就能实时“克隆”你的声音

本文中&#xff0c;Google 团队提出了一种文本语音合成&#xff08;text to speech&#xff09;神经系统&#xff0c;能通过少量样本学习到多个不同说话者&#xff08;speaker&#xff09;的语音特征&#xff0c;并合成他们的讲话音频。此外&#xff0c;对于训练时网络没有接触…

Using JSON for data transfer

为什么80%的码农都做不了架构师&#xff1f;>>> JSON basics At its simplest, JSON allows you to transform a set of data represented in a JavaScript object into a string that you can easily pass from one function to another, or -- in the case of as…

jquery的扩展方法介绍

最近一直在写js&#xff0c;这其中也少不了一位js的主角了jQuery&#xff0c;下面介绍的是jQuery的一些扩展&#xff0c;也就是jQuery的扩展方法&#xff0c;jQuery的扩展方法有两种方式&#xff0c;一种是jQuery本身的扩展方法&#xff0c;另一种是jQuery所选对象的扩展方法&a…

Gtk-WARNING : cannot open display----这个问题在NVIDIA TX2上碰到过就是DISPLAY=“:0“

切换到root权限&#xff0c;在终端下使用gedit时出现下面的错误&#xff1a; No protocol specified (gedit:14333): Gtk-WARNING **: cannot open display: :0.0 下面是从网上找到的正解&#xff0c;贴——分析——总结之&#xff1a; 原因&#xff1a; 当使用su 到另外一个用…

蓝桥杯vip答案java_Java实现 蓝桥杯VIP 算法训练 麦森数

算法训练 麦森数时间限制&#xff1a;1.0s 内存限制&#xff1a;256.0MB问题描述形如2P-1的素数称为麦森数&#xff0c;这时P一定也是个素数。但反过来不一定&#xff0c;即如果P是个素数&#xff0c;2P-1不一定也是素数。到1998年底&#xff0c;人们已找到了37个麦森数。最大的…

Visual Studio 2010 中JS注释制作

Visual Studio 2010中的js注释已经很强大了&#xff0c;但怎么才能和调用c#的方法一样容易呢&#xff1f;怎样才能让每个参数都有注释说明呢&#xff1f;底下就是想要的答案。 先上图&#xff0c;如图所示&#xff1a; 其中红色的办法为注释效果&#xff0c;当然制作的方法也在…

windows下配置caffe-matlab接口

一、环境说明 也是安装顺序。特别强调的是除VS2015以外&#xff0c;其他软件的安装路径都最好不要包含空格。 1、Windows 64位系统。 2、Visual Studio 2015(VS2015, 对应VC14)。 3、Matlab 2017a。Matlab的版本倒不是很重要&#xff0c;只要支持Matlab 2015a之后的版本都应该…

java在文档末尾添加_如何在打开表单后将子文件添加到Word文档的末尾?

我m trying to write a macro that adds subdocuments to the end of a Word document when the Word document is opened. The document in question already has some text in it, so before running the macro I d喜欢将光标移动到文档的末尾 . 我可以使用代码实现这一点&am…

oracle的db link

cd $ORACLE_HOME/network/admin vi tnsnames.ora 添加 CCPBS_19 (DESCRIPTION (ADDRESS_LIST (ADDRESS (PROTOCOL TCP)(HOST 10.130.38.19)(PORT 1521)) ) (CONNECT_DATA (SERVICE_NAME CCPBS) ) ) >create public database link ecbm_19 …

NVelocity标签使用详解

本文使用的NVelocity版本为1.1.1&#xff0c;应该是目前为止最新的版本吧&#xff0c;前几天在google上找了一个自称是NVelocity 1.6.1 bate2的dll&#xff0c;下载下来一看更新时间是2009年的&#xff0c;还没版本NVelocity 1.1.1&#xff08;2010年出的&#xff09; 新呢&…

一文搞懂蓝绿发布、灰度发布和滚动发布

一文搞懂蓝绿发布、灰度发布和滚动发布 应用程序升级面临最大挑战是新旧业务切换&#xff0c;将软件从测试的最后阶段带到生产环境&#xff0c;同时要保证系统不间断提供服务。 长期以来&#xff0c;业务升级渐渐形成了几个发布策略&#xff1a;蓝绿发布、灰度发布和滚动发布&…

NVelocity标签设置缓存的解决方案

意外的问题总会让人措手不及&#xff0c;今天与大家分享的就是NVelocity设置缓存的问题&#xff0c;之前刚google了一下发现没什么太好的解决方案&#xff0c;希望在这能为需要的朋友找出满意的答案&#xff0c;上一篇blog刚说了NVelocity的用法&#xff0c;这就不在重复了&…

实数历史无穷小能否带领我们直接走向今日科学之辉煌?

本篇文章朋友在深圳吃饭的时候突然想到的...这段时间就有想写几篇关于实数历史的博客&#xff0c;所以回家到之后就奋笔疾书的写出来发布了 历史不能重演&#xff0c;这是毫无疑问的。数学是一门基础学科&#xff0c;影响到本日科学技术的方方面面&#xff0c;可以说&#xff0…

java成员方法的一般格式为_Java基本知识(四)

一、二维数组1、定义方式m&#xff1a;代表当前二维数组中有多少个一维数组&#xff1b;n&#xff1a;代表每个一维数组的长度(1)数据类型[][] 数组名new 数据类型[m][n](2)数据类型[][] 数组名new 数据类型[m][ ]&#xff0c;只给定m个一维数组&#xff0c;每个一维数组长度动…

免费的定时任务托管 clock.sh

自己有很多定时任务要跑&#xff0c;所以之前搞了一个定时运行的系统。 在 V2EX 看到很多有类似需求的朋友&#xff1a; https://www.v2ex.com/t/252810https://www.v2ex.com/t/448726https://www.v2ex.com/t/579740https://www.v2ex.com/t/241229https://hk.v2ex.com/t/1134…

Android Webservices 返回多行多列数据(Dataset)

对于之前从事.net或者java开发人员&#xff0c;习惯了从后台获取网格数据&#xff08;多行多列DataTable&#xff09;&#xff0c;但转行从事android开发&#xff0c;难免会不习惯 Android调用Webservice时&#xff0c;如果返回值是一个boolean或者string值时可以通过下面方式接…