官术网_书友最值得收藏!

3.4 基于傳統特征的傳統圖像分類方法

3.3節介紹了如何使用圖片的顏色以及形狀特征,在圖像中標注足球的位置。這個標注過程實際上還是基于人工規則進行的,存在很多問題:

  • 只能識別藍黃相間的球。
  • 只能識別綠色草地上的球。
  • 攝像機距離拉遠、拉近后球的像素大小改變,仍然無法識別。

由此可見,人工規則在實際應用的場景中會遇到各種預想不到的結果,在這些情況下,人工規則的表現會大打折扣。為了解決這些問題,圖像處理技術引入了機器學習方法,希望通過機器規則來代替人工規則。這一思(tao)路(lu),總體如下:

(1)針對某一圖片,將幾百、上千像素圖片簡化為少數幾個區域,計算每個區域中輪廓特征的走向。

(2)將正負樣本所有圖片執行第三步,將輪廓走向圖放入機器學習分類器進行訓練。

(3)將訓練好的分類器應用在新的圖片中。

我們審視這一思路,發現這個過程的核心思想其實是在簡化圖片——第一步中,原本圖片里各種不同的物體被減少到只剩下輪廓了,但這還不夠,最后計算的是一個區域內的輪廓走向,此時一張1200×800×3大小的圖片,可能只剩下1000個點了,信息減少了上千倍。

這么做的原因首先是傳統的機器學習分類器,對輸入數據的大小有一個大致的上限,幾千張圖像數據如果不經過簡化,直接送入模型,模型是無法訓練輸入數據的;其次,圖像數據最有趣的一點是圖中一個像素點和周圍像素點周圍聯系非常緊密,數據的冗余度很大,這種冗余體現在很多時候,即使給圖片壓縮、涂黑、打馬賽克,我們也大致知道這張圖片的內容;同理,對圖片進行簡化,也是基于這一思想。

本節基于這個思路來介紹一下如何用python-opencv處理圖像,對圖片進行簡化處理,然后用上一章的機器學習方法進行圖像分類。我們使用優達學城(Udacity)自動駕駛納米學位的一個開源項目一部分內容作為講解材料,希望了解完整部分的讀者可以去優達學城官網udacity.cn以及開源地址https://github.com/udacity/CarND-Vehicle-Detection查看完整內容。

我們使用了優達學城標注的一個行車記錄儀數據集,這個數據集來自GTI以及KITTI數據集,標注了車輛以及非車輛的情況,具體如下:

運算結果:

其結果如圖3-18所示。

圖3-18 運行結果

我們的任務是利用幾千張這樣的標注圖片組成的數據集來訓練一個分類器,以區別輸入圖片是否是車輛。

3.4.1 將圖片簡化為少數區域并計算每個區域輪廓特征的方向

這里其實是運用方向梯度直方圖算法(Histogram of Oriented Gradients, HOG)來實現的。這一算法可以分為以下步驟(http://www.learnopencv.com/histogram-of-oriented-gradients/):

  • 圖像歸一化(可選)。
  • 計算圖像中x以及y方向的梯度。
  • 根據梯度,計算梯度柱狀圖。
  • 對塊狀區域進行歸一化處理。
  • 展開結果,將一張圖片轉換成一個一維的特征向量。
  • 提取的特征,交給支持向量機或神經網絡分類器進行訓練分類。

例如,可以將如圖3-19所示的左圖作為HOG算法的輸入文件,得到類似右圖的結果。首先,HOG算法的結果只表示輪廓線的變換,無關顏色(如白色的背景以及右下角黑色部分)都沒有輪廓線;其次,整張圖x、y方向有成百上千的像素點,這里被縮小到了32×32的網格區域,這一點類似前面提到的二維碼的讀取。當然,這里與二維碼不同的是,除了分組求平均值以外,還考慮了輪廓線的方向性,即線條顏色深淺表示了輪廓線數目的多少,同時線條的方向也可以表示這塊區域內輪廓線的總體走勢。

圖3-19 HOG算法實例(圖片來自skimage的官方文檔)

進一步閱讀官方文檔,發現用法如下:

          fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16),
    cells_per_block=(1, 1), visualize=True)

這里有三個可以調的參數,即orientations、pixels_per_cell以及cells_per_block。這三個參數的含義簡單說明如下:

  • pixels_per_cell是指多少個像素作為一個網格來計算,這個值越高,切出來的網格就越少,整個HOG的結果就越粗略。
  • orientation是指切出來每個網格中有幾種方向的走勢,如果是四種,就是上、下、左、右;如果是八種,就再增加上左、上右、下左、下右四種方向。
  • cells_per_block是指一個網格中使用幾個方向指針,如果是十字交叉的情況,則至少需要兩個方向指針進行交叉,才可以表示出十字。

然后就是借助matplotlib可視化包查看一下不同參數的結果,如圖3-20所示。

圖3-20 使用不同的HOG參數分析輸入圖片得出不同的結果

這里決定用cell_per_block = 2,因為感覺結果中最多只出現了兩個方向的交叉。然后orientations = 9對拐角處的特征保留得更好,看起來像車的形狀。最后,pix_per_cell = 8看起來正好可以保持車的形狀,取6得到的網格過多,取10則得到的網格過少。

3.4.2 將HOG變換運用在所有正負樣本中

這里將正負樣本抽樣相關的函數寫成一個class,然后在這里引用class進行相應的操作,得到正負樣本在各個圖片中的區域。然后從這些區域中提取圖像文件,resize到64×64,計算HOG值,進而保存在矩陣中。

注意,下一步需要利用機器學習進行相應的判別,為了評價分類的準確性,這里需要將正負樣本進一步切割為訓練集和測試集。

3.4.3 訓練模型

完成前面的步驟后將開始模型的訓練。訓練的第一步是需要對數據進行標準化處理:

    X_scalerM = StandardScaler()
    X_trainT = X_scalerM.fit_transform(X_train)
    X_testT  = X_scalerM.transform(X_test)
X_trainTs,y_trainTs = sklearn.utils.shuffle(X_trainT, y_train)

使用sklearn的支持向量機模塊進行訓練。訓練后,看看驗證集的表現:

    svc = SVC(random_state=0, C=1)
    t=time.time()
    svc.fit(X_trainTs, y_trainTs)
    t2 = time.time()
    print(round(t2-t, 2), 'Seconds to train SVC...')
    #51.54 Seconds to train SVC...

訓練完成。接下來,用劃分出來的驗證集查看模型的表現。

3.4.4 將訓練好的分類器運用在新的圖片中

開始劃分數據時就使用train_test_split(pd_SampClass, test_size=0.33, random_state=42),分別劃分了訓練集以及驗證集。其中,66%的數據被劃分為訓練集,用于上一步的模型訓練。

這里,將用剩下的33%作為驗證集來檢驗模型的表現。首先看準確率:

    print('Test Accuracy of SVC = ', round(svc.score(X_testT, y_test), 4))

運行結果:

          # out:
          Test Accuracy of SVC =  0.9869

98%的分類準確率還是不錯的。接下來選十個樣本看結果:

    n_predict = 10
    print('My SVC predicts: ', svc.predict(X_testT[0:n_predict]))

運行結果:

          # out:
          My SVC predicts:  [1 1 1 0 0 0 0 1 1 1]
    print('For these',n_predict, 'labels: ', y_test[0:n_predict])

運行結果:

          # out:
          For these 10 labels:  [1 1 1 0 0 0 0 1 1 1]

選的前十個測試樣本,結果都是預測正確。最后看AUC值:

    pred = svc.predict(X_testT)
    print("AUC for Merge dataset = %1.2f,\n" % (roc_auc_score(pred, y_test)))

運行結果:

          # out:
          AUC for Merge dataset = 0.99,
    print(confusion_matrix(pred, y_test))

運行結果:

          # out:
          [[2929   55]
           [  22 2855]]

發現大多數預測準確,假陽性的數量是真陰性的2倍多,是一個基本可用的模型。至于這個模型的適用性如何,讀者可以在網上找圖片,resize到64×64,看看是否可以成功預測。

最后,總結本章所學的內容。本章開始部分提到,要用機器學習方法分析傳統圖像數據,可以有三種思路:

  • 手動提取重要的特征,用數字表示。如鳶尾花數據集,當年就是用尺子量出來的長度、寬度,交給機器學習分類器。
  • 用簡單的圖像處理操作,將圖片轉換為少數幾個簡單的輪廓特征,交給機器學習分類器。
  • 用深度神經網絡,讓深度學習模型自動提取圖片的各種特征,再用模型自動提取的特征訓練分類器。

本章介紹的是第二種方法,即提取簡單特征,交給機器學習分類器,如支持向量機。這種方法的問題想必讀者也有切身體會:

(1)“笨”——連足球都不認識,需要手動提取顏色、輪廓,然后過濾噪聲,最后交給霍夫變換檢測器,計算機才認識這是個圓形。

(2)“眼花”——我們拿到的是一個高像素的圖片,需要將圖片的信息不斷模糊、減少信息量,機器學習模型才能“認識”這張圖片,才能用這種簡化后的圖片進行模型訓練。

我們再思考一下,為什么傳統計算機模型會顯得很“笨”,而且眼神不好?一個很重要的原因是,傳統的機器學習模型缺乏特征組合能力,尤其是對圖像輸入,計算機可以理解單獨的一個像素,但是把單一像素與周圍三五個點一起考慮,計算機模型在組合的時候,似乎不太能把握這一組點的關系,所以我們會用opencv skimage把人類在識別諸如球體、車輛這樣的物體的關鍵因素提取出來,然后將提取的信息交給機器學習模型。

接下來介紹的基于深度神經網絡的方法,特征提取部分就并不完全由人手動完成,計算機模型可以幫助數據分析者提取諸如球形、車體框架這樣的特征。于是我們發現,相比傳統的圖像處理技術,計算機不“笨”了、不需要人提取特征了,眼神也變好了,可以直接識別原始圖片了。這也是深度學習技術總是和人工智能相提并論的一個很重要的原因。

主站蜘蛛池模板: 获嘉县| 酉阳| 平阴县| 万安县| 正宁县| 建阳市| 犍为县| 镇原县| 武义县| 宝应县| 岳普湖县| 富民县| 托里县| 宜昌市| 肃宁县| 山东| 米易县| 和顺县| 平利县| 武鸣县| 岳阳市| 海盐县| 中西区| 靖远县| 九寨沟县| 调兵山市| 大同市| 扶余县| 灌南县| 张家界市| 华坪县| 尼木县| 威信县| 伊金霍洛旗| 昆明市| 宜州市| 新泰市| 北海市| 喀喇沁旗| 阳曲县| 札达县|