Yolov5图像识别教程包成功-幽络源原创

Yolov5图像识别教程包成功-幽络源原创

前置环境资源下载

提示:要开外网才能下载的环境我都放在了网盘里,教程中用到的环境可从这里一并下载:

https://pan.quark.cn/s/f0c36aa1ef60

1. 下载YOLOv5源码

2. 下载预训练检查点文件

  • 官方地址:https://github.com/ultralytics/yolov5
  • 页面向下拉,会看到 “Pretrained Checkpoints” 表格,任选一个进行下载(我这里使用的是 yolov5x.pt)。
  • 下载完成后,将 .pt 文件放入 YOLOv5 源码的根目录。

3. 下载CUDA

4. 下载3个Python库:torchtorchvisiontorchaudio

  • 提示torch 是算法核心,torchvision 用于处理图像,torchaudio 处理音频/视频。这一条很关键,仔细看,因为涉及到版本匹配

  • 刚才我们下载的CUDA是12.2版本对吧,我们进入PyTorch官网往下拉可以看到一个注释为CUDA 12.1的,所以我就选择差别不大的12.1版本的命令下载,这官网里都给我们把版本匹配好了,就不要自己一个一个不指定版本去下载,ok获取到命令如下,如果下载失败,看下面第5条

# CUDA 12.1
pip install torch==2.2.1 torchvision==0.17.1 torchaudio==2.2.1 --index-url https://download.pytorch.org/whl/cu121

a34f87f29fa35dcf8dd3089357af755f

5. 使用国内镜像下载库失败的解决方法

官方的命令下载这三个库很多人因为网络超时导致中途下载失败,当然也有下载顺利的人,而尝试使用国内镜像去下载这三个库时,好像是没有GPU版本的,下载下来的只有CPU版本的,因此提供如下安装这三个库的方式,包成功!!!

下载地址:浏览器进入 PyTorch 官方站 https://download.pytorch.org/whl/torch_stable.html

使用快捷键ctrl+f搜索并下载

torch:搜索 cu121/torch-2.2.1,选择 cp39-win 的版本。

torch

torchvision:搜索 cu121/torchvision-0.17.1,选择 cp39-win 的版本。

torchvision

torchaudio:搜索 cu121/torchaudio-2.2.1,选择 cp39-win 的版本。

torchaudio

安装步骤

下载完后随便放到一个目录(如:D:\C01MyENV),然后打开CMD命令行进入这个目录,执行以下三条命令安装:

pip install "torch-2.2.1+cu121-cp39-cp39-win_amd64.whl"
pip install "torchvision-0.17.1+cu121-cp39-cp39-win_amd64.whl"
pip install "torchaudio-2.2.1+cu121-cp39-cp39-win_amd64.whl"

安装过成如图

安装1

安装2

安装3

环境验证

验证CUDA是否可用

在Python中运行以下代码,查看你的CUDA是否可用:

import torch

# 检查是否有可用的 GPU
print("CUDA是否可用=>", torch.cuda.is_available())
print("pytorch版本=>"+torch.__version__)
print("是否支持CUDA=>"+str(torch.cuda.is_available()))
# 如果有 GPU 可用,打印 GPU 数量和名称
if torch.cuda.is_available():
    print("GPU设备数量=>", torch.cuda.device_count())
    print("当前使用GPU=>", torch.cuda.get_device_name(torch.cuda.current_device()))
else:
    print("没有GPU可用,当前将运行在CPU上")

运行后你会看到如下界面,表示GPU版本的Yolov5环境成功了,如图:

环境验证

Yolov5源码用到的库一键下载

CMD命令进入yolov5源码包,执行pip install -r requirements.txt,此命令会下载requirements.txt文件中指定版本的包。只要你配置了国内的镜像,这一步必然是顺利的。

下载标注工具

1. 下载labelImg工具

2. 安装 pyQT5 依赖

  • 由于 labelImg 依赖于 pyQT5,需要先安装它。

    安装命令

    pip install pyqt5

3. 安装 libs.resources 模块

  • 打开 CMD,进入到 labelImg 源码目录,执行以下命令安装 libs.resources 模块:

    安装命令

    pyrcc5 -o libs/resources.py resources.qrc

4. 删除预制标签

  • 为了避免初学者在标记时混淆,请删除 labelImg-master\data\predefined_classes.txt 文件中的所有内容,注意是删除内容,不是让你删除文件。

5. 启动 labelImg

  • CMD命令进入 labelImg 源码目录,运行以下命令启动标注工具:

    启动命令

    python labelImg.py
  • 之后,每次启动 labelImg 都可以直接运行此命令。

准备图片

为快速操作,我这里使用如下爬虫,快速爬取图片,然后筛选24张进行标注训练

'''
key_word:图片名称关键词
img_num:爬取图片轮数,1轮30张
'''
import json
import math
import os.path
import sys
import time

import requests

def catch_img(key_word,rounds): #关键字、爬取轮次,一轮30张
    if not os.path.exists(key_word):
        os.mkdir(key_word)
    for count in range(rounds):
        print(str(count)+"轮")
        pn=count*30
        url = "https://images.baidu.com/search/acjson?tn=resultjson_com&logid=11514788725054802565&ipn=rj&ct=201326592&is=&fp=result&fr=&word="+str(key_word)+"&queryWord="+str(key_word)+"&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=&expermode=&nojc=&isAsync=&pn="+str(pn)+"&rn=30&gsm=1e&1717479169689="
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'}
        res = requests.get(url, headers=headers)
        if len(res.json()["data"])==1:
            print("无图片可获取了")
            sys.exit()
        json_data=res.json()["data"] #获取json数据
        json_str= json.dumps(json_data, indent=2) #json转json字符串
        list_data=json.loads(json_str) #json字符串转list/dict
        for obj in list_data:
            try:
                pic_url=obj["thumbURL"] #图像链接
            except:
                continue
            r = requests.get(pic_url,headers=headers)
            with open(str(key_word)+"\\"+str(time.time())+".jpg", mode="wb") as f:
                f.write(r.content)

if __name__ == '__main__':
    catch_img("桥梁地基冲刷照片",20)

1. 标注数据集

1.1 创建文件目录

  • yolov5 目录下创建 yoloData 目录,随后在 yoloData 目录下建立以下两个子目录:
    • txtData:用于存放标注的标签文件(.txt 格式)
    • picData:用于存放需要标注的图片文件

1.2 准备图片文件

  • 将需要标注的图片放入 yoloData/picData 目录中。

1.3 启动 labelImg 并设置参数

  1. 启动 labelImg
  2. 点击打开目录,选择 yoloData/picData 目录。
  3. 将左边的存储格式由默认的 PascalVOC 改为 YOLO
  4. 点击文件 -> 改变存放目录,将标签的存放目录设置为 yoloData/txtData
  5. 如图一定要按步骤来,不然可能会闪退

labelImg1

labelimg2

1.4 开始标注

  1. 例如,如果你要标注图片中的桥墩损坏部位,按下 W 键调出标注十字架,框选出损坏部位并保存,随后输入自定义的缺陷英文名称(如 error_pos),然后继续标注下一张图片。
  2. 可以在同一张图片中标记多个部位。
  3. 标记第一张图片时会提示你先命名标记的类别,类别可以自定义(我这里设置为 error_pos)。

1.5 常用快捷键

  • W:调出标注十字架
  • A:切换到上一张图片
  • D:切换到下一张图片
  • Del:删除标注框
  • Ctrl+U:选择标注的图片文件夹
  • Ctrl+R:选择标注好的标签文件夹

1.6 检查标注结果

  • 标记完后,检查 txtData 目录中的标签文件(.txt)与 picData 目录中的图片文件名称是否对应,数量是否一致。

2. 划分数据集

在我们创建的yoloData目录下建立SplitData.py文件,加入如下代码然后执行会将txt标签和图篇按照8:1:1的比例划分为训练集、测试集、验证集到新的目录

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):
    '''====1.将数据集打乱===='''
    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)
    # 将两个文件通过zip()函数绑定。
    data = list(zip(each_class_image, each_class_label))
    # 计算总长度
    total = len(each_class_image)
    # random.shuffle()函数打乱顺序
    random.shuffle(data)
    # 再将两个列表解绑
    each_class_image, each_class_label = zip(*data)

    '''====2.分别获取train、val、test这三个文件夹对应的图片和标签===='''
    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):]

    '''====3.设置相应的路径保存格式,将图片和标签对应保存下来===='''
    # train
    for image in train_images:
        print(image)
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'train' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in train_labels:
        print(label)
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'train' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    # val
    for image in val_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'val' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in val_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'val' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    # test
    for image in test_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'test' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in test_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'test' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)


if __name__ == '__main__':
    file_path = r"D:\A03PyThonProjects395\yolov5-master\yoloData\picData" #原图片路径
    txt_path = r"D:\A03PyThonProjects395\yolov5-master\yoloData\txtData"  #.txt标签路径
    new_file_path = r"D:\A03PyThonProjects395\yolov5-master\yoloData\splitData" #划分后的目录
    # 设置划分比例
    split_data(file_path, txt_path, new_file_path, train_rate=0.8, val_rate=0.1, test_rate=0.1)

3. 训练模型

1修改VOC.yaml:

将data目录下的VOC.yaml文件修改内容为如下: download及其以下的配置不用改动,download以上的全部改掉为如下

train: D:\A03PyThonProjects395\yolov5-master\yoloData\splitData\train #训练集绝对路径
val: D:\A03PyThonProjects395\yolov5-master\yoloData\splitData\val #验证集绝对路径

# Classes
names: ['error_pos'] #这个error_pos是我们标记数据时设置的勾画物体名称,若忘记了可以在txtData目录下的classes.txt看到

nc: 1 #这里填写1的原因:在我们标记数据集之前,我们清空了labelImg-master\data\predefined_classes.txt,然后标记数据时,添加了类别名为error_pos,yolov5在索引我们的类别时是从0开始的,我们的类别只有一个error_pos,所以这里填1,如果不太明白可以简单理解为多少个类别就填几

# Download script/URL (optional) ---------------------------------------------------------------------------------------
download: |..........download这块及其一下都不用改动......

2.修改模型配置文件:

因为我们这里使用的预训练权重是yolov5x.pt,因此将models目录下的yolov5x.yaml文件改动如下:

nc: 1 # number of classes  ,只需要把这个改为1就行了

3.正式训练模型前的配置

训练模型是用train.py ,在训练之前,先定位到train.py的parse_opt方法,可以看到有很多训练参数,这里解释下可能需要修改的参数:

--weights:加载的权重文件路径,默认是根目录下的yolov5s.pt,我用的是yolov5x.pt,因此要改为yolov5x.pt
--cfg:这个要指定我们的models/yolov5x.yaml文件
--data:是指定数据集配置文件,我们这里填data/VOC.yaml
--epochs:表示训练的轮次,要训练300轮就改成300
--batch-size:表示每一批训练的批次大小,这个大小根据GPU或CPU指定,一般为16,32,64,128,256等
--workers:表示使用的核心数量,默认为8
--device:选项有0、1、2、3、cpu,0、1、2、3表示选择第几个GPU,我这里就一个显卡,填0就行了

以上是可能需要修改的参数,下面列出所有参数解释:
opt参数解析: 
• cfg:   模型配置文件,网络结构
• data:   数据集配置文件,数据集路径,类名等
• hyp:   超参数文件
• epochs:   训练总轮次
• batch-size:   批次大小
• img-size:   输入图片分辨率大小
• rect:   是否采用矩形训练,默认False
• resume:   接着打断训练上次的结果接着训练
• nosave:   不保存模型,默认False
• notest:   不进行test,默认False
• noautoanchor:   不自动调整anchor,默认False
• evolve:   是否进行超参数进化,默认False
• bucket:   谷歌云盘bucket,一般不会用到
• cache-images:   是否提前缓存图片到内存,以加快训练速度,默认False
• weights:   加载的权重文件
• name:   数据集名字,如果设置:results.txt to results_name.txt,默认无
• device:   训练的设备,cpu;0(表示一个gpu设备cuda:0);0,1,2,3(多个gpu设备)
• multi-scale:   是否进行多尺度训练,默认False
• single-cls:    数据集是否只有一个类别,默认False
• adam:   是否使用adam优化器
• sync-bn:   是否使用跨卡同步BN,在DDP模式使用
• local_rank:   gpu编号
• logdir:   存放日志的目录
• workers:   dataloader的最大worker数量

最后我修改过的parse_opt结果如下:

parser.add_argument("--weights", type=str, default=ROOT / "yolov5x.pt", help="initial weights path")
parser.add_argument("--cfg", type=str, default="models/yolov5x.yaml", help="model.yaml path")
parser.add_argument("--data", type=str, default=ROOT / "data/VOC.yaml", help="dataset.yaml path")
parser.add_argument("--hyp", type=str, default=ROOT / "data/hyps/hyp.scratch-low.yaml", help="hyperparameters path")
parser.add_argument("--epochs", type=int, default=100, help="total training epochs")
parser.add_argument("--batch-size", type=int, default=16, help="total batch size for all GPUs, -1 for autobatch")
parser.add_argument("--device", default="0", help="cuda device, i.e. 0 or 0,1,2,3 or cpu")

4.开始训练:

参数配置完后执行train.py开始训练

如图表示在训练了,不愧是GPU,3秒一轮,CPU训练非常慢

训练中

5.查询训练结果

训练完后结果会保存在runs的tarin文件里,训练出的最优模型它命名为best.pt,如图

训练完

4.验证模型

验证模型靠的是根目录下的val.py文件,进入val.py文件,定位到parse_opt方法,这里要改动几个参数为我们自己的:

--data:指定验证集的配置文件,即我们data下的VOC.yaml
 --weights:指定模型权重文件,选择我们训练模型后runs下最好的权重文件best.pt,我这里最好的是exp2目录下的best.pt

最后我改动的参数为如下(就改了两个位置):

parser.add_argument("--data", type=str, default=ROOT / "data/VOC.yaml", help="dataset.yaml path")
parser.add_argument("--weights", nargs="+", type=str, default=ROOT / "runs/train/exp2/weights/best.pt", help="model path(s)")

然后运行val.py进行验证,运行后,会在runs目录下生成val的目录,里面就是验证的结果,可能你现在还看不懂,总之可以简单理解为这些图表表示了模型的准确率,当然我这里为了快速教学,用了24张图片肯定是不够的,如图

验证完

5. 用模型检测其他图片

当我们用val.py验证后通过图标查看识别率还不错的话,就可以开始用detect.py进行检测看看效果了

先在根目录创建一个otherPics目录,然后随便网上找几张和你模型需要识别相关的图片,比如我是用来识别桥梁地基冲刷缺陷的,我就找这类图,然后放入otherPics目录

来到detect.py文件下,同样是定位到parse_opt方法,要改动几个参数,这里同验证模型改参数一样:

--weights:指定为自己的最好的训练模型,即runs/train下最好的best.pt
--source:指定要测试的图片的目录,我这里是otherPics
--data:指定数据集配置文件,即我们的data/VOC.yaml
--conf-thres:指定置信度,越小则越信任识别的内容,当然也就越不准确,默认0.25,我这里因为用的图片少,所以调的很低

最终我配置为如下

parser.add_argument("--weights", nargs="+", type=str, default=ROOT / "runs/train/exp2/weights/best.pt", help="model path or triton URL")
parser.add_argument("--source", type=str, default=ROOT / "otherPics", help="file/dir/URL/glob/screen/0(webcam)")
parser.add_argument("--data", type=str, default=ROOT / "data/VOC.yaml", help="(optional) dataset.yaml path")
parser.add_argument("--conf-thres", type=float, default=0.07, help="confidence threshold")

然后运行detect.py,执行完成后会在runs下生成detect目录,目录内便是识别后的图片,如图

结果

至此,幽络源的图像识别教程结束

补充:如有需要,可以自行将detect改为传入照片然后就返回识别后的信息。

© 版权声明
THE END
喜欢就支持一下吧
分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称

    暂无评论内容