图像分割实战-系列教程17:deeplabV3+ VOC分割实战5-------main.py

在这里插入图片描述

🍁🍁🍁图像分割实战-系列教程 总目录

有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传

deeplab系列算法概述
deeplabV3+ VOC分割实战1
deeplabV3+ VOC分割实战2
deeplabV3+ VOC分割实战3
deeplabV3+ VOC分割实战4
deeplabV3+ VOC分割实战5

10、main.py的main()函数

def main():
    opts = get_argparser().parse_args()
    if opts.dataset.lower() == 'voc':
        opts.num_classes = 21
    elif opts.dataset.lower() == 'cityscapes':
        opts.num_classes = 19
  1. 定义main函数
  2. 调用参数函数,解析命令行参数
  3. 判断数据集名称是否为voc,是则设置类别数为21,21=20个对象+1背景
    # Setup visualization
    vis = Visualizer(port=opts.vis_port, env=opts.vis_env) if opts.enable_vis else None
    if vis is not None:  # display options
        vis.vis_table("Options", vars(opts))
    os.environ['CUDA_VISIBLE_DEVICES'] = opts.gpu_id
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print("Device: %s" % device)

设置可视化工具和配置训练设备

  1. 根据 opts.enable_vis 的值决定是否创建一个 Visualizer 对象,其端口和环境设置由 opts.vis_portopts.vis_env 提供。Visualizer 是一个python可视化工具类,用于在训练过程中显示图像、图表等信息
  2. 检查是否启用了可视化
  3. 如果可视化被启用,这一行调用 vis 对象的 vis_table 方法来显示配置选项。vars(opts) 是将 opts 对象转换为字典,其中包含了所有的命令行参数
  4. 设置环境变量 CUDA_VISIBLE_DEVICES,其值为 opts.gpu_id
  5. 如果GPU可用,则使用 CUDA;否则,使用 CPU
  6. 打印出使用的设备信息
    torch.manual_seed(opts.random_seed)
    np.random.seed(opts.random_seed)
    random.seed(opts.random_seed)
    if opts.dataset=='voc' and not opts.crop_val:
        opts.val_batch_size = 1
    train_dst, val_dst = get_dataset(opts)
    train_loader = data.DataLoader( train_dst, batch_size=opts.batch_size, shuffle=True, num_workers=0)
    val_loader = data.DataLoader( val_dst, batch_size=opts.val_batch_size, shuffle=True, num_workers=0)
    print("Dataset: %s, Train set: %d, Val set: %d" % (opts.dataset, len(train_dst), len(val_dst)))
  1. 分别为pytorch
  2. numpy
  3. python设置全局随机种子
  4. 检查是否使用VOC数据集并且没有启用验证集的裁剪
  5. 如果条件满足,将验证批次大小设置为 1
  6. 调用 get_dataset 函数来获取训练和验证数据集,该函数在第3部分已经解析
  7. 训练集DataLoader,opts.batch_size训练批次大小
  8. 验证集DataLoader,opts.val_batch_size验证批次大小
  9. 打印出使用的数据集名称以及训练和验证集的大小
    model_map = {
        'deeplabv3_resnet50': network.deeplabv3_resnet50,
        'deeplabv3plus_resnet50': network.deeplabv3plus_resnet50,
        'deeplabv3_resnet101': network.deeplabv3_resnet101,
        'deeplabv3plus_resnet101': network.deeplabv3plus_resnet101,
        'deeplabv3_mobilenet': network.deeplabv3_mobilenet,
        'deeplabv3plus_mobilenet': network.deeplabv3plus_mobilenet
    }
    model = model_map[opts.model](num_classes=opts.num_classes, output_stride=opts.output_stride)
    if opts.separable_conv and 'plus' in opts.model:
        network.convert_to_separable_conv(model.classifier)
    utils.set_bn_momentum(model.backbone, momentum=0.01)

这部分设置网络的参数

  1. 定义一个模型映射字典,字典包括本项目可选择的多个网络:

  2. deeplabv3的resnet50

  3. deeplabv3+的resnet50

  4. deeplabv3的resnet101

  5. deeplabv3+的resnet101

  6. deeplabv3的mobilenet

  7. deeplabv3+的mobilenet,这些网络在Network文件夹中使用一定方法构建,在这里直接导入

  8. 从预设要选择的网络名称、类别数、输出通道数加载网络

  9. 检查是否启用可分离卷积、模型名称包含 ‘plus’

  10. 如果条件满足,则对模型的分类器部分应用可分离卷积的转换

  11. 调用set_bn_momentum函数,设置批量归一化的动量,set_bn_momentum函数:

    def set_bn_momentum(model, momentum=0.1):
        for m in model.modules():
            if isinstance(m, nn.BatchNorm2d):
                m.momentum = momentum
    
    metrics = StreamSegMetrics(opts.num_classes)
    optimizer = torch.optim.SGD(params=[
        {'params': model.backbone.parameters(), 'lr': 0.1*opts.lr},
        {'params': model.classifier.parameters(), 'lr': opts.lr},
    ], lr=opts.lr, momentum=0.9, weight_decay=opts.weight_decay)
    if opts.lr_policy=='poly':
        scheduler = utils.PolyLR(optimizer, opts.total_itrs, power=0.9)
    elif opts.lr_policy=='step':
        scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=opts.step_size, gamma=0.1)
    if opts.loss_type == 'focal_loss':
        criterion = utils.FocalLoss(ignore_index=255, size_average=True)
    elif opts.loss_type == 'cross_entropy':
        criterion = nn.CrossEntropyLoss(ignore_index=255, reduction='mean')
    

评价指标、优化器、学习率、损失函数

  1. StreamSegMetrics类是一个评价指标,用于在语义分割任务中跟踪模型的性能,计算的指标包括总体准确率、平均准确率、频率加权平均准确率、平均交并比(IoU)和每个类别的 IoU,通过计算混淆矩阵和从中派生出的多个指标。实例化出一个对象
  2. 设置SGD为优化器,并设置一些参数
  3. 设置backbone的学习率,预训练的backbone部分通常需要较小的学习率来微调
  4. 设置分类器的学习率
  5. 设置优化器的初始全局学习率,设置动量帮助加速SGD并抑制震荡,设置权重衰减用于防止过拟合
  6. 如果学习率策略设为 “poly”
  7. 则使用多项式衰减
  8. 如果学习率策略设为 “step”
  9. 则使用阶梯式衰减
  10. 根据 opts.loss_type 的值选择合适的损失函数 ,如果损失函数类型为 “focal_loss”
  11. 则使用焦点损失(Focal Loss),这对于处理类别不平衡问题很有效、
  12. 如果损失函数类型为 “cross_entropy”
  13. 则使用交叉熵损失
	utils.mkdir('checkpoints')
    best_score = 0.0
    cur_itrs = 0
    cur_epochs = 0
    if opts.ckpt is not None and os.path.isfile(opts.ckpt):
        checkpoint = torch.load(opts.ckpt, map_location=torch.device('cpu'))
        model.load_state_dict(checkpoint["model_state"])
        model = nn.DataParallel(model)
        model.to(device)
        if opts.continue_training:
            optimizer.load_state_dict(checkpoint["optimizer_state"])
            scheduler.load_state_dict(checkpoint["scheduler_state"])
            cur_itrs = checkpoint["cur_itrs"]
            best_score = checkpoint['best_score']
            print("Training state restored from %s" % opts.ckpt)
        print("Model restored from %s" % opts.ckpt)
        del checkpoint  # free memory
    else:
        print("[!] Retrain")
        model = nn.DataParallel(model)
        model.to(device)

checkpoints,检查点

  1. 创建 “checkpoints” 文件夹,存储训练过程中的模型检查点
  2. 初始化最佳分数为0,记录验证集上的最高分数
  3. 初始化当前迭代次数为0
  4. 初始化当前轮数为0
  5. 检查是否提供了检查点文件,并且该文件确实存在
  6. 加载检查点文件,意味着无论检查点是在CPU还是GPU上保存的,都会先被加载到CPU内存中
  7. 从检查点中恢复模型的状态
  8. 使用 DataParallel 来利用多个GPU(如果可用)
  9. 模型放入GPU
  10. 检查是否需要从检查点继续训练
  11. 从检查点恢复优化器的状态
  12. 从检查点恢复学习率调度器的状态
  13. 从检查点恢复当前迭代次数
  14. 从检查点恢复当前最佳分数
  15. 打印模型恢复信息
  16. 删除检查点变量以释放内存
  17. 如果没有提供有效的检查点文件
  18. 打印重新训练的信息
  19. 使用 DataParallel 来利用多个GPU(如果可用)
  20. 模型放入GPU
    vis_sample_id = np.random.randint(0, len(val_loader), opts.vis_num_samples, np.int32) if opts.enable_vis else None
    denorm = utils.Denormalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # denormalization for ori images
    if opts.test_only:
        model.eval()
        val_score, ret_samples = validate(
            opts=opts, model=model, loader=val_loader, device=device, metrics=metrics, ret_samples_ids=vis_sample_id)
        print(metrics.to_str(val_score))
        return
    

训练中的可视化设置、测试模式处理、初始化变量

  1. 选择可视化样本:如果启用了可视化则从验证数据加载器中随机选择一定数量的样本进行可视化,否则,vis_sample_id 设为 None
  2. 反标准化操作:创建一个反标准化对象,将用于将预处理(标准化)后的图像恢复到原始图像的颜色空间
  3. 检查是否仅进行测试,如果是:
  4. 将模型设置为评估模式
  5. 调用 validate 函数,返回评分、选定的样本
  6. 打印评估结果
  7. 结束函数执行。
    interval_loss = 0
    while True: #cur_itrs < opts.total_itrs:
        model.train()
        cur_epochs += 1
        for (images, labels) in train_loader:
            cur_itrs += 1
            images = images.to(device, dtype=torch.float32)
            labels = labels.to(device, dtype=torch.long)
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            np_loss = loss.detach().cpu().numpy()
            interval_loss += np_loss
  1. 初始化间隔损失为0
  2. 开始无限循环(达到最大迭代次数停止)
  3. 开启模型训练模式
  4. 当前epoch+1
  5. 从训练集dataloader取出数据和标签
  6. 当前迭代次数+1
  7. 训练数据进入GPU
  8. 训练标签进入GPU
  9. 梯度清零
  10. 训练数据进入模型后得到输出
  11. 输出和标签通过损失函数计算损失
  12. 反向传播,计算损失相对于模型参数的梯度
  13. 根据计算的梯度更新模型的权重
  14. 将损失从GPU(如果使用)转移到CPU,并转换为NumPy格式
  15. 累加损失
            if vis is not None:
                vis.vis_scalar('Loss', cur_itrs, np_loss)
            if (cur_itrs) % 10 == 0:
                interval_loss = interval_loss/10
                print("Epoch %d, Itrs %d/%d, Loss=%f" % (cur_epochs, cur_itrs, opts.total_itrs, interval_loss))
                interval_loss = 0.0

可视化、日志记录部分:

  1. 条件可视化:检查是否创建了可视化对象
  2. 使用可视化工具来记录当前迭代的损失。 'Loss' 是要记录的数据的名称,cur_itrs 是当前迭代次数,np_loss 是当前迭代的损失值
  3. 每当当前迭代次数是10的倍数时执行以下操作:
  4. 计算过去10次迭代的平均损失
  5. 打印当前的epoch、迭代次数、总迭代次数、平均损失
  6. 重置间隔损失,为计算下一个间隔的平均损失做准备
            if (cur_itrs) % opts.val_interval == 0:
                save_ckpt('checkpoints/latest_%s_%s_os%d.pth' % (opts.model, opts.dataset, opts.output_stride))
                print("validation...")
                model.eval()
                val_score, ret_samples = validate(
                    opts=opts, model=model, loader=val_loader, device=device, metrics=metrics, ret_samples_ids=vis_sample_id)
                print(metrics.to_str(val_score))
                if val_score['Mean IoU'] > best_score:  # save best model
                    best_score = val_score['Mean IoU']
                    save_ckpt('checkpoints/best_%s_%s_os%d.pth' % (opts.model, opts.dataset,opts.output_stride))
                if vis is not None:  # visualize validation score and samples
                    vis.vis_scalar("[Val] Overall Acc", cur_itrs, val_score['Overall Acc'])
                    vis.vis_scalar("[Val] Mean IoU", cur_itrs, val_score['Mean IoU'])
                    vis.vis_table("[Val] Class IoU", val_score['Class IoU'])
                    for k, (img, target, lbl) in enumerate(ret_samples):
                        img = (denorm(img) * 255).astype(np.uint8)
                        target = train_dst.decode_target(target).transpose(2, 0, 1).astype(np.uint8)
                        lbl = train_dst.decode_target(lbl).transpose(2, 0, 1).astype(np.uint8)
                        concat_img = np.concatenate((img, target, lbl), axis=2)  # concat along width
                        vis.vis_image('Sample %d' % k, concat_img)
                model.train()
            scheduler.step()  
            if cur_itrs >=  opts.total_itrs:
                return        

验证、模型保存、可视化反馈:

  1. 每隔一定的迭代次数,程序将执行一次验证过程
  2. 保存当前模型的状态到检查点。这里的文件名包含模型类型、数据集、输出步长
  3. 打印正在验证中
  4. 将模型设置为评估模式
  5. 执行验证函数,
  6. 返回性能得分、一些样本图片
  7. 打印验证得分
  8. 如果当前验证得分的平均交并比(Mean IoU)高于之前的最佳得分
  9. 更新最佳得分
  10. 保存当前模型
  11. 如果可视化被启用
  12. 可视化总体准确率
  13. 可视化平均 IoU
  14. 可视化各类别的 IoU
  15. for循环取出返回的样本,每个样本包含原始图像(img)、真实标签(target)、模型预测的标签(lbl),对返回的样本进行可视化:
  16. 对原始图像应用反标准化操作
  17. 将目标标签从模型输出的格式解码成可视化格式
  18. 将预测标签从模型输出的格式解码成可视化格式
  19. 将原始图像、真实标签和预测标签沿着宽度方向拼接在一起
  20. 使用可视化工具显示拼接后的图像
  21. 将模型设置回训练模式
  22. 更新学习率
  23. 如果当前迭代次数达到或超过预设的总迭代次数
  24. 则结束训练

deeplab系列算法概述
deeplabV3+ VOC分割实战1
deeplabV3+ VOC分割实战2
deeplabV3+ VOC分割实战3
deeplabV3+ VOC分割实战4
deeplabV3+ VOC分割实战5

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: labelimg-script.py是一个用于图像标注的Python脚本,它可以帮助用户在图像上创建标签。图像标注是将物体或感兴趣区域在图像中进行标记的过程,常用于机器学习和计算机视觉领域。 该脚本主要提供了一个图形用户界面(GUI),使用户可以方便地绘制各种形状的标签,如矩形、圆形、多边形等。用户可以通过点击图像上的坐标点或拖动鼠标来绘制标签,还可以对标签进行编辑和调整。 除了绘制标签外,该脚本还提供了一些其他功能,如保存和加载标签数据,自动调整窗口大小以适应图像大小,查看标签的详细信息等。用户还可以通过快捷键来操作,提高工作效率。 该脚本适用于各种标注任务,如目标检测、图像分割、姿态估计等。用户可以根据自己的需求进行相应的修改和定制。 总之,labelimg-script.py是一个灵活实用的图像标注工具,可以帮助用户快速准确地完成标注任务,为后续的机器学习和计算机视觉工作提供支持。 ### 回答2: labelimg-script.py是一个用Python编写的脚本文件,它用于自动化一种名为LabelImg的图像标注工具的标注过程。LabelImg是一个开源的图像标注工具,它允许用户绘制边界框来标注图像中的目标物体。但是,对于大量的图像标注任务来说,手动绘制边界框是一个非常耗时且繁琐的过程。因此,labelimg-script.py的目的就是为了简化这个过程,提高标注的效率。 该脚本可以通过命令行接受输入参数,例如输入要标注的图像文件夹路径、标注结果输出文件夹路径等。它可以自动遍历指定的图像文件夹,将每张图像自动加载到LabelImg工具中,然后通过调用模拟用户操作的方式来完成边界框的绘制。一旦完成绘制,脚本将自动保存标注结果,并将结果导出到指定的输出文件夹中。 使用labelimg-script.py可以极大地减少人工标注的工作量,特别是对于需要标注大量图像的任务来说。例如在计算机视觉领域的目标检测任务中,通常需要对许多图像进行标注。使用该脚本可以自动完成大部分标注工作,从而节省了大量的时间和劳力。 总之,labelimg-script.py是一个实用的工具,通过自动化图像标注过程,提高了标注的效率和准确性,为图像处理和机器学习任务提供了便利。 ### 回答3: labelimg-script.py 是一个用于图像标注的 Python 脚本。它可以帮助用户在图像上绘制边界框或者创建标注文件,以便用于对象检测任务的训练和评估。该脚本提供了一个用户友好的图形界面,使得图像标注相对简单和高效。 使用该脚本,用户可以打开图像文件,然后使用鼠标绘制矩形框来标记图像中的物体或目标。这些矩形框充当了标注框,用于表示图像中感兴趣的区域。用户可以选择添加不同类别的标签,并为每个标注框分配相应的类别。 此外,该脚本还提供了一些基本的编辑功能,如移动和调整标注框的大小、删除和添加标注框等。用户还可以导出标注信息,生成常见的标注文件格式,例如 PASCAL VOC、YOLO 和 TensorFlow Object Detection API 等格式,以便进行进一步的训练或模型评估。 labelimg-script.py 提供了一种简单但实用的方法来处理图像标注任务,用户只需要少量的编程知识即可进行标注工作。它的灵活性使得它成为许多计算机视觉研究者和从业者的首选工具之一。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器学习杨卓越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值