一瞥(You Only Look Once, YOLO),是檢測Pascal VOC 2012數據集內對象/目標的系統,能夠檢測出20種Pascal對象:
人person
鳥bird、貓cat、牛cow、狗dog、馬horse、羊sheep
飛機aeroplane、自行車bicycle、船boat、巴士bus、汽車car、摩托車motorbike、火車train
瓶子bottle、椅子chair、餐桌dining table、盆景potted plant、沙發sofa、顯示器tv/monitor
YOLO由以下參與者共同完成:Santosh、Ross和Ali,詳細內容參見其paper
以下教程分爲9部分(不要害怕,easy),運行系統Ubuntu 14.04。OpenCV、cuda、GPU這些依賴是可選項,如果沒有也可以,就是慢點(其實是慢很多)啦。最後會添加一下官網教程中沒有的安裝錯誤和修改信息。
本篇教程內容全部翻譯自官網
1.How It Works
先前的檢測系統多使用分類器(classifier)或者定位器(localizer)進行檢測任務,把圖片的不同局部位置和多種尺度輸入到模型中去,圖片得分較高的區域(region)作爲檢測目標。
YOLO是一個全新的方法,把一整張圖片一下子應用到一個神經網絡中去。網絡把圖片分成不同的區域,然後給出每個區域的邊框預測和概率,並依據概率大小對所有邊框分配權重。最後,設置閾值,只輸出得分(概率值)超過閾值的檢測結果。
我們的模型相比於基於分類器的模型有一些優勢,在測試階段,整張圖片一次輸入到模型中,所以預測結果結合了圖片的全局信息。同時,模型只是用一次網絡計算來做預測,而在R-CNN中一張圖片就需要進行上千次的網絡計算!所以YOLO非常快,比R-CNN快1000倍,比Fast R-CNN快100倍。整個系統的細節見paper
2.Detection Using A Pre-Trained Model
本節內容會知道你如何使用YOLO預訓練好的模型進行目標檢測。在這之前,你應該安裝好DarkNet,安裝方法戳這裏。
安裝好DarkNet之後,在darknet的子目錄cfg/下已經有了一些網絡模型的配置文件,在使用之前,需要下載好預訓練好的權重文件yolo.weights(1.0 GB).
現在,使用DarkNet的yolo命令進行一下測試吧(假設你在darknet/目錄下,自己修改好yolo.weights和image的路徑)
./darknet yolo test cfg/yolo.cfg <path>/yolo.weights <image>
如果你沒有現成的圖片,不妨直接使用darknet/data/下面的某張圖片。
進行上面的測試,Darknet會打印出檢測到的目標對象和可信度,以及耗時。使用CPU時,每張圖片耗時爲6-12秒,GPU版本會快,快很多。
如果安裝DarkNet的時候,沒有使用OpenCV,上面的測試不會直接顯示出圖片結果,你需要自己手動打開predictions.png. 打開你會看到類似於下圖的預測結果
如果想運行一次DarkNet檢測多張圖片的話,你應該先運行以下命令載入預訓練模型
./darknet yolo test cfg/yolo.cfg yolo.weights
模型載入成功後,會提示輸入圖片路徑Enter Image Path:
鍵入類似於data/eagle.jpg的路徑,檢測這張圖片,給出結果之後,會繼續提示Enter Image Path。注意如果你連續輸入了多張圖片,之前的結果會被下一次的檢測結果覆蓋掉,因爲預測結果都叫predictions.jpg。。。要退出/中斷程序的話,直接鍵入Ctrl-C(自己記住這個命令,後面會再用)即可。
3.A Smaller Model
上面的YOLO模型會佔用很多GPU內存,方法類似,只需要調用不同的配置文件,載入相應的權重文件即可。在這裏,提供一個更小版本的模型,使用yolo-small.cfg配置文件,調用yolo-small.weights(359MB),命令如下
./darknet yolo test cfg/yolo-small.cfg yolo-small.weights
這個小版本的YOLO大概佔用1.1GB的GPU內存~
4.A Tiny Model, yolo-tiny.weights(172 MB)
./darknet yolo test cfg/yolo-tiny.cfg yolo-tiny.weights
佔用611MB的GPU內存,在Titan X上的速度是150 fps
5.YOLO Model Comparison
yolo.cfg,基於extraction網絡,處理一張圖片的速度爲45fps,訓練數據來源2007 train/val + 2012 train/val + 2007、2012所有數據
yolo-small.cfg,全連接層變小,佔用內存變小,50fps,訓練數據來源2007 train/val + 2012 train/val
yolo-tiny.cfg,更加小型的網絡,基於DarkNet reference network,155fps,數據來源2007 train/val + 2012 train/val
6.Changing The Detection Threshold
YOLO默認返回可信度至少爲0.2的檢測結果,可以通過-thres <val>參數改變可信度閾值,例如設置爲0:
./darknet yolo test cfg/yolo.cfg yolo.weights data/dog.jpg -thresh 0
這將可能返回所有的檢測結果。
7.Real-Time Detection On VOC 2012
如果編譯時使用了CUDA,那麼預測的速度回遠遠超過你(手動)輸入圖片的速度。爲了更快速地檢測多張圖片的內容,應該使用yolo的valid子程序。
首先預備好數據並生成元數據給DarkNet。這裏我們使用VOC2012的數據(需要註冊一個賬號才能下載),下載2012test.rar文件之後,運行以下命令
tar xf 2012test.tar
cp VOCdevkit/VOC2012/ImageSets/Main/test.txt .
sed 's?^?'`pwd`'/VOCdevkit/VOC2012/JPEGImages/?; s?$?.jpg?' test.txt > voc.2012.test
這些命令首先解壓數據包,然後生成全路徑的測試圖像,然後把voc.2012.test移動到darknet/data子目錄下
mv voc.2012.test <path-to>/darknet/data
OKAY,現在使用這些圖片做檢測,我們使用CUDA版本的,超級快!運行下面命令
./darknet yolo valid cfg/yolo.cfg yolo.weights
運行上面命令後,你會看到一串數字在屏幕上飛,數字表示當前處理了多少圖片。VOC 2012 test數據集共有10991張圖片,共耗時250秒,相當於44fps。如果你用Selective Search方法的話,要耗時6小時!相比之下,咱的方法整個pipeline才耗時4分鐘,pretty cool!
預測結果在results/子目錄下,其格式爲Pascal VOC要求提交的特殊格式。
如果你想復現我們在Pascal挑戰賽中的結果,你得使用yolo-rescore.weights纔行。
8.Real-Time Detection on a Webcam
只是簡單地跑一下測試數據集,而且看不到實時的結果,真的挺無趣的。所以,我們把輸入改成webcam
挖個坑,後面填
9.Training YOLO
其實,你可以從頭開始訓練YOLO,如果你想的話。你可以嘗試不同的訓練方法,設置不同的超參數,以及使用自己的數據集。咱們下面嘗試自己訓練Pascal VOC數據集。
9.1下載Pascal VOC Data
咱們先下載2007年到2012年的VOC數據,下載之前,新建一個文件夾(比如VOC)存放這些數據,進入此文件夾,按如下方式下載數據,然後解壓。
curl -O http://pjreddie.com/media/files/VOCtrainval_11-May-2012.tar
curl -O http://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar
curl -O http://pjreddie.com/media/files/VOCtest_06-Nov-2007.tar
tar xf VOCtrainval_11-May-2012.tar
tar xf VOCtrainval_06-Nov-2007.tar
tar xf VOCtest_06-Nov-2007.tar
解壓完之後,所有數據都自動存放在VOCdevkit/子目錄下了。
9.2生成VOC的標註信息
接下來生成DarkNet訓練所需的標籤文件,該文件擴展名爲.txt,文件內每一行對應一張圖片的標註信息,具體格式如下
<object-class> <x> <y> <width> <height>
其中的x, y, width和height是對應圖片上的座標和寬、高。只要運行一下DarkNet項目中scripts/子目錄下面的voc_label.py腳本,就會自動生成VOC的標註文件。如果你沒找到這個文件,可以再重新下載一下。下載和腳本運行方式如下
curl -O http://pjreddie.com/media/files/voc_label.py
python voc_label.py
這個腳本大概要運行幾分鐘,運行結束之後,你會看到多了兩個文件夾,VOCdevkit/VOC2007/labels/和VOCdevkit/VOC2012/labels/。
現在,你的VOC目錄下應該是這個樣子的
ls
2007_test.txt VOCdevkit
2007_train.txt voc_label.py
2007_val.txt VOCtest_06-Nov-2007.tar
2012_train.txt VOCtrainval_06-Nov-2007.tar
2012_val.txt VOCtrainval_11-May-2012.tar
其中的文本文件,比如2007_test.txt,包含的內容是VOC 2007年的test數據集標註信息。DarkNet需要一個txt文件提供所有標註信息,所以我們還需要把這些信息導入到一個txt文件中。本例中,我們使用2007年的train和validation數據和2012年的train數據作爲訓練集,2012年的validation數據作驗證數據。具體使用如下命令
cat 2007_* 2012_train.txt > train.txt
OKAY,現在2007年的所有圖片和2012年的train數據集的圖片路徑都在train.txt文件裏面了。標註信息在下面兩個路徑中
/darknet/VOC/VOCdevkit/VOC2007/labels/
/darknet/VOC/VOCdevkit/VOC2012/labels/
上面所做的就是訓練自己的數據集之前所要準備的數據信息了。
9.3重定向DarkNet到Pascal數據
進入DarkNet目錄中,src/子目錄裏面有一個yolo.c文件,打開並編輯一下其中的18、19行(54、55行?不重要,自己確定)
18 char *train_images = "/your_path/VOC_train/train.txt";
19 char *backup_directory = "/your_path/backup/";
其中,train_images指向的是訓練文件,backup_directory指向的是訓練過程中權重的備份路徑。編輯好yolo.c之後,保存,重新編譯一下DarkNet。
9.4下載預訓練之後的卷積權重
訓練的時候使用來自Extraction模型的卷積層權重,這個模型訓練時用的是Imagenet數據。從這(54MB)下載這些權重。如果你想直接用Extraction模型生成這些預訓練好的權重,你得先下載預訓練好的Extraction模型,運行下面的命令
./darknet partial cfg/extraction.cfg extraction.weights extraction.conv.weights 25
勸告大家直接下載權重會更簡單。。。
9.5訓練
運行下面命令開始訓練
./darknet yolo train cfg/yolo.cfg extraction.conv.weights
運行時,屏幕會提示一下數字和任務信息。
如果你想訓練更快些,同時降低提示信息頻率,首先終止訓練,然後在cfg/yolo.cfg中修改一下第三行的信息
3 subdivisions = 2
或修改成4,或更大,比如64。然後重新開始訓練
9.6訓練Checkpoints
每訓練128000張圖片之後,DarkNet自動保存checkpoint信息到你在src/yolo.c中指定的備份路徑下。checkpoint的文件名類似於yolo_12000.weights。你可以使用這些checkpoint信息重新開始訓練,避免從頭開始。
40,000次迭代之後,DarkNet會保存模型的權重,然後結束訓練,最後的權重會以yolo.weights命名。
恭喜,這就訓練結束了~
Good Luck!!
上兩張訓練時的截圖
下面是你安裝過程中可能遇到的問題和解決辦法
Q1.使用GPU=1,運行測試命令,例如
./darknet imtest data/eagle.jpg
或者
./darknet yolo demo cfg/yolo.cfg yolo.weights並鍵入圖片地址
報以下錯誤
L2 Norm: 372.007568
CUDA Error:invalid device function
darknet: ./src/cuda.c:21: check_error: Assertion `0' failed.
Aborted (core dumped)
看了看./src/cuda.c的代碼也沒發現啥。。。
出現這個問題是因爲DarkNet的配置信息Makefile文件裏面的GPU架構和實際安裝的GPU不對應。
ARCH= --gpu-architecture=compute_xx --gpu-code=compute_xx
經測試,k40m和k40顯卡應該設置爲
ARCH= --gpu-architecture=compute_35 --gpu-code=compute_35
tk1顯卡的設置應該爲
ARCH=--gpu-architecture=compute_20 --gpu-code=compute_20
或許這些信息對你有所幫助