(超详细)机器学习,利用yolov5从零开始训练自己的模型----------模型的训练及应用
就此终结,对于gui界面本人只是略懂皮毛,不再讲诉。若需要此项目进行学习,可去下载。
目录
2.利用爬虫爬一些自己需要的数据集再对其进行处理(清洗,标记)
一.引言
在上一个文章中搭建好了环境,可以开始下一步。
二.模型训练的进行
1.yolov5源文件的准备及测试
1.1源代码的获取(GitHub)
可以去GitHub下载源码,官网如下:GitHub
在查找界面输入yolov5,找到第一个内容,点进去
得到如下界面,点击master,有个Tags,就可以下载不同版本的yolov5了,这里下载了v5.0版本
下载完成后,解压,再使用pycharm打开解压后的文件
打开后,找到右下角,配置解释器,配置3.8的那一个。如不清楚此处,请查看上篇文章环境的配置
解释器配置完毕后,找到文件中的requirements.txt可以看到需要安装包(上边黄色的提示框)
找到下边第四个终端输入
pip install -r requirements.txt
,就可以安装所需要的包
如下,安装完成,可以利用detect.py文件先来预测一下
可以看到两个图片运行模型预测完毕,同时提示Results saved to runs\detect\exp,即预测结果保存路径
找到该文件下,可以发现运行预测成功,检测出了人和公交车
1.2源代码的获取(百度网盘)
注:没办法去GitHub下载文件可以在这下载:https://pan.baidu.com/s/1cjV1cn1ceHzVMQcvpaYEVw
提取码:bua7
2.数据集的获取及处理
2.1数据集的获取的两种方式
1.从GitHub上下载别人处理好的数据集(不再演示)
2.利用爬虫爬一些自己需要的数据集再对其进行处理(清洗,标记)
代码如下
# -*- coding: utf-8 -*-
# @Time : 2021/6/17 20:29
# @Author : dejahu
# @Email : 1148392984@qq.com
# @File : get_data.py
# @Software: PyCharm
# @Brief : 爬取百度图片
import requests
import re
import os
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}
name = input('请输入要爬取的图片类别:')
num = 0
num_1 = 0
num_2 = 0
x = input('请输入要爬取的图片数量?(1等于60张图片,2等于120张图片):')
list_1 = []
for i in range(int(x)):
name_1 = os.getcwd()
name_2 = os.path.join(name_1, 'data/' + name)
url = 'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + name + '&pn=' + str(i * 30)
res = requests.get(url, headers=headers)
htlm_1 = res.content.decode()
a = re.findall('"objURL":"(.*?)",', htlm_1)
if not os.path.exists(name_2):
os.makedirs(name_2)
for b in a:
try:
b_1 = re.findall('https:(.*?)&', b)
b_2 = ''.join(b_1)
if b_2 not in list_1:
num = num + 1
img = requests.get(b)
f = open(os.path.join(name_1, 'data/' + name, name + str(num) + '.jpg'), 'ab')
print('---------正在下载第' + str(num) + '张图片----------')
f.write(img.content)
f.close()
list_1.append(b_2)
elif b_2 in list_1:
num_1 = num_1 + 1
continue
except Exception as e:
print('---------第' + str(num) + '张图片无法下载----------')
num_2 = num_2 + 1
continue
# 为了防止下载的数据有坏图,直接在下载过程中对数据进行清洗
print('下载完成,总共下载{}张,成功下载:{}张,重复下载:{}张,下载失败:{}张'.format(num + num_1 + num_2, num, num_1, num_2))
在刚才的文件中创建一个py文件,将代码复制上运行即可,输入要下载的图片名称及数量,自动开始下载到指定路径下 可以看到图片已下载完成 因为下载的图片有好图有坏图(下载失败的图片),而且图片名字含有中文,这是不允许的,故需要对其进行清洗,利用如下代码清洗图片
import shutil
import cv2
import os
import os.path as osp
import numpy as np
from tqdm import tqdm
# 实际的图片保存和读取的过程中存在中文,所以这里通过这两种方式来应对中文读取的情况。
# handle chinese path
def cv_imread(file_path, type=-1):
cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
if type == 0:
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
return cv_img
def cv_imwrite(file_path, cv_img, is_gray=True):
if len(cv_img.shape) == 3 and is_gray:
cv_img = cv_img[:, :, 0]
cv2.imencode(file_path[-4:], cv_img)[1].tofile(file_path)
def data_clean(src_folder, english_name):
clean_folder = src_folder + "_cleaned"
if os.path.isdir(clean_folder):
print("保存目录已存在")
shutil.rmtree(clean_folder)
os.mkdir(clean_folder)
# 数据清晰的过程主要是通过oepncv来进行读取,读取之后没有问题就可以进行保存
# 数据清晰的过程中,一是为了保证数据是可以读取的,二是需要将原先的中文修改为英文,方便后续的程序读取。
image_names = os.listdir(src_folder)
with tqdm(total=len(image_names)) as pabr:
for i, image_name in enumerate(image_names):
image_path = osp.join(src_folder, image_name)
try:
img = cv_imread(image_path)
img_channel = img.shape[-1]
if img_channel == 3:
save_image_name = english_name + "_" + str(i) + ".jpg"
save_path = osp.join(clean_folder, save_image_name)
cv_imwrite(file_path=save_path, cv_img=img, is_gray=False)
except:
print("{}是坏图".format(image_name))
pabr.update(1)
if __name__ == '__main__':
data_clean(src_folder="C:/Users/A/Desktop/yolov5-5.0(1)/data/橙子", english_name="orange")
如出现以下问题,将路径的斜杠改为反斜杠可以解决(后续需要复制路径时,都要更改,后续不再赘诉)
可以看到图片已清洗完毕
按照同样的方法可以得到猕猴桃的清洗后的数据
将清洗后的图片全部放在data文件下的images文件夹中,开始下载图片和清洗图片的文件夹在把图片移出后,删除即可,同时新建一个文件夹名称为labels,用于存储标记后的数据
接下来就是对下载好的图片进行标记
在pycharm终端中输入
pip install labelimg
如下图
再次在终端输入
labelimg
打开软件后,点击open dir 找到刚才放置的图片位置,如下图
change save dir 找到如下图位置即可,刚才创建的文件夹下我的是C:\Users\A\Desktop\yolov5-5.0(1)\data\labels
注:左边按键第8个,要改成yolo,点击几下就切换成yolo了,如下图
注意点击create rectbox圈出图片中猕猴桃的位置,输入标签,保存,如下图,图中的每个猕猴桃都必须完成上述操作,橙子同样操作,把所有图片全部标记完,可以得到如下文件
当所有数据标记好后,还要对其进行训练集测试集和验证集的划分,对images和labels里面的文件依次使用如下脚本,与上边爬虫下载图片和清洗图片文件相似,创建使用如下代码即可,注意修改文件路径。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import random
import shutil
from shutil import copy2
import os.path as osp
def data_set_split(src_data_folder, target_data_folder, train_scale=0.6, val_scale=0.2, test_scale=0.2):
print("开始数据集划分")
split_names = ['train', 'val', 'test']
for split_name in split_names:
split_path = os.path.join(target_data_folder, split_name)
if not os.path.isdir(split_path):
os.mkdir(split_path)
current_all_data = os.listdir(src_data_folder)
current_data_length = len(current_all_data)
current_data_index_list = list(range(current_data_length))
random.shuffle(current_data_index_list)
train_folder = os.path.join(target_data_folder, 'train')
val_folder = os.path.join(target_data_folder, 'val')
test_folder = os.path.join(target_data_folder, 'test')
train_stop_flag = int(current_data_length * train_scale) # Use int to avoid float
val_stop_flag = int(current_data_length * (train_scale + val_scale)) # Use int to avoid float
current_idx = 0
train_num = 0
val_num = 0
test_num = 0
for i in current_data_index_list:
src_img_path = os.path.join(src_data_folder, current_all_data[i])
if current_idx < train_stop_flag:
copy2(src_img_path, train_folder)
train_num = train_num + 1
elif current_idx < val_stop_flag:
copy2(src_img_path, val_folder)
val_num = val_num + 1
else:
copy2(src_img_path, test_folder)
test_num = test_num + 1
current_idx = current_idx + 1
print("按照{}:{}:{}的比例划分完成,一共{}张图片".format(train_scale, val_scale, test_scale, current_data_length))
print("训练集{}:{}张".format(train_folder, train_num))
print("验证集{}:{}张".format(val_folder, val_num))
print("测试集{}:{}张".format(test_folder, test_num))
if __name__ == '__main__':
src_data_folder = "C:/Users/A/Desktop/yolov5-5.0(1)/data/images" # todo 修改你的原始数据集路径
target_data_folder = src_data_folder + "_" + "split"
if osp.isdir(target_data_folder):
print("target folder 已存在,正在删除...")
shutil.rmtree(target_data_folder)
os.mkdir(target_data_folder)
print("Target folder 创建成功")
data_set_split(src_data_folder, target_data_folder)
print("*****************************************************************")
print("数据集划分完成,请在{}目录下查看".format(target_data_folder))
分好类后得到如下测试集中的文件,一个是图片一个是标签文件
把images和labels文件删除,把images_split和labels_split文件名称改为images和labels
3.模型的训练
3.1voc.yaml文件的修改
在scripts文件夹中找到voc.yaml文件打开进行修改
将代码中第十行的下载注释掉
第十三行十四行修改为自己图片分类的训练集和验证集的文件路径,如下,注意修改路径不要绝对路径,否则会报错
第17行,nc后边的数字代表多少类,我这里是猕猴桃和橙子,共两类,改为2,若要训练多种可视情况修改
第20行代表那两类的名称,即orange和kiwi修改即可
就此voc.yaml文件修改完毕
3.2权重yaml文件的修改
在models文件夹中找到yolov5l.yaml文件打开进行修改
同样将nc改为2即可
3.3train.py文件的修改
找到第458行,这里default后修改为weights下的yolov5l.pt的地址,如下图
第459行,default修改为刚才修改的权重文件的地址如下图
第460行,这里这里default修改为刚才修改的voc.yaml文件的地址,如下图
第462行,这里的数字我修改为了5,意思是训练5轮,方便演示,可以根据自己的需要修改
运行,报错
打开报错的那几个文件,把其中的int改为int_ 如下图,大概改了3.4个
出现以下错误
找到loss文件中的gain,如下图
修改为
再次运行,开始训练
训练完成,可以看到最好的一次训练的模型和最后一次训练的模型放在了下述位置
根据电脑显存不同,可以适当调节batch-size的大小,为2的次方数
4.模型的使用
4.1训练好的模型的使用
上述演示的数据集太小,且训练的轮数不够,结果不明显,我现在这个用的模型和文件是几千张图片训练出来的,数据集过少和训练轮数少,会导致识别不出来物体
打开detect.py文件,先修改文件路径,把训练好文件的路径放在如图151行
第152行,default改为放置测试集的图片的路径,当改为0时,会自动打开摄像头识别
运行,显示已经将识别的文件放在以下位置
打开文件查看,发现已经完成识别
4.2水果数据集下载:
链接:https://pan.baidu.com/s/1jtwF4FB4_7vUWDXiY9SxRQ
提取码:41qs
三.结语
就此终结,对于gui界面本人只是略懂皮毛,不再讲诉。作者学疏才浅,请多见谅,谢谢。若需要此项目进行学习,前往某鱼,搜索 亦携秋水揽星河
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)