鄧慶昌,程 科
(江蘇科技大學(xué)計(jì)算機(jī)學(xué)院,江蘇鎮(zhèn)江 212000)
目標(biāo)檢測(cè)是計(jì)算機(jī)視覺(jué)和數(shù)字圖像處理領(lǐng)域的熱門(mén)研究方向,其可在給定圖像中精確定位屬于特定類別的對(duì)象,并為每個(gè)對(duì)象分配相應(yīng)的類別標(biāo)簽,采用邊界框標(biāo)識(shí)出其位置,目前已廣泛應(yīng)用于人臉檢測(cè)[1-2]、安全帽佩戴檢測(cè)[3-6]、口罩佩戴檢測(cè)[7-8]、煙火檢測(cè)[9]等領(lǐng)域。
目標(biāo)檢測(cè)研究中使用的數(shù)據(jù)集包括公共數(shù)據(jù)集、自定義數(shù)據(jù)集以及公共數(shù)據(jù)集與自定義數(shù)據(jù)集混合的數(shù)據(jù)集。例如,張達(dá)為等[10]使用長(zhǎng)沙理工大學(xué)中國(guó)交通標(biāo)志檢測(cè)數(shù)據(jù)集CCTSDB 研究實(shí)時(shí)交通標(biāo)志檢測(cè)方法;候少麒等[11]建立了基于空洞卷積金字塔網(wǎng)絡(luò)的目標(biāo)檢測(cè)算法,并采用公共數(shù)據(jù)集VOC2007 和VOC2012 進(jìn)行了性能評(píng)價(jià)。公共數(shù)據(jù)集使用方便、效果好,但無(wú)法滿足一些細(xì)化場(chǎng)景的需求,此時(shí)需要?jiǎng)?chuàng)建自定義數(shù)據(jù)集。例如徐濤等[12]研究機(jī)坪工作人員反光背心檢測(cè)問(wèn)題時(shí)尚未有對(duì)應(yīng)的公開(kāi)數(shù)據(jù)集,其通過(guò)拍攝得到圖片數(shù)據(jù)并采用人工標(biāo)注得到自定義數(shù)據(jù)集;張永亮等[13]在進(jìn)行交通標(biāo)志檢測(cè)時(shí)通過(guò)相機(jī)實(shí)地拍攝大量真實(shí)道路場(chǎng)景和交通標(biāo)志獲取圖片數(shù)據(jù);馬永剛等[14]通過(guò)車載視覺(jué)傳感器采集了10 000 幀有軌電車運(yùn)行視頻中的圖片數(shù)據(jù)用于有軌電車在途障礙物檢測(cè)。在自定義目標(biāo)檢測(cè)數(shù)據(jù)集的構(gòu)建過(guò)程中,數(shù)據(jù)的采集和標(biāo)注多采用全人工方式,沒(méi)有相似圖片處理和無(wú)用圖片清理等中間處理說(shuō)明。
隨著目標(biāo)檢測(cè)領(lǐng)域的逐漸細(xì)化,公共數(shù)據(jù)集已難以滿足實(shí)際需要,制作符合個(gè)性化研究需求的數(shù)據(jù)集十分必要。然而,制作目標(biāo)檢測(cè)數(shù)據(jù)集一方面需要獲取大量圖片數(shù)據(jù),另一方面需要對(duì)圖片數(shù)據(jù)進(jìn)行標(biāo)注,表明相應(yīng)位置是否含有物體并明確其類別,如果均采用人工實(shí)現(xiàn)將花費(fèi)大量時(shí)間和精力。為此,本文以創(chuàng)建自定義安全帽佩戴檢測(cè)數(shù)據(jù)集為例,設(shè)計(jì)一種自定義目標(biāo)檢測(cè)數(shù)據(jù)集的收集與半自動(dòng)標(biāo)注方法,通過(guò)Scrapy 爬取和OpenCV 庫(kù)獲取視頻幀的方式得到圖片數(shù)據(jù),使用訓(xùn)練好的目標(biāo)檢測(cè)模型生成標(biāo)注文件,并通過(guò)人工修正得到最終數(shù)據(jù)集,避免了大量人工過(guò)濾不良數(shù)據(jù)的操作。
Scrapy 是適用于Python 語(yǔ)言的一個(gè)快速、高層次的屏幕抓取和Web 抓取框架,用于抓取Web 站點(diǎn)并從頁(yè)面中提取結(jié)構(gòu)化數(shù)據(jù)[15-18]。Scrapy 集成了網(wǎng)頁(yè)請(qǐng)求、下載機(jī)制和重試機(jī)制等內(nèi)容,使爬蟲(chóng)工作者從大量重復(fù)操作中解放出來(lái),專注于網(wǎng)頁(yè)爬取規(guī)則的編寫(xiě),用戶只需定制開(kāi)發(fā)若干個(gè)模塊便可輕松實(shí)現(xiàn)爬蟲(chóng)操作,通過(guò)少量代碼完成大量工作。
Scrapy 的框架如圖1 所示,包含引擎(Engine)、物品(Item)、管道(Pipeline)、下載器(Downloader)、爬蟲(chóng)(Spider)和調(diào)度器(Scheduler)等組件。其中Engine 負(fù)責(zé)除Item外其他模塊的通訊和數(shù)據(jù)傳遞等;Item 為數(shù)據(jù)存儲(chǔ)的對(duì)象,可以定義不同屬性;Pipeline 負(fù)責(zé)處理Spider 返回的Item 對(duì)象,并可以對(duì)Item 對(duì)象進(jìn)行進(jìn)一步處理;Downloader負(fù)責(zé)下載Engine 發(fā)送的所有Requests 請(qǐng)求結(jié)果,并將獲取到的響應(yīng)交還給Engine;Spider 負(fù)責(zé)發(fā)起Request 請(qǐng)求,接受Engine 返回的響應(yīng)并對(duì)其進(jìn)行解析,提取所需信息并交給Item 對(duì)象,還可以獲取下一頁(yè)的鏈接進(jìn)行遞歸爬取;Scheduler 負(fù)責(zé)接收Engine 發(fā)送過(guò)來(lái)的Request 請(qǐng)求,并按照一定的方式進(jìn)行整理排列,當(dāng)Engine 需要使用Request請(qǐng)求時(shí)返還給Engine。
Fig.1 Framework of Scrapy圖1 Scrapy框架
JSON(JavaScript Object Notation)是一種輕量級(jí)數(shù)據(jù)交換格式,便于人們閱讀和編寫(xiě),同時(shí)也易于機(jī)器解析和生成。JSON 采用完全獨(dú)立于語(yǔ)言的文本格式,但也延續(xù)了類似于C 語(yǔ)言家族(包括C、C++、C#、Java、JavaScript、Perl,Python 等)的習(xí)慣,這些特性使得JSON 成為理想的數(shù)據(jù)交換語(yǔ)言。在網(wǎng)頁(yè)中使用JSON 作為數(shù)據(jù)包傳輸格式時(shí)效率很高,相較于XML 數(shù)據(jù)格式擁有更高的有效數(shù)據(jù)量[19]。
OpenCV 是一個(gè)基于BSD(Berkly Software Distribution)許可發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)軟件庫(kù),實(shí)現(xiàn)了計(jì)算機(jī)視覺(jué)和圖像處理方面的很多通用算法。OpenCV 的應(yīng)用領(lǐng)域非常廣泛,包括圖像拼接、圖像降噪、產(chǎn)品質(zhì)檢、人機(jī)交互、人臉識(shí)別、動(dòng)作識(shí)別、動(dòng)作跟蹤等[20-21]。OpenCV 還提供了機(jī)器學(xué)習(xí)模塊,用戶可以使用正態(tài)貝葉斯、K 最近鄰、支持向量機(jī)、決策樹(shù)、隨機(jī)森林、人工神經(jīng)網(wǎng)絡(luò)等機(jī)器學(xué)習(xí)算法。
目標(biāo)檢測(cè)數(shù)據(jù)集的收集與半自動(dòng)標(biāo)注方法總體設(shè)計(jì)流程見(jiàn)圖2。該流程適用于大多數(shù)目標(biāo)檢測(cè)任務(wù),本文以創(chuàng)建安全帽佩戴檢測(cè)數(shù)據(jù)集為例實(shí)現(xiàn)整個(gè)流程。
自定義目標(biāo)檢測(cè)數(shù)據(jù)集的一個(gè)來(lái)源是網(wǎng)絡(luò)爬蟲(chóng)爬取,通??梢酝ㄟ^(guò)搜索引擎(如百度、必應(yīng)和谷歌)搜索相應(yīng)的關(guān)鍵詞,然后分析頁(yè)面,確定一定規(guī)則以爬取圖片鏈接并進(jìn)行下載;另一個(gè)來(lái)源是通過(guò)視頻獲取,如對(duì)現(xiàn)場(chǎng)拍攝或網(wǎng)絡(luò)下載的視頻進(jìn)行逐幀處理可得到所需圖片數(shù)據(jù)。爬蟲(chóng)爬取的文件可能存在相同和相似圖片,且視頻獲取的相鄰幀圖片之間相似度極大,因此設(shè)計(jì)去重模塊檢測(cè)圖片之間的相似度,僅保留相似圖片中的一張。
Fig.2 Overall design process圖2 總體設(shè)計(jì)流程
收集到的圖片數(shù)據(jù)需要經(jīng)過(guò)標(biāo)注后才可以在目標(biāo)檢測(cè)模型中進(jìn)行訓(xùn)練,然而圖片數(shù)量龐大,純?nèi)斯?biāo)注將耗費(fèi)大量時(shí)間,因此本文設(shè)計(jì)了半自動(dòng)標(biāo)注方法。半自動(dòng)標(biāo)注主要通過(guò)某個(gè)目標(biāo)檢測(cè)網(wǎng)絡(luò)訓(xùn)練部分已經(jīng)標(biāo)注好的數(shù)據(jù)集,如果有相符的公共數(shù)據(jù)集可直接用于模型訓(xùn)練,否則就要先對(duì)收集到的部分圖片進(jìn)行標(biāo)注,然后通過(guò)訓(xùn)練好的模型預(yù)測(cè)自行收集的圖片數(shù)據(jù),得到預(yù)測(cè)的標(biāo)注框和類別信息,并使用這些信息生成對(duì)應(yīng)的標(biāo)注文件。生成的標(biāo)注文件會(huì)存在誤標(biāo)注的情況,需要人工進(jìn)行更正和排除,因此稱為半自動(dòng)標(biāo)注方法。
3.1.1 Item數(shù)據(jù)定義
Scrapy 框架爬取圖片需要Item 對(duì)象具有image_urls 屬性,如果另行設(shè)置images 屬性,圖片下載得到的信息便會(huì)保存到這個(gè)屬性中,包括是否下載成功和下載位置等信息。本文使用的Item 定義為:
3.1.2 數(shù)據(jù)爬取
通過(guò)百度圖片搜索關(guān)鍵詞的方法獲取圖片url,通過(guò)百度圖片搜索的JSON 接口(https://image.baidu.com/search/acjson)發(fā)起請(qǐng)求,請(qǐng)求url實(shí)例如下:
其中,word 表示搜索的關(guān)鍵詞;pn 表示從第幾張圖片
開(kāi)始;rn表示搜索返回的圖片數(shù)量。
返回的JSON 數(shù)據(jù)示例為:
可以從返回的JSON 數(shù)據(jù)中獲取所有的middleURL 作為Item 對(duì)象的image_urls,解析獲取的JSON 數(shù)據(jù)流程為:
3.1.3 配置圖片下載和存儲(chǔ)
通過(guò)配置settings.py 的ITEM_PIPELINES 可指定使用ImagebaiduspiderPipeline 作為圖片的下載通道,并設(shè)置IMAGES_STORE 指定圖片下載的文件夾全路徑,設(shè)置RETRY_TIMES 指定下載失敗的重試次數(shù)。本文實(shí)驗(yàn)使用的部分配置為:
通過(guò)Python 和OpenCV 可以獲取視頻的逐幀圖片,流程如圖3 所示。一個(gè)視頻通過(guò)OpenCV 讀取后可以循環(huán)獲取每一幀圖片,由于視頻幀數(shù)量大,且相鄰幀一般變化不大,因此設(shè)置skip 參數(shù),代表每隔skip 數(shù)量的視頻幀取一幀保存。獲取視頻幀的部分代碼如下:
Fig.3 Flow of getting pictures frame by frame from video圖3 視頻逐幀獲取圖片流程
通過(guò)比較圖片之間的相似度可以排除一些重復(fù)和相似的圖片。遍歷兩張圖片的所有像素并作差以判斷圖片是否相同的方法雖然速度快,但太過(guò)嚴(yán)格,一旦僅有一個(gè)像素不同便會(huì)判斷圖片不相同,因此只能用于排除重復(fù)圖片,不能用于排除相似圖片。本文通過(guò)直方圖比較的方式判別圖片的相似度,原理是獲取被比較圖片的直方圖數(shù)據(jù)并進(jìn)行歸一化,比較歸一化后的數(shù)據(jù)得到相似指數(shù),通過(guò)設(shè)定相似指數(shù)閾值判斷兩張圖片是否相似。
通過(guò)Python 和OpenCV 計(jì)算相似度的代碼為:
本文實(shí)驗(yàn)相似指數(shù)閾值設(shè)置為0.99,去重前后圖片數(shù)量比較見(jiàn)圖4(彩圖掃OSID 碼可見(jiàn),下同)。通過(guò)Scrapy 爬取1 477 張圖片,通過(guò)24 個(gè)視頻逐幀獲取21 069 張圖片,共收集到22 546 張圖,去重后得到17 493 張圖片,保存于文件夾D:/predata/helmet_img 下。
Fig.4 Comparison of the number of pictures before and after deduplication圖4 去重前后圖片數(shù)量比較
通過(guò)訓(xùn)練目標(biāo)檢測(cè)模型實(shí)現(xiàn)對(duì)圖片數(shù)據(jù)的自動(dòng)標(biāo)注。本文選擇YOLOv5 模型,訓(xùn)練數(shù)據(jù)集為開(kāi)源的SHWD(Safety-Helmet-Wearing-Dataset)安全帽佩戴數(shù)據(jù)集,包括7 581 張圖像,其中有9 044 個(gè)佩戴安全帽對(duì)象和111 514個(gè)未佩戴安全帽對(duì)象。數(shù)據(jù)集的標(biāo)注方法見(jiàn)圖5,佩戴安全帽的頭部標(biāo)注為hat,未佩戴安全帽的頭部標(biāo)注為person。
模型訓(xùn)練命令如下:
其中,--data 表示配置訓(xùn)練使用的數(shù)據(jù)源,本文使用的數(shù)據(jù)源為YOLO 標(biāo)注格式的SHWD 數(shù)據(jù)集;--hyp 表示指定超參數(shù)配置文件,本文使用默認(rèn)的hyp.scratch.yaml;--name 表示保存訓(xùn)練結(jié)果的文件名。
Fig.5 Example of data set annotation圖5 數(shù)據(jù)集標(biāo)注示例
訓(xùn)練結(jié)束后可使用得到的best.pt(runs/train/helmet/weights/best.pt)預(yù)測(cè)自行收集到的圖片數(shù)據(jù)。
使用訓(xùn)練好的YOLOv5模型對(duì)收集到的圖片數(shù)據(jù)生成對(duì)應(yīng)的標(biāo)注,執(zhí)行命令為:
其中,--weights 表示預(yù)測(cè)使用的模型權(quán)重文件,本文設(shè)置為前面訓(xùn)練結(jié)果的best.pt 文件;--source 表示預(yù)測(cè)的源,本文設(shè)置為自行收集圖片所在的文件夾;--conf-thres表示置信度閾值,只有預(yù)測(cè)框的置信度大于閾值才會(huì)生成標(biāo)注,可按需設(shè)置;--nosave 表示不保存預(yù)測(cè)結(jié)果圖片,因?yàn)閮H需要標(biāo)注文件;--save-txt 表示保存預(yù)測(cè)的標(biāo)注文件。
由于收集到的圖片中含有大量非目標(biāo)圖片,有必要進(jìn)行過(guò)濾。讀取生成的標(biāo)注文件,只保留含有hat標(biāo)注和person 標(biāo)注的文件及其對(duì)應(yīng)圖片,如此可過(guò)濾大量無(wú)用數(shù)據(jù),免去人工過(guò)濾步驟,最后得到質(zhì)量較好的數(shù)據(jù)。數(shù)據(jù)過(guò)濾流程見(jiàn)圖6。
過(guò)濾后得到含有hat 標(biāo)注(可能有person 標(biāo)注)的數(shù)據(jù)10 951個(gè),僅含有person 標(biāo)注的數(shù)據(jù)1 563個(gè)。有標(biāo)簽數(shù)據(jù)的分組主要是為了加快人工修正速率,因?yàn)槎嗄繕?biāo)標(biāo)注需要經(jīng)常轉(zhuǎn)換標(biāo)簽,會(huì)花費(fèi)一定時(shí)間。過(guò)濾掉沒(méi)有標(biāo)注的數(shù)據(jù)共4 979 個(gè),主要包含沒(méi)有人體、有部分人體卻沒(méi)有頭部、有頭部但沒(méi)有被識(shí)別出來(lái)的圖片等。未標(biāo)注的圖片示例見(jiàn)圖7。
經(jīng)過(guò)以上操作得到的數(shù)據(jù)集已經(jīng)包含圖片文件及其對(duì)應(yīng)的標(biāo)注文件,然而通過(guò)YOLOv5 生成的標(biāo)注文件并不會(huì)100%正確,還需要進(jìn)行人工修正。LableImg 軟件可以通過(guò)Open Dir 指定圖片文件目錄,通過(guò)Change Save Dir 指定標(biāo)注的文件目錄,標(biāo)注的格式指定為YOLO,具體示例見(jiàn)圖8。
Fig.6 Process of filtering data圖6 數(shù)據(jù)過(guò)濾流程
Fig.7 Examples of unlabeled pictures圖7 未標(biāo)注的圖片示例
LableImg 軟件可以非常方便地實(shí)現(xiàn)標(biāo)注文件的可視化和修改,修改項(xiàng)目包括有目標(biāo)而未正確標(biāo)注、標(biāo)注框位置錯(cuò)誤、標(biāo)注框類別錯(cuò)誤和標(biāo)注框大小不合適等,示例見(jiàn)圖9。
Fig.8 Example of using LabelImg圖8 LabelImg使用示例
Fig.9 Examples of annotations that need to be modified圖9 需要修改標(biāo)注的示例
通過(guò)訓(xùn)練好的YOLOv5模型預(yù)測(cè)得到的標(biāo)注僅可作為人工標(biāo)注的參考,在進(jìn)行人工修正時(shí),不僅需要修改明顯錯(cuò)誤的標(biāo)注,必要時(shí)還可以拉升標(biāo)注框的長(zhǎng)寬比例,對(duì)標(biāo)注正確的標(biāo)注框進(jìn)行微調(diào)。更正過(guò)程會(huì)刪除部分不合理數(shù)據(jù),最后共得到10 967 張圖片及其對(duì)應(yīng)的標(biāo)簽。對(duì)更正后的數(shù)據(jù)集進(jìn)行訓(xùn)練集、驗(yàn)證集和測(cè)試集劃分便可用于YOLO 模型的訓(xùn)練,也可以通過(guò)編寫(xiě)腳本轉(zhuǎn)化為其他格式(如VOC 和COCO 格式等)用于其他目標(biāo)檢測(cè)模型的訓(xùn)練。格式之間的不同主要體現(xiàn)在標(biāo)注框上,YOLO 標(biāo)簽的格式包含標(biāo)注框的歸一化中心坐標(biāo)(x_center,y_center)和寬高(w,h),而VOC 格式的標(biāo)注框格式包含標(biāo)注框左上角的坐標(biāo)(xmin,ymin)和右上角的坐標(biāo)(xmax,ymax)。設(shè)圖片實(shí)際寬高分別為width 和height,YOLO 格式的標(biāo)注框轉(zhuǎn)換為VOC 格式的公式為:
由于收集得到的數(shù)據(jù)集由自動(dòng)檢測(cè)結(jié)果和人工標(biāo)注結(jié)果混合而成,這樣的數(shù)據(jù)集不利于模型進(jìn)一步學(xué)習(xí)。本文使用YOLOv5 模型進(jìn)行半自動(dòng)人工標(biāo)注,如果再使用修正后的數(shù)據(jù)集訓(xùn)練YOLOv5 模型是不合適的,因此得到的數(shù)據(jù)集可以應(yīng)用于除YOLOv5模型以外的其他目標(biāo)檢測(cè)網(wǎng)絡(luò)的訓(xùn)練或不需要進(jìn)行深層次改進(jìn)的目標(biāo)檢測(cè)任務(wù)中。當(dāng)希望獲得更好的目標(biāo)檢測(cè)模型而對(duì)數(shù)據(jù)集要求更高時(shí),可以通過(guò)生成的標(biāo)注獲取所需圖片后不使用自動(dòng)生成標(biāo)注方法,而使用人工方式對(duì)全部數(shù)據(jù)進(jìn)行標(biāo)注。
本文設(shè)計(jì)的自定義目標(biāo)檢測(cè)數(shù)據(jù)集的收集與半自動(dòng)標(biāo)注方法通過(guò)爬蟲(chóng)技術(shù)和視頻取幀獲得了大量目標(biāo)檢測(cè)圖片數(shù)據(jù),通過(guò)訓(xùn)練好的目標(biāo)檢測(cè)模型和人工修正方便快速地創(chuàng)建了數(shù)據(jù)量巨大的數(shù)據(jù)集,且在制作過(guò)程中便可以通過(guò)算法過(guò)濾大量無(wú)用數(shù)據(jù),大大減少了人工過(guò)濾時(shí)間。然而該方法還有很多需要優(yōu)化之處,如處理大量圖片時(shí)設(shè)計(jì)的去重算法會(huì)花費(fèi)大量時(shí)間;需要訓(xùn)練某個(gè)目標(biāo)檢測(cè)算法時(shí)需要熟悉該算法并搭建訓(xùn)練環(huán)境,如果沒(méi)有公共數(shù)據(jù)集用于訓(xùn)練,則需要從收集的數(shù)據(jù)中先標(biāo)注部分?jǐn)?shù)據(jù)用于訓(xùn)練。本文方法雖然實(shí)現(xiàn)了半人工標(biāo)注,但人工修正仍然需要花費(fèi)一定時(shí)間,選擇預(yù)測(cè)準(zhǔn)確度高的模型可以大大降低人工修正難度。