人工智能技術(shù)及應(yīng)用 課件 張文安ch6-行人檢測(cè)實(shí)踐;ch7-車(chē)道線檢測(cè)實(shí)踐_第1頁(yè)
人工智能技術(shù)及應(yīng)用 課件 張文安ch6-行人檢測(cè)實(shí)踐;ch7-車(chē)道線檢測(cè)實(shí)踐_第2頁(yè)
人工智能技術(shù)及應(yīng)用 課件 張文安ch6-行人檢測(cè)實(shí)踐;ch7-車(chē)道線檢測(cè)實(shí)踐_第3頁(yè)
人工智能技術(shù)及應(yīng)用 課件 張文安ch6-行人檢測(cè)實(shí)踐;ch7-車(chē)道線檢測(cè)實(shí)踐_第4頁(yè)
人工智能技術(shù)及應(yīng)用 課件 張文安ch6-行人檢測(cè)實(shí)踐;ch7-車(chē)道線檢測(cè)實(shí)踐_第5頁(yè)
已閱讀5頁(yè),還剩65頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

6行人檢測(cè)實(shí)踐HISTORYOFDEVELOPMENTChapter06本章目錄數(shù)據(jù)采集與標(biāo)注01模型訓(xùn)練02模型轉(zhuǎn)換與量化03項(xiàng)目落地與部署046行人檢測(cè)實(shí)踐本章主要介紹的是基于目標(biāo)檢測(cè)的行人識(shí)別,行人檢測(cè)主要用于保障車(chē)輛盲區(qū)的安全,尤其是商用車(chē),由于車(chē)身龐大,存在較多盲區(qū),且車(chē)長(zhǎng)帶來(lái)的內(nèi)輪差也會(huì)讓行人不經(jīng)意間就進(jìn)入了車(chē)輛的危險(xiǎn)區(qū)域。行人檢測(cè)利用攝像頭照射車(chē)輛盲區(qū),一旦有行人進(jìn)入盲區(qū)則對(duì)司機(jī)和行人進(jìn)行提醒。整個(gè)項(xiàng)目主要流程如圖所示,本章節(jié)也會(huì)按照該順序依次講解整個(gè)流程。6.1數(shù)據(jù)集采集與標(biāo)注6.1.1素材采集數(shù)據(jù)來(lái)源主要有兩個(gè):1)公開(kāi)數(shù)據(jù)集行人檢測(cè)是一個(gè)應(yīng)用范圍比較廣的項(xiàng)目,行人標(biāo)簽也是各大數(shù)據(jù)集中常見(jiàn)的標(biāo)簽,前期沒(méi)有足夠的“財(cái)力”和“精力”去收集、標(biāo)注素材的情況下,使用公開(kāi)數(shù)據(jù)集訓(xùn)練是一個(gè)不錯(cuò)的辦法。除了深度學(xué)習(xí)界人盡皆知的coco、voc數(shù)據(jù)集,還有不少可以用來(lái)訓(xùn)練的帶有行人標(biāo)簽的公開(kāi)數(shù)據(jù)集,其實(shí)相比coco、voc數(shù)據(jù)集,這些數(shù)據(jù)集會(huì)更加符合本實(shí)踐項(xiàng)目的場(chǎng)景。數(shù)據(jù)集:CaltechPedestrianDetectionBenchmark存放地址:/Image_Datasets/CaltechPedestrians/數(shù)據(jù)集:TheCityscapesDataset存放地址:/數(shù)據(jù)集:TheEuroCityPersonsDataset存放地址:https://eurocity-dataset.tudelft.nl/2)自主采集如果有私家車(chē),并且裝了行車(chē)記錄儀,可以從行車(chē)記錄儀中導(dǎo)出視頻作為素材,如果沒(méi)有,那么在視頻網(wǎng)站搜索行車(chē)記錄儀,也能獲取到他人上傳的行車(chē)記錄儀視頻,挑選清晰度較高的視頻下載即可。6.1數(shù)據(jù)集采集與標(biāo)注針對(duì)以上幾點(diǎn)標(biāo)注要求,給出幾個(gè)標(biāo)注的示例。1)如下左圖人多雜亂,盡可能標(biāo)記人能識(shí)別的人,遠(yuǎn)處雜亂無(wú)法區(qū)分輪廓的人不做標(biāo)記。2)如上右圖左邊遠(yuǎn)處騎車(chē)可以辨別人形,需要標(biāo)記;右邊兩人雖有重疊但依舊可以單獨(dú)區(qū)分開(kāi),需要分開(kāi)標(biāo)記;中間的人手臂部分超出身體輪廓太多,僅標(biāo)記身體部分;中間偏右的黑色人群無(wú)法區(qū)分不做標(biāo)記。6.1數(shù)據(jù)集采集與標(biāo)注針對(duì)以上幾點(diǎn)標(biāo)注要求,給出幾個(gè)標(biāo)注的示例。3)如下左圖對(duì)于這類(lèi)已經(jīng)動(dòng)態(tài)模糊比較嚴(yán)重的情況,不需要標(biāo)記(圖中框只是展示下),否則會(huì)對(duì)訓(xùn)練造成干擾。4)如上右圖被護(hù)欄擋住的行人,如果某些角度隔著護(hù)欄依舊可以看到腿需要標(biāo)注全身,若護(hù)欄將腿完全擋住,則僅標(biāo)記身體露出的部分。6.1數(shù)據(jù)集采集與標(biāo)注針對(duì)以上幾點(diǎn)標(biāo)注要求,給出幾個(gè)標(biāo)注的示例。5)如下左圖人行道上的行人和騎車(chē)的人雖然被柱子和樹(shù)遮擋,但依舊可以辨別為人,需要標(biāo)記,但標(biāo)記露出的部分,不要將柱子標(biāo)記進(jìn)去;對(duì)于騎車(chē)的人不要刻意去標(biāo)記車(chē)的部分,把人的輪廓標(biāo)記全,框里面盡量是人的信息。6)如上右圖中間騎車(chē)帶人雖然有兩個(gè)人,但已經(jīng)完全重疊,只需要標(biāo)記一個(gè)即可。6.1數(shù)據(jù)集采集與標(biāo)注6.1.3小結(jié)素材是一切深度學(xué)習(xí)項(xiàng)目的基礎(chǔ),行人識(shí)別的項(xiàng)目在素材采集和標(biāo)注方面難度并不算太大。前期使用廣大公開(kāi)數(shù)據(jù)集的行人素材,也可以讓算法得到一個(gè)不錯(cuò)的效果,但倘若要把效果做到更好,在素材方面則需要用更多真實(shí)的場(chǎng)景進(jìn)行擴(kuò)充。如今市面上還有很多素材標(biāo)注公司,他們不光提供素材標(biāo)注的服務(wù),同時(shí)出售素材或者按需求采集素材,如果項(xiàng)目時(shí)間緊迫但有足夠的預(yù)算,找他們幫忙也是一個(gè)不錯(cuò)的選擇。6.2模型訓(xùn)練6.2.1模型設(shè)計(jì)思想本實(shí)驗(yàn)使用SSD的目標(biāo)檢測(cè)網(wǎng)絡(luò),在正式進(jìn)入項(xiàng)目之前,簡(jiǎn)單介紹下其設(shè)計(jì)思想。若想了解詳細(xì)細(xì)節(jié),可以參考論文《SSD:SingleShotMultiBoxDetector》。SSD是一種引人注目的目標(biāo)檢測(cè)結(jié)構(gòu),它結(jié)合了直接回歸框和分類(lèi)概率的方法,又利用大量的預(yù)選框來(lái)提升識(shí)別準(zhǔn)確度。ssd在預(yù)測(cè)階段不僅僅使用最后一層的特征映射,而是取出中間層的特征,在不同尺寸的特征映射上對(duì)結(jié)果進(jìn)行預(yù)測(cè),雖然增加運(yùn)算量,但使檢測(cè)結(jié)果具有更多個(gè)可能性,從而提升精度。如圖所示是ssd的模型,從圖中可以看出SSD的主干網(wǎng)絡(luò)為VGG網(wǎng)絡(luò),作者在VGG-16的基礎(chǔ)上,將FC6和FC7層轉(zhuǎn)化為卷積層,去掉了所有的Dropout層和FC8層,添加了Conv6,Conv7,Conv8和Conv9層。6.2模型訓(xùn)練為了從特征獲取預(yù)測(cè)結(jié)果,分別取出conv4的第三層卷積特征、fc7卷積特征,conv6的第二次卷積特征,conv7的第二次卷積特征,conv8的第二次卷積特征和conv9的第二次卷積特征,共六個(gè)特征層作為有效特征層如圖所示。對(duì)獲取到的每個(gè)有效特征層做一次num_anchorsx4的卷積和一次num_anchorsxnum_classes的卷積,num_anchors指的是該特征層每一個(gè)特征點(diǎn)所擁有的先驗(yàn)框數(shù)量。上述提到的六個(gè)特征層,每個(gè)特征層的每個(gè)特征點(diǎn)對(duì)應(yīng)的先驗(yàn)框數(shù)量分別為4、6、6、6、4、4。其中num_anchorsx4的卷積用于預(yù)測(cè)該特征層上每一個(gè)網(wǎng)格點(diǎn)上每一個(gè)先驗(yàn)框的變化情況;num_anchorsxnum_classes的卷積用于預(yù)測(cè)該特征層上每一個(gè)網(wǎng)格點(diǎn)上每一個(gè)預(yù)測(cè)對(duì)應(yīng)的種類(lèi)。利用num_anchorsx4的卷積對(duì)每一個(gè)有效特征層對(duì)應(yīng)的先驗(yàn)框進(jìn)行調(diào)整可以獲得預(yù)測(cè)框。6.2模型訓(xùn)練SSD解碼過(guò)程可以分為兩部分:(1)將每個(gè)網(wǎng)格的中心點(diǎn)加上它對(duì)應(yīng)的x_offset和y_offset,加完之后的記過(guò)就是預(yù)測(cè)框的中心;(2)利用h和w調(diào)整先驗(yàn)框獲得預(yù)測(cè)框的寬和高。獲得預(yù)測(cè)框的中心和寬高時(shí),便可以在圖片上繪制預(yù)測(cè)框了。但是想要獲得最終的預(yù)測(cè)結(jié)果,還要對(duì)每一個(gè)預(yù)測(cè)框在進(jìn)行得分排序與非極大抑制篩選,這一部分基本上時(shí)目標(biāo)檢測(cè)領(lǐng)域通用的部分。實(shí)現(xiàn)代碼見(jiàn)代碼清單6-3,這里僅展示部分代碼importnumpyasnpimporttorchfromtorchimportnnfromtorchvision.opsimportnmsclassBBoxUtility(object):

def__init__(self,num_classes):

self.num_classes=num_classes

...6.2模型訓(xùn)練6.2.2數(shù)據(jù)集制作數(shù)據(jù)集制作采取VOC格式,在project下新建目錄VOCdevkit,整個(gè)數(shù)據(jù)集的目錄結(jié)構(gòu)如下,將標(biāo)簽文件放在VOCdevkit文件夾下VOC_xxx下的Annotation中,將.jpg格式的圖片放在JPEGImages中。VOCdevkit|--VOC_xxx|--JPEGImages存放圖片|--Annotations存放xml標(biāo)注文件|--ImageSets|--Main存放不帶后綴的文件名列表|--subdir2...|--dir2...在完成數(shù)據(jù)集的擺放后,需對(duì)數(shù)據(jù)集進(jìn)行下一步處理,目的是為了獲得訓(xùn)練用的_xxx_train.txt和_xxx_val.txt,在工程下新建voc_annotation.py,腳本見(jiàn)代碼清單6-46.2模型訓(xùn)練6.2.3訓(xùn)練如果訓(xùn)練過(guò)程中存在中斷訓(xùn)練的操作,可以將model_path設(shè)置成logs文件夾下的權(quán)值文件,將已經(jīng)訓(xùn)練了一部分的權(quán)值再次載入。同時(shí)修改下方的凍結(jié)階段或者解凍階段的參數(shù),來(lái)保證模型epoch的連續(xù)性。當(dāng)model_path=''的時(shí)候不加載整個(gè)模型的權(quán)值。此處使用的是整個(gè)模型的權(quán)重,因此是在train.py進(jìn)行加載的,下面的pretrain不影響此處的權(quán)值加載。如果想要讓模型從主干的預(yù)訓(xùn)練權(quán)值開(kāi)始訓(xùn)練,則設(shè)置model_path='',下面的pretrain=True,此時(shí)僅加載主干。如果想要讓模型從0開(kāi)始訓(xùn)練,則設(shè)置model_path='',下面的pretrain=Fasle,F(xiàn)reeze_Train=Fasle,此時(shí)從0開(kāi)始訓(xùn)練,且沒(méi)有凍結(jié)主干的過(guò)程。一般來(lái)講,從0開(kāi)始訓(xùn)練效果會(huì)很差,因?yàn)闄?quán)值太過(guò)隨機(jī),特征提取效果不明顯。網(wǎng)絡(luò)一般不從0開(kāi)始訓(xùn)練,至少會(huì)使用主干部分的權(quán)值,有些論文提到可以不用預(yù)訓(xùn)練,主要原因是他們數(shù)據(jù)集較大且調(diào)參能力優(yōu)秀。如果一定要訓(xùn)練網(wǎng)絡(luò)的主干部分,可以了解imagenet數(shù)據(jù)集,首先訓(xùn)練分類(lèi)模型,分類(lèi)模型的主干部分和該模型通用,基于此進(jìn)行訓(xùn)練。6.2模型訓(xùn)練6.2.3訓(xùn)練訓(xùn)練分為兩個(gè)階段,分別時(shí)凍結(jié)階段和解凍階段,顯存不足與數(shù)據(jù)集的大小無(wú)關(guān),提示顯存不足請(qǐng)調(diào)小batch_size收到BatchNorm層影響,batch_size最小為2,不能為1。凍結(jié)階段訓(xùn)練參數(shù),此時(shí)模型的主干被凍結(jié)了,特征提取網(wǎng)絡(luò)不發(fā)生改變,占用的顯存較小進(jìn)隊(duì)網(wǎng)絡(luò)進(jìn)行微調(diào)。解凍階段訓(xùn)練參數(shù),此時(shí)模型的主干不被凍結(jié)了,特征提取網(wǎng)絡(luò)會(huì)發(fā)生改變,占用的顯存較大,網(wǎng)絡(luò)所有的參數(shù)都會(huì)發(fā)生改變。Freeze_Train設(shè)為T(mén)rue,也就是默認(rèn)先凍結(jié)主干訓(xùn)練后解凍訓(xùn)練。num_workers用于設(shè)置是否使用多線程讀取數(shù)據(jù),開(kāi)啟后會(huì)加快數(shù)據(jù)讀取速度,但是會(huì)占用更多內(nèi)存,內(nèi)存較小的電腦可以設(shè)置為2或0。train_annotation_path和val_annotation_path是獲取圖片和標(biāo)簽的路徑。6.2模型訓(xùn)練6.2.3訓(xùn)練運(yùn)行train.py文件,如下左圖可以觀察到已經(jīng)開(kāi)始訓(xùn)練模型。訓(xùn)練完成之后可以觀察到在log文件下,存取了訓(xùn)練過(guò)程中的權(quán)值文件,如上右圖所示。6.2模型訓(xùn)練6.2.4預(yù)測(cè)和評(píng)估訓(xùn)練結(jié)果預(yù)測(cè)需要用到兩個(gè)文件,分別是ssd.py和predict.py,代碼詳見(jiàn)本書(shū)附帶資料,和之前一樣,需要去ssd.py里面修改model_path以及classes_path為自己對(duì)應(yīng)的訓(xùn)練權(quán)重文件和目標(biāo)識(shí)別種類(lèi)。在此我們選擇上一步訓(xùn)練模型表現(xiàn)最好的權(quán)重,對(duì)應(yīng)設(shè)置如下:"model_path":'logs/best_epoch_weights.pth',"classes_path":'model_data/cls_classes.txt',predict.py代碼如下,該代碼將單張圖片預(yù)測(cè)、攝像頭檢測(cè)、FPS檢測(cè)和目錄遍歷檢測(cè)多功能融為一體,具體測(cè)試模式由參數(shù)mode決定,當(dāng)mode為predict時(shí)表示單張圖片預(yù)測(cè);為video表示視頻檢測(cè),可調(diào)用攝像頭或者視頻進(jìn)行檢測(cè);為fps表示測(cè)試fps,使用的圖片是img里的street.jpg;為dir_predict表示遍歷文件夾進(jìn)行檢測(cè)并保存,默認(rèn)遍歷img文件夾,保存img_out文件夾,為export_onnx表示將模型導(dǎo)出為onnx。6.2模型訓(xùn)練6.2.4預(yù)測(cè)和評(píng)估在終端輸入pythonpredict.py運(yùn)行predict.py。運(yùn)行時(shí)要求輸入待檢測(cè)圖片的路徑,在這里我們把測(cè)試圖片test.jpg放入了img文件夾下,所以這里輸入的路徑為img/test.jpg,預(yù)測(cè)完成之后會(huì)將結(jié)果以img.img(如圖所示)形式保存在工程根目錄下。6.2模型訓(xùn)練6.2.4預(yù)測(cè)和評(píng)估評(píng)估需要用到get_map.py文件,同樣需要設(shè)置model_path和classes_path,設(shè)置方式和預(yù)測(cè)時(shí)的設(shè)置相同。隨后便可以在終端輸入pythonget_map.py運(yùn)行g(shù)et_map.py文件,運(yùn)行時(shí)在終端的顯示如圖所示,從圖中可以看出此模型預(yù)測(cè)出行人這一類(lèi)別時(shí)的AP值為91.23%,在門(mén)限值為0.5的情況下,F(xiàn)1值為0.85,召回率為73.81%,精確度值為99.20%。6.2模型訓(xùn)練6.2.4預(yù)測(cè)和評(píng)估不同門(mén)限值對(duì)應(yīng)的F1值、召回率和精確度也對(duì)應(yīng)繪制成了圖片如圖所示,保存至map_out文件夾中。6.3模型轉(zhuǎn)換與量化6.3.1模型轉(zhuǎn)換ONNX(OpenNeuralNetworkExchange)是一種開(kāi)放的深度學(xué)習(xí)模型表示格式,它旨在提供一個(gè)通用的格式,用于在不同的深度學(xué)習(xí)框架之間無(wú)縫地交換模型。所以為了更好完成后續(xù)的部署工作,可將模型轉(zhuǎn)換為onnx格式。具體是在predict.py中調(diào)用了ssd.py的方法convert_to_onnx,其實(shí)現(xiàn)代碼見(jiàn)代碼清單6-7,這里僅展示部分代碼。defconvert_to_onnx(self,simplify,model_path):importonnxself.generate(onnx=True)

im=torch.zeros(1,3,*self.input_shape).to('cpu')#imagesize(1,3,512,512)BCHWinput_layer_names=["images"]output_layer_names=["output"]

#Exportthemodelprint(f'Startingexportwithonnx{onnx.__version__}.')torch.onnx.export(,調(diào)用時(shí),我們只需在predict.py文件里將mode設(shè)置為export_onnx即可,隨后保存predict.py文件,運(yùn)行可以發(fā)現(xiàn)在model_data文件夾下生成了對(duì)應(yīng)的model.onnx文件。6.3模型轉(zhuǎn)換與量化6.3.2模型量化上面的所有步驟完成后,其實(shí)如果項(xiàng)目是用在PC端的,那么這個(gè)權(quán)重已經(jīng)可以落地了,但是本章節(jié)的最終目標(biāo)是將它在AIBOX中運(yùn)行,所以針對(duì)AIBOX的環(huán)境,需要對(duì)模型文件進(jìn)行量化。模型量化所需要用到的rknn-toolkit的container環(huán)境詳見(jiàn)3.6章節(jié)。首先進(jìn)入rknn-toolkit新建img文件夾存放一批素材用于量化,素材需要盡可能覆蓋所有可能出現(xiàn)的場(chǎng)景,將它們的尺寸調(diào)整為網(wǎng)絡(luò)輸入的大小,并生成文件列表,程序見(jiàn)代碼清單6-8,這里僅展示部分代碼。defmain():img_path="./%s"%(img_flod)out_path="./%s%d_%d"%(img_flod,img_w,img_h)ifnotos.path.exists(out_path):os.mkdir(out_path)txt_file=open("./%s%d_%d.txt"%(img_flod,img_w,img_h),"w")......6.3模型轉(zhuǎn)換與量化6.3.3小結(jié)模型訓(xùn)練階段會(huì)遇到的各個(gè)步驟,也是深度學(xué)習(xí)項(xiàng)目中的重要環(huán)節(jié)之一,模型的訓(xùn)練結(jié)果很大程度上會(huì)直接影響到項(xiàng)目落地后的用戶體驗(yàn)。在經(jīng)歷過(guò)不同硬件設(shè)備開(kāi)發(fā)以后就會(huì)發(fā)現(xiàn),量化也是整個(gè)過(guò)程中必不可少的一環(huán),因?yàn)榱炕诩铀偻评淼耐瑫r(shí),也是對(duì)硬件環(huán)境的一種適配。其實(shí)即便是落地在PC上的項(xiàng)目,原模型可以直接運(yùn)行的情況下,考慮到性能也會(huì)使用例如tensorRT等方式對(duì)模型進(jìn)行量化。6.4項(xiàng)目落地與部署6.4.1項(xiàng)目工程工程目錄結(jié)構(gòu)如下otest|--sdk_rk1808相關(guān)sdk|--src源碼 |--otest主模塊程序 |--assets模型文件 |--test測(cè)試程序|--build_emv.cmake編譯環(huán)境配置,供CMakeLists調(diào)用|--CMakeLists.txt用于生成makefile,各源碼模塊中也有對(duì)應(yīng)文件,逐級(jí)調(diào)用6.4項(xiàng)目落地與部署源碼讀者可以直接從隨書(shū)的資源中獲取,本章節(jié)主要是梳理源碼結(jié)構(gòu)如圖所示,對(duì)幾個(gè)重要的模塊進(jìn)行講解,幫助讀者更快地理解代碼。視頻源:獲取攝像頭數(shù)據(jù),用測(cè)試模塊所配置的回調(diào)函數(shù),向測(cè)試模塊回調(diào)傳輸圖像數(shù)據(jù)。測(cè)試模塊:向視頻源配置一個(gè)用于傳輸圖像的回調(diào)函數(shù),向主模塊配置一個(gè)用于傳輸推理結(jié)果的回調(diào)函數(shù)。將視頻源回調(diào)來(lái)的圖像數(shù)據(jù)傳給主模塊推理,并將主模塊回調(diào)來(lái)的推理結(jié)果提供給繪圖模塊。主模塊:接收?qǐng)D像數(shù)據(jù),用測(cè)試模塊所配置的回調(diào)函數(shù),向測(cè)試模塊回調(diào)推理結(jié)果。主模塊是另起線程進(jìn)行異步推理,因?yàn)橐坏┩评淼膸实陀谝曨l源的幀率(25FPS)會(huì)導(dǎo)致阻塞。繪圖:繪圖模塊將測(cè)試模塊傳輸過(guò)來(lái)的推理結(jié)果,繪制在畫(huà)面上用于展示。6.4項(xiàng)目落地與部署6.4.2源碼解析1)主模塊對(duì)模塊進(jìn)行初始化,代碼見(jiàn)代碼清單6-9,這里僅展示部分代碼。if(item.image_header.width>0anditem.image_header.height>0){///默認(rèn)值constchar*default_model="assets/model.rknn";constchar*default_prior_box="assets/otest_model_box_priors.txt";constchar*default_label_list="assets/otest_model_labels_list.txt";在初始化模塊中,首先從傳入的ini配置文件中讀取模型文件,若沒(méi)有配置這里直接給予了一個(gè)默認(rèn)值。初始化推理模塊后,程序可以直接從模型文件里讀取模型的輸入尺寸,然后利用初始化傳入的視頻源尺寸和模型的尺寸初始化rga。6.4項(xiàng)目落地與部署6.4.2源碼解析1)主模塊對(duì)rga進(jìn)行初始化,代碼見(jiàn)代碼清單6-9,這里僅展示部分代碼。boolret=false;ac::rga::SrcConfigsrc;ac::rga::DstConfigdst;autork_format=Convert2RkFormat(origin_header_.format);if(rk_format>=0){

///原始圖片信息src.width=origin_header_.width;src.height=origin_header_.height;src.format=ac::rga::RkFormat(rk_format);在對(duì)rga初始化的過(guò)程中,需要指定原始圖像的信息、原始圖像中需要轉(zhuǎn)換的部分、目標(biāo)圖像的信息,也就是告訴rga,需要從一種圖轉(zhuǎn)換成另一種圖。6.4項(xiàng)目落地與部署6.4.2源碼解析1)主模塊更新最新圖像,代碼見(jiàn)代碼清單6-9,這里僅展示部分代碼。boolret=false;if(valid_flag_and(callback_.method!=nullptr)and(buffer_!=nullptr)and(notbuffer_->IsFull())and(data!=nullptr)and(size>0)){constauto&prev_pairs=rga_prev_->RgaBlit(reinterpret_cast<constuint8_t*>(data),size,true);......外部調(diào)用update函數(shù),為主模塊更新最新一幀的圖像經(jīng)過(guò)rga的轉(zhuǎn)換送入緩沖區(qū)。取名更新也是因?yàn)?,外部送入圖片和主模塊的推理是異步操作,中間用一個(gè)單項(xiàng)緩沖區(qū)連接,外部所傳入的圖片會(huì)不斷更新緩沖區(qū),內(nèi)部在推理完成后會(huì)從緩沖區(qū)取數(shù)據(jù)。當(dāng)處理的幀率低于視頻幀率時(shí),外部送入的圖片會(huì)不斷更新緩沖區(qū)的圖片,從而保證每次推理的圖片都是最近的視頻畫(huà)面。6.4項(xiàng)目落地與部署6.4.2源碼解析1)主模塊子線程循環(huán)推理,代碼見(jiàn)代碼清單6-9,這里僅展示部分代碼。std::vector<TRectEx>boxes;while(true){///這一行代碼可能阻塞constauto&pairs=buffer_->Read();constauto&img=std::get<0>(pairs);constauto&callback=std::get<1>(pairs);.........run函數(shù)循環(huán)運(yùn)行在子線程中,直到反初始化或者析構(gòu)時(shí)收到停止信號(hào)才會(huì)退出循環(huán)。該函數(shù)主要功能就是從緩沖區(qū)中取出圖片進(jìn)行推理,并將推理的結(jié)果,通過(guò)外部傳入的回調(diào)函數(shù)傳遞出去。6.4項(xiàng)目落地與部署6.4.2源碼解析2)推理模塊推理模塊的代碼在ssd_detector.cpp中,主要工作就是調(diào)用rk的接口進(jìn)行圖片的推理,并對(duì)推理結(jié)果做后處理后輸出。這部分其實(shí)就是將PC上的推理代碼,將Python翻譯成C++即可,讀者可以對(duì)照著量化章節(jié)的代碼閱讀源碼,這里不再贅述。6.4項(xiàng)目落地與部署6.4.3部署工程開(kāi)發(fā)環(huán)境的搭建可以參考3.6.WSL安裝,以下的全部指令都是在WSL下運(yùn)行。新建build文件夾,并進(jìn)入到build中,執(zhí)行cmake命令。cmake..當(dāng)看到如下打印時(shí)則表明執(zhí)行成功。--Configuringdone--Generatingdone執(zhí)行編譯makeinstall如果沒(méi)有報(bào)錯(cuò)并且打印了一連串的--Installing:信息,則表示執(zhí)行成功。6.4項(xiàng)目落地與部署6.4.3部署工程至此在build下會(huì)生成一個(gè)install的目錄,結(jié)構(gòu)如下:install |--otest |--assets模型文件,從src/otest/assets中拷貝過(guò)來(lái)的 |--otest_model_box_priors.txt |--otest_model_labels_list.txt |--otest_model.rknn |--include主模塊庫(kù)的頭文件,從src/otest中拷貝過(guò)來(lái)的 |--otest_proc.h |--lib主模塊的庫(kù)文件和相關(guān)聯(lián)的一些庫(kù) |--libotest_proc.so |--libpredictor.so |--... |--test_test可執(zhí)行文件,測(cè)試模塊編譯出來(lái)的6.4項(xiàng)目落地與部署6.4.3部署工程進(jìn)入到install文件及下,將程序推入AIBOX。adbpushotest/home如果是通過(guò)網(wǎng)線鏈接AIBOX也可以直接拖拽進(jìn)去。進(jìn)入到AIBOX中,進(jìn)入剛才推送程序的路徑,這里是/home/otest,對(duì)可執(zhí)行程序賦權(quán)限后執(zhí)行chmod755test_test./test_test程序開(kāi)始運(yùn)行,并打印出如下圖所示的單張圖片的推理速度、當(dāng)前的推理幀率、視頻流幀率。6.4項(xiàng)目落地與部署6.4.3部署工程程序運(yùn)行結(jié)果如下圖所示。6.4項(xiàng)目落地與部署6.4.4小結(jié)至此整個(gè)行人識(shí)別實(shí)驗(yàn)全部完成,如果讀者照著這個(gè)流程走完一遍,不妨運(yùn)行起程序,拿起攝像頭對(duì)準(zhǔn)身邊的那個(gè)人,看看他是否被框中顯示在屏幕上。其實(shí)所有的深度學(xué)習(xí)落地項(xiàng)目都會(huì)經(jīng)歷這幾個(gè)步驟,更進(jìn)一步的,可以在落地的程序上對(duì)模型的輸出結(jié)果按照個(gè)人的需求做其他的邏輯,比如限定行人的遠(yuǎn)近、范圍,這些就有待讀者發(fā)散思維進(jìn)行探索了。6.5課后習(xí)題

1)什么是行人檢測(cè)?2)行人檢測(cè)有哪些方法?3)什么是SSD算法?7車(chē)道線檢測(cè)實(shí)踐LANELINEINSPECTIONPRACTICEChapter07本章目錄數(shù)據(jù)采集與標(biāo)注01環(huán)境部署02模型訓(xùn)練03模型的量化04項(xiàng)目部署與落地05本章總體介紹車(chē)道線檢測(cè)是輔助駕駛中必不可少的一項(xiàng),它的主要目標(biāo)是通過(guò)計(jì)算機(jī)視覺(jué)和圖像處理技術(shù),從道路圖像中精確提取出車(chē)道線的位置和形狀信息。這些提取到的車(chē)道線信息可以用于車(chē)道保持、車(chē)道偏離預(yù)警、自動(dòng)駕駛路徑規(guī)劃等應(yīng)用。通過(guò)實(shí)現(xiàn)準(zhǔn)確的車(chē)道線檢測(cè)系統(tǒng),可以提高駕駛安全性,減少交通事故的發(fā)生,并為駕駛員提供更好的駕駛體驗(yàn)?;谝曈X(jué)的車(chē)道線檢測(cè)方法可以分為:傳統(tǒng)圖像方法和深度學(xué)習(xí)方法兩類(lèi)。其中傳統(tǒng)的圖像檢測(cè)方法可以通過(guò)邊緣檢測(cè)、濾波或是顏色空間的車(chē)道線檢測(cè)等方式得到車(chē)道線區(qū)域,再結(jié)合相關(guān)圖像檢測(cè)算法實(shí)現(xiàn)車(chē)道線檢測(cè)。但面對(duì)環(huán)境明顯變化的場(chǎng)景并不能很好的檢測(cè),工作量大且魯棒性差。而深度學(xué)習(xí)的方法有較好的魯棒性,且準(zhǔn)確率更高。它大致有基于分類(lèi)和目標(biāo)檢測(cè)的方法和基于端到端圖像分割的方法等相關(guān)車(chē)道線檢測(cè)方法。而本書(shū)的車(chē)道線檢測(cè)采用的是UNet的語(yǔ)義分割網(wǎng)絡(luò)。本章總體介紹車(chē)道線檢測(cè)算法的流程如下圖所示。主要思路是:通過(guò)素材采集獲取訓(xùn)練要用的原始數(shù)據(jù),再經(jīng)過(guò)標(biāo)注與生成標(biāo)簽圖兩個(gè)步驟將原始數(shù)據(jù)轉(zhuǎn)化為可以被學(xué)習(xí)訓(xùn)練的素材,然后通過(guò)模型訓(xùn)練得到相應(yīng)模型,最后經(jīng)過(guò)模型量化、轉(zhuǎn)換和部署等步驟將模型優(yōu)化并轉(zhuǎn)化成可被嵌入式平臺(tái)運(yùn)行的程序。車(chē)道線項(xiàng)目流程圖7.1數(shù)據(jù)集采集與標(biāo)注素材的獲取一般有兩種途徑,一種是自己利用相關(guān)設(shè)備如行車(chē)記錄儀獲取,另一種是通過(guò)下載公開(kāi)的數(shù)據(jù)集獲取。車(chē)道線檢測(cè)相關(guān)的數(shù)據(jù)集有TuSimple、CULane、CurveLanes、BDD100k等。素材標(biāo)注使用Labelme工具,本項(xiàng)目提供的例程的“數(shù)據(jù)集”文件夾內(nèi)已經(jīng)提供原圖與對(duì)應(yīng)標(biāo)注文件,車(chē)道線識(shí)別項(xiàng)目對(duì)于車(chē)道線的標(biāo)注有以下幾點(diǎn)要求:需要標(biāo)注的內(nèi)容為圖片中人眼可以識(shí)別的車(chē)道線,包括實(shí)線、虛線、白線和黃線。對(duì)于雙線的車(chē)道線,兩條分開(kāi)標(biāo)注。對(duì)于虛線中間沒(méi)有車(chē)道線的部分進(jìn)行補(bǔ)足。對(duì)于沒(méi)有車(chē)道線的圖片,直接跳過(guò),不做處理。7.1數(shù)據(jù)集采集與標(biāo)注下圖是按以上要求所給出的標(biāo)注示例。車(chē)道線項(xiàng)目流程圖相較于分類(lèi)和目標(biāo)檢測(cè),語(yǔ)義分割的素材多了一步從標(biāo)簽文件到分割圖的轉(zhuǎn)換。因?yàn)檎Z(yǔ)義分割是像素級(jí)別的推理,每個(gè)像素點(diǎn)都有其對(duì)應(yīng)的標(biāo)簽,因此在訓(xùn)練中,它的標(biāo)簽就是和它等大的一張分割圖。7.2環(huán)境部署深度學(xué)習(xí)的框架除了PyTorch外還有TensorFlow框架,本項(xiàng)目在TensorFlow框架下訓(xùn)練,所以在進(jìn)行本章之前需要進(jìn)行TensorFlow環(huán)境的搭建,其環(huán)境總體搭建步驟如下:(1)在Ubuntu系統(tǒng)(WSL2、虛擬機(jī)或多系統(tǒng))下搭建TensorFlow環(huán)境的docker(2)在docker環(huán)境內(nèi)安裝本項(xiàng)目的相關(guān)庫(kù)當(dāng)然,若有需求也可以在創(chuàng)建一個(gè)docker容器后,在其內(nèi)部建立conda的虛擬環(huán)境,然后安裝本項(xiàng)目需要的TensorFlow環(huán)境與相關(guān)庫(kù)。7.2環(huán)境部署7.2.1docker環(huán)境部署針對(duì)不同的顯卡,需要搭建不同的環(huán)境。本項(xiàng)目以30系顯卡為例進(jìn)行環(huán)境搭建介紹,30系顯卡需要CUDA11.1,可以使用NVIDIA提供的docker鏡像—NVIDIA-TensorFlow。如果沒(méi)有安裝過(guò)NVIDIA-docker,首先要進(jìn)行NVIDIA-docker的安裝,它是使用上述鏡像的前提,如下是安裝步驟:$distribution=$(./etc/os-release;echo$ID$VERSION_ID)$curl-s-Lhttps://nvidia.github.io/nvidia-docker/gpgkey|sudoapt-keyadd-$curl-s-Lhttps://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list|sudotee/etc/apt/sources.list.d/nvidia-docker.list$sudoapt-getupdate$sudoapt-getinstall-ynvidia-docker27.2環(huán)境部署7.2.1docker環(huán)境部署接著進(jìn)行NVIDIA-TensorFlow的docker環(huán)境部署#拉取鏡像nvidia-dockerpullnvcr.io/nvidia/tensorflow:20.10-tf1-py3#創(chuàng)建容器nvidia-dockerrun-d-it-p10022:22-p10500:5000-v/home:/home--namenvidia_tensorflownvcr.io/nvidia/tensorflow:20.10-tf1-py3#-p代表了端口的映射-p宿主機(jī)端口:容器端口這里預(yù)留了22可以用于ssh登錄5000后面會(huì)用到#進(jìn)入容器nvidia-dockerexec-itnvidia_tensorflow/bin/bash安裝TensorFlowwheel的索引pipinstallnvidia-index用官方提供的命令安裝依賴的包pipinstallnvidia-tensorflow[horovod]7.2環(huán)境部署7.2.1docker環(huán)境部署下載完成后進(jìn)入對(duì)應(yīng)的目錄,因?yàn)檫@些依賴包安裝存在一定順序,所以按以下順序執(zhí)行指令。若覺(jué)得一條一條執(zhí)行繁瑣,可以建一個(gè)后綴名為.sh的shell腳本文件,將下列指令復(fù)制進(jìn)文件后執(zhí)行sh文件名.sh指令提高效率。pipinstallgoogle_pasta-0.2.0-py3-none-any.whlpipinstallnvidia_cublas-4-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cuda_cupti-11.1.69-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cuda_nvcc-11.1.74-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cuda_cupti-11.1.69-cp36-cp36m-linux_x86_64.whlnvidia_cuda_nvcc-11.1.74-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cuda_nvrtc-11.1.74-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cuda_runtime-11.1.74-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cudnn-8.0.70-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cufft-4-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_curand-4-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cusolver-4-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_cusparse-75-cp36-cp36m-linux_x86_64.whl7.2環(huán)境部署7.2.1docker環(huán)境部署pipinstallnvidia_dali_cuda110-0.26.0-1608709-py3-none-manylinux2014_x86_64.whlpipinstallnvidia_dali_nvtf_plugin-0.26.0+nv20.10-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_nccl-2.7.8-cp36-cp36m-linux_x86_64.whlpipinstallnvidia_tensorboard-1.15.0+nv20.10-py3-none-any.whlpipinstallnvidia_tensorrt--cp36-none-linux_x86_64.whlpipinstallnvidia_tensorflow-1.15.4+nv20.10-cp36-cp36m-linux_x86_64.whlpipinstalltensorflow_estimator-1.15.1-py2.py3-none-any.whlpipinstallnvidia_horovod-0.20.0+nv20.10-cp36-cp36m-linux_x86_64.whl此外本項(xiàng)目還需要用到以下幾個(gè)Python包,讀者可以使用以下命令安裝或者直接使用項(xiàng)目中的requirements.txt導(dǎo)入。pipinstallscipy==1.1.0-i/simplepipinstallscikit-learn-i/simplepipinstalltqdm-i/simple7.2環(huán)境部署7.2.2安裝TensorFlowObjectDetectionAPITensorFlowObjectDetectionAPI是一個(gè)基于TensorFlow構(gòu)建的開(kāi)源框架,用于目標(biāo)檢測(cè)任務(wù)。它提供了豐富的目標(biāo)檢測(cè)模型,其中包括了一些經(jīng)典的模型架構(gòu),如FasterR-CNN、SSD、Mask-RCNN等,具體可見(jiàn)TensorFlow的GitHub的model倉(cāng)庫(kù)。7.3模型訓(xùn)練項(xiàng)目文件夾為project,項(xiàng)目目錄如圖?!安渴鸫a”文件夾包含的是模型部署的代碼,“權(quán)重轉(zhuǎn)換與量化”包含的是模型量化轉(zhuǎn)換的相關(guān)代碼,本節(jié)介紹“訓(xùn)練代碼”和“數(shù)據(jù)集”文件夾部分,實(shí)現(xiàn)數(shù)據(jù)集制作與模型訓(xùn)練與保存。標(biāo)簽轉(zhuǎn)換程序、數(shù)據(jù)集制作程序和模型及訓(xùn)練程序這三部分對(duì)應(yīng)在“訓(xùn)練代碼”文件夾下,分別對(duì)應(yīng)的是ldw_draw.py、make_dataset.py和剩下其他程序,目錄結(jié)構(gòu)如圖所示。models內(nèi)存有模型程序,builders內(nèi)存有模型接口程序,utils是相關(guān)的輔助函數(shù)集合,train.py是模型訓(xùn)練程序,ckpt2pb.py是將訓(xùn)練完成后的ckpt文件轉(zhuǎn)換為pb文件的程序,eval.py是評(píng)估程序用訓(xùn)練過(guò)程中保存的pb文件進(jìn)行推理。項(xiàng)目目錄結(jié)構(gòu)traincode目錄結(jié)構(gòu)7.3模型訓(xùn)練7.3.1模型設(shè)計(jì)思想本項(xiàng)目使用UNet的語(yǔ)義分割網(wǎng)絡(luò),從圖中可以看到,其形狀類(lèi)似字母“U”所以被稱為UNet。參考論文《U-Net:ConvolutionalNetworksforBiomedicalImageSegmentation》,起初UNet被用于醫(yī)學(xué)領(lǐng)域,而后UNet憑借著突出的效果被廣泛應(yīng)用。UNet本質(zhì)上是一個(gè)編碼器和解碼器的結(jié)構(gòu),左邊是特征提取,右邊是采樣恢復(fù)原始分辨率,中間采用跳層鏈接的方式將位置信息和語(yǔ)義信息融合。UNet網(wǎng)絡(luò)結(jié)構(gòu)7.3模型訓(xùn)練7.3.2標(biāo)簽轉(zhuǎn)換7.1節(jié)中標(biāo)注完的素材僅僅是多了一個(gè)標(biāo)簽文件,保存了所標(biāo)注的那些多邊形的類(lèi)別和位置。而實(shí)際在訓(xùn)練中用到的是像素級(jí)別的標(biāo)簽,也就是對(duì)于原圖上每個(gè)像素點(diǎn),都會(huì)有一個(gè)對(duì)應(yīng)了類(lèi)別的標(biāo)簽,這個(gè)時(shí)候就需要利用標(biāo)注文件來(lái)生成分割用的標(biāo)簽圖。本項(xiàng)目提供的標(biāo)簽轉(zhuǎn)換程序?yàn)閘dw_draw.py。詳見(jiàn)代碼清單7-1。將對(duì)應(yīng)腳本—ldw_draw.sh中的Path參數(shù)配置成讀者自己電腦上的標(biāo)注圖片的所在目錄,執(zhí)行腳本,結(jié)果如下。image中存放原始圖片;json中存放標(biāo)注文件;roadmap中存放分割標(biāo)簽圖片,轉(zhuǎn)換后的目錄結(jié)構(gòu)和圖片經(jīng)過(guò)轉(zhuǎn)換后的結(jié)果如圖所示。轉(zhuǎn)換后的目錄結(jié)構(gòu)轉(zhuǎn)換前后對(duì)比,原圖(左),轉(zhuǎn)換后圖(右)7.3模型訓(xùn)練7.3.3數(shù)據(jù)集制作在project下的“數(shù)據(jù)集”目錄中放置數(shù)據(jù)集,在“數(shù)據(jù)集”下再建一層子目錄,用于數(shù)據(jù)集分類(lèi)。這里就以type1、type2為例,將轉(zhuǎn)化完成后的素材文件夾放入子文件夾中。對(duì)于本項(xiàng)目提供的例程,需要將“數(shù)據(jù)集”文件夾內(nèi)data文件夾放入“訓(xùn)練代碼”文件夾內(nèi)make_dataset.py所在目錄下,或者讀者可以修改make_dataset.py的相關(guān)路徑。詳見(jiàn)代碼清單7-2。將腳本—make_datase.sh中的dataset參數(shù)配置成data下的子目錄,樣例數(shù)據(jù)集中有兩個(gè)子目錄type1、type2,存有上一小節(jié)所轉(zhuǎn)換的相關(guān)素材。input_height和input_width根據(jù)實(shí)際情況配置,所演示的項(xiàng)目中是256*128。修改make_datase.sh中的type1、type2后分別執(zhí)行。完成后其目錄結(jié)構(gòu)如圖所示,新增兩個(gè)文件夾。數(shù)據(jù)集制作后的目錄結(jié)構(gòu)7.3模型訓(xùn)練7.3.3數(shù)據(jù)集制作新增文件夾的目錄結(jié)構(gòu)如圖所示,test:測(cè)試集圖片;test_label:測(cè)試機(jī)標(biāo)簽;train:訓(xùn)練集圖片;train_label:訓(xùn)練集標(biāo)簽;val:驗(yàn)證集圖片;val_label:驗(yàn)證集標(biāo)簽。同時(shí),處理完的素材文件夾會(huì)被移動(dòng)到data/done下面,以便于未來(lái)多次制作數(shù)據(jù)集時(shí)不會(huì)重復(fù)操作。新增文件夾的目錄結(jié)構(gòu)7.3模型訓(xùn)練7.3.4網(wǎng)絡(luò)搭建在“訓(xùn)練代碼”文件夾下models目錄中放置需要搭建的模型文件,這里就以上面提到的UNet為例。本項(xiàng)目提供的例程在models下有一個(gè)UNet.py程序。詳見(jiàn)代碼清單7-3。在traincode下builders目錄,本項(xiàng)目提供一個(gè)model_builder.py程序作為創(chuàng)建模型總的接口,用于不同類(lèi)型模型的選擇和搭建。importsys,osimporttensorflowastfimportsubprocess#存放模型的目錄sys.path.append("models")#載入模型的搭建函數(shù)frommodels.UNetimportbuild_unet#自定義模型名稱SUPPORTED_MODELS=["UNet"]#統(tǒng)一的模型搭建接口defbuild_model(model_name,net_input,num_classes,is_training=False):print("Preparingthemodel...") ifmodel_namenotinSUPPORTED_MODELS: raiseValueError("Themodelyouselectedisnotsupported.Thefollowingmodelsarecurrentlysupported:{0}".format(SUPPORTED_MODELS)) network=None #根據(jù)模型名稱調(diào)用對(duì)應(yīng)的模型搭建函數(shù)

ifmodel_name=="UNet": network=build_unet(net_input,num_classes,is_training=is_training) else: raiseValueError("Error:themodel%disnotavailable.Trycheckingwhichmodelsareavailableusingthecommandpythonmain.py--help") returnnetwork7.3模型訓(xùn)練7.3.5模型訓(xùn)練訓(xùn)練的代碼由相關(guān)數(shù)據(jù)的讀取、訓(xùn)練參數(shù)設(shè)置、數(shù)據(jù)增強(qiáng)、訓(xùn)練信息顯示及保存、繼續(xù)訓(xùn)練等相關(guān)部分構(gòu)成。在訓(xùn)練開(kāi)始前,需要對(duì)訓(xùn)練進(jìn)行一些相關(guān)參數(shù)的設(shè)置,其中一些參數(shù)的設(shè)置將會(huì)影響訓(xùn)練模型的效果。相關(guān)參數(shù)有:num_epochs:總訓(xùn)練輪數(shù);epoch_start_i:開(kāi)始輪數(shù),配合繼續(xù)訓(xùn)練使用,程序會(huì)自動(dòng)加載epoch_start_i-1的權(quán)重;validation_step:間隔多少輪驗(yàn)證一次模型;continue_training:是否繼續(xù)訓(xùn)練;dataset:數(shù)據(jù)集,可配置列表;imgprocess:載入圖片操作,裁剪或者縮放;input_height:網(wǎng)絡(luò)輸入的高;input_width:網(wǎng)絡(luò)輸入的寬;batch_size:每個(gè)批次圖片數(shù)量;num_val_images:每次驗(yàn)證取多少?gòu)堯?yàn)證集中的圖片;h_flip:數(shù)據(jù)增強(qiáng)是否進(jìn)行水平翻轉(zhuǎn);v_flip:數(shù)據(jù)增強(qiáng)是否進(jìn)行垂直翻轉(zhuǎn);brightness:數(shù)據(jù)增強(qiáng)是否隨機(jī)亮度;color:數(shù)據(jù)增強(qiáng)是否隨機(jī)添加顏色;rotation:數(shù)據(jù)增強(qiáng)隨機(jī)旋轉(zhuǎn)角度;model:訓(xùn)練的模型;savedir:保存的路徑;7.3模型訓(xùn)練7.3.5模型訓(xùn)練數(shù)據(jù)增強(qiáng)是一種在深度學(xué)習(xí)中廣泛使用的技術(shù),用于擴(kuò)充訓(xùn)練數(shù)據(jù)集,以提高模型的泛化能力和魯棒性。數(shù)據(jù)增強(qiáng)通過(guò)對(duì)原始訓(xùn)練數(shù)據(jù)應(yīng)用一系列隨機(jī)變換或變形操作,生成額外的訓(xùn)練樣本,從而增加數(shù)據(jù)的多樣性。數(shù)據(jù)增強(qiáng)部分,程序根據(jù)讀者傳入的訓(xùn)練參數(shù),再載入每個(gè)批次的圖片時(shí)會(huì)對(duì)圖片進(jìn)行隨機(jī)數(shù)據(jù)增強(qiáng)的操作。詳見(jiàn)代碼清單7-4。損失函數(shù),也稱為目標(biāo)函數(shù)或代價(jià)函數(shù),是深度學(xué)習(xí)模型中的一個(gè)關(guān)鍵組成部分。損失函數(shù)用于度量模型的預(yù)測(cè)輸出與真實(shí)標(biāo)簽之間的差異或錯(cuò)誤程度,通過(guò)最小化該差異來(lái)優(yōu)化模型的參數(shù)。本項(xiàng)目損失函數(shù)部分采用的是focal_loss,其主要側(cè)重于根據(jù)樣本的難易程度給樣本對(duì)應(yīng)的損失增加權(quán)重。deffocal_loss(prediction_tensor,target_tensor,weights=None,alpha=0.25,gamma=2):

sigmoid_p=tf.nn.sigmoid(prediction_tensor)#創(chuàng)建一個(gè)將所有元素設(shè)置為0的張量

zeros=array_ops.zeros_like(sigmoid_p,dtype=sigmoid_p.dtype)#正樣本損失(車(chē)道線)

pos_p_sub=array_ops.where(target_tensor>zeros,target_tensor-sigmoid_p,zeros)#負(fù)樣本損失(背景)

neg_p_sub=array_ops.where(target_tensor>zeros,zeros,sigmoid_p)#-ylog(p^)-(1-y)log(1-p^)

per_entry_cross_ent=-alpha*(pos_p_sub**gamma)*tf.log(tf.clip_by_value(sigmoid_p,1e-8,1.0))-(1-alpha)*(neg_p_sub**gamma)*tf.log(tf.clip_by_value(1.0-sigmoid_p,1e-8,1.0))returntf.reduce_mean(per_entry_cross_ent)7.3模型訓(xùn)練7.3.5模型訓(xùn)練載入每個(gè)批次的圖片,語(yǔ)義分割的標(biāo)簽是一張圖,所以在送入網(wǎng)絡(luò)之前要對(duì)rgb對(duì)應(yīng)的標(biāo)簽做一次轉(zhuǎn)化,再進(jìn)行獨(dú)熱編碼(one-hot)。defone_hot_it(label,label_values):semantic_map=[]#label_values從csv文件中載入forcolourinlabel_values:equality=np.equal(label,colour)class_map=np.all(equality,axis=-1)semantic_map.append(class_map)semantic_map=np.stack(semantic_map,axis=-1)returnsemantic_map評(píng)估指標(biāo)部分,打印了整體分?jǐn)?shù)、各類(lèi)別分?jǐn)?shù)、F1、IOU。defevaluate_segmentation(pred,label,num_classes,score_averaging="weighted"):flat_pred=pred.flatten()flat_label=label.flatten()#計(jì)算全局的分?jǐn)?shù)

global_accuracy=compute_global_accuracy(flat_pred,flat_label)#計(jì)算每個(gè)類(lèi)別的分?jǐn)?shù)

class_accuracies=compute_class_accuracies(flat_pred,flat_label,num_classes)#計(jì)算精確率

prec=precision_score(flat_pred,flat_label,average=score_averaging)#計(jì)算召回率

rec=recall_score(flat_pred,flat_label,average=score_averaging)#計(jì)算F1f1=f1_score(flat_pred,flat_label,average=score_averaging)#計(jì)算IOUiou=compute_mean_iou(flat_pred,flat_label)returnglobal_accuracy,class_accuracies,prec,rec,f1,iou7.3模型訓(xùn)練7.3.5模型訓(xùn)練執(zhí)行文件夾內(nèi)的train.sh腳本后進(jìn)行訓(xùn)練,其訓(xùn)練部分過(guò)程如圖所示。訓(xùn)練過(guò)程7.3模型訓(xùn)練7.3.5模型訓(xùn)練訓(xùn)練結(jié)束后將多出一個(gè)checkpoints文件夾,如圖所示。訓(xùn)練后文件夾結(jié)構(gòu)checkpoints文件夾中包含了訓(xùn)練過(guò)程中的一些保存信息,如圖所示。訓(xùn)練信息保存文件夾結(jié)構(gòu)其中每個(gè)文件夾內(nèi)保存了對(duì)應(yīng)epoch的訓(xùn)練信息,訓(xùn)練是以ckpt的形式保存模型的,包含三個(gè)文件:(1).mate文件保存了當(dāng)前圖結(jié)構(gòu)(2).data文件保存了當(dāng)前參數(shù)名和值(3).index文件保存了輔助索引信息7.3模型訓(xùn)練7.3.5模型訓(xùn)練這里需要把ckpt固化成pb模型文件,真正部署的時(shí)候,一般不會(huì)提供ckpt的模型,而是固化成pb模型。程序見(jiàn)ckpt2pb.py,如圖所示,其中frozen_graph.pb文件就是后續(xù)小節(jié)“模型轉(zhuǎn)換”所需要的模型保存文件。在評(píng)估階段會(huì)用到數(shù)據(jù)集中的test部分,由于目錄結(jié)構(gòu)類(lèi)似,所以這一部分的代碼其實(shí)就是train中驗(yàn)證部分給單獨(dú)提取出來(lái),用訓(xùn)練過(guò)程中保存的pb文件進(jìn)行推理,代碼詳見(jiàn)eval.py,運(yùn)行腳本后會(huì)從train目錄的checkpoint文件中找到model_checkpoint_path權(quán)重進(jìn)行評(píng)估。run_once參數(shù)的作用在于是否定時(shí)對(duì)權(quán)重進(jìn)行評(píng)估,eval操作是可以和train同時(shí)進(jìn)行的,因?yàn)閠rain會(huì)定期保存權(quán)重,對(duì)應(yīng)的checkpoint中model_checkpoint_path權(quán)重隨之變化,所以可以實(shí)時(shí)對(duì)權(quán)重進(jìn)行評(píng)估,如圖所示。保存節(jié)點(diǎn)文件夾結(jié)構(gòu)評(píng)估結(jié)果7.4模型的量化7.4.1RKNN量化上面的所有步驟完成后,其實(shí)如果項(xiàng)目是用在PC端的,那么這個(gè)權(quán)重已經(jīng)可以落地了,但是本章節(jié)的最終目標(biāo)是將它在AIBOX中運(yùn)行,所以,針對(duì)AIBOX的環(huán)境,需要對(duì)模型文件進(jìn)行量化。模型量化所需要用到的RKNN-toolkit的container環(huán)境詳見(jiàn)前面章節(jié)。本書(shū)提供的此部分代碼在“權(quán)重轉(zhuǎn)換與量化”文件夾下,結(jié)構(gòu)如圖所示。這部分的作用是將模型轉(zhuǎn)化成RV1808芯片可用的類(lèi)型,從而實(shí)現(xiàn)后續(xù)的部署。其中l(wèi)dw.py是將pb文件轉(zhuǎn)換為RKNN文件的程序,resize_ldw.py是調(diào)整素材的程序,test.py用于生成后的RKNN模型的推理。ret.png是執(zhí)行推理后的結(jié)果,它表示所轉(zhuǎn)化的RKNN模型文件可以實(shí)現(xiàn)車(chē)道線的檢測(cè),并能看出其檢測(cè)效果。RKNN模型轉(zhuǎn)換文件夾結(jié)構(gòu)7.4模型的量化7.4.1RKNN量化其中有一個(gè)注意點(diǎn),就是圖片輸入的順序。車(chē)道線檢測(cè)的模型,用于輸入網(wǎng)絡(luò)訓(xùn)練的圖片其通道次序?yàn)锽GR,按照訓(xùn)練和部署需要統(tǒng)一的標(biāo)準(zhǔn),部署在AIBOX上送入網(wǎng)絡(luò)推理的圖片通道次序也應(yīng)該是BGR。RKNN的量化過(guò)程中,程序會(huì)讀取一個(gè)列表中的圖像送入網(wǎng)絡(luò)量化,內(nèi)部讀取圖片的方式是按照RGB來(lái)的,和OpenCV是相反的。所以如果要用BGR的圖片進(jìn)行量化,在準(zhǔn)備數(shù)據(jù)集的時(shí)候,如果用OpenCV打開(kāi),就要做一步操作,就是BGR2RGB。雖然參數(shù)上是BGR到RGB的轉(zhuǎn)化,但本質(zhì)上是通道變更,當(dāng)OpenCV將圖片按照RGB的格式保存以后,其他默認(rèn)以RGB載入圖片的包將圖片加載后,實(shí)際得到的就是BGR。首先準(zhǔn)備好一批素材用于量化,素材需要盡可能覆蓋所有可能出現(xiàn)的場(chǎng)景,將它們的尺寸調(diào)整為網(wǎng)絡(luò)輸入的大小,并生成文件列表,程序見(jiàn)代碼清單7-5。然后運(yùn)行l(wèi)dw.py程序?qū)b模型轉(zhuǎn)換為RKNN模型,程序見(jiàn)代碼清單。7.4模型的量化7.4.1RKNN量化量化部分重點(diǎn)要講的是推理的部分,在PC上推理出正確的結(jié)果,那么在部署的時(shí)候只需要把對(duì)應(yīng)的Python代碼翻譯成C++即可。PC推理的代碼在test.py中,核心代碼片段如下。print('-->Runningmodel')outputs=rknn.inference(inputs=[img])print('done')

nout=len(outputs)foriinrange(np.array(outputs).shape[2]):l1=outputs[0][0][i][0]l2=outputs[0][0][i][1]ifl1>l2:#這里可以參考訓(xùn)練工程中的輸出節(jié)點(diǎn)來(lái)理解

#logit=tf.reshape(network,(-1,args.input_height*args.input_width,num_classes),name='logits')

#當(dāng)通道0的數(shù)值大時(shí)則該像素格推理為背景,填充0,黑色

#當(dāng)通道1的數(shù)值大時(shí)則該像素格推力為車(chē)道線,填充255,白色

img[i//img_w][i%img_w][0]=0

img[i//img_w][i%img_w][1]=0

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論