YOLOv8+孪生神经网络 终于解决了中文点选验证码


时隔三个月,忙活了很久的中文点选验证码的识别,终于尘埃落定了,浅浅记录一下吧。前期为了偷懒,试过模板匹配、特征匹配、ocr文字识别(使用的是ddddocr)等方法,最终都以失败告终。无奈之下,还是使用了孪生神经网络,当然,不得不感慨孪生神经网络的强大,最终也是实现了95%以上的准确率。。。但有一种杀鸡焉用宰牛刀的感觉hhhh。anyway,终于得空整理这些东西了,整理出来发出来给大家参考一下。。。

先来看看验证码是啥样的吧,参考下图在这里插入图片描述
想要训练模型,需要的数据当然不是一张图就能行的啦,所以,通过爬虫准备大量数据,爬虫到的图片格式是这样滴:在这里插入图片描述
在这里插入图片描述
是的,一张验证码是由一张大图和一张小图共两张图片组成的。想在大图中找到小图中的四个字,当然应该想一些办法啦,比如把小图中的字截下来与大图中的进行比对,笔者试过诸如图像匹配、ddddocr文字识别等方法(希望工作量小一点),最终都以失败告终。最后还是妥协给了孪生神经网络。

第一步,需要将大图中的5个汉字截取下来,目标检测是一个很好的办法,也作为笔者对最新的YOLO模型的初次尝试吧。

解法流程

先把解决这个问题的流程放在文章开头吧,之后需要那一部分在目录跳转就可以。

Created with Raphaël 2.3.0 收集数据(爬虫) 训练目标检测模型(YOLOv8) 裁剪图片,标注数据,训练孪生神经网络 预测,返回坐标

YOLOv8

YOLOv8是Ultralytics公司最新推出的YOLO系列目标检测算法,可以用于图像分类、物体检测和实例分割等任务。根据官方描述,Yolov8是一个SOTA模型,它建立在Yolo系列历史版本的基础上,并引入了新的功能和改进点,以进一步提升性能和灵活性,使其成为实现目标检测、图像分割、姿态估计等任务的最佳选择。

此外,Yolov8还有一个特点就是可扩展性,ultralytics将开源库命名为:“ultralytics”,而不是YOLOv8,原因是 ultralytics 将这个库定位为算法框架,而非某一个特定算法。其希望这个库不仅仅能够用于 YOLO 系列模型,而是能够支持非 YOLO 模型以及分类分割姿态估计等各类任务。

总而言之,ultralytics 开源库的两个主要优点是:

  • 融合众多当前 SOTA 技术于一体
  • 未来将支持其他 YOLO 系列以及 YOLO 之外的更多算法

虚拟环境

新建虚拟环境

conda create -n your_env_name python=x.x

注意,YOLOv8要求:Python>=3.7,PyTorch>=1.7.

查看虚拟环境是否新建成功,有哪些虚拟环境,可以通过以下命令:

conda env list 
conda info -e

激活虚拟环境

conda activate your_env_name

查看虚拟环境中有哪些包,可以使用下面的命令

pip list
conda list

删除虚拟环境

conda remove -n your_env_name --all

安装

pip安装(本人使用,非常简单)

pip install ultralytics

一般情况下,直接输入上面的命令特别特别慢,可以添加镜像(附一个镜像汇总链接:https://zhuanlan.zhihu.com/p/298372291),比如使用清华镜像:

pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple

剩下的就不用管了,只需要等待安装完成即可。

源码安装

源码安装可以看这篇blog:https://blog.csdn.net/weixin_45662399/article/details/134499605

训练

下载预训练权重(建议事先下载好,模型自己下载太慢了)

预训练权重在下面地址中可以下载:
https://gitcode.com/ultralytics/ultralytics/overviewutm_source=csdn_github_accelerator&isLogin=1
官方给出5个预训练权重,从小到大分别为YOLOv8nYOLOv8sYOLOv8mYOLOv8lYOLOv8x,当然啦,模型大了,对应的速度也就慢一点了,所以选择合适的模型是很重要的。本人使用的是YOLOv8nYOLOv8s
在这里插入图片描述

数据标注

在这个例子中,将大图中的字看成一类,只需要识别出大图中的5个汉字就好了。
说实话,数据有点多,为了偷懒,用百度easydl标注的数据。
在这里插入图片描述

具体用法:

第一步,先在数据总览中创建数据集
在这里插入图片描述

第二步:先自己手动标注,保证每一个标签都有不少于10个时,在数据标注中选择智能标注,剩下只需要大致检查一下标注就行了。

第三步,在数据总览的数据集后面选择多人标注,就会进入到下面这个页面,点击导出,就能导出标注信息了。在这里插入图片描述

不足的是,导出的数据格式并不是YOLO格式的,因此需要转为YOLO格式,我导出的是voc格式,voc转YOLO格式可参照这篇blog:
https://blog.csdn.net/qq_43161211/article/details/122959052

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"] ### 注意与自己的类对应,对应,对应,不然转好的txt文件是空的
#classes=["ball"]
 
TRAIN_RATIO = 80 ### 按自己的要求划分,这里代表是train:test=8:2
 
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 - 1
    y = (box[2] + box[3])/2.0 - 1
    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()

修改.yaml配置文件

.yaml配置文件包括训练集、验证集、测试集的路径,nc表示类别数量,names为类别名称。创建data文件夹,创建一个data.yaml文件:

train: C:/Users/admin/Desktop/images/train #训练集路径
val: C:/Users/admin/Desktop/images/val #验证集路径
test: C:/Users/admin/Desktop/images/test #测试集路径
# number of classes
nc: 1
# class names
names: ['1']

训练代码

YOLOv8支持命令行命令,也支持python代码。

命令行
yolo train data=data.yaml ( 你的配置文件(xx.yaml)) model=yolov8n.pt epochs=300 imgsz=640 batch=8 workers=0 device=0
python代码
from ultralytics import YOLO
 # 加载模型
model = YOLO('yolov8n.pt') 
 # 训练模型
 results = model.train(data='data.yaml', epochs=300, imgsz=640)

训练结果

训练结果保存在runs/detect/train文件夹,文件夹内容如下:在这里插入图片描述

weights文件夹

在weights文件夹中包含best.pt和last.pt,best.pt是损失值最小的模型文件,last.pt是最后一次训练的权重。
在这里插入图片描述
训练结果分析可参照https://blog.csdn.net/weixin_45277161/article/details/131046636.

预测

通过训练,得到了YOLOv8模型,记下来就是根据图片进行预测啦。同样地,预测也可通过命令行方式和python代码实现。

命令行

yolo predict model=runs/detect/train/weights/best.pt source=C:/Users/admin/Desktop/image1.png

pyhton代码

from ultralytics import YOLO
# 加载模型
model = YOLO('best.pt')
 
# 模型预测,save=True 的时候表示直接保存yolov8的预测结果
metrics = model.predict('image1.jpg', save=True)

孪生神经网络(Siamese network)

呼,终于码完YOLOv8了,接下来就该码孪生神经网络了。本文使用的孪生神经网络代码来自于https://github.com/bubbliiiing/siamese-pytorch/tree/bilibili

孪生神经网络的背景我就不介绍了,毕竟在使用的时候并不考虑背景。我们直接来看应用场景。

应用场景

Siamese network就是“连体的神经网络”,两个神经网络共享权值,用于处理两个输入"比较类似"的情况。比如,我们要计算两个句子或者词汇的语义相似度,使用siamese network比较适合。孪生神经网络

当两个神经网络的权值不共享时,称为伪孪生神经网络。在伪孪生神经网络中,两个神经网络可以是不同的神经网络。(比如一个是lstm一个是cnn)伪孪生神经网络适用于处理两个输入"有一定差别"的情况。如果验证标题与正文的描述是否一致(标题和正文长度差别很大),或者文字是否描述了一幅图片(一个是图片,一个是文字),就应该使用伪孪生神经网络。

准备数据集

训练之前,还是要标注数据的。说到标注数据,这可是个麻烦事了。对于大图中的汉字,采取先裁剪后标注的两步骤方法。在标注之前,先将大图上汉字的图片用YOLOv8切割。

from ultralytics import YOLO
import cv2
import hashlib
import numpy as np
import os
#切割大图
model = YOLO('best.pt') #加载yolo模型
def cai_save(img_big):
    results = model.predict(img_big)
    img_big_cai = [] #裁剪图片并保存在列表中
    for i in results[0].boxes.xyxy:
        i = list(map(int, i))
        img_c = img_big[i[1]:i[3],i[0]:i[2]]
        img_big_cai.append(img_c)
    for img_array in img_big_cai:
        fd = img_array * np.random.randint(10)
        fmd5 = hashlib.md5(fd).hexdigest() + '.jpg'
        cv2.imwrite(os.path.join('./cai_big_images', fmd5), img_array)
dir_path = './big_images'
files = os.listdir(dir_path_train)
for file in files:
    img = cv2.imread(dir_path+file)
    cai_save(img)

在这里插入图片描述

由于小图中需要验证的汉字坐标是固定的,因此直接裁剪+标注一步完成。接着借助https://blog.csdn.net/aaronjny/article/details/109732693中的标注脚本,来标注数据。因为小图中汉字的字体是一样的,因此将它们单独放到了一个文件夹correct_words,将标注的大图中的汉字放到了文件夹gen_words(emmmm,裁剪出来几万张图片实在标注不完,只标注了一部分)。

import os
from glob import glob
import cv2
from tqdm import tqdm

def extract_correct_word():
    save_dir = './correct_words/'
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    images = glob('img_small/*.png')
    cai = [[166, 12, 192, 38], [199, 12, 225, 38], [232, 12, 258, 38], [265, 12, 291, 38]]
    for image_path in tqdm(images):
        image_small = cv2.imread(image_path)
        for coord in cai:
            im = image_small[coord[1]:coord[3], coord[0]:coord[2]]
            cv2.imshow('text', im)
            cv2.waitKey(100)
            word = input('请输入当前选中汉字:')
            name = word+'.png'
            # cv2.imencode(保存格式, 保存图片)[1].tofile(保存路径)
            re = cv2.imencode('.png', im)[1].tofile(os.path.join(save_dir, name))
            del im
            cv2.destroyAllWindows()
        os.remove(image_path) #每标注一张图,从原来文件夹img_small中删除这张图,将标注图片和信息保存到新的文件夹correct_words中
def extract_gen_word():
    save_dir = './gen_words/'
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    images = glob('cai_big_images/*.png')
    for image_path in tqdm(images):
        num = image_path.split('/')[-1].split('.')[0]
        im = cv2.imread(image_path)
        cv2.imshow('text', im)
        cv2.waitKey(100)
        word = input('请输入当前选中汉字:')
        name = word+'-'+num+'.png'
            # cv2.imencode(保存格式, 保存图片)[1].tofile(保存路径)
        re = cv2.imencode('.png', im)[1].tofile(os.path.join(save_dir, name))
        del im
        cv2.destroyAllWindows()
        os.remove(image_path)
if __name__ == '__main__':
    #extract_correct_word()
    extract_gen_word()

对于大图中的汉字,标注命名方式为:字-hash值.png,不认识或者不好辨认的字全部标注为1-hash值;小图中的汉字直接命名为 汉字.png
在这里插入图片描述
在这里插入图片描述

训练孪生神经网络

孪生神经网络的输入是一个正样本一个负样本,在本次训练中,正样本和负样本分别取自gen_words和correct_words两个文件夹,因此本次训练的数据集格式与https://blog.csdn.net/weixin_44791964/article/details/107343394不同,所以将bubbliiiing中的代码中关于数据集的部分小小修改了一下。训练过程如下。
在这里插入图片描述

预测

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

返回坐标

在这里插入图片描述

YOLOv8训练参数说明

最后再补一个训练参数说明吧

参数默认值说明
modelNone指定用于训练的模型文件。接受指向 .pt 预训练模型或 .yaml 配置文件。对于定义模型结构或初始化权重至关重要。
dataNone数据集配置文件的路径(例如 coco128.yaml).该文件包含特定于数据集的参数,包括训练数据和验证数据的路径、类名和类数。
epochs100训练周期数。每个周期代表对整个数据集进行一次完整的训练。调整该值会影响训练时间和模型性能。
timeNone最长训练时间(小时)。如果设置了该值,则会覆盖 epochs 参数,允许训练在指定的持续时间后自动停止。对于时间有限的训练场景非常有用。
patience100在验证指标没有改善的情况下,提前停止训练所需的周期数。当性能趋于平稳时停止训练,有助于防止过度拟合。
batch16训练的批量大小,表示在更新模型内部参数之前要处理多少张图像。自动批处理 (batch=-1)会根据 GPU 内存可用性动态调整批处理大小。
imgsz640用于训练的目标图像尺寸。所有图像在输入模型前都会被调整到这一尺寸。影响模型精度和计算复杂度。
saveTrue可保存训练检查点和最终模型权重。这对恢复训练或模型部署非常有用。
save_period-1保存模型检查点的频率,以 epochs 为单位。值为-1 时将禁用此功能。该功能适用于在长时间训练过程中保存临时模型。
cacheFalse在内存中缓存数据集图像 (True/ram)、磁盘 (disk),或禁用它 (False).通过减少磁盘 I/O 提高训练速度,但代价是增加内存使用量。
deviceNone指定用于训练的计算设备:单个 GPU (device=0)、多个 GPU (device=0,1)、CPU (device=cpu),或苹果芯片的 MPS (device=mps).
workers8加载数据的工作线程数(每 RANK 多 GPU 训练)。影响数据预处理和输入模型的速度,尤其适用于多 GPU 设置。
projectNone保存训练结果的项目目录名称。允许有组织地存储不同的实验。
nameNone训练运行的名称。用于在项目文件夹内创建一个子目录,用于存储训练日志和输出结果。
exist_okFalse如果为 True,则允许覆盖现有的项目/名称目录。这对迭代实验非常有用,无需手动清除之前的输出。
pretrainedTrue决定是否从预处理模型开始训练。可以是布尔值,也可以是加载权重的特定模型的字符串路径。提高训练效率和模型性能。
optimizer‘auto’为培训选择优化器。选项包括 SGD, Adam, AdamW, NAdam, RAdam, RMSProp 等,或 auto 用于根据模型配置进行自动选择。影响收敛速度和稳定性
verboseFalse在训练过程中启用冗长输出,提供详细日志和进度更新。有助于调试和密切监控培训过程。
seed0为训练设置随机种子,确保在相同配置下运行的结果具有可重复性。
deterministicTrue强制使用确定性算法,确保可重复性,但由于对非确定性算法的限制,可能会影响性能和速度。
single_clsFalse在训练过程中将多类数据集中的所有类别视为单一类别。适用于二元分类任务,或侧重于对象的存在而非分类。
rectFalse可进行矩形训练,优化批次组成以减少填充。这可以提高效率和速度,但可能会影响模型的准确性。
cos_lrFalse利用余弦学习率调度器,根据历时的余弦曲线调整学习率。这有助于管理学习率,实现更好的收敛。
close_mosaic10在训练完成前禁用最后 N 个历元的马赛克数据增强以稳定训练。设置为 0 则禁用此功能。
resumeFalse从上次保存的检查点恢复训练。自动加载模型权重、优化器状态和历时计数,无缝继续训练。
ampTrue启用自动混合精度 (AMP) 训练,可减少内存使用量并加快训练速度,同时将对精度的影响降至最低。
fraction1.0指定用于训练的数据集的部分。允许在完整数据集的子集上进行训练,这对实验或资源有限的情况非常有用。
profileFalse在训练过程中,可对ONNX 和TensorRT 速度进行剖析,有助于优化模型部署。
freezeNone冻结模型的前 N 层或按索引指定的层,从而减少可训练参数的数量。这对微调或迁移学习非常有用。
lr00.01初始学习率(即 SGD=1E-2, Adam=1E-3) .调整这个值对优化过程至关重要,会影响模型权重的更新速度。
lrf0.01最终学习率占初始学习率的百分比 = (lr0 * lrf),与调度程序结合使用,随着时间的推移调整学习率。
momentum0.937用于 SGD 的动量因子,或用于 Adam 优化器的 beta1,用于将过去的梯度纳入当前更新。
weight_decay0.0005L2 正则化项,对大权重进行惩罚,以防止过度拟合。
warmup_epochs3.0学习率预热的历元数,学习率从低值逐渐增加到初始学习率,以在早期稳定训练。
warmup_momentum0.8热身阶段的初始动力,在热身期间逐渐调整到设定动力。
warmup_bias_lr0.1热身阶段的偏置参数学习率,有助于稳定初始历元的模型训练。
box7.5损失函数中边框损失部分的权重,影响对准确预测边框坐标的重视程度。
cls0.5分类损失在总损失函数中的权重,影响正确分类预测相对于其他部分的重要性。
dfl1.5分布焦点损失权重,在某些YOLO 版本中用于精细分类。
pose12.0姿态损失在姿态估计模型中的权重,影响准确预测姿态关键点的重点。
kobj2.0姿态估计模型中关键点对象性损失的权重,在检测可信度和姿态精度之间取得平衡。
label_smoothing0.0应用标签平滑,将硬标签软化为目标标签和标签均匀分布的混合标签,可以提高泛化效果。
nbs64用于损耗正常化的标称批量大小。
overlap_maskTrue决定在训练过程中分割掩码是否应该重叠,适用于实例分割任务。
mask_ratio4分割掩码的下采样率,影响训练时使用的掩码分辨率。
dropout0.0分类任务中正则化的放弃率,通过在训练过程中随机省略单元来防止过拟合。
valTrue可在训练过程中进行验证,以便在单独的数据集上对模型性能进行定期评估。
plotsFalse生成并保存训练和验证指标图以及预测示例图,以便直观地了解模型性能和学习进度。
  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资源说明】 基于孪生神经网络实现的点选识别python源码(带注释)+运行说明+数据集+预训练模型.zip ## 效果 4090训练100轮 测试集可以达到98.6%以上,基本上已经破解了该类验证码。 ![效果演示](./beeb1dc9cdf4f18a98a51d631745ba75.png "效果演示") ## 坑 注意啊,建议重新把yolo分割文字那个部分训练下,因为我这个样本是别人从前台截图后标注训练的,导致泛化性能不是很好!! 有能力的话建议把样本都重新标注下。 ### 如何使用? 下载数据集和预训练模型:https://systems.lanzout.com/iWUqz15mo57a #### 环境安装 安装环境,我用到的是python3.10 ``` conda create -n geetest python=3.8 ``` 安装必要的环境 ``` pip3 install -r requirement.txt ``` ### CUDA安装 安装cuda和 cudnn ``` conda install cudnn=8.1.0.77 cudatoolkit=11.2.0 ``` #### 数据准备 准备数据集,放入data中,格式为 id_序号.jpg|png,id可以采用uuid,序号第一张图是1,第二张图是2,只能两张图 例如,相同的两个字, ``xxxxx_1.jpg``和``xxxxx_2.jpg`` ### 训练模型 配置训练参数,config.py中,一般来说只需要配置gpu就行了,如果你没有gpu就不填,就自动使用cpu 开始训练 ``` python train.py ``` 预测 ``` python predict.py ``` 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,也适用于小白学习入门进阶。当然也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或者热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值