本文翻譯自
翻譯:coneypo,working in Intel for IoT,有問題或者建議歡迎留言交流
在這篇文章中,我們會介紹如何利用 Intel 的 OpenVINO 軟件包來,發揮 OpenCV 中 Deep Neural Network (DNN) / 深度神經網絡 模塊的的最大性能;
我們也對 CPU 上 OpenCV 和其他深度學習庫的性能進行了比較;
OpenCV 中基於 DNN 實現的模型,在很多深度學習任務中,如分類,目標檢測,目標追蹤和姿態估計,都表現出色;
我們會在這篇文章中探究,是否可能通過 Intel OpenVINO + OpenCV 這樣的組合來進行加速;
0. 目錄
1. 訓練與推理
1. 訓練和推理
在開始介紹之前,我們要強調這篇文章專注於 Speeding up inference / 加快推理 而不是訓練;讓我們來看看兩者區別:
1. Training / 訓練
把深度神經網路視為一個有很多 knobs (parameters) / 旋鈕 的黑盒,當旋鈕的設置是正確的時候,神經網絡就會比較高可能性的給出正確答案;
訓練就是來給網絡投喂百萬級別的訓練數據點,以至於神經網絡可以按部就班的調整這些旋鈕,使得接近正確值;
這種百萬級別的數據處理經常是通過 GPU 來進行運算的;
當前 OpenCV 沒有提供訓練一個 DNN 的方法,然而你可以利用比如 Tensorflow, MxNet, Caffe 等等框架來進行 DNN 模型的訓練,然后在你的代碼里導入;
2. Inference / 推理
一旦網絡訓練完成,就可以輸入新的數據來獲取輸出;使用一個訓練好的模型,進行輸入輸出的過程,就叫做 inference / 推理;
一個推理引擎會將輸入的數據通過神經網絡產生輸出結果,這里有很多優化方式來加速推理過程;
比如一個高效的推理引擎可以進行神經網絡的 pruning / 修剪,將多個 Layers 融合到一步計算過程;
如果硬件支持 16-bit 浮點數運算 (2倍於 32-bit 浮點數運算),一個推理引擎會提高兩倍推理速度,而且不會丟失精度,這種方式稱之為 quantization / 量化;
2. OpenVINO Toolkit 介紹
OpenVINO 代表 Open Visual Inferencing and Neural Network Optimization / 開放視覺推理和神經網絡優化;
正如 OpenVINO 名稱所描述,OpenVINO 被設計用來給網絡加速,在視覺推理任務中,比如圖像分類和目標檢測;
幾乎所有用來解決視覺任務的 DNN 是 Convolutional Neural Networks (CNN) / 卷積神經網絡;
OpenVINO 對於特定的硬件有特定的硬件加速方式來加速計算過程;
2.1 為什么使用 OpenVINO?
如果你 AI 新入門,或者對於 AI 不是很了解,你會發現這塊會很有意思;
當我們想起 AI,我們經常會想起一些公司,比如 Google, Facebook, Amazon, IBM, Baidu 等等;
確實他們推動了算法的發展,但是 AI 不僅在 Training / 訓練 上對於算力要求高,在 Inferencing / 推理 的時候對於資源的要求也高;
因此,我們在 AI 興起的時候,也應該去關注一些硬件公司;
Convolutional Neural Networks (CNN) / 卷積神經網絡 經常在 GPU 上進行訓練;
NVIDIA 能夠提供幾乎最好的的硬件 GPU,與此同時軟件上面使用 CUDA 和 cuDNN 進行深度學習;
NVIDIA 幾乎壟斷了深度學習的市場,當訓練模型的時候;
然而 GPU 過於昂貴,往往在推理的時候也是不需要的;事實上,大多數的推理是在 CPU 上進行的;
比如 Dropbox 使用 CPU farm 來進行文檔的 OCR;
在低成本的設備上進行深度學習,GPU 往往是開銷最大;比如你幾乎不可能花費幾百刀去買一個 GPU 去給一個監控攝像頭;
這些小設備,比如監控攝像頭或者樹莓派,經常被稱為 Edge devices / 邊緣設備 或者 IoT devices / 物聯網設備;
在推理領域,Intel 占有很大份額;除了制造 CPU,Intel 也生產繼承了 GPU 的 Vision Processing Units (VPU) 和 FPGA,這些都用來做推理;
Intel 明白盡管選擇很多會很好,但是這也是 AI 開發者的噩夢,因為要在不同平台上進行開發就要學習和適應不同平台的開發環境;
幸運的是,Intel 通過 OpenVINO 解決了這種問題,給 AI 開發者提供了一種 Unified Framework / 統一的框架;
OpenVINO 使得可以邊緣端進行 CNN-based 深度學習推理,支持跨平台的異構執行,通過一些 OpenCV 和 OpenVX 中一些函數庫和預優化的核來加速產品落地時間;
2.2 計算機視覺 Pipeline 和 OpenVINO
上面框圖中,除了有最左邊 Custom Code / 定制代碼 實現的任務;
除此之外,你有右邊兩種模塊:
1. CV/non-DL, 非基於深度學習的計算機視覺任務
2. DL, 基於深度學習的計算機視覺任務
首先,它會優化 OpenCV 中實現的,許多基於傳統計算機視覺算法的很多 calls,然后它對於深度學習推理也有特定的優化;
我們如果將 OpenCV 和 OpenVINO 一起使用會從中受益;
3. 使用 OpenVINO 進行深度學習
這一節中,我們會介紹如何在深度學習應用中使用 OpenVINO。
3.1 訓練一個深度學習模型
正如我們之前所提到過,OpenCV 或者 OpenVINO 不會給你提供訓練神經網絡的工具(OpenVINO 專注於 Inference 而不是 Training);
你可以通過下列任一支持的類型模型來訓練神經網絡,或者從 zoo 模型下載:
1. Caffe Model Zoo
2. Tensorflow Model Zoo
3. MxNet Model zoo
4. Open Neural Network Exchange (ONNX) Model zoo
3.2 優化模型和創建一個 Intermediate Representation (IR) / 中間表示
之前步驟獲得的模型往往沒有進行性能的優化,因此,我們利用 OpenVINO 提供的 Model Optimizer / 模型優化器, 來創建一個稱之為 Intermediate Representiation (IR) / 中間表示文件 的優化模型;
IR 完全與硬件無關,只取決於神經網絡的架構;
下圖中展示了用 OpenVINO 部署方式和大多數深度學習框架部署方式的區別:
可以看到模型優化器通過以下機制來優化模型:
1. 對模型進行修剪:移除部分在訓練時候需要的,而推理時候不需要的網絡;DropOut 就是這種網絡層的一個例子;
2. 融合操作:有些時候多步操作可以融合成一步,模型優化器檢測到這種就會進行必要的融合;
優化過程結束后會生成一個 IR model / 中間表示模型,模型可以被分成兩部分:
1. model.xml: XML 文件包含網絡架構;
2. model.bin: bin 文件包含 Weights / 權重 和 Biases / 誤差
3.3 OpenVINO 推理引擎: 硬件特殊優化
IR 模型與硬件無關,但是 OpenVINO 通過 Inference Engine plugin / 推理引擎插件 在特定的硬件上進行優化;
這個 Plugin 在所有 Intel 的硬件上 (GPUs, CPUs, VPUs, FPGSs) 都可以獲得:
3.4 OpenVINO 和 OpenCV
盡管 OpenCV 的 DNN 已經被高度優化,通過推理引擎我們可以進一步提高性能;
下圖中展示了使用 OpenCV DNN 的兩種方式;如果在您的平台上可以使用,我們高度推薦 OpenVINO + OpenCV 的組合;
4. Linux 中安裝 OpenVINO Toolkit
這一節我們會介紹如何在 Linux 中安裝和測試 OpenVINO;
Windows 中的 Openvino 安裝可以參考 Intel’s website.
4.1 OpenVINO Toolkit 安裝
1. 首先去 OpenVINO Toolkit Download page 注冊並下載適合你系統的正確版本,這里我們介紹 Linux 系統中的安裝:
2. 你會下載下來如 “l_openvino_toolkit_p_2020.1.023.tgz” 這樣一個壓縮文件,解壓然后安裝;
1 cd ~/Downloads/ 2 tar -zxvf l_openvino_toolkit_p_2020.1.023.tgz 3 4 cd l_openvino_toolkit_p_2020.1.023/ 5 sudo ./install_openvino_dependencies.sh 6 sudo ./install_GUI.sh
注意: 如果你 sudo ./install_GUI.sh 的話,路徑會是 "/opt/intel/openvino_2020.1.023/" 這種;
如果不是 sudo 身份安裝,路徑會是 "/home/user/intel/openvino_2020.1.023/";
3. 修改環境變量
vim /home/user/.bashrc
在最后一行加入
source /opt/intel/openvino_2020.1.023/bin/setupvars.sh
4. 打開一個新的 Terminal,可以看到 "OpenVINO enviroment initialized"
5. 配置模型優化器,讓我們去模型優化器的路徑,然后安裝所需文件:
cd /opt/intel/openvino_2020.1.023/deployment_tools/model_optimizer/install_prerequisites/ sudo ./install_prerequisites.sh
4.2 測試 OpenVINO 安裝
我們可以用 Image Classification demo 來測試安裝:
cd /opt/intel/openvino_2020.1.023/deployment_tools/demo/ sudo ./demo_squeezenet_download_convert_run.sh
可以看到 "Demo completed successfully":
還可以去跑 Inference Pipepline demo:
sudo ./demo_security_barrier_camera.sh
可以看到輸出的檢測結果:
5. 使用 OpenCV 和 OpenVINO IE 進行圖像分類
現在讓我們來看看如何利用 OpenVINO IE + OpenCV 進行圖像分類。
1. 首先需要加載需要的模塊:
C++
1 #include <fstream> 2 #include <sstream> 3 #include <opencv2/dnn.hpp> 4 #include <opencv2/imgproc.hpp> 5 #include <opencv2/highgui.hpp> 6 #include <iostream> 7 8 using namespace std; 9 using namespace cv; 10 using namespace cv::dnn;
Python
1 import numpy as np 2 import time 3 import cv2
2. 下一步指定 Caffe 的根路徑和模型路徑:
C++
1 string caffe_root = "/home/zt/caffe/"; 2 Mat image = imread("/home/zt/caffe/examples/images/cat.jpg"); 3 string labels_file = "/home/zt/caffe/data/ilsvrc12/synset_words.txt"; 4 string prototxt = "/home/zt/caffe/models/bvlc_reference_caffenet/deploy.prototxt"; 5 string model = "/home/zt/caffe/models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel";
Python
1 caffe_root = '/home/zt/caffe/' 2 image = cv2.imread('/home/zt/caffe/examples/images/cat.jpg') 3 labels_file = caffe_root + 'data/ilsvrc12/synset_words.txt' 4 prototxt = caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt' 5 model = caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'
3. 接下來就是常用的圖像分類代碼,加了一點輕微改動;
我們會聲明優先選取 cv2.dnn.DNN_BACKEEND_INFERENCE_ENGINE;
C++
1 // load the labels file 2 std::ifstream ifs(labels_file.c_str()); 3 if (!ifs.is_open()) 4 CV_Error(Error::StsError, "File " + labels_file + " not found"); 5 string line; 6 while (std::getline(ifs, line)) 7 { 8 classes.push_back(line); 9 } 10 } 11 blobFromImage(image, blob, 1, Size(224, 224), Scalar(104,117,123)); 12 cout << "[INFO] loading model..." << endl; 13 Net net = readNetFromCaffe(prototxt, model); 14 net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE); 15 net.setPreferableTarget(DNN_TARGET_CPU); 16 17 // set the blob as input to the network and perform a forward-pass to 18 // obtain our output classification 19 net.setInput(blob) 20 preds = net.forward() 21 22 double freq = getTickFrequency() / 1000; 23 std::vector<double> layersTimes; 24 double t = net.getPerfProfile(layersTimes) / freq; 25 cout << "[INFO] classification took " << t << " ms" << endl;
Python
1 // load the labels file 2 rows = open(labels_file).read().strip().split("\n") 3 classes = [r[r.find(" ") + 1:].split(",")[0] for r in rows] 4 5 blob = cv2.dnn.blobFromImage(image,1,(224,224),(104,117,123)) 6 print("[INFO] loading model...") 7 net = cv2.dnn.readNetFromCaffe(prototxt,model) 8 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE) 9 net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) 10 # set the blob as input to the network and perform a forward-pass to 11 # obtain our output classification 12 net.setInput(blob) 13 start = time.time() 14 preds = net.forward() 15 end = time.time() 16 print("[INFO] classification took " + str((end-start)*1000) + " ms")
就是這樣,僅僅需要用 OpenVINO IE 來替代原生的 OpenCV (cv2.dnn.DNN_BACKEDN_OPENCV);
6. OpenCV 和 OpenCV + IE 的比較
這些比較任務在一台使用 OpenCV-3.4.3,只有 CPU 的 Ubuntu 16.04 AWS 機器上測試;
取100次的平均時間;
Image Classification / 圖像分類
Object Detection / 目標檢測
Pose Estimation / 姿態估計
從這些數據中可以很清楚的看到,使用 OpenCV + OpenVINO 可以提高計算機視覺庫的性能;
# 英文版權 @
# 翻譯中文版權 @ coneypo
# 轉載請注明出處