點擊 我愛計算機視覺 標星,更快獲取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

(不會時時在線,如果沒能及時通過還請見諒)

長按關注 我愛計算機視覺

相關文章