摘要:鳥類識別是深度學習和機器視覺領域的一個熱門應用,本文詳細介紹基於YOLOv5的鳥類檢測識別系統,在介紹演演算法原理的同時,給出Python的實現程式碼以及PyQt的UI介面。在介面中可以選擇各種鳥類圖片、視訊以及開啟攝像頭進行檢測識別;可通過UI介面選擇檔案,切換標記識別目標,支援切換模型,支援使用者登入註冊介面;基於YOLOv5模型訓練實現,提供訓練資料集和訓練程式碼,檢測速度快、識別精度較高;另外,還提供了可訓練程式碼和資料集。博文給出了Python程式碼介紹和使用教學,適合新入門的朋友參考,完整程式碼資原始檔請轉至文末的下載連結。本博文目錄如下:
完整資源下載:https://mbd.pub/o/bread/ZJaUm5hv
參考視訊演示:https://www.bilibili.com/video/BV1QL411C783/
離線依賴庫下載:https://pan.baidu.com/s/1hW9z9ofV1FRSezTSj59JSg?pwd=oy4n (提取碼:oy4n )
作為一個地區生物多樣性與生態環境的重要指標,「鳥類數量及分佈」越來越受到自然保護區、溼地公園、動物保護監管部門等機構的重視,實時監測鳥類品種、數量與分佈,成為各地區的常態化工作。本文使用YOLOv5目標檢測演演算法,可以為鳥類監測識別提供AI技術支援,提升監測識別效率,解決單純人工監測造成的低效與誤差,為鳥類保護養育提供更好的資料支撐。
鳥類監測識別具有較高複雜性,鳥類飛行路線不定、落點不定、時間不定,監測區域多樣(森林、溼地、湖泊、草地等),部分鳥類習性、形體、顏色具有極高相似度,這些因素使得對鳥類監測識別技術的要求極高。傳統的機器視覺演演算法難以實現準確快速識別鳥類的品種和位置,近年來,機器學習和深度學習取得了較大的發展,深度學習方法在檢測精度和速度方面與傳統方法相比表現出更良好的效能。YOLOv5是單階段目標檢測演演算法YOLO的第五代,根據實驗得出結論,其在速度與準確效能方面都有了明顯提升,其論文可參考TPH-YOLOv5: Improved YOLOv5 Based on Transformer Prediction Head for Object Detection on Drone-captured Scenarios,開源的程式碼可見https://github.com/ultralytics/yolov5(官方原始碼倉庫)。
自動化的鳥類識別能夠幫助人們更方便地瞭解地理區域內特定鳥類的數量和活動情況,目前網上鳥類檢測和識別的應用較少,能夠參考的例子不多,幾乎沒有人將其開發成一個可以展示的完整軟體,並不方便選擇圖片、視訊檔和實時檢測。對此這裡博主利用加州理工學院鳥類資料集(The Caltech-UCSD Birds-200-2011 Dataset)訓練YOLOv5模型,並給出自行設計的UI介面,保持博主同款的簡約風,功能也可以滿足圖片、視訊和攝像頭的識別檢測,切換模型、儲存結果等,希望大家可以喜歡,初始介面如下圖:
檢測鳥的種類時的介面截圖(點選圖片可放大)如下圖,可識別畫面中存在的多個鳥的類別,也可開啟攝像頭或視訊檢測:
詳細的功能演示效果參見博主的B站視訊或下一節的動圖演示,覺得不錯的朋友敬請點贊、關注加收藏!系統UI介面的設計工作量較大,介面美化更需仔細雕琢,大家有任何建議或意見和可在下方評論交流。
鳥類檢測識別系統主要用於野外或日常生活場景中鳥類影象的識別,顯示鳥類目標在影象中的類別、位置、數目、置信度等;可對圖片、視訊檔讀取的影象,或從攝像頭獲取的實時畫面中的鳥類進行識別,演演算法模型可選擇替換;系統介面包含使用者註冊、登入功能,方便使用者進行管理和使用;識別結果視覺化,結果實時顯示並能夠進行目標逐個標註、顯示和資料展示;畫面顯示視窗可縮放、拖動、自適應,結果可點選按鈕儲存,方便後續查閱使用。
軟體好不好用,顏值很重要,首先我們還是通過動圖看一下鳥類識別的效果,系統主要實現的功能是對圖片、視訊和攝像頭畫面中的鳥類進行識別,檢測的結果視覺化顯示在介面和影象中,提供模型切換、單個目標選中等功能,其演示效果如下。
(一)使用者註冊登入介面
這裡設計了一個登入介面,可以註冊賬號和密碼,然後進行登入。介面還是參考了當前流行的UI設計,左側是一個動圖,右側輸入賬號、密碼、驗證碼等等。
(二)選擇鳥類圖片識別
系統允許選擇圖片檔案進行識別,點選圖片選擇按鈕圖示選擇圖片後,顯示所有鳥類識別的結果,可通過下拉選框檢視單個鳥類的結果。本功能的介面展示如下圖所示:
(三)視訊識別效果展示
很多時候我們需要識別一段視訊中的鳥的種類,這裡設計了視訊選擇功能。點選視訊按鈕可選擇待檢測的視訊,系統會自動解析視訊逐幀識別鳥類,並將結果標記在畫面中,效果如下圖所示:
(四)攝像頭檢測效果展示
在真實場景中,我們往往利用裝置攝像頭獲取實時畫面,同時需要對畫面中的鳥類進行識別,因此本文考慮到此項功能。如下圖所示,點選攝像頭按鈕後系統進入準備狀態,系統顯示實時畫面並開始檢測畫面中的鳥,識別結果展示如下圖:
(五)切換鳥類檢測模型
可選擇訓練得到的檢測模型,利用調優後的模型進行檢測,對於YOLOv5的預訓練模型通用適用。這裡可以自由切換不同的模型,以比較不同的檢測效果。
這裡我們使用的鳥類識別資料集,是加州理工學院鳥類資料集(The Caltech-UCSD Birds-200-2011 Dataset),CUB 資料集一共 200 個類別,共 11788 張圖片,每張圖片除包括類別標籤外,還有一個標註的物體邊框(Bounding Box)、關鍵點和一些其他屬性,屬於具有較高細粒度的鳥類影象資料集。
CUB資料集中每個物種都與Wikipedia文章相關聯,並按科學分類(順序、科、屬、物種)進行組織,包含200類鳥類子類,其中訓練資料集有5994張影象,測試集有5794張影象。每張影象均提供了影象類標記資訊,影象中鳥的bounding box,鳥的關鍵part資訊,以及鳥類的屬性資訊,下載CUB資料並解壓後得到如下的資料夾
由於CUB資料集的標註檔案和YOLO的格式不一致,這裡我們選取CUB資料集中的類別,轉換為YOLO格式。標籤格式轉換的程式碼可參考部落格:CUB_200_2011資料集轉Yolo格式,最終我們得到YOLO格式的資料集檔案,並進行模型訓練。
在訓練模型之前,為了讓我們的資料能夠被YOLO找到,我們需要寫一個data.yaml檔案儲存在案例目錄下,在其中記錄下資料的路徑和模型要識別的標記類別,檔案內容如下所示。YOLO通過讀取目錄下的data.yaml檔案,進而找到我們資料集儲存的位置才能讀取資料進行訓練驗證。
train: F:\BlogCode\BirdDet\Bird\train.txt # 訓練集
val: F:\BlogCode\BirdDet\Bird\test.txt # 驗證集
nc: 36 # 訓練的類別
names: ['Acadian_Flycatcher','American_Crow','American_Goldfinch','American_Pipit',
'American_Redstart','American_Three_toed_Woodpecker','Anna_Hummingbird','Artic_Tern','Baird_Sparrow','Baltimore_Oriole',
'Bank_Swallow','Barn_Swallow','Bay_breasted_Warbler','Belted_Kingfisher',
'Bewick_Wren','Black_Tern','Black_and_white_Warbler','Black_billed_Cuckoo','Black_capped_Vireo','Black_footed_Albatross','Black_throated_Blue_Warbler',
'Black_throated_Sparrow','Blue_Grosbeak','Blue_Jay','Blue_headed_Vireo','Blue_winged_Warbler','Boat_tailed_Grackle',
'Bobolink','Bohemian_Waxwing','Brandt_Cormorant','Brewer_Blackbird','Brewer_Sparrow','Bronzed_Cowbird',
'Brown_Creeper','Brown_Pelican','Brown_Thrasher']
訓練模型通過呼叫模型資料夾下的train.py進行,可以通過--batch引數和--epochs引數調整訓練批次大小和訓練輪數。YOLOv5提供了在COCO資料集上預訓練後的引數,我們可以通過引數--weights yolov5s.pt載入預訓練引數進行遷移學習,或在訓練巨量資料集(比如COCO)時用一個空的--weights ''引數從零開始訓練。然後設定各種引數,程式碼如下:
parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+', type=str, default='./weights/best.pt',
help='model.pt path(s)') # 模型路徑僅支援.pt檔案
parser.add_argument('--img-size', type=int, default=480, help='inference size (pixels)') # 檢測影象大小,僅支援480
parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold') # 置信度閾值
parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS') # NMS閾值
# 選中執行機器的GPU或者cpu,有GPU則GPU,沒有則cpu,若想僅使用cpu,可以填cpu即可
parser.add_argument('--device', default='',
help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--save-dir', type=str, default='inference', help='directory to save results') # 檔案儲存路徑
parser.add_argument('--classes', nargs='+', type=int,
help='filter by class: --class 0, or --class 0 2 3') # 分開類別
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS') # 使用NMS
opt = parser.parse_args() # opt區域性變數,重要
out, weight, imgsz = opt.save_dir, opt.weights, opt.img_size # 得到檔案儲存路徑,檔案權重路徑,影象尺寸
device = select_device(opt.device) # 檢驗計算單元,gpu還是cpu
half = device.type != 'cpu' # 如果使用gpu則進行半精度推理
model = attempt_load(weight, map_location=device) # 讀取模型
我們可以在終端輸入如下命令進行訓練,當然也可以直接點選train.py執行。
python train.py --batch 32 --epochs 300 --data data.yaml --weights yolov5s.pt --hyp data/hyps/hyp.scratch-med.yaml --cache
在深度學習中,我們通常通過損失函數下降的曲線來觀察模型訓練的情況。而YOLOv5訓練時主要包含三個方面的損失:矩形框損失(box_loss)、置信度損失(obj_loss)和分類損失(cls_loss),在訓練結束後,我們也可以在logs目錄下找到生成對若干訓練過程統計圖。下圖為博主訓練鳥類識別的模型訓練曲線圖。
在我們的訓練過程中,mAP50作為一種常用的目標檢測評估指標很快達到了較高水平,而mAP50:95也在訓練的過程中不斷提升,說明我們模型從訓練-驗證的角度表現良好。讀入一個測試資料夾進行預測,通過訓練得到的選取驗證集上效果最好的權重best.pt進行實驗,得到PR曲線如下圖所示。
在訓練完成後得到最佳模型,接下來我們將幀影象輸入到這個網路進行預測,從而得到預測結果,預測方法(predict.py)部分的程式碼如下所示:
def predict(img):
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float()
img /= 255.0
if img.ndimension() == 3:
img = img.unsqueeze(0)
t1 = time_synchronized()
pred = model(img, augment=False)[0]
pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes,
agnostic=opt.agnostic_nms)
t2 = time_synchronized()
InferNms = round((t2 - t1), 2)
return pred, InferNms
得到預測結果我們便可以將幀影象中的鳥類框出,然後在圖片上用opencv繪圖操作,輸出鳥的類別及鳥的預測分數。以下是讀取一個鳥類圖片並進行檢測的指令碼,首先將圖片資料進行預處理後送predict進行檢測,然後計算標記框的位置並在圖中標註出來。
if __name__ == '__main__':
img_path = "./UI_rec/test_/Bobolink_0079_10736.jpg"
image = cv_imread(img_path)
img0 = image.copy()
img = letterbox(img0, new_shape=imgsz)[0]
img = np.stack(img, 0)
img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, to 3x416x416
img = np.ascontiguousarray(img)
pred, useTime = predict(img)
det = pred[0]
p, s, im0 = None, '', img0
if det is not None and len(det): # 如果有檢測資訊則進入
det[:, :4] = scale_coords(img.shape[1:], det[:, :4], im0.shape).round() # 把影象縮放至im0的尺寸
number_i = 0 # 類別預編號
detInfo = []
for *xyxy, conf, cls in reversed(det): # 遍歷檢測資訊
c1, c2 = (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3]))
# 將檢測資訊新增到字典中
detInfo.append([names[int(cls)], [c1[0], c1[1], c2[0], c2[1]], '%.2f' % conf])
number_i += 1 # 編號數+1
label = '%s %.2f' % (names[int(cls)], conf)
# 畫出檢測到的目標物
plot_one_box(image, xyxy, label=label, color=colors[int(cls)])
# 實時顯示檢測畫面
cv2.imshow('Stream', image)
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
c = cv2.waitKey(0) & 0xff
執行得到的結果如下圖所示,圖中鳥類的種類和置信度值都標註出來了,預測速度較快。基於此模型我們可以將其設計成一個帶有介面的系統,在介面上選擇圖片、視訊或攝像頭然後呼叫模型進行檢測。
博主對整個系統進行了詳細測試,最終開發出一版流暢得到清新介面,就是博文演示部分的展示,完整的UI介面、測試圖片視訊、程式碼檔案,以及Python離線依賴包(方便安裝執行,也可自行設定環境),均已打包上傳,感興趣的朋友可以通過下載連結獲取。
若您想獲得博文中涉及的實現完整全部程式檔案(包括測試圖片、視訊,py, UI檔案等,如下圖),這裡已打包上傳至博主的麵包多平臺,見可參考部落格與視訊,已將所有涉及的檔案同時打包到裡面,點選即可執行,完整檔案截圖如下:
在資料夾下的資源顯示如下,其中包含了Python的離線依賴包,讀者可在正確安裝Anaconda和Pycharm軟體後,進行安裝,詳細演示也可見本人B站視訊。
注意:該程式碼採用Pycharm+Python3.8開發,經過測試能成功執行,執行介面的主程式為runMain.py和LoginUI.py,測試圖片指令碼可執行testPicture.py,測試視訊指令碼可執行testVideo.py。為確保程式順利執行,請按照requirements.txt設定Python依賴包的版本。Python版本:3.8,請勿使用其他版本,詳見requirements.txt檔案;專案完整檔案下載請見以下連結給出:➷➷➷
完整資源下載:https://mbd.pub/o/bread/ZJaUm5hv
參考視訊演示:https://www.bilibili.com/video/BV1QL411C783/
離線依賴庫下載連結:https://pan.baidu.com/s/1hW9z9ofV1FRSezTSj59JSg?pwd=oy4n (提取碼:oy4n )
由於博主能力有限,博文中提及的方法即使經過試驗,也難免會有疏漏之處。希望您能熱心指出其中的錯誤,以便下次修改時能以一個更完美更嚴謹的樣子,呈現在大家面前。同時如果有更好的實現方法也請您不吝賜教。