OpenCV入門及應用案例:手把手教你做DNN圖像分類


導讀:本文將介紹OpenCV的源碼結構、OpenCV深度學習應用的典型流程,以及深度學習和OpenCV DNN(Deep Neural Networks,深度神經網絡)模塊的背景知識,讓讀者可以快速認識OpenCV,消除神祕感,同時對計算機視覺從傳統算法到深度學習算法的演進歷史有所瞭解。

作者:吳至文 郭葉軍 宗煒 李鵬 趙娟

來源:大數據DT(ID:hzdashuju)

OpenCV是一個計算機視覺開源庫,提供了處理圖像和視頻的能力。OpenCV的影響力非常大,有超過47 000的社區用戶,以及超過1400萬次的下載量。其應用領域橫跨圖像處理、交互式藝術、視頻監督、地圖拼接和高級機器人等。作爲一個有十幾年歷史的開源項目,OpenCV擁有廣大的用戶羣體和開發者羣體。

在數字的世界中,一幅圖像由多個(像素)組成。圖像處理就是對其中一個像素或者一個區域內的像素(塊)進行處理。無論是初學者還是富有經驗的研發人員,他們都需要藉助軟件工具來分析這些像素和圖像塊,OpenCV則是其中最常用、最重要的一個軟件工具。

OpenCV成爲最主要的圖像處理工具包,是因爲它功能齊全,支持目前主流的圖像、視頻處理算法,而且對外提供C++、Python和Java的接口,用戶調用方便。本書的代碼分析、示例程序及環境搭建基於OpenCV 4.1版本,源代碼位於GitHub的OpenCV倉庫。

01 OpenCV庫

OpenCV由各種不同組件組成。OpenCV源代碼主要由OpenCV core(核心庫)、opencv_contrib和opencv_extra等子倉庫組成。近些年,OpenCV的主倉庫增加了深度學習相關的子倉庫:OpenVINO(即DLDT, Deep Learning Deployment Toolkit)、open_model_zoo,以及標註工具CVAT等。

下面分別介紹3個主要的代碼庫:OpenCV core、opencv_contrib、opencv_extra。

1. 核心庫OpenCV core

核心庫是OpenCV的主要算法來源。OpenCV採用模塊化結構設計,包含了多個共享或者靜態庫。目前OpenCV核心庫提供了很多組件,如下所示。

  • 核心功能模塊:這是一個小巧而高效的模塊,定義了基礎的數據結構,包含緊密多尺度向量矩陣和一些供其他模塊使用的基礎函數

  • 圖像處理模塊:它包括了線性和非線性的圖像濾波、幾何圖像變換(圖像縮放、仿射變換、透視矯正、通用的基於表格的像素映射)、色域變換及直方圖生成與分析等

  • 視頻:這是一個視頻分析模塊,包含運動檢測、背景減除和對象追蹤等算法

  • calib3d:包含基礎的多視角幾何算法、單個和立體相機標定算法、對象姿勢預測算法、立體一致性算法,以及3D元素重建

  • Features2d:圖像顯著特徵檢測、特徵點描述和匹配

  • Objdetect:對象檢測和預先定義的類別檢測(如臉、眼、杯子、人、車等)

  • Highgui:提供了比較容易使用的UI接口

  • Video I/O:提供了基本的視頻存取訪問和編解碼功能

  • GPU:爲不同的OpenCV算法模塊提供GPU加速算法

  • 其他:如FLANN和Google測試封裝層、Python綁定等

2. opencv_contrib

opencv_contrib代碼庫主要用於管理新功能模塊的開發。該庫的設計主要基於以下考慮:處於初始開發階段的功能模塊,它的API定義會經常變化,各種測試也不夠全面。

爲了不影響OpenCV核心模塊的穩定性,這些新功能模塊會發布到opencv_contrib中。等到模塊足夠成熟並且在社區得到了足夠的關注和使用之後,這個模塊便會被移到OpenCV核心庫,這意味着核心庫開發團隊將會對該模塊進行全面的測試,保證這個模塊具有產品級的質量。

例如,對於DNN這個模塊,OpenCV 3.1開始出現在opencv_contrib中,到了3.3版本才移到了OpenCV核心庫。

opencv_contrib需要和OpenCV核心庫一同編譯。下載好opencv_contrib的源代碼並在CMake執行時傳入參數:-DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib源碼路徑>/modules。

如果編譯時遇到問題,則可以在OpenCV核心庫和opencv_contrib庫的問題彙報頁面,查看一下是否有現成的解決方案,如果沒有,則讀者可新建一個問題。OpenCV是一個活躍的社區,只要問題描述清晰、完整,一般會很快得到反饋。

3. opencv_extra

opencv_extra倉庫存放了運行測試和示例程序時需要使用的一些測試數據和腳本。例如,運行DNN模塊測試程序或者示例程序時需要用到預訓練模型,這些模型可以通過opencv_extra中的腳本來自動下載。近些年添加的opencv/open_model_zoo倉庫也增加了很多預訓練好的深度學習模型,這些模型大多做過性能和速度上的調優。

02 OpenCV深度學習應用的典型流程

OpenCV是一個自包含庫,可以不依賴於任何第三方庫而運行,這個特性給開發調試帶來了很大的便利。另外,OpenCV還提供了硬件加速功能,使得算法能夠在各種平臺高效地執行。

下面以一個識別性別和年齡的深度學習應用爲例,展現OpenCV深度學習應用的典型流程。該應用使用C++語言,總共只需要百來行代碼便可實現人臉檢測、性別和年齡的識別功能,還可以方便地使用硬件的加速能力,提高程序的運行效率。此處展示核心流程,故以僞代碼爲例,完整的源代碼由本書的參考代碼庫提供。

該應用的核心流程如下:首先讀取兩個網絡模型參數(分別是性別和年齡),然後檢測人臉,轉換輸入圖像,最後運行網絡前向預測。僞代碼如下:

// 引入OpenCV DNN模塊的命名空間
using namespace cv::dnn;
// 創建人臉檢測器
CascadeClassifier cascade;

// 導入性別和年齡深度神經網絡模型
Net gender_net=dnn::readNetFromCaffe(gender_modelTxt, gender_modelBin);
Net age_net=dnn::readNetFromCaffe(age_modelTxt, age_modelBin);
// 人臉檢測
cascade.load(cascadeName);
cascade.detectMultiScale(input_gray_file, output_faces_data);

// 準備深度神經網絡的輸入數據
Mat inputBlob=blobFromImage(input.getMat(ACCESS_READ));
gender_net.setInput(inputBlob, "data");
age_net.setInput(inputBlob, "data");

// 執行模型的前向運算,即模型推理
Mat gender_prob=gender_net.forward("prob");
Mat age_prob=age_net.forward("prob");

應用識別效果如圖1-1所示。

▲圖1-1 應用識別效果圖

以上僞代碼很好地展示了OpenCV深度學習應用的典型流程,如圖1-2所示。

▲圖1-2 OpenCV深度學習應用的典型流程

03 OpenCV深度學習模塊

深度學習模塊是OpenCV爲支持基於深度學習的計算機視覺應用所加入的新特性。OpenCV DNN模塊於OpenCV 3.1版本開始出現在opencv_contrib庫中,從3.3版本開始被納入OpenCV核心庫。

本節主要講解OpenCV深度學習模塊的實現原理和主要特性,通過這些內容,讀者可以對OpenCV DNN有一個總體瞭解,並對OpenCV深度學習模塊的應用代碼有一個初步的印象。

作爲計算機視覺領域的“標準庫”,OpenCV爲用戶提供深度學習的支持是題中應有之義。OpenCV選擇重新實現一個深度學習框架而不是直接調用現有的各種框架(如TensorFlow、Caffe等),有如下幾點原因。

  • 輕量:OpenCV的深度學習模塊只實現了模型推理功能,這使得相關代碼非常精簡,加速了安裝和編譯過程。

  • 最少的外部依賴:重新實現一遍深度學習框架使得對外部依賴減到最小,大大方便了深度學習應用的部署。

  • 方便集成:①如果原來的應用是基於OpenCV開發的,通過深度學習模塊可以非常方便地加入對神經網絡推理的支持;②如果網絡模型來自多個框架,如一個來自TensorFlow,一個來自Caffe,則深度學習模塊可以方便整合網絡運算結果。

  • 通用性:①提供統一的接口來操作網絡模型;②內部所做的優化和加速對所有網絡模型格式都適用;③支持多種設備和操作系統。

1. 主要特性

OpenCV深度學習模塊只提供網絡推理功能,不支持網絡訓練。像所有的推理框架一樣,加載和運行網絡模型是基本的功能。深度學習模塊支持TensorFlow、Caffe、Torch、DarkNet、ONNX和OpenVINO格式的網絡模型,用戶無須考慮原格式的差異。在加載過程中,各種格式的模型被轉換成統一的內部網絡結構。

深度學習模塊支持所有的基本網絡層類型和子結構,包括AbsVal、AveragePooling、BatchNormalization、Concatenation、Convolution (with DILATION)、Crop、DetectionOutput、Dropout、Eltwise、Flatten、FullConvolution、FullyConnected、LRN、LSTM、MaxPooling、MaxUnpooling、MVN、NormalizeBBox、Padding、Permute、Power、PReLU、PriorBox、Relu、RNN、Scale、Shift、Sigmoid、Slice、Softmax、Split和Tanh。

如果需要的層類型不在這個支持列表之內,則可以通過腳註中的申請鏈接來請求新的層類型的支持,OpenCV的開發者們有可能會在將來加入對該層類型的支持。讀者也可以自己動手實現新的層類型,並把代碼反饋回社區,參與到深度學習模塊的開發中來。

除了實現基本的層類型,支持常見的網絡架構也很重要,經過嚴格測試,深度學習模塊支持的網絡架構如下所示。

  • 圖像分類網絡

  • CaffeAlexNet、GoogLeNet、VGG、ResNet、SqueezeNet、DenseNet、ShuffleNet

  • TensorFlowInception、MobileNet

  • Darknetdarknet-imagenet

  • ONNXAlexNet、GoogleNet、CaffeNet、RCNN_ILSVRC13、ZFNet512、VGG16、VGG16_bn、ResNet-18v1、ResNet-50v1、CNN Mnist、MobileNetv2、LResNet100E-IR、Emotion FERPlus、Squeezenet、DenseNet121、Inception-v1/v2、ShuffleNet

  • 對象檢測網絡

  • CaffeSSD、VGG、MobileNet-SSD、Faster-RCNN、R-FCN、OpenCV face detector

  • TensorFlowSSD、Faster-RCNN、Mask-RCNN、EAST

  • DarknetYOLOv2、Tiny YOLO、YOLOv3

  • ONNXTinyYOLOv2

  • 語義分割網絡:FCN(Caffe)、ENet(Torch)、ResNet101_DUC_HDC(ONNX)

  • 姿勢估計網絡:openpose(Caffe)

  • 圖像處理網絡:Colorization(Caffe)、Fast-Neural-Style(Torch)

  • 人臉識別網絡:openface(Torch)

2. OpenCV DNN圖像分類舉例(Python)

C++和Python是OpenCV應用開發的主要語言,1.1.2節介紹了一個基於C++語言的深度學習應用,本節繼續介紹一個基於Python的圖像分類示例。

首先引入必要的Python庫:

import numpy as np # 引入numpy庫
import cv2 as cv # 引入OpenCV庫,深度學習模塊包含在其中

讀入類別文件:

with open('synset_words.txt') as f:
    classes=[x[x.find(' ') + 1:] for x in f]

讀入待分類的圖片:

image=cv.imread('space_shuttle.jpg')

調用深度學習模塊的blobFromImage方法將圖片對象轉換成網絡模型的輸入張量(tensor)。該張量的大小是224×224,參數中的(104,117,123)表示需要從輸入張量減掉的均值,它是從訓練網絡模型時用到的數據集計算出來的,這裏直接使用即可。第二個參數“1”表示將OpenCV的默認通道順序BGR轉換成網絡模型要求的RGB通道順序。

input=cv.dnn.blobFromImage(image, 1, (224, 224), (104, 117, 123))

下面來加載Caffe網絡模型。注意,相關的模型參數和配置文件可在這裏下載:

http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel

https://github.com/opencv/opencv_extra/blob/4.1.0/testdata/dnn/bvlc_googlenet.prototxt

net=cv.dnn.readNetFromCaffe('bvlc_googlenet.prototxt',
                            'bvlc_googlenet.caffemodel')

設置網絡模型輸入:

net.setInput(input)

執行網絡推理並得到輸出結果:

out=net.forward()

從網絡輸出中獲取最大的5個可能種類的索引值並輸出類別名稱和概率值:

indexes=np.argsort(out[0])[-5:]
for i in reversed(indexes):
 print ('class:', classes[i], ' probability:', out[0][i])

通過這個例子,我們可以看到一個基於深度學習模型的分類應用並不複雜,主要分3部分:模型導入、網絡執行和結果解析。

小結

通過本章的學習,讀者可以瞭解到OpenCV的主要組成部分,尤其是OpenCV深度學習模塊的基本情況。基於C++和Python的例子爲讀者展示了OpenCV深度學習應用的主要流程。

關於作者:吳至文,Intel亞太研發有限公司資深圖形圖像工程師,擁有多年算法開發優化經驗,技術領域涵蓋顯示系統、視覺處理、深度學習框架加速,尤其擅長基於OpenCL和Vulkan的算法設計及優化,是OpenCV DNN模塊Vulkan後端的作者、OpenCL後端主要貢獻者之一。

郭葉軍,Intel資深圖形圖像工程師。多年圖形芯片驅動開發經驗,主要包括OpenGL驅動和OpenCL驅動。目前關注視頻分析中的深度學習,是FFmpeg深度學習模塊的代碼維護者。

宗煒,Intel資深圖形圖像工程師,長期從事計算機視覺算法與應用、數字圖像處理、Camera成像算法開發,在CPU/GPU/ISP異構計算算法設計與優化上經驗頗豐,是圖像處理與計算機視覺算法開源項目libXCam的維護者和主要貢獻者。

李鵬,阿里巴巴高級技術專家,原Intel亞太研發有限公司資深圖形圖像工程師。涉及領域包括顯示系統、圖形圖像處理、深度學習框架加速。是OpenCV DNN模塊OpenCL後端主要貢獻者之一。

趙娟,Intel高級研發經理,鑽研圖形圖像、視頻編解碼和視頻處理十幾年,帶領團隊深耕視頻編解碼和處理軟硬件加速、深度學習算法分析與設計,致力於讓開源軟件在圖形圖像視頻市場落地,並組織團隊把多年的“乾貨”整理成書,與視頻行業的朋友們一起探討與成長。

本文摘編自OpenCV深度學習應用與性能優化實踐》,經出版方授權發佈。

延伸閱讀OpenCV深度學習應用與性能優化實踐

點擊上圖瞭解及購買

轉載請聯繫微信:DoctorData

推薦語:Intel音視頻團隊與阿里巴巴圖像處理專家聯合撰寫,知名專家聯袂推薦,深入解析OpenCV DNN 模塊、基於GPU/CPU的加速實現、性能優化技巧與可視化工具,以及人臉活體檢測(完整案例)與主流識別項目解析。

劃重點????

乾貨直達????

更多精彩????

在公衆號對話框輸入以下關鍵詞

查看更多優質內容!

PPT | 讀書 | 書單 | 硬核 | 乾貨 | 講明白

大數據 | 雲計算 | 數據庫 | Python | 可視化 | 神操作

AI | 人工智能 | 機器學習 | 深度學習 | 神經網絡

5G | 中臺 | 用戶畫像 1024 | 大神 | 數學 | 揭祕

據統計,99%的大咖都完成了這個神操作

????

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章