如何使用 OpenVINO 來優化 OpenCV

2020-04-02     sandag

在這篇文章中,我們會介紹如何利用 Intel 的 OpenVINO 軟體包來,發揮 OpenCV 中 Deep Neural Network (DNN) / 深度神經網絡 模塊的的最大性能;

我們也對 CPU 上 OpenCV 和其他深度學習庫的性能進行了比較;

OpenCV 中基於 DNN 實現的模型,在很多深度學習任務中,如分類,目標檢測,目標追蹤和姿態估計,都表現出色;

我們會在這篇文章中探究,是否可能通過 Intel OpenVINO + OpenCV 這樣的組合來進行加速;

0. 目錄

1. 訓練與推理

2. 介紹 OpenVINO Toolkit

2.1 為什麼要用 OpenVINO?

2.2 OpenVINO 中的 Computer Vision Pipeline / 視覺處理

3. 使用 OpenVINO 進行深度學習

3.1 訓練一個深度學習模型

3.2 優化模型並且創建一個 Intermediate Representation (IR) / 中間表示

3.3 OpenVINO 推理引擎:硬體加速

3.4 OpenVINO 和 OpenCV

4. Linux 中 OpenVINO 的安裝

4.1 OpenVINO Toolkit 安裝

4.2 測試 OpenVINO 的安裝

5. 使用 OpenCV+OpenVINO IE 圖像分類

6. OpenCV 和 OpenCV+IE 的性能比較

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 去給一個監控攝像頭;

這些小設備,比如監控攝像頭或者樹莓派,經常被稱為 E dge 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_2019.3.376.tgz」 這樣一個壓縮文件,解壓然後安裝;

1 cd ~/Downloads/
2 tar -zxvf l_openvino_toolkit_p_2019.3.376.tgz -C ~/openvino-toolkit/
3
4 cd ~/openvino-toolkit/l_openvino_toolkit_p_2019.3.376/
5
6 sudo ./install_openvino_dependencies.sh
7 sudo ./install_GUI.sh

注意: 如果你 sudo ./install_GUI.sh 的話,路徑會是 " /opt/intel/openvino_2019.3.376/" 這種;

如果不是 sudo 身份安裝,路徑會是 "/home/user/intel/openvino_2019.3.376/" ;

3. 修改環境變量

vim /home/user/.bashrc

在最後一行加入

source /opt/intel/openvino_2019.3.376/bin/setupvars.sh

4. 打開一個新的 Terminal,可以看到 "OpenVINO enviroment initialized"

5. 配置模型優化器,讓我們去模型優化器的路徑,然後安裝所需文件:

1 cd /opt/intel/openvino_2019.3.376/deployment_tools/model_optimizer/install_prerequisites/
2 ./install_prerequisites.sh

4.2 測試 OpenVINO 安裝

我們可以用 Image Classification demo 來測試安裝:

1 cd /opt/intel/openvino_2019.3.376/deployment_tools/demo/
2 ./demo_squeezenet_download_convert_run.sh

可以看到 "Demo completed successfully":

還可以去跑 Inference Pipepline demo :

./demo_security_barrier_camera.sh

可以看到輸出的檢測結果:

5. 使用 OpenCV 和 OpenVINO IE 進行圖像分類

現在讓我們來看看如何利用 OpenVINO IE + OpenCV 進行圖像分類。

1. 首先需要加載需要的模塊:

C++

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
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 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 可以提高計算機視覺庫的性能;

文章來源: https://twgreatdaily.com/5GEUPXEBnkjnB-0zIOzh.html