版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
6行人檢測實踐HISTORYOFDEVELOPMENTChapter06本章目錄數(shù)據(jù)采集與標注01模型訓練02模型轉換與量化03項目落地與部署046行人檢測實踐本章主要介紹的是基于目標檢測的行人識別,行人檢測主要用于保障車輛盲區(qū)的安全,尤其是商用車,由于車身龐大,存在較多盲區(qū),且車長帶來的內輪差也會讓行人不經(jīng)意間就進入了車輛的危險區(qū)域。行人檢測利用攝像頭照射車輛盲區(qū),一旦有行人進入盲區(qū)則對司機和行人進行提醒。整個項目主要流程如圖所示,本章節(jié)也會按照該順序依次講解整個流程。6.1數(shù)據(jù)集采集與標注6.1.1素材采集數(shù)據(jù)來源主要有兩個:1)公開數(shù)據(jù)集行人檢測是一個應用范圍比較廣的項目,行人標簽也是各大數(shù)據(jù)集中常見的標簽,前期沒有足夠的“財力”和“精力”去收集、標注素材的情況下,使用公開數(shù)據(jù)集訓練是一個不錯的辦法。除了深度學習界人盡皆知的coco、voc數(shù)據(jù)集,還有不少可以用來訓練的帶有行人標簽的公開數(shù)據(jù)集,其實相比coco、voc數(shù)據(jù)集,這些數(shù)據(jù)集會更加符合本實踐項目的場景。數(shù)據(jù)集:CaltechPedestrianDetectionBenchmark存放地址:/Image_Datasets/CaltechPedestrians/數(shù)據(jù)集:TheCityscapesDataset存放地址:/數(shù)據(jù)集:TheEuroCityPersonsDataset存放地址:https://eurocity-dataset.tudelft.nl/2)自主采集如果有私家車,并且裝了行車記錄儀,可以從行車記錄儀中導出視頻作為素材,如果沒有,那么在視頻網(wǎng)站搜索行車記錄儀,也能獲取到他人上傳的行車記錄儀視頻,挑選清晰度較高的視頻下載即可。6.1數(shù)據(jù)集采集與標注針對以上幾點標注要求,給出幾個標注的示例。1)如下左圖人多雜亂,盡可能標記人能識別的人,遠處雜亂無法區(qū)分輪廓的人不做標記。2)如上右圖左邊遠處騎車可以辨別人形,需要標記;右邊兩人雖有重疊但依舊可以單獨區(qū)分開,需要分開標記;中間的人手臂部分超出身體輪廓太多,僅標記身體部分;中間偏右的黑色人群無法區(qū)分不做標記。6.1數(shù)據(jù)集采集與標注針對以上幾點標注要求,給出幾個標注的示例。3)如下左圖對于這類已經(jīng)動態(tài)模糊比較嚴重的情況,不需要標記(圖中框只是展示下),否則會對訓練造成干擾。4)如上右圖被護欄擋住的行人,如果某些角度隔著護欄依舊可以看到腿需要標注全身,若護欄將腿完全擋住,則僅標記身體露出的部分。6.1數(shù)據(jù)集采集與標注針對以上幾點標注要求,給出幾個標注的示例。5)如下左圖人行道上的行人和騎車的人雖然被柱子和樹遮擋,但依舊可以辨別為人,需要標記,但標記露出的部分,不要將柱子標記進去;對于騎車的人不要刻意去標記車的部分,把人的輪廓標記全,框里面盡量是人的信息。6)如上右圖中間騎車帶人雖然有兩個人,但已經(jīng)完全重疊,只需要標記一個即可。6.1數(shù)據(jù)集采集與標注6.1.3小結素材是一切深度學習項目的基礎,行人識別的項目在素材采集和標注方面難度并不算太大。前期使用廣大公開數(shù)據(jù)集的行人素材,也可以讓算法得到一個不錯的效果,但倘若要把效果做到更好,在素材方面則需要用更多真實的場景進行擴充。如今市面上還有很多素材標注公司,他們不光提供素材標注的服務,同時出售素材或者按需求采集素材,如果項目時間緊迫但有足夠的預算,找他們幫忙也是一個不錯的選擇。6.2模型訓練6.2.1模型設計思想本實驗使用SSD的目標檢測網(wǎng)絡,在正式進入項目之前,簡單介紹下其設計思想。若想了解詳細細節(jié),可以參考論文《SSD:SingleShotMultiBoxDetector》。SSD是一種引人注目的目標檢測結構,它結合了直接回歸框和分類概率的方法,又利用大量的預選框來提升識別準確度。ssd在預測階段不僅僅使用最后一層的特征映射,而是取出中間層的特征,在不同尺寸的特征映射上對結果進行預測,雖然增加運算量,但使檢測結果具有更多個可能性,從而提升精度。如圖所示是ssd的模型,從圖中可以看出SSD的主干網(wǎng)絡為VGG網(wǎng)絡,作者在VGG-16的基礎上,將FC6和FC7層轉化為卷積層,去掉了所有的Dropout層和FC8層,添加了Conv6,Conv7,Conv8和Conv9層。6.2模型訓練為了從特征獲取預測結果,分別取出conv4的第三層卷積特征、fc7卷積特征,conv6的第二次卷積特征,conv7的第二次卷積特征,conv8的第二次卷積特征和conv9的第二次卷積特征,共六個特征層作為有效特征層如圖所示。對獲取到的每個有效特征層做一次num_anchorsx4的卷積和一次num_anchorsxnum_classes的卷積,num_anchors指的是該特征層每一個特征點所擁有的先驗框數(shù)量。上述提到的六個特征層,每個特征層的每個特征點對應的先驗框數(shù)量分別為4、6、6、6、4、4。其中num_anchorsx4的卷積用于預測該特征層上每一個網(wǎng)格點上每一個先驗框的變化情況;num_anchorsxnum_classes的卷積用于預測該特征層上每一個網(wǎng)格點上每一個預測對應的種類。利用num_anchorsx4的卷積對每一個有效特征層對應的先驗框進行調整可以獲得預測框。6.2模型訓練SSD解碼過程可以分為兩部分:(1)將每個網(wǎng)格的中心點加上它對應的x_offset和y_offset,加完之后的記過就是預測框的中心;(2)利用h和w調整先驗框獲得預測框的寬和高。獲得預測框的中心和寬高時,便可以在圖片上繪制預測框了。但是想要獲得最終的預測結果,還要對每一個預測框在進行得分排序與非極大抑制篩選,這一部分基本上時目標檢測領域通用的部分。實現(xiàn)代碼見代碼清單6-3,這里僅展示部分代碼importnumpyasnpimporttorchfromtorchimportnnfromtorchvision.opsimportnmsclassBBoxUtility(object):
def__init__(self,num_classes):
self.num_classes=num_classes
...6.2模型訓練6.2.2數(shù)據(jù)集制作數(shù)據(jù)集制作采取VOC格式,在project下新建目錄VOCdevkit,整個數(shù)據(jù)集的目錄結構如下,將標簽文件放在VOCdevkit文件夾下VOC_xxx下的Annotation中,將.jpg格式的圖片放在JPEGImages中。VOCdevkit|--VOC_xxx|--JPEGImages存放圖片|--Annotations存放xml標注文件|--ImageSets|--Main存放不帶后綴的文件名列表|--subdir2...|--dir2...在完成數(shù)據(jù)集的擺放后,需對數(shù)據(jù)集進行下一步處理,目的是為了獲得訓練用的_xxx_train.txt和_xxx_val.txt,在工程下新建voc_annotation.py,腳本見代碼清單6-46.2模型訓練6.2.3訓練如果訓練過程中存在中斷訓練的操作,可以將model_path設置成logs文件夾下的權值文件,將已經(jīng)訓練了一部分的權值再次載入。同時修改下方的凍結階段或者解凍階段的參數(shù),來保證模型epoch的連續(xù)性。當model_path=''的時候不加載整個模型的權值。此處使用的是整個模型的權重,因此是在train.py進行加載的,下面的pretrain不影響此處的權值加載。如果想要讓模型從主干的預訓練權值開始訓練,則設置model_path='',下面的pretrain=True,此時僅加載主干。如果想要讓模型從0開始訓練,則設置model_path='',下面的pretrain=Fasle,F(xiàn)reeze_Train=Fasle,此時從0開始訓練,且沒有凍結主干的過程。一般來講,從0開始訓練效果會很差,因為權值太過隨機,特征提取效果不明顯。網(wǎng)絡一般不從0開始訓練,至少會使用主干部分的權值,有些論文提到可以不用預訓練,主要原因是他們數(shù)據(jù)集較大且調參能力優(yōu)秀。如果一定要訓練網(wǎng)絡的主干部分,可以了解imagenet數(shù)據(jù)集,首先訓練分類模型,分類模型的主干部分和該模型通用,基于此進行訓練。6.2模型訓練6.2.3訓練訓練分為兩個階段,分別時凍結階段和解凍階段,顯存不足與數(shù)據(jù)集的大小無關,提示顯存不足請調小batch_size收到BatchNorm層影響,batch_size最小為2,不能為1。凍結階段訓練參數(shù),此時模型的主干被凍結了,特征提取網(wǎng)絡不發(fā)生改變,占用的顯存較小進隊網(wǎng)絡進行微調。解凍階段訓練參數(shù),此時模型的主干不被凍結了,特征提取網(wǎng)絡會發(fā)生改變,占用的顯存較大,網(wǎng)絡所有的參數(shù)都會發(fā)生改變。Freeze_Train設為True,也就是默認先凍結主干訓練后解凍訓練。num_workers用于設置是否使用多線程讀取數(shù)據(jù),開啟后會加快數(shù)據(jù)讀取速度,但是會占用更多內存,內存較小的電腦可以設置為2或0。train_annotation_path和val_annotation_path是獲取圖片和標簽的路徑。6.2模型訓練6.2.3訓練運行train.py文件,如下左圖可以觀察到已經(jīng)開始訓練模型。訓練完成之后可以觀察到在log文件下,存取了訓練過程中的權值文件,如上右圖所示。6.2模型訓練6.2.4預測和評估訓練結果預測需要用到兩個文件,分別是ssd.py和predict.py,代碼詳見本書附帶資料,和之前一樣,需要去ssd.py里面修改model_path以及classes_path為自己對應的訓練權重文件和目標識別種類。在此我們選擇上一步訓練模型表現(xiàn)最好的權重,對應設置如下:"model_path":'logs/best_epoch_weights.pth',"classes_path":'model_data/cls_classes.txt',predict.py代碼如下,該代碼將單張圖片預測、攝像頭檢測、FPS檢測和目錄遍歷檢測多功能融為一體,具體測試模式由參數(shù)mode決定,當mode為predict時表示單張圖片預測;為video表示視頻檢測,可調用攝像頭或者視頻進行檢測;為fps表示測試fps,使用的圖片是img里的street.jpg;為dir_predict表示遍歷文件夾進行檢測并保存,默認遍歷img文件夾,保存img_out文件夾,為export_onnx表示將模型導出為onnx。6.2模型訓練6.2.4預測和評估在終端輸入pythonpredict.py運行predict.py。運行時要求輸入待檢測圖片的路徑,在這里我們把測試圖片test.jpg放入了img文件夾下,所以這里輸入的路徑為img/test.jpg,預測完成之后會將結果以img.img(如圖所示)形式保存在工程根目錄下。6.2模型訓練6.2.4預測和評估評估需要用到get_map.py文件,同樣需要設置model_path和classes_path,設置方式和預測時的設置相同。隨后便可以在終端輸入pythonget_map.py運行get_map.py文件,運行時在終端的顯示如圖所示,從圖中可以看出此模型預測出行人這一類別時的AP值為91.23%,在門限值為0.5的情況下,F(xiàn)1值為0.85,召回率為73.81%,精確度值為99.20%。6.2模型訓練6.2.4預測和評估不同門限值對應的F1值、召回率和精確度也對應繪制成了圖片如圖所示,保存至map_out文件夾中。6.3模型轉換與量化6.3.1模型轉換ONNX(OpenNeuralNetworkExchange)是一種開放的深度學習模型表示格式,它旨在提供一個通用的格式,用于在不同的深度學習框架之間無縫地交換模型。所以為了更好完成后續(xù)的部署工作,可將模型轉換為onnx格式。具體是在predict.py中調用了ssd.py的方法convert_to_onnx,其實現(xià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(,調用時,我們只需在predict.py文件里將mode設置為export_onnx即可,隨后保存predict.py文件,運行可以發(fā)現(xiàn)在model_data文件夾下生成了對應的model.onnx文件。6.3模型轉換與量化6.3.2模型量化上面的所有步驟完成后,其實如果項目是用在PC端的,那么這個權重已經(jīng)可以落地了,但是本章節(jié)的最終目標是將它在AIBOX中運行,所以針對AIBOX的環(huán)境,需要對模型文件進行量化。模型量化所需要用到的rknn-toolkit的container環(huán)境詳見3.6章節(jié)。首先進入rknn-toolkit新建img文件夾存放一批素材用于量化,素材需要盡可能覆蓋所有可能出現(xiàn)的場景,將它們的尺寸調整為網(wǎng)絡輸入的大小,并生成文件列表,程序見代碼清單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模型轉換與量化6.3.3小結模型訓練階段會遇到的各個步驟,也是深度學習項目中的重要環(huán)節(jié)之一,模型的訓練結果很大程度上會直接影響到項目落地后的用戶體驗。在經(jīng)歷過不同硬件設備開發(fā)以后就會發(fā)現(xiàn),量化也是整個過程中必不可少的一環(huán),因為量化在加速推理的同時,也是對硬件環(huán)境的一種適配。其實即便是落地在PC上的項目,原模型可以直接運行的情況下,考慮到性能也會使用例如tensorRT等方式對模型進行量化。6.4項目落地與部署6.4.1項目工程工程目錄結構如下otest|--sdk_rk1808相關sdk|--src源碼 |--otest主模塊程序 |--assets模型文件 |--test測試程序|--build_emv.cmake編譯環(huán)境配置,供CMakeLists調用|--CMakeLists.txt用于生成makefile,各源碼模塊中也有對應文件,逐級調用6.4項目落地與部署源碼讀者可以直接從隨書的資源中獲取,本章節(jié)主要是梳理源碼結構如圖所示,對幾個重要的模塊進行講解,幫助讀者更快地理解代碼。視頻源:獲取攝像頭數(shù)據(jù),用測試模塊所配置的回調函數(shù),向測試模塊回調傳輸圖像數(shù)據(jù)。測試模塊:向視頻源配置一個用于傳輸圖像的回調函數(shù),向主模塊配置一個用于傳輸推理結果的回調函數(shù)。將視頻源回調來的圖像數(shù)據(jù)傳給主模塊推理,并將主模塊回調來的推理結果提供給繪圖模塊。主模塊:接收圖像數(shù)據(jù),用測試模塊所配置的回調函數(shù),向測試模塊回調推理結果。主模塊是另起線程進行異步推理,因為一旦推理的幀率低于視頻源的幀率(25FPS)會導致阻塞。繪圖:繪圖模塊將測試模塊傳輸過來的推理結果,繪制在畫面上用于展示。6.4項目落地與部署6.4.2源碼解析1)主模塊對模塊進行初始化,代碼見代碼清單6-9,這里僅展示部分代碼。if(item.image_header.width>0anditem.image_header.height>0){///默認值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配置文件中讀取模型文件,若沒有配置這里直接給予了一個默認值。初始化推理模塊后,程序可以直接從模型文件里讀取模型的輸入尺寸,然后利用初始化傳入的視頻源尺寸和模型的尺寸初始化rga。6.4項目落地與部署6.4.2源碼解析1)主模塊對rga進行初始化,代碼見代碼清單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);在對rga初始化的過程中,需要指定原始圖像的信息、原始圖像中需要轉換的部分、目標圖像的信息,也就是告訴rga,需要從一種圖轉換成另一種圖。6.4項目落地與部署6.4.2源碼解析1)主模塊更新最新圖像,代碼見代碼清單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);......外部調用update函數(shù),為主模塊更新最新一幀的圖像經(jīng)過rga的轉換送入緩沖區(qū)。取名更新也是因為,外部送入圖片和主模塊的推理是異步操作,中間用一個單項緩沖區(qū)連接,外部所傳入的圖片會不斷更新緩沖區(qū),內部在推理完成后會從緩沖區(qū)取數(shù)據(jù)。當處理的幀率低于視頻幀率時,外部送入的圖片會不斷更新緩沖區(qū)的圖片,從而保證每次推理的圖片都是最近的視頻畫面。6.4項目落地與部署6.4.2源碼解析1)主模塊子線程循環(huá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)運行在子線程中,直到反初始化或者析構時收到停止信號才會退出循環(huán)。該函數(shù)主要功能就是從緩沖區(qū)中取出圖片進行推理,并將推理的結果,通過外部傳入的回調函數(shù)傳遞出去。6.4項目落地與部署6.4.2源碼解析2)推理模塊推理模塊的代碼在ssd_detector.cpp中,主要工作就是調用rk的接口進行圖片的推理,并對推理結果做后處理后輸出。這部分其實就是將PC上的推理代碼,將Python翻譯成C++即可,讀者可以對照著量化章節(jié)的代碼閱讀源碼,這里不再贅述。6.4項目落地與部署6.4.3部署工程開發(fā)環(huán)境的搭建可以參考3.6.WSL安裝,以下的全部指令都是在WSL下運行。新建build文件夾,并進入到build中,執(zhí)行cmake命令。cmake..當看到如下打印時則表明執(zhí)行成功。--Configuringdone--Generatingdone執(zhí)行編譯makeinstall如果沒有報錯并且打印了一連串的--Installing:信息,則表示執(zhí)行成功。6.4項目落地與部署6.4.3部署工程至此在build下會生成一個install的目錄,結構如下:install |--otest |--assets模型文件,從src/otest/assets中拷貝過來的 |--otest_model_box_priors.txt |--otest_model_labels_list.txt |--otest_model.rknn |--include主模塊庫的頭文件,從src/otest中拷貝過來的 |--otest_proc.h |--lib主模塊的庫文件和相關聯(lián)的一些庫 |--libotest_proc.so |--libpredictor.so |--... |--test_test可執(zhí)行文件,測試模塊編譯出來的6.4項目落地與部署6.4.3部署工程進入到install文件及下,將程序推入AIBOX。adbpushotest/home如果是通過網(wǎng)線鏈接AIBOX也可以直接拖拽進去。進入到AIBOX中,進入剛才推送程序的路徑,這里是/home/otest,對可執(zhí)行程序賦權限后執(zhí)行chmod755test_test./test_test程序開始運行,并打印出如下圖所示的單張圖片的推理速度、當前的推理幀率、視頻流幀率。6.4項目落地與部署6.4.3部署工程程序運行結果如下圖所示。6.4項目落地與部署6.4.4小結至此整個行人識別實驗全部完成,如果讀者照著這個流程走完一遍,不妨運行起程序,拿起攝像頭對準身邊的那個人,看看他是否被框中顯示在屏幕上。其實所有的深度學習落地項目都會經(jīng)歷這幾個步驟,更進一步的,可以在落地的程序上對模型的輸出結果按照個人的需求做其他的邏輯,比如限定行人的遠近、范圍,這些就有待讀者發(fā)散思維進行探索了。6.5課后習題
1)什么是行人檢測?2)行人檢測有哪些方法?3)什么是SSD算法?7車道線檢測實踐LANELINEINSPECTIONPRACTICEChapter07本章目錄數(shù)據(jù)采集與標注01環(huán)境部署02模型訓練03模型的量化04項目部署與落地05本章總體介紹車道線檢測是輔助駕駛中必不可少的一項,它的主要目標是通過計算機視覺和圖像處理技術,從道路圖像中精確提取出車道線的位置和形狀信息。這些提取到的車道線信息可以用于車道保持、車道偏離預警、自動駕駛路徑規(guī)劃等應用。通過實現(xiàn)準確的車道線檢測系統(tǒng),可以提高駕駛安全性,減少交通事故的發(fā)生,并為駕駛員提供更好的駕駛體驗?;谝曈X的車道線檢測方法可以分為:傳統(tǒng)圖像方法和深度學習方法兩類。其中傳統(tǒng)的圖像檢測方法可以通過邊緣檢測、濾波或是顏色空間的車道線檢測等方式得到車道線區(qū)域,再結合相關圖像檢測算法實現(xiàn)車道線檢測。但面對環(huán)境明顯變化的場景并不能很好的檢測,工作量大且魯棒性差。而深度學習的方法有較好的魯棒性,且準確率更高。它大致有基于分類和目標檢測的方法和基于端到端圖像分割的方法等相關車道線檢測方法。而本書的車道線檢測采用的是UNet的語義分割網(wǎng)絡。本章總體介紹車道線檢測算法的流程如下圖所示。主要思路是:通過素材采集獲取訓練要用的原始數(shù)據(jù),再經(jīng)過標注與生成標簽圖兩個步驟將原始數(shù)據(jù)轉化為可以被學習訓練的素材,然后通過模型訓練得到相應模型,最后經(jīng)過模型量化、轉換和部署等步驟將模型優(yōu)化并轉化成可被嵌入式平臺運行的程序。車道線項目流程圖7.1數(shù)據(jù)集采集與標注素材的獲取一般有兩種途徑,一種是自己利用相關設備如行車記錄儀獲取,另一種是通過下載公開的數(shù)據(jù)集獲取。車道線檢測相關的數(shù)據(jù)集有TuSimple、CULane、CurveLanes、BDD100k等。素材標注使用Labelme工具,本項目提供的例程的“數(shù)據(jù)集”文件夾內已經(jīng)提供原圖與對應標注文件,車道線識別項目對于車道線的標注有以下幾點要求:需要標注的內容為圖片中人眼可以識別的車道線,包括實線、虛線、白線和黃線。對于雙線的車道線,兩條分開標注。對于虛線中間沒有車道線的部分進行補足。對于沒有車道線的圖片,直接跳過,不做處理。7.1數(shù)據(jù)集采集與標注下圖是按以上要求所給出的標注示例。車道線項目流程圖相較于分類和目標檢測,語義分割的素材多了一步從標簽文件到分割圖的轉換。因為語義分割是像素級別的推理,每個像素點都有其對應的標簽,因此在訓練中,它的標簽就是和它等大的一張分割圖。7.2環(huán)境部署深度學習的框架除了PyTorch外還有TensorFlow框架,本項目在TensorFlow框架下訓練,所以在進行本章之前需要進行TensorFlow環(huán)境的搭建,其環(huán)境總體搭建步驟如下:(1)在Ubuntu系統(tǒng)(WSL2、虛擬機或多系統(tǒng))下搭建TensorFlow環(huán)境的docker(2)在docker環(huán)境內安裝本項目的相關庫當然,若有需求也可以在創(chuàng)建一個docker容器后,在其內部建立conda的虛擬環(huán)境,然后安裝本項目需要的TensorFlow環(huán)境與相關庫。7.2環(huán)境部署7.2.1docker環(huán)境部署針對不同的顯卡,需要搭建不同的環(huán)境。本項目以30系顯卡為例進行環(huán)境搭建介紹,30系顯卡需要CUDA11.1,可以使用NVIDIA提供的docker鏡像—NVIDIA-TensorFlow。如果沒有安裝過NVIDIA-docker,首先要進行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)境部署接著進行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宿主機端口:容器端口這里預留了22可以用于ssh登錄5000后面會用到#進入容器nvidia-dockerexec-itnvidia_tensorflow/bin/bash安裝TensorFlowwheel的索引pipinstallnvidia-index用官方提供的命令安裝依賴的包pipinstallnvidia-tensorflow[horovod]7.2環(huán)境部署7.2.1docker環(huán)境部署下載完成后進入對應的目錄,因為這些依賴包安裝存在一定順序,所以按以下順序執(zhí)行指令。若覺得一條一條執(zhí)行繁瑣,可以建一個后綴名為.sh的shell腳本文件,將下列指令復制進文件后執(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此外本項目還需要用到以下幾個Python包,讀者可以使用以下命令安裝或者直接使用項目中的requirements.txt導入。pipinstallscipy==1.1.0-i/simplepipinstallscikit-learn-i/simplepipinstalltqdm-i/simple7.2環(huán)境部署7.2.2安裝TensorFlowObjectDetectionAPITensorFlowObjectDetectionAPI是一個基于TensorFlow構建的開源框架,用于目標檢測任務。它提供了豐富的目標檢測模型,其中包括了一些經(jīng)典的模型架構,如FasterR-CNN、SSD、Mask-RCNN等,具體可見TensorFlow的GitHub的model倉庫。7.3模型訓練項目文件夾為project,項目目錄如圖。“部署代碼”文件夾包含的是模型部署的代碼,“權重轉換與量化”包含的是模型量化轉換的相關代碼,本節(jié)介紹“訓練代碼”和“數(shù)據(jù)集”文件夾部分,實現(xiàn)數(shù)據(jù)集制作與模型訓練與保存。標簽轉換程序、數(shù)據(jù)集制作程序和模型及訓練程序這三部分對應在“訓練代碼”文件夾下,分別對應的是ldw_draw.py、make_dataset.py和剩下其他程序,目錄結構如圖所示。models內存有模型程序,builders內存有模型接口程序,utils是相關的輔助函數(shù)集合,train.py是模型訓練程序,ckpt2pb.py是將訓練完成后的ckpt文件轉換為pb文件的程序,eval.py是評估程序用訓練過程中保存的pb文件進行推理。項目目錄結構traincode目錄結構7.3模型訓練7.3.1模型設計思想本項目使用UNet的語義分割網(wǎng)絡,從圖中可以看到,其形狀類似字母“U”所以被稱為UNet。參考論文《U-Net:ConvolutionalNetworksforBiomedicalImageSegmentation》,起初UNet被用于醫(yī)學領域,而后UNet憑借著突出的效果被廣泛應用。UNet本質上是一個編碼器和解碼器的結構,左邊是特征提取,右邊是采樣恢復原始分辨率,中間采用跳層鏈接的方式將位置信息和語義信息融合。UNet網(wǎng)絡結構7.3模型訓練7.3.2標簽轉換7.1節(jié)中標注完的素材僅僅是多了一個標簽文件,保存了所標注的那些多邊形的類別和位置。而實際在訓練中用到的是像素級別的標簽,也就是對于原圖上每個像素點,都會有一個對應了類別的標簽,這個時候就需要利用標注文件來生成分割用的標簽圖。本項目提供的標簽轉換程序為ldw_draw.py。詳見代碼清單7-1。將對應腳本—ldw_draw.sh中的Path參數(shù)配置成讀者自己電腦上的標注圖片的所在目錄,執(zhí)行腳本,結果如下。image中存放原始圖片;json中存放標注文件;roadmap中存放分割標簽圖片,轉換后的目錄結構和圖片經(jīng)過轉換后的結果如圖所示。轉換后的目錄結構轉換前后對比,原圖(左),轉換后圖(右)7.3模型訓練7.3.3數(shù)據(jù)集制作在project下的“數(shù)據(jù)集”目錄中放置數(shù)據(jù)集,在“數(shù)據(jù)集”下再建一層子目錄,用于數(shù)據(jù)集分類。這里就以type1、type2為例,將轉化完成后的素材文件夾放入子文件夾中。對于本項目提供的例程,需要將“數(shù)據(jù)集”文件夾內data文件夾放入“訓練代碼”文件夾內make_dataset.py所在目錄下,或者讀者可以修改make_dataset.py的相關路徑。詳見代碼清單7-2。將腳本—make_datase.sh中的dataset參數(shù)配置成data下的子目錄,樣例數(shù)據(jù)集中有兩個子目錄type1、type2,存有上一小節(jié)所轉換的相關素材。input_height和input_width根據(jù)實際情況配置,所演示的項目中是256*128。修改make_datase.sh中的type1、type2后分別執(zhí)行。完成后其目錄結構如圖所示,新增兩個文件夾。數(shù)據(jù)集制作后的目錄結構7.3模型訓練7.3.3數(shù)據(jù)集制作新增文件夾的目錄結構如圖所示,test:測試集圖片;test_label:測試機標簽;train:訓練集圖片;train_label:訓練集標簽;val:驗證集圖片;val_label:驗證集標簽。同時,處理完的素材文件夾會被移動到data/done下面,以便于未來多次制作數(shù)據(jù)集時不會重復操作。新增文件夾的目錄結構7.3模型訓練7.3.4網(wǎng)絡搭建在“訓練代碼”文件夾下models目錄中放置需要搭建的模型文件,這里就以上面提到的UNet為例。本項目提供的例程在models下有一個UNet.py程序。詳見代碼清單7-3。在traincode下builders目錄,本項目提供一個model_builder.py程序作為創(chuàng)建模型總的接口,用于不同類型模型的選擇和搭建。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ù)模型名稱調用對應的模型搭建函數(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模型訓練7.3.5模型訓練訓練的代碼由相關數(shù)據(jù)的讀取、訓練參數(shù)設置、數(shù)據(jù)增強、訓練信息顯示及保存、繼續(xù)訓練等相關部分構成。在訓練開始前,需要對訓練進行一些相關參數(shù)的設置,其中一些參數(shù)的設置將會影響訓練模型的效果。相關參數(shù)有:num_epochs:總訓練輪數(shù);epoch_start_i:開始輪數(shù),配合繼續(xù)訓練使用,程序會自動加載epoch_start_i-1的權重;validation_step:間隔多少輪驗證一次模型;continue_training:是否繼續(xù)訓練;dataset:數(shù)據(jù)集,可配置列表;imgprocess:載入圖片操作,裁剪或者縮放;input_height:網(wǎng)絡輸入的高;input_width:網(wǎng)絡輸入的寬;batch_size:每個批次圖片數(shù)量;num_val_images:每次驗證取多少張驗證集中的圖片;h_flip:數(shù)據(jù)增強是否進行水平翻轉;v_flip:數(shù)據(jù)增強是否進行垂直翻轉;brightness:數(shù)據(jù)增強是否隨機亮度;color:數(shù)據(jù)增強是否隨機添加顏色;rotation:數(shù)據(jù)增強隨機旋轉角度;model:訓練的模型;savedir:保存的路徑;7.3模型訓練7.3.5模型訓練數(shù)據(jù)增強是一種在深度學習中廣泛使用的技術,用于擴充訓練數(shù)據(jù)集,以提高模型的泛化能力和魯棒性。數(shù)據(jù)增強通過對原始訓練數(shù)據(jù)應用一系列隨機變換或變形操作,生成額外的訓練樣本,從而增加數(shù)據(jù)的多樣性。數(shù)據(jù)增強部分,程序根據(jù)讀者傳入的訓練參數(shù),再載入每個批次的圖片時會對圖片進行隨機數(shù)據(jù)增強的操作。詳見代碼清單7-4。損失函數(shù),也稱為目標函數(shù)或代價函數(shù),是深度學習模型中的一個關鍵組成部分。損失函數(shù)用于度量模型的預測輸出與真實標簽之間的差異或錯誤程度,通過最小化該差異來優(yōu)化模型的參數(shù)。本項目損失函數(shù)部分采用的是focal_loss,其主要側重于根據(jù)樣本的難易程度給樣本對應的損失增加權重。deffocal_loss(prediction_tensor,target_tensor,weights=None,alpha=0.25,gamma=2):
sigmoid_p=tf.nn.sigmoid(prediction_tensor)#創(chuàng)建一個將所有元素設置為0的張量
zeros=array_ops.zeros_like(sigmoid_p,dtype=sigmoid_p.dtype)#正樣本損失(車道線)
pos_p_sub=array_ops.where(target_tensor>zeros,target_tensor-sigmoid_p,zeros)#負樣本損失(背景)
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模型訓練7.3.5模型訓練載入每個批次的圖片,語義分割的標簽是一張圖,所以在送入網(wǎng)絡之前要對rgb對應的標簽做一次轉化,再進行獨熱編碼(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評估指標部分,打印了整體分數(shù)、各類別分數(shù)、F1、IOU。defevaluate_segmentation(pred,label,num_classes,score_averaging="weighted"):flat_pred=pred.flatten()flat_label=label.flatten()#計算全局的分數(shù)
global_accuracy=compute_global_accuracy(flat_pred,flat_label)#計算每個類別的分數(shù)
class_accuracies=compute_class_accuracies(flat_pred,flat_label,num_classes)#計算精確率
prec=precision_score(flat_pred,flat_label,average=score_averaging)#計算召回率
rec=recall_score(flat_pred,flat_label,average=score_averaging)#計算F1f1=f1_score(flat_pred,flat_label,average=score_averaging)#計算IOUiou=compute_mean_iou(flat_pred,flat_label)returnglobal_accuracy,class_accuracies,prec,rec,f1,iou7.3模型訓練7.3.5模型訓練執(zhí)行文件夾內的train.sh腳本后進行訓練,其訓練部分過程如圖所示。訓練過程7.3模型訓練7.3.5模型訓練訓練結束后將多出一個checkpoints文件夾,如圖所示。訓練后文件夾結構checkpoints文件夾中包含了訓練過程中的一些保存信息,如圖所示。訓練信息保存文件夾結構其中每個文件夾內保存了對應epoch的訓練信息,訓練是以ckpt的形式保存模型的,包含三個文件:(1).mate文件保存了當前圖結構(2).data文件保存了當前參數(shù)名和值(3).index文件保存了輔助索引信息7.3模型訓練7.3.5模型訓練這里需要把ckpt固化成pb模型文件,真正部署的時候,一般不會提供ckpt的模型,而是固化成pb模型。程序見ckpt2pb.py,如圖所示,其中frozen_graph.pb文件就是后續(xù)小節(jié)“模型轉換”所需要的模型保存文件。在評估階段會用到數(shù)據(jù)集中的test部分,由于目錄結構類似,所以這一部分的代碼其實就是train中驗證部分給單獨提取出來,用訓練過程中保存的pb文件進行推理,代碼詳見eval.py,運行腳本后會從train目錄的checkpoint文件中找到model_checkpoint_path權重進行評估。run_once參數(shù)的作用在于是否定時對權重進行評估,eval操作是可以和train同時進行的,因為train會定期保存權重,對應的checkpoint中model_checkpoint_path權重隨之變化,所以可以實時對權重進行評估,如圖所示。保存節(jié)點文件夾結構評估結果7.4模型的量化7.4.1RKNN量化上面的所有步驟完成后,其實如果項目是用在PC端的,那么這個權重已經(jīng)可以落地了,但是本章節(jié)的最終目標是將它在AIBOX中運行,所以,針對AIBOX的環(huán)境,需要對模型文件進行量化。模型量化所需要用到的RKNN-toolkit的container環(huán)境詳見前面章節(jié)。本書提供的此部分代碼在“權重轉換與量化”文件夾下,結構如圖所示。這部分的作用是將模型轉化成RV1808芯片可用的類型,從而實現(xiàn)后續(xù)的部署。其中l(wèi)dw.py是將pb文件轉換為RKNN文件的程序,resize_ldw.py是調整素材的程序,test.py用于生成后的RKNN模型的推理。ret.png是執(zhí)行推理后的結果,它表示所轉化的RKNN模型文件可以實現(xiàn)車道線的檢測,并能看出其檢測效果。RKNN模型轉換文件夾結構7.4模型的量化7.4.1RKNN量化其中有一個注意點,就是圖片輸入的順序。車道線檢測的模型,用于輸入網(wǎng)絡訓練的圖片其通道次序為BGR,按照訓練和部署需要統(tǒng)一的標準,部署在AIBOX上送入網(wǎng)絡推理的圖片通道次序也應該是BGR。RKNN的量化過程中,程序會讀取一個列表中的圖像送入網(wǎng)絡量化,內部讀取圖片的方式是按照RGB來的,和OpenCV是相反的。所以如果要用BGR的圖片進行量化,在準備數(shù)據(jù)集的時候,如果用OpenCV打開,就要做一步操作,就是BGR2RGB。雖然參數(shù)上是BGR到RGB的轉化,但本質上是通道變更,當OpenCV將圖片按照RGB的格式保存以后,其他默認以RGB載入圖片的包將圖片加載后,實際得到的就是BGR。首先準備好一批素材用于量化,素材需要盡可能覆蓋所有可能出現(xiàn)的場景,將它們的尺寸調整為網(wǎng)絡輸入的大小,并生成文件列表,程序見代碼清單7-5。然后運行l(wèi)dw.py程序將pb模型轉換為RKNN模型,程序見代碼清單。7.4模型的量化7.4.1RKNN量化量化部分重點要講的是推理的部分,在PC上推理出正確的結果,那么在部署的時候只需要把對應的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:#這里可以參考訓練工程中的輸出節(jié)點來理解
#logit=tf.reshape(network,(-1,args.input_height*args.input_width,num_classes),name='logits')
#當通道0的數(shù)值大時則該像素格推理為背景,填充0,黑色
#當通道1的數(shù)值大時則該像素格推力為車道線,填充255,白色
img[i//img_w][i%img_w][0]=0
img[i//img_w][i%img_w][1]=0
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《砌體結構章》課件
- 《電壓比較器的應用》課件
- 單位管理制度合并選集【人力資源管理篇】十篇
- 單位管理制度分享匯編人力資源管理篇
- 單位管理制度呈現(xiàn)合集人力資源管理篇
- 寒假自習課 25春初中道德與法治八年級下冊教學課件 第三單元 第五課 第3課時 基本經(jīng)濟制度
- 《員工考績計算》課件
- 中國風國潮風古風模板120
- 2013年高考語文試卷(福建)(空白卷)
- 建材行業(yè)會計資金運作監(jiān)督工作總結
- 人教版(2024)八年級上冊物理期末測試卷(含答案)
- 2024關于家長會家長代表發(fā)言稿(30篇)
- 中醫(yī)內科學:中醫(yī)內科學肢體經(jīng)絡病證考試題(題庫版)
- 燈具行業(yè)采購工作總結
- 大學寫作智慧樹知到期末考試答案章節(jié)答案2024年麗水學院
- NB-T31022-2012風力發(fā)電工程達標投產(chǎn)驗收規(guī)程
- GJB9001C產(chǎn)品風險評估報告
- 2024年天津三源電力集團限公司社會招聘33人【重點基礎提升】模擬試題(共500題)附帶答案詳解
- 蘇教版六年級上冊科學期末測試卷帶答案
- 中式婚宴主題宴會設計方案策劃(2篇)
- 媒介與性別文化傳播智慧樹知到期末考試答案章節(jié)答案2024年浙江工業(yè)大學
評論
0/150
提交評論