深度学习-服务端训练+android客户端物体识别实战(caffe入门教程+mobilenet+ncnn+android)
文章目錄
- 背景
-
物體識別簡介
-
自動駕駛
- 淘寶京東使用物體識別技術
- 公司業務需求
-
深度學習簡介
-
深度學習的位置
- 深度學習概念
- 深度學習優勢
-
深度學習基礎知識
-
感知機
- 激活函數
- 多層感知機
- 卷積神經網絡
-
卷積層 * 池化層
- 模型訓練
-
前向傳播 * 反向傳播與參數優化
-
深度學習服務端框架
-
tensorFlow
- keras
- pytorch
- Caffe/Caffe2.0
-
caffe框架
-
為何選擇caffe
- caffe環境搭建
- caffe基礎
-
數據集?模塊概要圖?solver(prototxt) 執行者配置?神經網絡可視化?caffe中的基礎概念
-
blobs?layer 神經層?net 神經網絡 * forward/backward 前向傳播/反向傳播
-
輕量級客戶端框架-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
總結
以上是生活随笔為你收集整理的深度学习-服务端训练+android客户端物体识别实战(caffe入门教程+mobilenet+ncnn+android)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vm虚拟远程部署windows驱动
- 下一篇: Tensorflow中查看gpu是否可用