yolov3 model training - use yolov3 to train your own model

This article mainly describes the specific steps of using yolov3 to train the model in the Windows10 environment

Software preparation: anaconda3, pycharm

1. Program download and preparation

(1) yolov3 download

The github address of yolov3: yolov3
1. You can click here to select the version you want to download (this article takes 9.5.0 as an example)
insert image description here
2. Click download on the left to download the compressed package
insert image description here
3. The downloaded and decompressed folder is as shown in the figure Shown:
insert image description here
insert image description here
Open the project directory in pycharm as shown below:
insert image description here

(2) Training set folder creation

1. Under the yolov3-9.5.0 project folder, create a new folder named VOCdevkit 2.
Under the VOCdevkit folder, create three new folders named images , labels , and VOC2007
3. In the images and labels files Create two new folders named train and val under the folder
4. Create three folders named Annotations , JPEGImages , and YOLOLabels under the VOC2007 folder , as shown in the
figure below:
insert image description here
Annotations: xml tag folder
JPEGImages: image file Folder
YOLOLabels: txt label folder (yolov training requires label files in txt format)

(3) Pre-training weight download

Loading pre-trained weights for network training can reduce network training time and improve accuracy. The larger the pre-training weight, the higher the training accuracy, but the slower the detection speed.

1. Pre-training weight download address: yolov5 weight
This article chooses to download yolov3-tiny.pt
(different pre-training weights correspond to different network layers, we need to use the corresponding yaml files according to the pre-training weights, namely A file named yolov3-tiny.yaml needs to be used in subsequent training)

insert image description here
2. Save the downloaded weight file in the weights folder
insert image description here

2. Environment Construction

(1) pytorch installation

For the specific steps to install pytorch through anaconda in the windows10 system, you can read this blog:
anaconda installs pytorch (anaconda3, Windows10)

(2) Apply pytorch to the project

In the previous step, we installed pytorch through anaconda and imported it into pycharm. Let's apply the compiler in the environment named pyotch to the project file.
1. Click FileSettings
insert image description here
2. Select Project Interpreter , select the pytorch environment just imported into pycharm , click Apply , and finally click Confirm
insert image description here
. In this way, we have successfully applied the compiler named pytorch environment to the yolov3-9.5.0 project

(3) Dependency package installation in requirements

1. Next, install the dependency packages required by the project, first open the terminal
insert image description here
2. Copy the command line in the requirements.txt file:

pip install -r requirements.txt

Paste it in the terminal and press Enter to run the command line, and the dependencies in the requirements will be installed.
insert image description here

(4) Problems that may be encountered in the construction of the environment

1.遇到错误 ERROR: Could not build wheels for pycocotools which use PEP 517 and cannot be installed directly

Refer to the problems that may be encountered in the environment construction in this blog :
target detection - target detection project based on Yolov5 (study notes)
(if there are other errors, it will be updated later)

3. Data set production

Use labelimg to make our own data set, the installation and basic operation of labelimg can read this blog:
Data set production - use labelimg to make a data set
The file format required for yolov network training is in txt format.
If you give the data set through labelimg When labeling, the output is in xml format, and the label file in xml format can be converted into a label file in txt format through code;
if the output is a label file in txt format, it can be used directly. At the same time, when training your own yolov3 detection model, the data set needs to be divided into training set and validation set, which can also be implemented through related codes.
This paper takes the identification of two labels "person" and "har" as an example, and the data set in this paper is based on the data set of identifying people wearing helmets as an example

This article uses labelimg to mark the label file in xml format as an example:
(The labeling process is omitted)
1. First, store the image dataset in the JPEGImages folder; store the xml label file in the Annotations folder; that is:
JPEGImages stores The image file
Annotations stores tags in xml format
as shown in the figure:
insert image description here

insert image description here
2. Create a new python file in the project, copy and paste the following code and run it to divide the data set into training set and validation set
(note that the label types in the following code classes = ["hat", "person" ] Modify it to its own label, the training set in the following code accounts for 80% of TRAIN_RATIO = 80 )

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile
 
classes = ["hat", "person"] #标签种类
#classes=["ball"]
 
TRAIN_RATIO = 80  #训练集占比
 
def clear_hidden_files(path):
    dir_list = os.listdir(path)
    for i in dir_list:
        abspath = os.path.join(os.path.abspath(path), i)
        if os.path.isfile(abspath):
            if i.startswith("._"):
                os.remove(abspath)
        else:
            clear_hidden_files(abspath)
 
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('VOCdevkit/VOC2007/Annotations/%s.xml' %image_id)
    out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' %image_id, 'w')
    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 = obj.find('difficult').text
        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')
    in_file.close()
    out_file.close()
 
wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):
    os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):
    os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):
        os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):
        os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):
        os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):
        os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):
        os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):
        os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):
        os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):
        os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):
        os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)
 
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir) # list image files
prob = random.randint(1, 100)
print("Probability: %d" % prob)
for i in range(0,len(list_imgs)):
    path = os.path.join(image_dir,list_imgs[i])
    if os.path.isfile(path):
        image_path = image_dir + list_imgs[i]
        voc_path = list_imgs[i]
        (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
        (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
        annotation_name = nameWithoutExtention + '.xml'
        annotation_path = os.path.join(annotation_dir, annotation_name)
        label_name = nameWithoutExtention + '.txt'
        label_path = os.path.join(yolo_labels_dir, label_name)
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    if(prob < TRAIN_RATIO): # train dataset
        if os.path.exists(annotation_path):
            train_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention) # convert label
            copyfile(image_path, yolov5_images_train_dir + voc_path)
            copyfile(label_path, yolov5_labels_train_dir + label_name)
    else: # test dataset
        if os.path.exists(annotation_path):
            test_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention) # convert label
            copyfile(image_path, yolov5_images_test_dir + voc_path)
            copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

Run this code, the process is shown in the following figure: (Note that the name of the dataset folder must be the same as the training set folder creation part above, you can directly copy and paste to run)
insert image description here

Then you can see the divided image dataset and label dataset in the images and labels folders respectively.

Fourth, yolov3 model training

(1) Modify the data configuration file

1. Find the voc.yaml file in the data directory, copy the file, and rename the copied file to facilitate subsequent operations. In this article, it is changed to hat.yaml
insert image description here
2. Click the hat.yaml file and modify the following parts:
Comment out the statement: download: bash data/scripts/get_voc.sh
Modify the train and val addresses to the data set address in your computer
Modify the number of classes value to the number of types of data set labels (the labels in this article are two types)
Modify the class names Types of labels for your own data set (hat and person in this article)

insert image description here

(2) Modify the model configuration file

The weight file selected to download earlier is yolov3-tiny.pt, we need to use the corresponding model to configure the yaml file

1. Find the yolov3-tiny.yaml file in the models directory, make a copy of the file, and rename the copied file to facilitate subsequent operations. This article is modified to yolov3-tiny_hat.yaml
insert image description here
2. Open yolov3-tiny_hat.yaml file, change the number of classes to the type of dataset label (the dataset identified in this article is two types)
insert image description here

(3) Train.py main function modification

Mainly modify the following five functions:
-weights: the path address of the initialized weight file
-cfg: the path address of the model yaml file
-data: the path address of the data yaml file
-epochs: the number of trainings -batch
-size: the file for one round of training Number
insert image description here
1. Open train.py and make the following modifications:
Modify the address of the weight file in "--weights" to the address of the file yolov3-tiny.pt
Modify the address of the model yaml file in "--cfg" to the address of the file yolov3-tiny_hat.yaml Address
Modify the address of the data yaml file in "–data" to the address of the file hat.yaml

    parser.add_argument('--weights', type=str, default='weights/yolov3-tiny.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='models/yolov3-tiny_hat.yaml', help='model.yaml path')
    parser.add_argument('--data', type=str, default='data/hat.yaml', help='data.yaml path')

As shown in the figure below:
insert image description here
The values ​​of "--epochs" and "--batch-size" can be set according to the GPU situation

2. Run train.py to start training the model
After loading the train and val datasets, you can see that the model starts training~
insert image description here

(4) Problems that may be encountered in model training

1. Encountered the error subprocess.CalledProcessError: Command 'git tag' returned non-zero exit status 1.

As shown in the figure below:
insert image description here
Solution:
insert image description here
Open the subprocess.py file, in line 410, change the check value to False and
insert image description here
click OK
insert image description here

2. Encountered the error UnicodeDecodeError:: 'utf-8' codec can't decode byte 0xc8 in position 0: invalid contin

As shown in the figure below:
insert image description here
Solution:
Open torch_utils.py and change the encoding method to decode('gb2312') on line 58
insert image description here

3. Encountered the error BrokenPipeError: [Errno 32] Broken pipe

As shown in the figure below:
insert image description here
Solution:
On line 488, change the value of '--workers' to 0
insert image description here

4. Encountered the error OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.

As shown in the figure below:
insert image description here
Solution:
In the envs folder of the anaconda installation directory, find the pytorch environment, enter the bin folder of the library, and delete the libiomp5md.dll file
insert image description here

5. Test results

After the training, two weight files will be generated in the runs/train/exp/weights directory, one is the weight file with the best training effect, and the other is the weight file for the last round of training
(the next best.pt weight file is example)
insert image description here

(1) Picture test steps

1. Copy and paste the best.pt weight file in the weights folder of the main directory (for the convenience of subsequent operations)
insert image description here
2. Put the picture you want to test in the data folder of the main directory, as shown in the figure:
insert image description here
3. Open defect .py, change the following parts: Change
"--weight" to the address of the best.pt weight file (in the weights folder) Change "--source" to the address
of the image to be tested (in the data folder)

parser.add_argument('--weights', nargs='+', type=str, default='weights/best.pt', help='model.pt path(s)')
parser.add_argument('--source', type=str, default='data/1.jpg', help='source')  # file/folder, 0 for webcam

As shown in the figure:
insert image description here
4. Run defect.py to get the result;
5. If the video is recognized, change "--source" to the video address to be tested (note the .mp4 suffix).
If the camera is recognized, Just set the value of "-source" to 0, that is:

parser.add_argument('--source', type=str, default='0', help='source')  # file/folder, 0 for webcam

Guess you like

Origin blog.csdn.net/thy0000/article/details/124579443