建立自己的YOLO辨識模型 – 以柑橘辨識為例

最初版本的Yolo論文公佈於2015年,刊登於arXiv公開論文網站上,掛名的作者分別是Joseph Redmon、Santosh Divvala、Ross Girshick以及Ali Farhadi,但主要開發者應該是Joseph Redmon吧,這是他的個人網站https://pjreddie.com/。除了電腦,他還喜愛滑雪、徒步旅行、攀岩以及和他的阿拉斯加雪撬犬Kelp玩,所以他的YOLO論文(https://arxiv.org/abs/1506.02640)寫得相當的平實有趣,V2版還被選為2017年最佳論文。

https://avatars3.githubusercontent.com/u/302108?s=400&v=4

Joseph Redmon曾經上TED演講介紹YOLO,可上此網址https://www.ted.com/talks/joseph_redmon_how_a_computer_learns_to_recognize_objects_instantly?language=zh-tw#t-434921觀看,他在影片中介紹了影像分類及物件偵測的不同,推廣Object detection的應用並展示了YOLO在實時偵測上的威力。

Yolo歷代各版本的特色比較

V1 V2 V3
Detect方式 Grid網格式,預設為7×7 Anchor box on feature map。

在CNN output的13×13 feature map進行預測(stride為32),每格搭配5個Anchor Boxes來預測Bounding Boxes。

(以輸入圖片尺寸為416 x 416為例)

Anchor box on feature map。

在13×13, 26×26, 52×52三種feature maps上進行預測(stride分別為32, 16, 8),每格搭配3個Anchor Boxes來預測Bounding Boxes。(以輸入圖片尺寸為416 x 416為例)

Bound box最大數量 7 x 7 x 2 = 98 13 x 13 x 5 = 845

(以輸入圖片尺寸為416 x 416為例)

(13×13+26×26+52×52)x3 = 3549

(以輸入圖片尺寸為416 x 416為例)

Image seize for input 448 x 448 416 x 416(default)

model可接受最高解析度 (height=608, width=608)

或任何大於32的2次方倍數。

全連結層

輸入的圖片不再受限於固定的尺寸,任意輸入維度都可以在整個網絡上運行。

Detection 一個 一個 三個,分別針對不同的size
Loss function sum-squared error loss sum-squared error loss binary cross-entropy loss
Output activation Softmax loss Softmax loss Logistic loss
Base model GoogLeNet VGG ResNet
Darknet model darknet-19 darknet-53
新增技術 Batch Normalization→ V2以BN取代V1的Dropout layer,mAP提昇。

High Resolution Classifier→ V1用224×244 training,V2提昇至448×448訓練。

Convolution with anchor boxes→V2在FC層進行regression預測bounding box,V2直接去除FC層參考Faster R-CNN的作法以anchor來預測bound box。

Multi-Scale Training→ V2每訓練10個Batch會隨機地選擇新的圖片尺寸進行訓練。→提昇模型針對不同尺寸的圖片的偵測效果。

多尺度預測→提昇了對小物體的偵測能力。

Anchor box增加 → IOU提高

亮點 YOLO:45 FPS

Fast YOLO:155FPS

YOLO9000:可偵測9,000種物品,67FPS 針對前一版,主要亮點並非在速度,而是小物體的偵測能力以及數量。

如何訓練自己的YOLO model

  1. dataset準備與架構

從V2開始,可以自行在cfg檔中設定輸入圖片的尺寸(預設416×416或最高608×608,或任何大於32的2次方倍數尺寸)。所以若在拍攝相片時能用愈高像素來拍更好,可label出的物件愈多,且在後續使用的彈性更大。

在相片的準備上,建議需注意多樣及差異性,假設我們要準備柑橘圖片for辨識使用,那麼拍攝時需注意到:

– 不同環境:比如溫室或戶外的場地,高架或平地種植的草莓。

– 不同季節:蔬果外觀顏色的變化。

– 不同時間:光影的變化帶來的差異,直射斜射或散射光。

– 不同氣候:雨天與乾季對於蔬果外形的影響。

– 不同生長周期:蔬果從發芽抽高長葉到開花結果成熟…等,不同時期的外觀變化。

2. 相片或攝影的選擇

使用影片匯出影格frames作為訓練用圖片,目前也是主流方法之一,與相片拍攝比較,個人覺得最大差異是在1.事前篩選(相片)或事後篩選(攝影)、以及 2.像素尺寸大小兩種:

相片 影片
優點
  1. 尺寸及解析度較高
  2. 篩選相片時間少, 可直接進行label
  3. 成本較低
  1. 直接針對目的物進行錄影,不需一張張拍攝,搜集data較方便省時。
  2. 短時間內便可搜集到各種不同角度不同視野的大量相片。
  3. 訓練時可針對欠缺的某一角度或形態的相片,再從影片檔中去取得再加入訓練。
缺點
  1. 拍攝時需考慮角度對焦及距離,搜集data會發費較多時間。
  2. 若缺少某一類相片,必須重回現場拍攝取得。
  1. 解析度較低,物體太小時無法利用裁圖方式來放大。
  2. 需花費時間針對影片中的frames進行篩選匯出,才能開始label。
  3. 1080P或4K錄影,硬體成本較相機高。

我個人偏好的模式是以相片為主攝影為輔,在準備dataset階段可先用相片拍攝大量相片後,再花點時間用攝影模式拍幾段影片,之後在訓練的過程中若發現效果不理想或有某一類型的圖片缺乏,可從影片中尋找符合該類型的frame加入訓練。

3. 建立相關資料夾

首先,先建立如下三個資料夾,然後將上一步欲用來訓練的相片放置於images資料夾中。

4. 開始label相片

Label軟體我們使用的是LabelImg,請從https://github.com/tzutalin/labelImg 下載並執行該軟體。剛執行時畫面是空的,請按「Open Dir」、「Change Save Dir」選擇剛剛建立的images以及labels資料夾,接下來便可從下窗格中選擇要label的相片,「按下Create RectBox」便可開始label。

在作label框選時,請考慮是否有足夠的紋理特徵?此外,若人眼都無法確定的物件,就放棄框選。

框選完所有的相片之後,您的資料夾下應會分別有相同數目的image檔及xml的label檔。

        請注意,目前新版for windows的LabelImg新增YOLO格式,因此可以直接輸出YOLO需要的檔案格式,您可以直接使用該格式,但我的習慣還是用較為流行的Pascal VOC格式,另外再寫一支程式將VOC轉為YOLO格式,好處是VOC較多人使用,而我們的dataset除了YOLO之外,還可以支援其它的object detection模型。

5.  轉換VOC labels為YOLO格式

YOLO所需要的label格式不同於我們所熟知、ImageNet使用的PASCAL VOC xml,而是採用text文字檔,第一欄為class的ID,其它皆以物件框相對於整張圖片的比例來呈現:

類別代碼

物件中心x位在整張圖片x的比例

物件中心y位在整張圖片y的比例

物件寬度w佔整張圖片寬度的比例

物件長度h佔整張圖片長度的比例

Category

number

Object center

in X

Object center

in Y

Object width

in X

Object height

in Y

例如下圖定義了三個名稱為「Orange」的label,右側為PASCAL VOC的格式,下方為YOLO的格式,可用如下計算方式來轉換VOC→YOLO。

轉換公式:

x = (xmin + (xmax-xmin)/2) * 1.0 / image_w

y = (ymin + (ymax-ymin)/2) * 1.0 / image_h

w = (xmax-xmin) * 1.0 / image_w

h = (ymax-ymin) * 1.0 / image_h

6. 建立YOLO資料夾,放置Label檔及圖片檔

YOLO的label檔是text格式的.txt,每張圖片對應一個txt檔,且兩者較要放置於同一資料夾中,因此,我建了一個資料夾名稱為YOLO,將所有images及txt檔全部放置於其下。稍後在訓練時,YOLO只會access該Yolos資料夾,Images和Labels這兩個已經不需要了。

7. 建立設定檔cfg資料夾

在Orange目錄下,新增cfg資料夾,我們將在此資料夾下放置YOLO設定檔。

有五個設定檔,分別為:

obj.names、obj.data、train.txt、test.txt、yolov3.cfg or yolov3-tiny.cfg

  1. obj.names:此檔內容為label的列表,例如mature與flower,YOLO在訓練與預測時皆需要讀取此檔。

mature

flower

  1. obj.data:定義label數目以及各個設定檔及weights目錄的path,YOLO訓練及預測時皆會讀取。

classes= 2

train  = cfg.orange/train.txt

valid  = cfg.orange/test.txt

names = /home/digits/jupyter/chtseng/opencv-cascade-make/yolo-v3/cfg.orange/obj.names

backup = cfg.orange/weights/

  1. train.txt:所有images檔案名稱列表中的80%(或其它比例,可視需求變更),訓練時YOLO會依次讀取該檔內容取出相片進行訓練.。您可以手動或寫程式取出固定比例的列表放置於此檔案內容中。

/dataset/orange/yolo/IMG_4287.jpg

/dataset/orange/yolo/IMG_4104.jpg

/dataset/orange/yolo/IMG_4291.jpg

/dataset/orange/yolo/IMG_4306.jpg

/dataset/orange/yolo/IMG_4429.jpg

  1. test.txt:所有images檔案名稱列表中的20%(或其它比例,可視需求變更),訓練時YOLO會依次讀取該檔內容取出相片進行validation.。您可以手動或寫程式取出固定比例的列表放置於此檔案內容中。

/dataset/orange/yolo/IMG_4102.jpg

/dataset/orange/yolo/IMG_4428.jpg

/dataset/orange/yolo/IMG_4318.jpg

  1. yolov3.cfg or yolov3-tiny.cfg :YOLO模型設定檔,請從Darknet安裝目錄下的cfg資料夾找到需要的YOLO cfg檔(標準或tiny YOLO),複製到本cfg資料夾。
  2. 修改yolo模型的cfg檔:

 如果您想訓練Tiny YOLO,請複製並修改yolov3-tiny.cfg如下:

    Line 3: set batch=24  using 24 images for every training step

    Line 4: set subdivisions=8  the batch will be divided by 8

    Line 127: set filters=(classes + 5)*3    in our case filters=21

    Line 135: set classes=2    the number of categories we want to detect

    Line 171: set filters=(classes + 5)*3   in our case filters=21

    Line 177: set classes=2    the number of categories we want to detect

如果您想訓練YOLO,請複製並修改yolov3.cfg如下:

    Line 3: set batch=24  using 24 images for every training step

    Line 4: set subdivisions=8  the batch will be divided by 8

    Line 603: set filters=(classes + 5)*3    in our case filters=21

    Line 610: set classes=2     the number of categories we want to detect

    Line 689: set filters=(classes + 5)*3    in our case filters=21

    Line 696: set classes=2, the number of categories we want to detect

    Line 776: set filters=(classes + 5)*3    in our case filters=21

    Line 783: set classes=2     the number of categories we want to detect

batch參數是指每批次取幾張圖片進行訓練,subdivisions參數是指要將每批次拆成幾組,以避免GPU memory不夠。如果您是使用12G的1080 Ti GPU,建議使用其預設的batch=24、subdivisions=8即可。

另外,由於標準YOLO V3有三個detector針對三種scale的feature map,因此要修改三組的filters及classes。Tiny YOLO只有兩個detector,因此要修改兩組。

修改完yolov3.cfg or yolov3-tiny.cfg之後,便可開始進行訓練了。

8. 開始訓練

  1. 新建一目錄 for 儲存訓練過程的weights權重檔,該目錄的路徑名稱定義於obj.data中的backup參數。

  1. 下載預訓練檔

請從https://pjreddie.com/media/files/darknet53.conv.74,下載darknet53.conv.74 weights pre-trained on Imagent,該檔大小約155MB,可同時用於訓練YOLO及Tiny YOLO。另外,也可以考慮使用Imagent+COCO datasets所訓練的yolov3.weights (https://pjreddie.com/media/files/yolov3.weights)或yolov3-tiny.weights(https://pjreddie.com/media/files/yolov3-tiny.weights)。

下載後的訓練檔請置於可讀取到的位置,下一步將用到。

  1. 執行darknet command開始訓練

../../darknet/darknet detector train cfg.orange/obj.data cfg.orange/yolov3-tiny.cfg darknet53.conv.74

  1. 訓練過程會持續的秀出各種數值,並且每隔100batches會寫出一個weights檔。其log說明如下:

  1. 一般來說,我們最需要注意的是紅框的average loss error,如果您訓練的圖片數目有數千個以上,那麼average loss error約0.06左右便可手動停止了,如果僅有數百張,那麼大約0.6左右便可先試著載入其weights檔測試看看辨識效果是否滿意。YOLO在訓練過程中每訓練100 batches便會寫入一個新的weights檔到目錄中,我們可以隨時取用以檢視目前的訓練成果

9. 檢視訓練成果

我們找一張圖片,然後使用下列的Darknet command來測試。

../../darknet/darknet  detector test cfg.orange/obj.data cfg.orange/yolov3-tiny.cfg cfg.orange/weights/yolo_18200.weights {要測試的相片路徑}

執行後,會將指定的測試相片進行檢測後,將結果輸出為predictions.jpg。

F:\vms\shares\predictions.png

 F:\vms\shares\predictions.png

F:\vms\shares\predictions.png

 F:\vms\shares\predictions.png

        只透過Darknet提供的指令來預測單張相片,是否感覺不方便也不過癮呢?因此接下來,我們要來看看如何透過Pythonv以及OpenCV來操控YOLO進行辨識。

 

廣告