使用yolo-v5訓練測試本身的數據

 使用環境:python3.6.八、CUDA10.0、Centos7.5html

目錄python

 

1、前言git

1.1下載yolov5代碼github

1.2安裝yolov5運行時須要的包web

1.3下載預訓練模型和測試docker

2、製做本身的訓練數據集網絡

2.1使用LabelImg標註本身的數據app

2.2從VOC標註數據轉換爲YOLO標註格式dom

3、使用yolov5訓練本身的數據集ide

3.1規範本身的數據集

3.2編寫yaml數據配置文件

3.3修改yolov5*.yaml配置文件

3.4修改運行train.py文件

3.5測試生成的模型

4、詳解


1、前言

1.1下載yolov5代碼

首先經過git命令從GitHub克隆yolov5最新代碼(固然也能夠選擇想要的版本號),該文采用最新的代碼,命令以下:

git clone --recursive https://github.com/ultralytics/yolov5.git

其中 --recursive 參數屬於我的習慣添加,主要是防止項目中參雜第三方的工程項目;克隆完成之後的文件夾以下(如下顯示的是克隆到本地的所有內容,可能有些.git、.dockerignore等等文件由於是隱藏文件沒有顯示出來,沒必要在乎):

1.2安裝yolov5運行時須要的包

在克隆的代碼中能夠找到requirements.txt文件,爲了不踩坑,儘可能不要直接安裝裏面的包,主要是針對pytorch版本;

若是你的電腦沒有GPU,能夠直接運行如下命令:

pip3 install -r requirements.txt

若是你的電腦有GPU,請不要直接運行以上命令,先更新pytorch爲1.6.0,具體命令以下:

pip3 install torch==1.6.0+cu92 torchvision==0.7.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html

而後把requirements.txt中有關torch的內容刪除,刪除以後的requirements.txt文件爲:

然後在運行:

pip3 install -r requirements.txt

1.3下載預訓練模型和測試

下載預訓練模型時儘可能從yolov5給定的連接處下載;

連接:https://github.com/ultralytics/yolov5

之因此不建議從別的地方下載預訓練模型,緣由是因爲時間關係有可能下載到的模型和yolov5的代碼不匹配,致使各類亂七八糟的錯誤,所以最好從上述連接上下載;(本文下載的是yolov5x.pt,若是由於網絡緣由致使模型下載失敗,也沒有關係,直接跳過測試就好,不影響訓練本身的數據模型)


模型下載完成之後放在和detect.py同級的目錄下,大體以下:

將detect.py中的代碼大體150~164行代碼作如下修改:

parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='yolov5x.pt', help='model.pt path(s)')  # 本文下載的是yolov5x.pt
    parser.add_argument('--source', type=str, default='inference/images', help='source')
    parser.add_argument('--output', type=str, default='inference/output', help='output folder')
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.4, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
    parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')  # 沒有GPU的話請改成 default='cpu'
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    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')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    opt = parser.parse_args()

以後運行detect.py,結果以下:

   

效果一級棒!

2、製做本身的訓練數據集

2.1使用LabelImg標註本身的數據

yolov5訓練集使用的是yolo的格式的標註方式,具體格式以下圖所示:

每行數據表明一個物體,每一行的含義爲:class_id center_x center_y width height,一個txt文件對應一個圖片,例如上圖000000000009.txt對應的既是000000000009.jpg,標註時只需將LabelImg中的 PascalVOC點擊轉換爲YOLO便可;

2.2從VOC標註數據轉換爲YOLO標註格式

若是已經有了標註出來的VOC標註文件(xml格式文件),只須要使用腳本轉換爲YOLO格式便可,這種方式能最快把數據集準備好,代碼以下:

"""
Creation Time : 2020.08.14

Create author : Tian FuKang
"""
import os
import glob
import pandas as pd
import random
import cv2
import xml.etree.ElementTree as ET


def resize_image(img, max_l):
    w = img.shape[1]
    h = img.shape[0]

    if w > h:
        scale = float(max_l) / float(w)
        w = max_l
        h = int(h * scale)
    else:
        scale = float(max_l) / float(h)
        h = max_l
        w = int(w * scale)

    img = cv2.resize(img, (w, h), interpolation=cv2.INTER_AREA)

    return img, scale


def xml_to_csv(path_1):
    xml_file_list = []

    # 在這裏修改你須要檢測的類別名字
    class_text = ['person', 'bicycle', 'car', 'motorcycle', 'airplane']

    for xml_file in glob.glob(path_1 + '/*.xml'):
        xml_file_list.append(xml_file)

    for i in range(0, len(xml_file_list)):

        tree = ET.parse(xml_file_list[i])
        root = tree.getroot()

        filename = root.find('filename').text

        name = str(i + 1).zfill(12)
        # 在這裏修改保存數據和標籤的文件路徑
        img_name = './data/images/train/' + name + '.jpg'
        txt_name = './data/labels/train/' + name + '.txt'

        file_txt = open(txt_name, mode='a', encoding='utf-8')

        image = cv2.imread(path_1.replace('image_xml', 'image/') + filename)
        image, scale = resize_image(image, 640)

        cv2.imwrite(img_name, image)

        for member in root.findall('object'):
            class_id = class_text.index(member[0].text)

            xmin = int(member[4][0].text)
            ymin = int(member[4][1].text)
            xmax = int(member[4][2].text)
            ymax = int(member[4][3].text)

            # round(x, 6) 這裏我設置了6位有效數字,可根據實際狀況更改
            center_x = round(((xmin + xmax) / 2.0) * scale / float(image.shape[1]), 6)
            center_y = round(((ymin + ymax) / 2.0) * scale / float(image.shape[0]), 6)
            box_w = round(float(xmax - xmin) * scale / float(image.shape[1]), 6)
            box_h = round(float(ymax - ymin) * scale / float(image.shape[0]), 6)

            file_txt.write(str(class_id))
            file_txt.write(' ')
            file_txt.write(str(center_x))
            file_txt.write(' ')
            file_txt.write(str(center_y))
            file_txt.write(' ')
            file_txt.write(str(box_w))
            file_txt.write(' ')
            file_txt.write(str(box_h))
            file_txt.write('\n')

        file_txt.close()


def main():
    # 在這裏修改xml文件的路徑,個人xml文件在image_xml文件夾中,所以是如下設置方式
    path_2 = './image_xml'
    xml_to_csv(path_2)
    print('Successfully converted xml to csv.')


main()

運行該腳本時須要注意如下幾點:1.保證修改了第36行,更改成本身的類別名稱;2.保證第50、51行的保存數據的文件夾存在;3.保證你的數據圖片和標註文件分別在image文件夾和image_xml文件夾裏面,而且image文件夾和image_xml文件夾在同一目錄下,由於在第5五、90行用到了這兩個文件夾;以後運行該腳本便可;

3、使用yolov5訓練本身的數據集

3.1規範本身的數據集

進入到以前目錄1.1中克隆的代碼的文件夾中,找到data文件夾,在data文件夾下新建以下目錄文件夾;

 其中目錄:

./data/custom/images/train/ 存放訓練集圖片

./data/custom/images/val/ 存放驗證集圖片

./data/custom/labels/train/ 存放訓練集標籤

./data/custom/labels/val/ 存放驗證集標籤

將本身上個步驟生成的數據集按照訓練集驗證集放入以上目錄中(訓練集驗證集數據比例可本身控制);注意:訓練集中的image和label的文件名要一一對應(例如./data/custom/images/train/0001.jpg和./data/custom/labels/train/0001.txt),同理驗證集也是如此;

3.2編寫yaml數據配置文件

仍是在yolov5項目的data文件夾下,新建文件custom.yaml,以下圖所示:

編輯內容以下:

# 設置訓練集和驗證集的目錄
train: ./data/code/images/train/
val: ./data/code/images/val/

# 類別數目
nc: 5

# 類別名
names: ['person', 'bicycle', 'car', 'motorcycle', 'airplane']

保存便可; 

3.3修改yolov5*.yaml配置文件

本文使用的yolov5s,所以修改的是yolov5s.yaml,修改方式很簡單,只須要修改類別數目便可,修改後的內容以下:

# parameters
nc: 5  # 主要修改此處爲本身的類別數量
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple

# anchors
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Focus, [64, 3]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, BottleneckCSP, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 9, BottleneckCSP, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, BottleneckCSP, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 1, SPP, [1024, [5, 9, 13]]],
   [-1, 3, BottleneckCSP, [1024, False]],  # 9
  ]

# YOLOv5 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, BottleneckCSP, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, BottleneckCSP, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, BottleneckCSP, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, BottleneckCSP, [1024, False]],  # 23 (P5/32-large)

   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

3.4修改運行train.py文件

完成上述步驟之後,還須要修改train.py文件中的一些代碼,主要集中在第383-409行,修改後以下所示:

parser = argparse.ArgumentParser()
    # --weights 由於是訓練本身的數據集,所以沒有必要加載預訓練模型,這裏改爲無,固然也能夠加載
    parser.add_argument('--weights', type=str, default='', help='initial weights path')
    # --cfg 這裏改爲默認是./models/yolov5x.yaml,由於使用了yolov5s
    parser.add_argument('--cfg', type=str, default='./models/yolov5s.yaml', help='model.yaml path')
    # --data 這裏改成默認是./data/custom.yaml
    parser.add_argument('--data', type=str, default='./data/custom.yaml', help='data.yaml path')
    parser.add_argument('--hyp', type=str, default='', help='hyperparameters path, i.e. data/hyp.scratch.yaml')
    # --epochs 迭代輪次能夠修改,本文默認爲300
    parser.add_argument('--epochs', type=int, default=300)
    # --batch-size 硬件很差的話,把16改成8或者4甚至更低(yolov5支持更小,問題不大)
    parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
    # --img-size 圖片大小能夠根據本身的數據設置,注意測試時同步大小就好,這裏不作修改
    parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='train,test sizes')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
    parser.add_argument('--resume', nargs='?', const='get_last', default=False,
                        help='resume from given path/last.pt, or most recent run if blank')
    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
    parser.add_argument('--notest', action='store_true', help='only test final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
    parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
    parser.add_argument('--name', default='', help='renames results.txt to results_name.txt if supplied')
    # --device 個人電腦有GPU卡,所以設置爲0,沒有設置爲cpu
    parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
    parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')
    parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')
    parser.add_argument('--logdir', type=str, default='runs/', help='logging directory')
    parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
    opt = parser.parse_args()

修改完之後運行train.py,運行過程以下:

訓練完成之後會在項目中生成如下內容:

至此訓練完成; 

3.5測試生成的模型

快速測試只須要修改detect.py文件中的第164-178行便可,修改跟訓練時相似,以下所示:

parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model.pt path(s)')
    parser.add_argument('--source', type=str, default='inference/images', help='source')  # file/folder, 0 for webcam
    parser.add_argument('--output', type=str, default='inference/output', help='output folder')  # output folder
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.4, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
    parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    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')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    opt = parser.parse_args()

而後把須要測試的圖片放到目錄:./inference/images/中,再把生成的模型best.pt修改成yolov5s.pt移動到和detect.py相同目錄,運行便可,在./inference/output/中查看測試結果;

後續會整理一個相對簡單的測試腳本,繼而更新;

4、詳解

更詳細的網絡解釋後續會持續更新;

相關文章
相關標籤/搜索