環境搭建、標註、訓練、推斷,超詳細的目標檢測開發流程
點擊 我愛計算機視覺 標星,更快獲取CVML新技術
本文轉載自飛槳PaddlePaddle。 基於PaddleDetection,詳細描述了一個完整目標檢測項目流程,非常值得收藏。
【飛槳開發者說】:餘志良,菲特(天津)智能科技有限公司項目經理,百度黃埔學院二期學員
PaddleDetection 是百度飛槳推出的物體檢測統一框架。支持現有的RCNN、SSD、YOLO等系列模型、支持 ResNet、ResNet-VD、ResNeXt、ResNeXt-VD、SENet、MobileNet、DarkNe等主幹網絡。針對不同的業務場景(性能、目標大小、準確率等)可以選擇框架中的不同模塊組合得到最適合的模型,實現任務。相比於tensorflow的Object_Detection,優勢之一就是將YOLOv3這一目標檢測的快速算法融合到了框架下。
文章將以一個Yolov3識別水果的例子爲說明,詳解如何利用PaddleDetection完成一個項目。
項目用到的工具 硬件:Win10(RTX2060)筆記本、某品牌服務器(4*T4)工業相機(Hikvision)軟件:pycharm、VS2019。
目錄:
1、環境部署
2、數據集準備
3、訓練
4、訓練過程可視化
5、模型導出
6、python進行單張/多張圖片的預測
7、python+qt(給客戶的演示demo)
8、C++進行單張預測(含編譯簡介)
9、C++預測代碼封裝成DLL、配合C#完成一個整體項目
10、擴展:關於PaddlePaddle代碼數據讀取的方式。
01
環境部署
1.1 安裝PaddlePaddle
利用anaconda創建一個名字叫做paddle-detection的Paddle環境(備註:下文中命令提示窗口出現的(paddle)是指該項目環境的名稱叫做paddle)。安裝鏈接如下:
https://www.paddlepaddle.org.cn/install/quick
1.2 安裝COCO-API
pip install Cython
pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
1.3 選擇一個文件夾,下載PaddleDetection
第一種方式:直接從github官網上進行下載:
https://github.com/PaddlePaddle/PaddleDetection
第二種方式:使用git進行下載:
git clone https://github.com/PaddlePaddle/PaddleDetection.git
1.4 安裝所需的Python其他依賴庫
依賴庫文檔在requirements.txt中給出,可使用
pip install -r requirements.txt
如下圖所示是requirements.txt文檔中的內容。
如圖爲requirements文件中的內容,圖中所示的均爲PaddleDetection的依賴庫。
在下圖所示內容中打“cmd”,然後出現在該路徑的命令提示符。
激活環境,並且 pip install -r requirements.txt
然後運行
當顯示Successfully…… ,基本上表示安裝完成了,具體是否成功,下一步的測試驗證。
1.5 確認測試通過
set PYTHONPATH=`pwd`:$PYTHONPATH
python ppdet/modeling/tests/test_architectures.py
備註:在paddle自帶的文檔中爲export PYTHONPATH=`pwd`:$PYTHONPATH
export是Linux下的用法,在Windows下將exoprt改成set。
但是發現運行報錯,報錯內容如下:
錯誤提示發現缺少“ppdet”這個模塊,ppdet(其實就是paddle detection的一個縮寫),但是我們在項目的路徑裏面可以發現有這個模塊,原因就是,我們的代碼所在的路徑無法讀取到該文件下的代碼,因此,我們需要在代碼中進行改進一下。
找到 ppdet/modeling/tests/test_architectures.py這個文件,然後添加紅框所示的代碼。備註,第二個紅框裏面的路徑是我的項目路徑。
出現如圖所示的代碼,表示運行成功。
至此,所有的運行環境已經配置成功。
02
數據集的準備
2.1 數據標註:
目前項目使用的數據集格式是VOC數據格式,使用labelimg作爲標註工具,標註工具的下載安裝見鏈接:
https://zhuanlan.zhihu.com/p/97807042
特別說明:項目中使用的數據集是PaddleDetection提供的演示示例數據集,下文將通過使用該數據集來說明。
首先,下載該數據集,下載地址: https://pan.baidu.com/wap/init?surl=ZO8OlqvWuMk_sqOwlo56rg
提取碼: vw3b
下載後如下圖所示:
標註方式如下:
打開軟件,並導入圖片:
選取標註文件的保存路徑:
點擊Change Save Dir ,然後將標註文件保存在某一個路徑下。
開始標註:點擊Create\nRectBo---框選目標--命名(下圖中命名爲apple)--點擊OK---點擊Save(完成一張)--點擊Next Image 標註下一張。
所有標註完成以後會生成很多的xml文件。
打開一個xml文件:
具體信息如下:
2.2 創建VOC數據集格式
其中Annotations存放標註生成的xml文件,JPEGImage存放圖片,ImageSets存放對訓練集和數據集的劃分。ImageSet下有Main文件,Mian下需要建立一個label_list.txt。label_list.txt是指標註的目標的名稱。其內容如下:
備註:train.txt、val.txt是根據下文中代碼(該代碼會命名爲:get_list.py,放置在了數據集鏈接的文件裏面)生成,分別是對訓練集和驗證集的劃分:
接上文所述,是生成生成train.txt、val.txt的代碼,該代碼會將300張水果圖片分成240張訓練集和60張驗證集。
import os
import random
train_precent=0.7
xml="C:/Users/zhili/Desktop/fruit-detection/Annotations"
save="C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main"
total_xml=os.listdir(xml)
num=len(total_xml)
tr=int(num*train_precent)
train=range(0,tr)
ftrain=open("C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main/train.txt","w")
ftest=open("C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main/test.txt","w")
for i in range(num):
name=total_xml[i][:-4]+"\n"
if i in train:
ftrain.write(name)
else:
ftest.write(name)
ftrain.close()
ftest.close()
如下圖是生成的train文件。
備註:在Main文件夾中生成的train.txt文件和val.txt文件僅僅是對數據集的劃分,還需要進一步的利用如下代碼(create_list.py,該代碼是paddle提供的)生成含有路徑信息以及圖像和xml文件一一對應的文件。
import os
import os.path as osp
import re
import random
devkit_dir = './'
years = ['2007', '2012']
def get_dir(devkit_dir, type):
return osp.join(devkit_dir, type)
def walk_dir(devkit_dir):
filelist_dir = get_dir(devkit_dir, 'ImageSets/Main')
annotation_dir = get_dir(devkit_dir, 'Annotations')
img_dir = get_dir(devkit_dir, 'JPEGImages')
trainval_list = []
test_list = []
added = set()
for _, _, files in os.walk(filelist_dir):
for fname in files:
img_ann_list = []
if re.match('train\.txt', fname):
img_ann_list = trainval_list
elif re.match('val\.txt', fname):
img_ann_list = test_list
else:
continue
fpath = osp.join(filelist_dir, fname)
for line in open(fpath):
name_prefix = line.strip().split()[0]
if name_prefix in added:
continue
added.add(name_prefix)
ann_path = osp.join(annotation_dir, name_prefix + '.xml')
img_path = osp.join(img_dir, name_prefix + '.jpg')
assert os.path.isfile(ann_path), 'file %s not found.' % ann_path
assert os.path.isfile(img_path), 'file %s not found.' % img_path
img_ann_list.append((img_path, ann_path))
return trainval_list, test_list
def prepare_filelist(devkit_dir, output_dir):
trainval_list = []
test_list = []
trainval, test = walk_dir(devkit_dir)
trainval_list.extend(trainval)
test_list.extend(test)
random.shuffle(trainval_list)
with open(osp.join(output_dir, 'train.txt'), 'w') as ftrainval:
for item in trainval_list:
ftrainval.write(item[0] + ' ' + item[1] + '\n')
with open(osp.join(output_dir, 'val.txt'), 'w') as ftest:
for item in test_list:
ftest.write(item[0] + ' ' + item[1] + '\n')
if __name__ == '__main__':
prepare_filelist(devkit_dir, '.')
這個時候的新生成的train.txt的內容如下:
最終生成如下所示的數據集格式如下,其中label_list.txt和Mian中的label_list.txt一致。train.txt文件和val.txt是新生成的圖像-xml的名稱路徑對應文件。
該完成後的數據集作者放置在了項目文件夾下:dataset/fruit下,並命名爲該文件夾爲fruit-detection,如下圖所示。
數據集生成後就可以根據如下的命令進行訓練。
03
訓練
在訓練之前,首先了解模型的配置文件,如文章開頭所述:PaddleDetection 是飛槳推出的物體檢測統一框架。支持現有的RCNN、SSD、YOLO等系列模型、支持 ResNet、ResNet-VD、ResNeXt、ResNeXt-VD、SENet、MobileNet、DarkNet等主幹網絡。而實現我們如何快速的完成不同模型的訓練體驗,就是需要依靠配置文件的切換。
如下所示就是該項目配置文件(config文件)的路徑:
如圖下圖就是我們選取的深度學習的配置文件,我們選取yolov3_mobilenet_v1_fruit.yml做爲本項目的訓練配置文件。該配置文件是使用YOLO v3的模型結構,同時主幹網絡爲 Mobilenrt V1。
這些參數可以根據我們自己的數據情況進行設計。
如設置:最大迭代步數:max_iters
預訓練模型的來源:pretrain_weights
數據路徑:dataset_dir
Batch_size的大小:batch_size
數據集類別:num_classes
需要着重關注點如下:需要根據自己的不同數據集進行訓練。
在將config文件配置好了以後,就可以進行訓練
set PYTHONPATH=$PYTHONPATH:.
set CUDA_VISIBLE_DEVICES=0(默認只有一個GPU)
python -u tools/train.py -c configs/yolov3_mobilenet_v1_fruit.yml --use_tb=True --tb_log_dir=tb_fruit_dir/scalar --eval
運行如下命令,即可開始訓練
出現如下圖所示現象,可以表示爲訓練正常,可等待訓練結束。
關於訓練命令的闡述:
-c configs/yolov3_mobilenet_v1_fruit.yml 用來指定配置文件
--use_tb 是否使用tb-paddle記錄數據,進而在TensorBoard中顯示,默認值是False
--tb_log_dir 指定 tb-paddle 記錄數據的存儲路徑
--eval 是否邊訓練邊測試
備註:
關於–eval參數的使用:
在訓練中交替執行評估, 評估在每個snapshot_iter時開始。每次評估後還會評出最佳mAP模型保存到best_model文件夾下,建議訓練時候使用該參數,可以使得完成訓練後快速找到最好的模型。
關於預訓練模型的來源:
在本案例中,預訓練模型是通過一個鏈接方式在訓練開始時候加載進行下載的,其實飛槳提供了豐富的預訓練模型庫,具體鏈接爲:
https://github.com/PaddlePaddle/PaddleDetection/blob/release/0.2/docs/MODEL_ZOO_cn.md
訓練過程出現的一個錯誤:
作者使用的電腦是筆記本,顯卡型號是RTX2060 顯存爲6G。在訓練過程中出現如下錯誤。
通過命令提示符中發現,竟然出現了(7184, 7184, 3)這樣大的圖片,而本身數據像素多數爲1000*1000左右。解決改問題的方式有兩個:
第一個是修改配置文件中的bufsize這個參數,將該值由128改成64 (備註,PaddleDetection新更新的配置文件文檔中,已經將該值設置成爲32),即可正常運行。在這裏解釋一下:PaddleDetection YOLOv3系列模型訓練時,由於圖像增強等預處理方式較多,默認會開啓多進程加速,子進程完成圖像讀取,圖像增強等預處理後,會將輸出結果放到一個隊列裏面等待模型訓練時獲取,bufsize這個參數即爲該隊列的最大長度,該隊列存儲在內存中,若機器內存較小並且隊列長度bufsize設置得較大,就會有上述報錯,報錯內容爲內存不夠,無法給隊列繼續分配內存。這個時候只要把bufsize調小一些保存內存足夠放下隊列即可。
第二個方式是修改配置文件中的ratio的參數,將該值由4.0改成了2.0,即可正常運行。 PaddleDetection中設置了數據增強功能:在RandomExpand這種數據增強裏,首先新建一張(原圖大小 * ratio)大小的空白圖片,然後在這張空白圖片上隨機找個位置,把原圖貼上去,之後再把這張新圖片縮放成原圖大小。當然如果顯存足夠大的話,也可以按照默認值來。
04
訓練過程可視化
訓練期間可以通過tensorboard實時觀察loss和精度值,啓動命令如下:
tensorboard --logdir tb_fruit_dir/scalar
05
模型導出
當我們訓練完成後,在項目文件的output中可以看到我們生成的模型文件,在代碼中我們設置模型每迭代200步保存一次,訓練總共有20000步,因此會生成100個訓練文件,由於我們使用 --eval參數進行邊訓練邊測試,因此我們可以獲得訓練過程中最好的模型文件,我們將做好的模型進行導出。
執行如下命令:
python tools/export_model.py -c configs/yolov3_mobilenet_v1_fruit.yml --output_dir=./inference_model -o weights=output/yolov3_mobilenet_v1_fruit/best_model
最終導出如下所示:
特別備註:目前導出的模型使用是爲了後面C++預測的,python預測目前不支持加載導出的模型。
06
模型預測
PaddleDetection給出的模型預測代碼是infer.py。該文件在項目文件夾tools裏面。改代碼提供了兩種預測方式第一種是單張圖片預測,第二種是以一個文件夾中的圖片進行預測。通過設置不同的預測方式達到自己的目的。如下,使用--infer_img=demo/xxx.jpg爲單張圖片進行預測,使用--infer_dir=demo爲用一個文件夾進行預測。其中demo是放置測試圖片的地方。
6.1 使用單張圖片進行預測
測試的結果保存在infer_output這個文件夾中
python -u tools/infer.py -c configs/yolov3_mobilenet_v1_fruit.yml -o weights= output/yolov3_mobilenet_v1_fruit/best_model --infer_img=demo/orange_71.jpg --output_dir=infer_output
特別注意:類似這種在命令提示符下輸入時候,一定注意自己輸入過程中的出現的多餘空格問題:如下圖所示,weights=後面出現了一個多的空格,導致模型文件讀不到。
6.2 使用一個文件夾中圖片進行預測
測試的結果保存在infer_output這個文件夾中:
python -u tools/infer.py -c configs/yolov3_mobilenet_v1_fruit.yml -o weights=output/yolov3_mobilenet_v1_fruit/best_model --infer_img=demo/test --output_dir=infer_output/testout
說明:
1、該文章多數內容來源於PaddleDetection的文檔,鏈接
https://github.com/PaddlePaddle/PaddleDetection
2、該文章運行環境爲Windows10 ,在原有文檔基礎上修改了一些Linux的用法。增加了創建VOC數據集以及如何劃分訓練集和驗證集。
3、該文章寫作過程中,受到了高松鶴同學、百度飛槳同學的大力幫助。
目標檢測交流羣
關注最新最前沿的2D、3D目標檢測 技術,掃碼添加CV君拉你入羣,(如已爲CV君其他賬號好友請直接私信)
( 請務必註明:目標檢測 ):
喜歡在QQ交流的童鞋可以加52CV官方QQ羣: 805388940 。
(不會時時在線,如果沒能及時通過還請見諒)
長按關注 我愛計算機視覺