反光衣识别算法冠军方案总结(附源码)|极市打榜
反光衣識別算法冠軍方案總結(附源碼)|極市打榜
原創 CV開發者都愛看的 [極市平臺](javascript:void(0)😉
極市平臺
微信號 extrememart
功能介紹 專注計算機視覺前沿資訊和技術干貨,官網:www.cvmart.net
作者丨nobug_w
編輯丨極市平臺
極市導讀
本文為反光衣識別算法的冠軍方案總結,作者總結了自己打榜時的經驗并給出了相關訓練和推理的代碼,希望能給大家帶來一些幫助~ >>加入極市CV技術交流群,走在計算機視覺的最前沿
平日比較關注極市平臺,最近在極市平臺看到類似競賽的算法打榜,有些榜有冠軍導師指導打榜,并且還有豐厚的獎品(又能躺還有獎品)。抱著試一試的心態,報名參加了一下,在獲得獎勵的同時讓自己也得到了項目上的鍛煉。下文總結了打榜時的經驗以及相關訓練和推理代碼,希望能給大家帶來一些幫助~
1.任務介紹
反光衣識別(學習訓練營專屬)對圖像進行實時檢測,可實時檢測指定區域內的現場工作人員是否按照要求穿反光衣(綠色反光衣或紅色反光衣任一即可),當發現視頻畫面內出現人員未穿反光衣時,系統主動觸發告警提示。真正做到施工工地安全信息化管理,做到事前預防,事中常態監測,事后規范管理。
算法打榜正在進行中
反光衣識別算法打榜(報名參與):
https://www.cvmart.net/topList/10044?tab=RealTime&dbType=1
2.評價指標
本榜最終得分采取準確率、算法性能絕對值綜合得分的形式,具體如下:
說明:
總分為本項目排行榜上的Score,排名:總分值越高,排名越靠前;
算法性能指的賽道標準值是 100 FPS, 如果所得性能值FPS≥賽道標準值FPS,則算法性能值得分=1;
評審標準:參賽者需要獲得算法精度和算法性能值的成績,且算法精度≥0.1,算法性能值FPS≥10,才能進入獲獎評選;
反光衣識別(學習訓練營專屬)是對新手十分友好的,只要總分達到0.8分即可獲得豐厚的獎勵。
獎勵正在進行中…
3.數據分析
本次比賽一共包括四類類別:reflective_vest(反光衣),no_reflective_vest(未穿或不規范穿反光衣)、person_reflective_vest(穿反光衣的行人)、person_no_reflective_vest(未穿或不規范穿反光衣的行人)。打榜者對圖像中反光衣穿著情況的進行目標檢測,給出目標框和對應的類別信息,且預警情況只有no_reflective_vest(未穿或不規范穿反光衣)這一情況。
數據集是由監控攝像頭采集的現場場景數據,訓練數據集的數量為36346張,測試數據集的數量為14024張??梢姅祿膱D像數量非常很多,因此如果采用十分龐大的網絡模型訓練,比如兩階段檢測模型,勢必會十分緩慢。
通過查看樣例集的數據,可以發現人員所處的環境比較復雜。另外,數據集是從監控攝像頭中采集,人員在近距離和遠距離都有,目標的尺度比較豐富。因此需要選用具有多尺度檢測能力的檢測器。雖然圖像中有時會存在比較小的目標,但是由于場景為施工現場,所以目標相對比較稀疏,遮擋情況不太嚴重,且與周圍環境相比目標特征也比較明顯。
4.技術展示
這次訓練技術展示分為兩個部分:訓練方法和推理方法。
通過以上分析以及往屆極市平臺介紹的方案,我們選擇YOLO算法。最近yolov5更新到v6.0版本,其性能優秀并且訓練、部署、調優等方面使用非常靈活方便。因此選擇YOLOv5作為baseline,在此基礎上根據實際情況進行具體模型的選擇和模型的修改。
其中,yolov5算法的框架如下圖所示。Yolov5s,m,x等結構僅僅為網絡深度和寬度差別,由yolov5*.yaml結構定義文件夾的超參數depth_multiple和width_multiple控制。
這是很早之前的一幅圖,現在YOLOv5的v6.0版本,已經有了修改,backbone主要修改如下:
1.第一層取消了Focus,采用卷積核大小為6,步長為2的卷積層代替。yolov5官方解答,Focus() 是用來降低FLOPS的,跟mAP無關。Focus模塊在v5中是圖片進入backbone前,對圖片進行切片操作,具體操作是在一張圖片中每隔一個像素拿到一個值,類似于鄰近下采樣,這樣就拿到了四張圖片,四張圖片互補,輸入通道擴充了4倍,即拼接起來的圖片相對于原先的RGB三通道模式變成了12個通道,最后將得到的新圖片再經過卷積操作,最終得到了沒有信息丟失情況下的二倍下采樣特征圖。
2.更改backbone的基本單元BottleneckCSP為c3模塊。在新版yolov5中,作者將BottleneckCSP(瓶頸層)模塊轉變為了C3模塊,其結構作用基本相同均為CSP架構,只是在修正單元的選擇上有所不同,其包含了3個標準卷積層以及多個Bottleneck模塊(數量由配置文件.yaml的ndepth_multiple參數乘積決定)從C3模塊的結構圖可以看出,C3相對于BottleneckCSP模塊不同的是,經歷過殘差輸出后的Conv模塊被去掉了,concat后的標準卷積模塊中的激活函數也由LeakyRelu變味了SiLU。
①C3模塊
②BottleNeckCSP模塊
3.更改Leaky_Relu激活函數為SiLU激活函數。作者在CONV模塊(CBL模塊)中封裝了三個功能:包括卷積(Conv2d)、BN以及Activate函數(在新版yolov5中,作者采用了SiLU函數作為激活函數),同時autopad(k, p)實現了padding的效果。
4.SPP更改為SPPF(Spatial Pyramid Pooling - Fast), 結果是一樣的,但是可以降低FLOPS,運行的更快。
官方介紹:
訓練方法
首先,在訓練之前,我們將訓練集進行劃分訓練集:測試集為8:2。其中訓練集圖像數量為29077,測試集圖像數量為7269.數據集目錄在’/home/data/309/’,如果是在實例中,100張樣例在’/home/data/309/sample_m’。
1.由于數據集的jpg和xml在一個文件夾,首先我們將圖片和標簽進行分離,源碼如下:
import osimport shutilfrom os import listdir, getcwdfrom os.path import joindatasets_path = '/home/data/309/'def jpg_xml(): if not os.path.exists(datasets_path + 'Annotations/'): os.makedirs(datasets_path + 'Annotations/') if not os.path.exists(datasets_path + 'images/'): os.makedirs(datasets_path + 'images/') filelist = os.listdir(datasets_path) for files in filelist: filename1 = os.path.splitext(files)[1] # 讀取文件后綴名 if filename1 == '.jpg': full_path = os.path.join(datasets_path, files) shutil.move(full_path, datasets_path+'images') elif filename1 == '.xml': full_path = os.path.join(datasets_path, files) shutil.move(full_path, datasets_path+'Annotations') else : continue2.然后根據自定義的訓練集和驗證集比例,生成txt。如果要更改比例,僅僅更改 trainval_percent和train_percent即可,源碼如下。
classes= ['reflective_vest','no_reflective_vest','person_reflective_vest','person_no_reflective_vest'] #自己訓練的類別import randomdef train_val_split(): trainval_percent = 0.2 train_percent = 0.8 images_filepath = datasets_path + 'images/' txtsavepath = datasets_path total_imgfiles = os.listdir(images_filepath) num = len(total_imgfiles) lists = range(num) tr = int(num * train_percent) train = random.sample(lists, tr) ftrain = open(txtsavepath + 'train.txt', 'w+') ftest = open(txtsavepath + 'test.txt', 'w+') fval = open(txtsavepath + 'val.txt', 'w+') for i in lists: name = images_filepath + total_imgfiles[i] + '\n' if i in train: ftrain.write(name) else: fval.write(name) ftest.write(name) ftrain.close() fval.close()ftest.close()3.最后將voc格式轉換為yolo格式,源碼如下。
def convert(size, box): dw = 1. / size[0] dh = 1. / size[1] x = (box[0] + box[1]) / 2.0 y = (box[2] + box[3]) / 2.0 w = box[1] - box[0] h = box[3] - box[2] x = x * dw w = w * dw y = y * dh h = h * dh return (x, y, w, h)def convert_annotation(image_id): in_file = open(datasets_path + 'Annotations/%s.xml' % (image_id),encoding='utf-8') out_file = open(datasets_path + 'labels/%s.txt' % (image_id), 'w',encoding='utf-8') tree = ET.parse(in_file) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) for obj in root.iter('object'): difficult = 0 cls = obj.find('name').text if cls not in classes or int(difficult) == 1: continue cls_id = classes.index(cls) xmlbox = obj.find('bndbox') b=(float(xmlbox.find('xmin').text),float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) bb = convert((w, h), b) out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')def generate_labels(): if not os.path.exists(datasets_path + 'labels/'): os.makedirs(datasets_path + 'labels/') sets = ['train', 'val'] for image_set in sets: image_ids = open(datasets_path + '%s.txt' % (image_set)).read().strip().split() for image_id in image_ids: convert_annotation(image_id.split('/')[-1][:-4])在第一次訓練時,我們選擇了yolov5m模型。在訓練了12小時后,僅僅訓練了幾個epoch,并且進行第一次測試,結果f1-score僅僅為0.2732,并且性能分很低。在時間緊張且計算資源有限的情況下,這顯然不能滿足我們的需求。
然后,我們選擇了yolov5s模型,進行第二次訓練。選擇hyp.scratch.yaml配置文件作為參數,并且修改了其中數據增強方式,主要將參數mosaic: 1.0 # image mosaic (probability) 數值修改為0.5。如下圖所示:
因為在數據集中小目標較少,不需要每次都進行mosaic。并且不采用裁剪、復制粘貼、旋轉、mixup。因為我覺得數據量其實已經足夠訓練yolov5s網絡了。并且為了加快訓練速度,輸入圖像改為512大小,能多訓練幾個epoch。優化器選擇SGD優化器即可。并且這里需要采用官方的yolov5s.pt作為預訓練模型,能加速模型的收殮。
在12小時訓練完成后,f1-score就可以到0.7543。
在第三次訓練時,采用同樣的方法進行訓練。一方面使測試集中的圖像參加到訓練過程中;另一方面,12個小時才訓練了幾個epoch,肯定沒有訓練充分。再等12小時后訓練完,f1-score就可以到0.7746。此時與0.8分就十分接近了。
最后,我們采用凍結訓練策略,并且訓練圖像大小修改為640。Yolov5凍結參數也十分方便,只需要傳遞參數即可。我們將backbone以及neck+head輪流凍結。并且直接采用hyp.scratch-med.yaml進行最后的訓練。這一部分具體看石工講的凍結訓練策略。通過最后一步,f1-sorce達到了0.8031。
這里需要對源碼進行修改,主要是因為在neck+head凍結時,yolov5只能順序凍結。這里需要修改,修改方式如下。修改后便可以凍結任意層。
①train.py修改前:
train.py修改后:
②train.py修改前:
train.py修改后:
此時我們計算一下,0.8-0.8031*0.9=0.07721。然后再0.07721/0.1=0.7721。即,性能分達到77.21就滿足了,是不是很容易了。
推理方法
在推理部分,我們這里直接pt文件直接進行推理,并沒有采用模型加速方案。但是不采用FP32精度進行推理,而是采用FP16進行推理。具體可以參考,detect.py文件中的方法。運行時直接采用添加—half即可采用FP16進行推理。在本次打榜中,我僅僅采用FP16半精度推理即可達到比賽要求。
根據https://www.cvmart.net/topList/10044?dbType=1&tab=RankDescription 的賽道說明,我們寫測試文件,源碼如下。
import jsonimport torchimport sysimport numpy as npfrom pathlib import Pathfrom ensemble_boxes import weighted_boxes_fusionfrom models.experimental import attempt_loadfrom utils.torch_utils import select_devicefrom utils.general import check_img_size, non_max_suppression, scale_coordsfrom utils.augmentations import letterbox@torch.no_grad()model_path = '/best.pt'def init(): weights = model_path device = 'cuda:0' # cuda device, i.e. 0 or 0,1,2,3 or half = True # use FP16 half-precision inference device = select_device(device) w = str(weights[0] if isinstance(weights, list) else weights) model = torch.jit.load(w) if 'torchscript' in w else attempt_load(weights, map_location=device) if half: model.half() # to FP16 model.eval() return modeldef process_image(handle=None, input_image=None, args=None, **kwargs): half = True # use FP16 half-precision inference conf_thres = 0.5 # confidence threshold iou_thres = 0.5 # NMS IOU threshold max_det = 1000 # maximum detections per image imgsz = [640, 640] names = { 0: 'reflective_vest', 1: 'no_reflective_vest', 2: 'person_reflective_vest', 3: 'person_no_reflective_vest' } stride = 32 fake_result = { } fake_result["algorithm_data"] = { "is_alert": False, "target_count": 0, "target_info": [] } fake_result["model_data"] = { "objects": [] } img = letterbox(input_image, imgsz, stride, True)[0] img = img.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB img /= 255.0 # 0 - 255 to 0.0 - 1.0 pred = handle(img, augment=False, visualize=False)[0] pred = non_max_suppression(pred, conf_thres, iou_thres, None, False, max_det=max_det) for i, det in enumerate(pred): # per image det[:, :4] = scale_coords(img.shape[2:], det[:, :4], input_image.shape).round() for *xyxy, conf, cls in reversed(det): xyxy_list = torch.tensor(xyxy).view(1, 4).view(-1).tolist() conf_list = conf.tolist() label = names[int(cls)] fake_result['model_data']['objects'].append({ "xmin": int(xyxy_list[0]), "ymin": int(xyxy_list[1]), "xmax": int(xyxy_list[2]), "ymax": int(xyxy_list[3]), "confidence": conf_list, "name": label }) if label == 'no_reflective_vest': fake_result['algorithm_data']['target_info'].append({ "xmin": int(xyxy_list[0]), "ymin": int(xyxy_list[1]), "xmax": int(xyxy_list[2]), "ymax": int(xyxy_list[3]), "confidence": conf_list, "name": "no_reflective_vest" }) fake_result['algorithm_data']['is_alert'] = True if len( fake_result['algorithm_data']['target_info']) > 0 else False fake_result['algorithm_data']["target_count"] = len(fake_result['algorithm_data']['target_info']) return json.dumps(fake_result, indent=4)5.討論與總結
本次極市平臺舉行的基于反光衣識別的新手訓練營項目,確實對新手十分的友好,容易上手,不需要添加額外的tricks,也不需要更換backbone,neck即可達到要求,能夠很好的熟悉平臺。本人作為新人,本次打榜相關的結論可歸納為以下幾點:
**選擇好baseline是基礎。**最開始本人由于經驗少,以為選擇大的模型肯定能取得好的分數。因此,我們要針對數據情況、計算資源、算法精度和性能選擇合適的baseline.
**做好數據分析是關鍵。**目標尺度分布,目標遮擋情況,目標密集程度,數據集數量等等方面,影響著我們選擇對應策略。比如,小目標過多的情況下,需要采用mosic數據增強策略;數據充足且豐富的情況下適當減少數據增強策略;圖像尺寸根據實際情況進行調整。
**多看別人經驗十分重要。**本次能上榜的原因也是石工之前的凍結訓練策略能運用上,才達到打榜要求。除此之外,還有許多提分經驗,希望大家多多嘗試。深度學習可能就是這樣,在別人上面可能有效,在自己工程上就無效了,要多嘗試。
針對賽題對性能的要求,采用FP16精度做推理,若需要更高的推理速度,可采用Openvino和TensorRT等方式部署模型。
作者介紹
王鋮,來自西北師范大學VIGP團隊成員,
研究方向:深度學習,目標檢測等
參考
https://github.com/ultralytics/yolov5
https://mp.weixin.qq.com/s/e07eRbNAkoDVRs7Q-rV0TA
https://mp.weixin.qq.com/s/VgDcS-edk9Mqkv-qSfcRJA
www.cvmart.net
https://blog.csdn.net/weixin_38842821/article/details/108544609
**打榜說明:**極市打榜是面向計算機視覺開發者的算法競技,參與者人人都可以通過提高算法分數(精度+性能分)獲得早鳥獎勵+分分超越獎勵,排行榜前三名的勝利者將有機會獲得該算法的極市復購訂單,獲得持續的訂單收益。
提供免費算力+真實場景數據集;早鳥獎勵+分分超越獎勵+持續訂單分成,實時提現!
反光衣識別算法打榜(報名參與):
https://www.cvmart.net/topList/10044?tab=RealTime&dbType=1
墨鏡識別、安全帽識別、占道經營識別等26個打榜算法地址(正在進行中):https://www.cvmart.net/topList
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6ChLxP51-1637837795137)(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)]
掃碼查看(報名)打榜
如果覺得有用,就請分享到朋友圈吧!
極市平臺
專注計算機視覺前沿資訊和技術干貨,官網:www.cvmart.net
582篇原創內容
公眾號
△點擊卡片關注極市平臺,獲取最新CV干貨
公眾號后臺回復“transformer”獲取最新Transformer綜述論文下載~
極市干貨
課程/比賽:珠港澳人工智能算法大賽|保姆級零基礎人工智能教程
算法trick:目標檢測比賽中的tricks集錦|從39個kaggle競賽中總結出來的圖像分割的Tips和Tricks
技術綜述:一文弄懂各種loss function|工業圖像異常檢測最新研究總結(2019-2020)
_CV技術社群邀請函 _#
△長按添加極市小助手
添加極市小助手微信(ID : cvmart4)
備注:姓名-學校/公司-研究方向-城市(如:小極-北大-目標檢測-深圳)
即可申請加入極市目標檢測/圖像分割/工業檢測/人臉/醫學影像/3D/SLAM/自動駕駛/超分辨率/姿態估計/ReID/GAN/圖像增強/OCR/視頻理解等技術交流群
每月大咖直播分享、真實項目需求對接、求職內推、算法競賽、干貨資訊匯總、與 10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發者互動交流~
覺得有用麻煩給個在看啦~[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Epwy0irU-1637837795141)(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)]
var first_sceen__time = (+new Date()); if ("" == 1 && document.getElementById(‘js_content’)) { document.getElementById(‘js_content’).addEventListener(“selectstart”,function(e){ e.preventDefault(); }); }
預覽時標簽不可點
收錄于話題 #
閱讀原文
閱讀
分享 收藏
贊 在看
反光衣識別算法冠軍方案總結(附源碼)|極市打榜
總結
以上是生活随笔為你收集整理的反光衣识别算法冠军方案总结(附源码)|极市打榜的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络架构之争:三大主流架构对决,谁是王者
- 下一篇: CVPR2021 论文大盘点:全景分割论