yolov5 配置环境,训练自己的数据集,实现识别图片,视频,视频流及代码注释

目录

A创建pytorch环境,pycharm配置环境

(1)为conda添加清华源:​编辑

(2)创建一个新的环境:

(3)查看我们刚才创建的环境是否成功:

(4)切换到新的环境:

(5)安装依赖的库:(1.26.4)

i.(6)安装pytorch:GPU

ii.(6)安装pytorch:CPU

安装所需要的库:http://t.csdnimg.cn/znzdj

B制作数据集

(1)在pycharm的终端里面安装labelimg

(2)终端输入:labelimg,打开labelimg

(3)打标签

C开始训练

D训练结果

(1)在本机的这个地方建立文件夹test_images然后将待检测的图片导入其中。

(2)修改图片中第三、四行中的部分代码​编辑

(3)运行结果可视化!!此处做了一个对比

Yolov5实时目标检测(视频流)

1. 修改detect.py

2. 修改utils文件夹下的dataloaders.py

i.在detect.py文件中找到if save_img语句

ii.在if save_img所在函数开头加入

iii.在if save_img:语句里面加入

iiii.运行detect.py,在输出文件里面得到添加了帧率的视频(!!但是到这里只有在输出视频里面显示了帧率)

iiiii.将此代码放入图片中所示位置后将在开启摄像头的画面中输出帧率

代码注释

一.代码参数的注释

i.detect.py

ii.train.py

iii.yolov5s.yaml

iiii.新建的mydata.yaml

二.代码中结果可视化部分的注释

i. 打印目标检测结果

ii. 在窗口中实时查看检测结果

iii.设置保存结果


A创建pytorch环境,pycharm配置环境

参考链接:

Windows安装Anaconda,创建pytorch环境,pycharm配置环境_安装pytorch时卡在100%下不下来-CSDN博客

(1)为conda添加清华源:
(2)创建一个新的环境:

创建完成的指令界面:

(3)查看我们刚才创建的环境是否成功:

(4)切换到新的环境:

(5)安装依赖的库:(1.26.4)

i.(6)安装pytorch:GPU
  1. 确定自己cuda的版本(前提是你有英伟达的显卡) 。命令: nvidia-smi
  2. 上pytorch官网找对应版本的torch和cudatoolkit  , PyTorch 翻到最下面可以看到

  1. 找到对应命令下载:
  1. 使用 conda list 查看安装的依赖:

ii.(6)安装pytorch:CPU

http://t.csdnimg.cn/JGTkv

  1. 进入Pytorch官网PyTorch,点击Get Started.(我的电脑是集成显卡,只能选择CPU版本,如下图所示)

  1. 复制Run this Command后面这段代码,在之前的命令行窗口中输入(输入之前要激活pytorch环境),记得删掉后面的-c pytorch(前提是Anaconda中添加了清华大学镜像源,否则不能删除),它表示从官网进行下载,可能会出现下载速度慢或者卡顿。

  1. 检查pytorch是否安装成功,输入下面三条代码,如图所示,即表示安装成功

安装成功:

pycharm中配置环境成功

安装所需要的库:http://t.csdnimg.cn/znzdj

(1)先下载yolov5项目:将文件解压缩后,剪切到创建的pycharm项目所在文件夹内

(2)在pycharm的终端里面安装所需要的库(先打开文件)

(3)测验detect.py --环境配置成功

B制作数据集

参考教程

使用Labelimg制作VOC数据集或yolo数据集的入门方法_dic-labels labelimgtoyol-CSDN博客

http://t.csdnimg.cn/v0wNq

http://t.csdnimg.cn/GPEAy

(1)在pycharm的终端里面安装labelimg

(2)终端输入:labelimg,打开labelimg

拍摄了207张照片放到一个文件夹中

(3)打标签

问题:由于训练的数据需要分为三个文件夹:训练集、测试集和验证集。(而我们做的时候只有yolo数据集,因此参考此链接将yolo数据集分为我们需要的三种)http://t.csdnimg.cn/cBTrc

import os
import shutil
import random

random.seed(0)  # 确保随机操作的可复现性

def split_data(file_path, xml_path, new_file_path, train_rate, val_rate, test_rate):
    # 存储图片和标注文件的列表
    each_class_image = []
    each_class_label = []
    
    # 将图片文件名添加到列表
    for image in os.listdir(file_path):
        each_class_image.append(image)
    
    # 将标注文件名添加到列表
    for label in os.listdir(xml_path):
        each_class_label.append(label)
    
    # 将图片和标注文件打包成元组列表并随机打乱
    data = list(zip(each_class_image, each_class_label))
    total = len(each_class_image)
    random.shuffle(data)
    
    # 解压元组列表,回到图片和标注文件列表
    each_class_image, each_class_label = zip(*data)
    
    # 按照指定的比例分配数据到训练集、验证集和测试集
    train_images = each_class_image[0:int(train_rate * total)]
    val_images = each_class_image[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_images = each_class_image[int((train_rate + val_rate) * total):]
    
    train_labels = each_class_label[0:int(train_rate * total)]
    val_labels = each_class_label[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_labels = each_class_label[int((train_rate + val_rate) * total):]

# 定义复制文件到新路径的操作
    def copy_files(files, old_path, new_path1):
        # 遍历列表中的每一个文件名
        for file in files:
            # 打印当前处理的文件名,这只是为了在处理过程中输出信息,便于跟踪进度
            print(file)
            # 使用os.path.join连接旧路径和新文件名,形成完整的旧文件路径
            old_file_path = os.path.join(old_path, file)
            # 检查新的路径是否存在,如果不存在则创建新的路径,这可以确保复制操作不会因为路径不存在而出错
            if not os.path.exists(new_path1):
                os.makedirs(new_path1)
            # 使用os.path.join连接新路径和新文件名,形成完整的新文件路径
            new_file_path = os.path.join(new_path1, file)
            # 使用shutil模块的copy函数复制旧文件到新路径,生成与旧文件相同的新的文件
            shutil.copy(old_file_path, new_file_path)

    # 复制训练、验证和测试的图片和标注文件到指定目录
    copy_files(train_images, file_path, os.path.join(new_file_path, 'train', 'images'))
    copy_files(train_labels, xml_path, os.path.join(new_file_path, 'train', 'labels'))
    copy_files(val_images, file_path, os.path.join(new_file_path, 'val', 'images'))
    copy_files(val_labels, xml_path, os.path.join(new_file_path, 'val', 'labels'))
    copy_files(test_images, file_path, os.path.join(new_file_path, 'test', 'images'))
    copy_files(test_labels, xml_path, os.path.join(new_file_path, 'test', 'labels'))

# 判断当前脚本是否为主程序入口,即直接运行该脚本
if __name__ == '__main__':
    # 定义文件路径变量,指向数据集的原图像文件所在路径
    file_path = "E:\myyolo\yolo\data"
    # 定义xml路径变量,指向数据集的标注后文件所在路径
    xml_path = "E:\myyolo\yolo\mydata"
    # 定义新文件路径变量,指向输出结果文件的新路径
    new_file_path = "E:\myyolo\yolo\final_data"
    # 调用split_data函数,分割数据集,并将结果分别存储到指定的路径中
    split_data(file_path, xml_path, new_file_path, train_rate=0.7, val_rate=0.1, test_rate=0.2)

运行结束后:

数据集已准备完毕

C开始训练

参考链接:http://t.csdnimg.cn/znzdj(从4.修改yolov5命令行参数开始)

【踩坑】YOLO5 训练模型的测试结果全部相反(标签混乱):http://t.csdnimg.cn/2OJIO

解决:

使用 labelImg 为图片打好标签后,在为模型配置数据集的 yaml 文件中,class name 列表中的元素顺序应该与标签文件夹中 classes.txt 文件中的标签顺序一致。

报错1:

解决:

在import os后加上

os.environ["GIT_PYTHON_REFRESH"] = "quiet"

报错2:http://t.csdnimg.cn/J7KbI

解决:点击报错里面的链接下载arial.ttf剪切到这个目录里面再重新运行一下train.py

训练成功:

D训练结果

参考链接:http://t.csdnimg.cn/znzdj

(1)在本机的这个地方建立文件夹test_images然后将待检测的图片导入其中。

(2)修改图片中第三、四行中的部分代码
(3)运行结果可视化!!此处做了一个对比

左为GPU,右为CPU

结果:左边的置信度明显高于右边!!

Yolov5实时目标检测(视频流)

参考链接:http://t.csdnimg.cn/a8Mwq

1. 修改detect.py

将红色框的default设置为0

2. 修改utils文件夹下的dataloaders.py

将387-395行中的代码注释,并将396行中的s修改为0,在运行detect.py。

  1. 在输出视频中添加帧率

参考链接:http://t.csdnimg.cn/lbQq8

i.在detect.py文件中找到if save_img语句

ii.在if save_img所在函数开头加入

tt = time.time()

iii.在if save_img:语句里面加入

# 添加帧率检测
cv2.putText(im0, "FPS:{:.1f}".format(1. / (time.time() - tt)), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 235), 4)
tt = time.time()

iiii.运行detect.py,在输出文件里面得到添加了帧率的视频(!!但是到这里只有在输出视频里面显示了帧率)

iiiii.将此代码放入图片中所示位置后将在开启摄像头的画面中输出帧率

代码注释

一.代码参数的注释

i.detect.py

def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp/weights/best.pt', help='model path or triton URL')       #需要的模型地址,选择best.pt

  parser.add_argument('--source', type=str, default='data/compare_images', help='file/dir/URL/glob/screen/0(webcam)')
  #图片或mp4视频存放地址

parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
#设置的检测概率大于0.25才显示出来

parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
#框选物体的框框重合度

parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
#default 默认为空,自动检测为cuda还是cpu

parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
parser.add_argument('--save-csv', action='store_true', help='save results in CSV format')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
#class name 列表中的元素顺序应该与标签文件夹中 classes.txt 文件中的标签顺序一致。

ii.train.py

def parse_opt(known=False):
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')  #参数yolov5s是在models里s、m、l几种不同大小的网络模型,s是最基础的也是跑起来最快的.

parser.add_argument('--epochs', type=int, default=100, help='total training epochs')    
#default=100 训练过程数据将被轮100次

  parser.add_argument('--batch-size', type=int, default=8, help='total batch size for all GPUs, -1 for autobatch')
  #default=8 一次往gpu中塞8张照片

parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
#模型训练和验证时输入图片的尺寸

parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
#只保留最后一次训练的权重

parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
#设置每次训练结果保存的主路径名称

parser.add_argument('--name', default='exp', help='save to project/name')
#设置每次训练结果保存的子路径名称

iii.yolov5s.yaml

nc: 2  #修改分类数
#再yolov5s.yaml里修改分类数

iiii.新建的mydata.yaml

train: D:\robort403\yolo_task\final_data\train   #训练集地址
val: D:\robort403\yolo_task\final_data\val       #验证集地址
test:  D:\robort403\yolo_task\final_data\test     #测试集地址

nc: 2  #分类数
names: ['cell phone', 'mouse']   #类名

二.代码中结果可视化部分的注释

i. 打印目标检测结果

# Write results
                for *xyxy, conf, cls in reversed(det):
                    c = int(cls)  #整数类别
                    label = names[c] if hide_conf else f'{names[c]}'  #标签名称
                    confidence = float(conf) #置信度
                    confidence_str = f'{confidence:.2f}'  #格式化为两位小数的字符串
                    if save_csv:   #保存为CSV文件
                        write_to_csv(p.name, label, confidence_str)

                    if save_txt:   #保存为文本文件                        xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  #归一化后的xywh坐标
                        line = (cls, *xywh, conf) if save_conf else (cls, *xywh)  #标签格式
                        with open(f'{txt_path}.txt', 'a') as f:
                            f.write(('%g ' * len(line)).rstrip() % line + '\n') #写入对应的文件夹里,路径默认为“runs\detect”

                    if save_img or save_crop or view_img:  #添加边界框到图像
                        c = int(cls)  #整数类别
                        label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')  #标签名称和置信度
                        annotator.box_label(xyxy, label, color=colors(c, True))   #在图像上绘制边界框和标签
                    if save_crop:  #保存裁剪的图像
                        save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)  #保存裁剪后的图像到指定路径中

ii. 在窗口中实时查看检测结果

# Stream results
            im0 = annotator.result() #获取到处理后的图像,保存在im0中
            cv2.putText(im0, "FPS:{:.1f}".format(1. / (time.time() - tt)), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2,(0, 0, 235), 4)  #在图像上显示当前图像帧率(FPS)
            if view_img:   #如果设置了view_img为True,即需要显示图像
                if platform.system() == 'Linux' and p not in windows:
                    windows.append(p)
                    cv2.namedWindow(str(p), cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)  # allow window resize (Linux)
                    cv2.resizeWindow(str(p), im0.shape[1], im0.shape[0])
                cv2.imshow(str(p), im0)  #在窗口中显示图像
                cv2.waitKey(1)  #等待用户输入,每1毫秒处理一次键盘事件

iii.设置保存结果

 # Save results (image with detections)
            if save_img:   #如果save_img为True,则保存图像
                tt = time.time()  #获取当前时间tt
                #根据数据集的模式进行不同的保存操作
                if dataset.mode == 'image': #如果数据集模式为’image’,即处理的是单张图像,则使用cv2.imwrite函数将im0保存到指定的路径save_path
                    cv2.imwrite(save_path, im0)
                else:  # 'video' or 'stream'  #如果数据集模式为’video’或’stream’,即处理的是视频或实时流,则需要进行一些判断。
                    if vid_path[i] != save_path:  #判断当前保存路径save_path是否与之前的视频路径vid_path[i]不同,如果不同,说明要保存新的视频。
                        vid_path[i] = save_path
                        if isinstance(vid_writer[i], cv2.VideoWriter):  #释放之前的视频写入器(如果已存在)
                            vid_writer[i].release()
                        #获取视频的帧率(fps)、宽度和高度    
                        if vid_cap:  #如果是视频文件,则使用cv2.VideoCapture函数打开视频文件获取这些信息
                            fps = vid_cap.get(cv2.CAP_PROP_FPS)
                            w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                            h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                        else:  #如果是实时流,则将帧率fps设置为30,宽度w和高度h设置为im0的形状
                            fps, w, h = 30, im0.shape[1], im0.shape[0]
                        save_path = str(Path(save_path).with_suffix('.mp4'))  #保存路径save_path转换为以’.mp4’为后缀的文件名,强制使用.mp4格式保存结果视频。
                        vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))  #cv2.VideoWriter函数创建视频写入器,写入器的参数包括保存路径、视频编码格式(使用mp4v编码)、帧率和视频大小(宽度和高度)。
                    vid_writer[i].write(im0)  #使用写入器的write函数将im0写入视频中。

  • 19
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值