Pytorch语义分割网络的详细训练过程——以NYUv2数据集为例

NYU-Depth数据集 数据集包含以下几个部分: 有标签的:视频数据的一个子集,伴随着密集多标签。此数据也已经被预处理,以填补缺少的深度标签。 原始数据集:利用Kinect测得的原始的RGB、Depth、加速度数据。 工具箱:用于操作数据和标签的有用的工具。 用于评估的训练和测试部分。 有标签的数据集有标签的数据集是原始数据集的子集。它是由成对的RGB和深度帧同步组成的,并且每个图像都有多个标签。除了加上标签的深度地图之外 阅读详情
AI摘要

本文详细介绍了如何在PyTorch中构建自定义数据集,包括理解Dataset和DataLoader,定义数据预处理方法,以及创建数据加载器。接着,文章展示了基于预训练VGG19的FCN8s模型搭建过程,并定义了损失函数和优化器,最后阐述了模型的迭代训练流程。

一、构建数据集

1. 对Dataset和DataLoader的理解

  Pytorch提供了一种十分方便的数据读取机制,即使用Dataset与DataLoader组合得到数据迭代器。在每次训练时,利用这个迭代器输出每一个batch的数据,并能在输出时对数据进行相应的预处理或数据增广操作。

  • 我们如果要自定义数据读取的方法,就需要继承torch.utils.data.Dataset,并将其封装到torch.utils.data.DataLoader中。

  • torch.utils.data.Dataset表示该数据集,继承该类可以重载其中的方法,实现多种数据读取及数据预处理。

  • torch.utils.data.DataLoader 封装了Data对象,实现单(多)进程迭代器输出数据集。

2. torch.utils.data.Dataset

  torch.utils.data.Dataset是代表自定义数据集方法的类,用户可以通过继承该类来自定义自己的数据集类,在继承时要求用户重载__len__()和__getitem__()这两个方法。

  • __len__():返回的是数据集的大小。

  • __getitem__():实现索引数据集中的某一个数据。此外,可以在__getitem__()中实现数据预处理。

3. torch.utils.data.DataLoader

  • DataLoader将Dataset对象或自定义数据类的对象封装成一个迭代器;

  • 这个迭代器可以迭代输出Dataset的内容;

  • 同时可以实现多进程、shuffle、不同采样策略,数据校对等等处理过程。

4. 代码分块解析

  • 自定义的数据集类为NYUv2_Dataset,继承自torch.utils.data.Dataset
class NYUv2_Dataset(Dataset):
    def __init__(self, data_root, img_transforms):
        self.data_root = data_root
        self.img_transforms = img_transforms
        data_list, label_list = read_image_path(root=self.data_root)
        self.data_list = data_list
        self.label_list = label_list

    def __len__(self):
        return len(self.data_list)

    def __getitem__(self, item):
        img = self.data_list[item]
        label = self.label_list[item]

        img = cv2.imread(img)
        label = cv2.imread(label)

        img, label = self.img_transforms(img, label)

        return img,label
  • 在NYUv2_Dataset类中,使用到了read_image_path()函数,输入为数据集的路径,输出为数据和标签的地址列表。
# 定义需要读取的数据路径的函数
def read_image_path(root=r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt"):
# 原始图像路径输出为data,标签图像路径输出为label
    image = np.loadtxt(root, dtype=str)
    n =len(image)
    data, label = [None]*n, [None]*n
    for i,fname in enumerate(image):
        data[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\JPEGImages\%s.jpg" % (fname)
        label[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\Segmentation_40\%s.png" % (fname)
    return data, label
  • 在NYUv2_Dataset类中,还使用到了img_transforms()函数,用来将原始图像和类别标签转变为Tensor格式,并将标签转化为每个像素值为一类数据。
def image2label(image, colormap):
    # 将标签转化为每个像素值为一类数据
    cm2lbl = np.zeros(256**3)
    for i,cm in enumerate(colormap):
        cm2lbl[(cm[0]*256+cm[1]*256+cm[2])] = i
    # 对一张图像转换
    image = np.array(image, dtype="int64")
    ix = (image[:,:,0]*256+image[:,:,1]*256+image[:,:,2])
    image2 = cm2lbl[ix]
    return image2

def img_transforms(data, label):
# 将标记图像数据进行二维标签化的操作
# 输出原始图像和类别标签的张量数据
    data_tfs = transforms.Compose([
        transforms.ToTensor(),
    ])
    data = data_tfs(data)
    label = torch.from_numpy(image2label(label, colormap)) # 把数组转换成张量,且二者共享内存,对张量进行修改比如重新赋值,那么原始数组也会相应发生改变
    return data, label

5. 完整代码

  下面展示了构建NYUv2数据集的全部代码,其中colormap是NYUv2数据集中分割标签的像素值(即类别),该部分代码实现了读取数据、数据处理、创建数据加载器dataloader。

colormap = [[0, 0, 0],
            [1, 1, 1],
            [2, 2, 2],
            [3, 3, 3],
            [4, 4, 4],
            [5, 5, 5],
            [6, 6, 6],
            [7, 7, 7],
            [8, 8, 8],
            [9, 9, 9],
            [10, 10, 10],
            [11, 11, 11],
            [12, 12, 12],
            [13, 13, 13],
            [14, 14, 14],
            [15, 15, 15],
            [16, 16, 16],
            [17, 17, 17],
            [18, 18, 18],
            [19, 19, 19],
            [20, 20, 20],
            [21, 21, 21],
            [22, 22, 22],
            [23, 23, 23],
            [24, 24, 24],
            [25, 25, 25],
            [26, 26, 26],
            [27, 27, 27],
            [28, 28, 28],
            [29, 29, 29],
            [30, 30, 30],
            [31, 31, 31],
            [32, 32, 32],
            [33, 33, 33],
            [34, 34, 34],
            [35, 35, 35],
            [36, 36, 36],
            [37, 37, 37],
            [38, 38, 38],
            [39, 39, 39],
            [40, 40, 40]]


# 定义计算设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def image2label(image, colormap):
    # 将标签转化为每个像素值为一类数据
    cm2lbl = np.zeros(256**3)
    for i,cm in enumerate(colormap):
        cm2lbl[(cm[0]*256+cm[1]*256+cm[2])] = i
    # 对一张图像转换
    image = np.array(image, dtype="int64")
    ix = (image[:,:,0]*256+image[:,:,1]*256+image[:,:,2])
    image2 = cm2lbl[ix]
    return image2

# 定义需要读取的数据路径的函数
def read_image_path(root=r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt"):
# 原始图像路径输出为data,标签图像路径输出为label
    image = np.loadtxt(root, dtype=str)
    n =len(image)
    data, label = [None]*n, [None]*n
    for i,fname in enumerate(image):
        data[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\JPEGImages\%s.jpg" % (fname)
        label[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\Segmentation_40\%s.png" % (fname)
    return data, label

# 单组图像的转换操作
def img_transforms(data, label):
# 将输入图像进行亮度、对比度、饱和度、色相的改变;将标记图像数据进行二维标签化的操作
# 输出原始图像和类别标签的张量数据
    data_tfs = transforms.Compose([
        transforms.ToTensor(),
    ])
    data = data_tfs(data)
    label = torch.from_numpy(image2label(label, colormap)) # 把数组转换成张量,且二者共享内存,对张量进行修改比如重新赋值,那么原始数组也会相应发生改变
    return data, label

class NYUv2_Dataset(Dataset):
    def __init__(self, data_root, img_transforms):
        self.data_root = data_root
        self.img_transforms = img_transforms
        data_list, label_list = read_image_path(root=self.data_root)
        self.data_list = data_list
        self.label_list = label_list

    def __len__(self):
        return len(self.data_list)

    def __getitem__(self, item):
        img = self.data_list[item]
        label = self.label_list[item]

        img = cv2.imread(img)
        label = cv2.imread(label)

        img, label = self.img_transforms(img, label)

        return img,label

nyuv2_train = NYUv2_Dataset(r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt", img_transforms)

nyuv2_val = NYUv2_Dataset(r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\val.txt", img_transforms)


# 创建数据加载器每个batch使用4张图像
train_loader = Data.DataLoader(nyuv2_train, batch_size=2, shuffle=True, num_workers=0, pin_memory=True)
val_loader = Data.DataLoader(nyuv2_val, batch_size=2, shuffle=True, num_workers=0, pin_memory=True)

6. 可视化

  通过可视化一个batch的数据,检查数据预处理是否正确

# 检查训练数据集的一个batch的样本的维度是否正确
for step,(b_x,b_y) in enumerate(train_loader):
    if step > 0:
        break
# 输出训练图像的尺寸和标签的尺寸,以及接受类型
# print("Train数据:",b_x)
# print("Train标签:",b_y)
#
# print("b_x.shape:",b_x.shape)
# print("b_y.shape:",b_y.shape)

# 可视化一个batch的图像,检查数据预处理是否正确
b_x_numpy = b_x.data.numpy()
b_x_numpy = b_x_numpy.transpose(0,2,3,1)
plt.imshow(b_x_numpy[1])
plt.show()

b_y_numpy = b_y.data.numpy()
plt.imshow(b_y_numpy[1])
plt.show()

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

二、模型搭建

  本文以预训练好的VGG19模型作为Backbone,然后自己搭建上采样部分网络,从而完成整个语义分割网络的模型搭建。

high, width = 320, 480

# 使用预训练好的VGG19网络作为backbone
model_vgg19 = vgg19(pretrained=True)
# 不使用VGG19网络后面的AdaptiveAvgPool2d和Linear层
base_model = model_vgg19.features
base_model = base_model.cuda()
# summary(base_model,input_size=(3, high, width))

# 定义FCN语义分割网络
class FCN8s(nn.Module):
    def __init__(self, num_classes):
        super().__init__()
        self.num_classes = num_classes
        model_vgg19 = vgg19(pretrained=True)
        # 不使用VGG19网络后面的AdaptiveAvgPool2d和Linear层
        self.base_model = model_vgg19.features
        # 定义几个需要的层操作,并且使用转置卷积将特征映射进行升维
        self.relu = nn.ReLU(inplace=True)
        self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
        self.bn1 = nn.BatchNorm2d(512)
        self.deconv2 = nn.ConvTranspose2d(512, 256, 3, 2, 1, 1, 1)
        self.bn2 = nn.BatchNorm2d(256)
        self.deconv3 = nn.ConvTranspose2d(256, 128, 3, 2, 1, 1, 1)
        self.bn3 = nn.BatchNorm2d(128)
        self.deconv4 = nn.ConvTranspose2d(128, 64, 3, 2, 1, 1, 1)
        self.bn4 = nn.BatchNorm2d(64)
        self.deconv5 = nn.ConvTranspose2d(64, 32, 3, 2, 1, 1, 1)
        self.bn5 = nn.BatchNorm2d(32)
        self.classifier = nn.Conv2d(32, num_classes, kernel_size=1)
        ## VGG19中MaxPool2d所在的层
        self.layers = {"4":"maxpool_1","9":"maxpool_2",
                       "18": "maxpool_3", "27": "maxpool_4",
                       "36": "maxpool_5"}
    def forward(self, x):
        output ={}
        for name, layer in self.base_model._modules.items():
            ## 从第一层开始获取图像的特征
            x = layer(x)
            ## 如果是layers参数指定的特征,那就保存到output中
            if name in self.layers:
                output[self.layers[name]] = x
        x5 = output["maxpool_5"]  ## size = (N, 512, x.H/32, x.W/32)
        x4 = output["maxpool_4"]  ## size = (N, 512, x.H/16, x.W/16)
        x3 = output["maxpool_3"]  ## size = (N, 512, x.H/8, x.W/8)
        ## 对特征进行相关的转置卷积操作,逐渐将图像放大到原始图像大小
        ## size = (N, 512, x.H/16, x.W/16)
        score = self.relu(self.deconv1(x5))
        ## 对应元素相加,size = (N, 512, x.H/16, x.W/16)
        score = self.bn1(score + x4)
        ## size = (N, 256, x.H/8, x.W/8)
        score = self.relu(self.deconv2(score))
        ## 对应元素相加,size = (N, 256, x.H/8, x.W/8)
        score = self.bn2(score + x3)
        ## size = (N, 128, x.H/4, x.W/4)
        score = self.bn3(self.relu(self.deconv3(score)))
        ## size = (N, 64, x.H/2, x.W/2)
        score = self.bn4(self.relu(self.deconv4(score)))
        ## size = (N, 32, x.H, x.W)
        score = self.bn5(self.relu(self.deconv5(score)))
        score = self.classifier(score)
        return score      ## size = (N, n_class, x.H/1, x.W/1)


fcn8s = FCN8s(41).to(device)
summary(fcn8s, input_size=(3, high, width))

  模型结构如下表所示:

Layer (type)Output ShapeParam
Conv2d-1[-1, 64, 320, 480]1,792
ReLU-2[-1, 64, 320, 480]0
Conv2d-3[-1, 64, 320, 480]36,928
ReLU-4[-1, 64, 320, 480]0
MaxPool2d-5[-1, 64, 160, 240]0
Conv2d-6[-1, 128, 160, 240]73,856
ReLU-7[-1, 128, 160, 240]0
Conv2d-8[-1, 128, 160, 240]147,584
ReLU-9[-1, 128, 160, 240]0
MaxPool2d-10[-1, 128, 80, 120]0
Conv2d-11[-1, 256, 80, 120]295,168
ReLU-12[-1, 256, 80, 120]0
Conv2d-13[-1, 256, 80, 120]590,080
ReLU-14[-1, 256, 80, 120]0
Conv2d-15[-1, 256, 80, 120]590,080
ReLU-16[-1, 256, 80, 120]0
Conv2d-17[-1, 256, 80, 120]590,080
ReLU-18[-1, 256, 80, 120]0
MaxPool2d-19[-1, 256, 40, 60]0
Conv2d-20[-1, 512, 40, 60]1,180,160
ReLU-21[-1, 512, 40, 60]0
Conv2d-22[-1, 512, 40, 60]2,359,808
ReLU-23[-1, 512, 40, 60]0
Conv2d-24[-1, 512, 40, 60]2,359,808
ReLU-25[-1, 512, 40, 60]0
Conv2d-26[-1, 512, 40, 60]2,359,808
ReLU-27[-1, 512, 40, 60]0
MaxPool2d-28[-1, 512, 20, 30]0
Conv2d-29[-1, 512, 20, 30]2,359,808
ReLU-30[-1, 512, 20, 30]0
Conv2d-31[-1, 512, 20, 30]2,359,808
ReLU-32[-1, 512, 20, 30]0
Conv2d-33[-1, 512, 20, 30]2,359,808
ReLU-34[-1, 512, 20, 30]0
Conv2d-35[-1, 512, 20, 30]2,359,808
ReLU-36[-1, 512, 20, 30]0
MaxPool2d-37[-1, 512, 10, 15]0
ConvTranspose2d-38[-1, 512, 20, 30]2,359,808
ReLU-39[-1, 512, 20, 30]0
BatchNorm2d-40[-1, 512, 20, 30]1,024
ConvTranspose2d-41[-1, 256, 40, 60]]1,179,904
ReLU-42[-1, 256, 40, 60]0
BatchNorm2d-43[-1, 256, 40, 60]512
ConvTranspose2d-44[-1, 128, 80, 120]295,040
ReLU-45[-1, 128, 80, 120]0
BatchNorm2d-46[-1, 128, 80, 120]256
ConvTranspose2d-47[-1, 64, 160, 240]73,792
ReLU-48[-1, 64, 160, 240]0
BatchNorm2d-49[-1, 64, 160, 240]128
ConvTranspose2d-50[-1, 32, 320, 480]18,464
ReLU-51[-1, 32, 320, 480]0
BatchNorm2d-52[-1, 32, 320, 480]64
Conv2d-53[-1, 41, 320, 480]1,353

三、定义损失函数和优化器

# 定义损失函数和优化器
LR = 0.0003
criterion = nn.NLLLoss()
optimizer = optim.Adam(fcn8s.parameters(), lr=LR,weight_decay=1e-4)

四、迭代训练

# 对模型进行迭代训练,对所有的数据训练epoch轮
fcn8s,train_process = train_model(
    fcn8s,criterion,optimizer,train_loader,
    val_loader, num_epochs=200)
## 保存训练好的模型fcn8s
torch.save(fcn8s,"fcnNYUv2.pt")
def train_model(model, criterion, optimizer, traindataloader, valdataloader, num_epochs = 25):
    """
    :param model: 网络模型
    :param criterion: 损失函数
    :param optimizer: 优化函数
    :param traindataloader: 训练的数据集
    :param valdataloader: 验证的数据集
    :param num_epochs: 训练的轮数
    """
    since = time.time()
    best_model_wts = copy.deepcopy(model.state_dict())
    best_loss = 1e10
    train_loss_all = []
    train_acc_all = []
    val_loss_all = []
    val_acc_all = []
    since = time.time()

    for epoch in range(num_epochs):
        print('Epoch {}/{}'.format(epoch, num_epochs-1))
        print('-' * 10)
        train_loss = 0.0
        train_num = 0
        val_loss = 0.0
        val_num = 0
        ## 每个epoch包括训练和验证阶段
        model.train()  ## 设置模型为训练模式
        for step,(b_x,b_y) in enumerate(traindataloader):
            optimizer.zero_grad()
            b_x = b_x.float().to(device)
            b_y = b_y.long().to(device)
            out = model(b_x)
            out = F.log_softmax(out, dim=1)
            pre_lab = torch.argmax(out,1) ## 预测的标签
            loss = criterion(out, b_y) ## 计算损失函数值
            loss.backward()
            optimizer.step()
            train_loss += loss.item() * len(b_y)
            train_num += len(b_y)
        ## 计算一个epoch在训练集上的损失和精度
        train_loss_all.append(train_loss / train_num)
        print('{} Train loss: {:.4f}'.format(epoch, train_loss_all[-1]))

        ## 计算一个epoch训练后在验证集上的损失
        model.eval() ## 设置模型为验证模式
        for step,(b_x,b_y) in enumerate(valdataloader):
            b_x = b_x.float().to(device)
            b_y = b_y.long().to(device)
            out = model(b_x)
            out = F.log_softmax(out, dim=1)
            pre_lab = torch.argmax(out,1) ## 预测的标签
            loss = criterion(out, b_y) ## 计算损失函数值
            val_loss += loss.item() * len(b_y)
            val_num += len(b_y)

        ## 计算一个epoch在验证集上的损失和精度
        val_loss_all.append(val_loss / val_num)
        print('{} Val loss: {:.4f}'.format(epoch, val_loss_all[-1]))

        ## 保存最好的网络参数
        if val_loss_all[-1] < best_loss:
            best_loss = val_loss_all[-1]
            best_model_wts = copy.deepcopy(model.state_dict())

        ## 每个epoch花费的时间
        time_use = time.time() - since
        print("Train and val complete in {:.0f}m {:.0f}s".format(time_use // 60, time_use %60))
    train_process = pd.DataFrame(
        data = {"epoch":range(num_epochs),
                "train_loss_all":train_loss_all,
                "val_loss_all":val_loss_all})
    ## 输出最好的模型
    model.load_state_dict(best_model_wts)
    return model,train_process

参考文章

Pytorch构建数据集——torch.utils.data.Dataset()和torch.utils.dataDataLoader()

Pytorch笔记05-自定义数据读取方式orch.utils.data.Dataset与Dataloader

nyuv240类数据集_【深度学习】在PyTorch中构建高效的自定义数据集 文章来源于磐创AI,作者磐创AI学习Dataset类的来龙去脉,使用干净的代码结构,同时最大限度地减少在训练期间管理大量数据的麻烦。神经网络训练在数据管理上可能很难做到“大规模”。PyTorch 最近已经出现在我的圈子里,尽管对Keras和TensorFlow感到满意,但我还是不得不尝试一下。令人惊讶的是,我发现它非常令人耳目一新,非常讨人喜欢,尤其是PyTorch 提供了一个Pytho... 阅读详情

相关推荐

ScanNet数据集实战指南:从数据获取到模型训练

本文提供了ScanNet数据集从申请下载到模型训练的完整实战指南。详细介绍了这一重要3D室内场景数据集的获取流程、核心文件解析方法,并指导读者构建PyTorch数据加载器,搭建基础的3D语义分割模型(如PointNet++)进行训练与验证,是开展3D视觉研究的实用入门教程。

weixin_29056145的博客 293

【数据集】——NYU Depth Dataset V2简介

简介: NYU-Depth V2数据集由微软Kinect的RGB和Depth摄像机记录的各种室内场景的视频序列组成。它的特点: 1449张标注的RGB图片和深度图 来自3个城市,464个场景 407024张没有标注的图片 每个对象都有一个类和一个实例号(cup1、cup2、cup3等),像实例分割 数据集有几个部分: 标签:视频数据的一个子集,带有密集的多类标签。这些数据也经过预处理,以填补缺失的深度标签。 Raw: Kinect提供的原始rgb、深度和加速度计数据。 工具箱:用于操作数据和标签的有用函

怡宝2号 1万+

NYUV2数据集的预处理及类别名txt

NYUV2数据集的预处理,包括提取原RGB图, 深度图,labels以及类别名的txt文件(已生成,可直接用)

NYUv2数据集的使用

另外,从Kinect设备得来的深度非线性已经被移除,每个深度图像的值都以米为单位。虽然帧不同步,但每个RGB,深度和加速度计文件的时间戳都包含在每个文件名中,并且可以使用Toolbox中的。- 绘制深度图的HxWxN矩阵,其中H和W分别为高度和宽度,N为图像数目,深度元素的值单位为米。- RGB图像的HxWx3xN矩阵,其中H和W分别是高度和宽度,N是图像的数量。- 用于标记数据集中的每个深度图像的文件名(在Raw数据集中)的Nx1单元数组。以前缀r和d开头的文件分别是来自RGB和深度相机的帧。

qq_43772102的博客 4872

pytorch-nyuv2:PyTorch NYUv2数据集类

PyTorch NYUv2数据集类 针对NYUv2数据集的PyTorch包装器专注于多任务学习。 可用的数据源:RGB,语义分割(13),表面法线,深度图像。 从以下位置下载数据: 例子 from nyuv2 import NYUv2 from torchvision import transforms t = transforms.Compose([transforms.RandomCrop(400), transforms.ToTensor()]) NYUv2(root="/somepath/NYUv2", download=True, rgb_transform=t, seg_transform=t, sn_transform=t, depth_transform=t) Dataset NYUv2 Number of datapoints: 795 S

NYU V2数据集提取数据-附件资源

NYU V2数据集提取数据-附件资源

LibMTL在6大基准数据集上的表现:NYUv2、Cityscapes等场景理解应用

LibMTL是一个基于PyTorch的多任务学习库,它为开发者提供了简单易用且可扩展的训练框架,帮助用户高效实现多任务学习模型。该库支持多种先进的多任务学习架构和权重优化策略,能够在各类场景理解任务中取得优异性能。 ## LibMTL框架概览 LibMTL采用模块化设计,主要包含数据加载、模型架构、权重优化、损失函数和评估指标等核心组件。其灵活的配置系统允许用户轻松调整训练参数,快速适配不同的

gitblog_00081的博客 438

nyuv2数据集,包含rawdepth、RGB图,这是去除了黑边重新调整尺寸后的数据

nyuv2数据集,包含rawdepth、RGB图,这是去除了黑边重新调整尺寸后的数据

终极MTAN实战教程:在NYUv2数据集上实现语义分割、深度估计、法线预测三合一

想要一次性完成室内场景的语义分割、深度估计和法线预测吗?MTAN(Multi-Task Attention Network)多任务注意力网络正是你需要的终极解决方案!🎯 这篇完整指南将带你从零开始,在NYUv2数据集上实现这三个计算机视觉任务的三合一训练。 ## 🎯 什么是MTAN多任务注意力网络? MTAN是一种创新的端到端多任务学习框架,通过注意力机制动态地为不同任务分配计算资源。与传

gitblog_00152的博客 349

[Adaptive Autosar]深入理解--Time Synchronization

目录 1.TS典型应用场景 2.CP和AP时间同步对比 3.时间同步基础知识 4.TBR部分参数说明 5. TS功能说明 5.1 基本说明 5.2 时间纠正计算说明 5.3 时间验证 Time Synchronization 时间同步,后面简称TS 1.TS典型应用场景 时间同步,典型应用就是在自动驾驶领域,自动驾驶领域涉及到各个传感器的数据采集,如IMU采集当前车身姿态和运动信息,毫米波雷达-超声波雷达-环视摄像头-前视摄像头...等等传感器捕获的数据,在算法中需要精确知道每个数.

AgingMoon的博客 3997

思科网络进阶——多生成树协议(MSTP)配置的一课一得

三、实验拓扑1)设计一个网络架构,要有核心层和接入层,都使用思科交换机。2)企业有4个部门,要求这四个部门都可以上网,但分属不同的VLAN中,这样今后可以做其它安全策略以确保网络安全,这些策略如今后学到的访问控制列表ACL。3)网络架构的设计要具有冗余,防止一条线路或一台设备终端导致的业务中断。4)由于硬件冗余而产生的环路要处理好,也就是要在逻辑上(或者说通过配置)防止物理环路的产生。5)不能因为防止物理环路而导致某端口没有流量,这样浪费端口资源及设备间互联的带宽资源。

zhu52010的博客 3398

MonoScene训练教程:从环境搭建到模型调参的实战技巧

想要掌握**MonoScene单目3D语义场景补全**技术吗?本教程将为你提供从零开始的完整训练指南,涵盖环境配置、数据集准备、模型训练和调参优化的全流程。MonoScene作为CVPR 2022的突破性成果,能够从单张图像预测3D语义占据网格,为自动驾驶、机器人导航等应用提供强大的场景理解能力。 ## 🚀 环境搭建与安装步骤 ### 创建Python虚拟环境 首先需要搭建合适的开发环境,推

gitblog_00805的博客 1062

CA51F3系列(国产)+低功耗模式

CA51F351P6芯片是基于1T 8051内核的8位微控制器,通常情况下,运行速度比传统的8051芯片快10倍,性能更加优越。内置8K Flash程序存储器,可多次重复编程的特性给用户开发带来了极大的方便。不仅保留了传统8051芯片的基本特性,还集成了12Bit ADC、LCD/LED驱动、Touch Key、16Bit PWM、 UART、RTC、低电压检测(LVD)等功能模块。支持IDLE、STOP和低速运行三种省电模式以适应不同功耗要求的应用。

WANGJIHUIwang的博客 572

BP-Net:用于深度完成的双边传播网络

BP-Net:用于深度完成的双边传播网络 项目介绍 BP-Net 是一篇论文的 PyTorch 实现,该论文题为《双边传播网络用于深度完成》(Bilateral Propagation Network for Depth Completion),旨在通过深度学习技术解决深度完成的任务。项目提供了一套完整的训练和测试流程,支持在 KITTI 和 NYUV2 数据集上进行训练和评估。 项目技术分析 B...

gitblog_00502的博客 1070

Python+Selenium实现抖音博主批量监控:300+账号实时更新通知(附完整代码)

本文详细介绍了如何使用Python和Selenium构建一个高可用的抖音博主批量监控系统。通过架构设计、Cookie管理、高效轮询与差异检测等核心模块,实现300+账号的实时更新追踪与通知。文章提供了完整的代码实现,并重点探讨了性能优化、异常处理及服务器部署等实战经验,帮助开发者打造稳定、可控的自动化监控解决方案。

weixin_29274969的博客 194

论文分享|ECCV2022,PATnet,Cross-Domain Few-Shot Semantic Segmentation,CDFSS新基准,文末有复现教程

这篇论文提出的跨域小样本语义分割(CD-FSS)任务,旨在将源域学习的分割能力迁移到目标域,仅需少量标注样本。针对传统小样本分割方法在跨域场景性能下降的问题,作者提出了基于金字塔锚点变换的网络(PATNet),通过将域相关特征转换为域无关特征,并引入任务自适应微调推理(TFI)提升目标域适应能力。实验表明,PATNet在1-shot和5-shot设置下分别比现有方法提升8.49%和10.61%的准确率。同时,作者构建了CD-FSS基准并设计了任务难度评估指标。代码和数据集已开源,复现难度中等。

m0_74277350的博客 1095

如何快速上手Light-Weight RefineNet:5分钟实现实时语义分割

想要在计算机视觉项目中实现高效的实时语义分割吗?Light-Weight RefineNet正是你需要的终极解决方案!这款基于PyTorch的轻量级语义分割框架,专门为实时应用场景设计,能够在保持高精度的同时大幅降低计算复杂度。本文将为你提供一个完整的快速入门指南,让你在5分钟内掌握这个强大的实时语义分割工具。🚀 ## 📋 什么是Light-Weight RefineNet? Light-

gitblog_00173的博客 604

STM32堆栈溢出问题及解决方法

堆栈是用于存储函数调用和局部变量的内存区域,它是一种先进后出的数据结构。如果函数嵌套层级过深或者局部变量占用的内存空间过大,堆栈的大小可能不足以容纳这些信息,从而导致堆栈溢出。在一些特殊情况下,可以使用堆内存替代堆栈,以避免堆栈溢出问题。在STM32的工程中,可以通过修改链接脚本文件(.ld文件)中的堆栈大小参数来增加堆栈空间。通常,堆栈大小设置为RAM的一小部分,但需要根据具体应用的需求进行调整。堆栈溢出是嵌入式系统开发中常见的问题之一,特别是在使用STM32微控制器时。3.3 使用堆内存替代堆栈。

ZwcCsharp的博客 2594

革命性视觉AI工具DPT:基于Transformer的单目深度估计与语义分割完全指南

DPT(Dense Prediction Transformers)是一款革命性的视觉AI工具,它将Transformer架构应用于密集预测任务,实现了高精度的单目深度估计与语义分割。本文将为你提供一份全面指南,帮助你快速上手这一强大工具,无需深厚的AI背景也能轻松实现复杂的视觉分析任务。 ## 🚀 DPT工具简介:Transformer架构的视觉突破 DPT(Dense Predictio

gitblog_00084的博客 520

docker-compose Install OrangeHRM

OrangeHRM是一个全面的人力资源管理HRM) 系统,它包含任何企业所需的所有基本功能。OrangeHRM旨在支持任何规模的团队,包括初创企业、中小企业以及大型跨国组织。

极致,细节 1004

Python爬虫终极实战:逆向解析+异步处理,高效爬取中关村在线万级产品数据

爬虫工程师的战场,已经从简单的HTML解析,转向了对网络协议、JavaScript执行逻辑的深度逆向工程。然后刷新页面,当浏览器发起这个请求时,执行会暂停,我们可以一步步跟蹤调用栈(Call Stack),找到发起请求前的JavaScript代码,从而发现参数的计算逻辑。它们会添加一个动态的、一次性的签名(token)或加密参数,用于验证请求的合法性。这是整个爬虫最核心、最具技术含量的部分。的请求,其响应体正是结构清晰的JSON数据,包含了当前页面的所有手机信息(产品ID、名称、价格、图片等)。

2201_76125261的博客 429

MTAN论文复现指南:从理论到代码的完整实现过程详解

想要深入理解多任务学习的前沿技术吗?这篇终极指南将带你从零开始,完整复现CVPR 2019的经典论文《End-to-End Multi-Task Learning with Attention》(MTAN)。多任务注意力网络(MTAN)通过**注意力机制**实现了任务间的有效知识共享,在计算机视觉领域取得了突破性进展。本文将详细介绍如何从理论到实践,一步步搭建和训练MTAN模型,让你轻松掌握这个强

gitblog_00700的博客 961

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

10个Light-Weight RefineNet使用技巧:从安装到高级应用

Light-Weight RefineNet是一个专为实时语义分割设计的轻量级深度学习框架,它在保持高精度的同时显著提升了处理速度,非常适合资源受限的应用场景。本文将分享10个实用技巧,帮助你从安装到高级应用全面掌握这个强大工具。 ## 1. 快速安装准备工作 🚀 在开始使用Light-Weight RefineNet之前,确保你的系统满足以下要求: - Ubuntu操作系统(推荐) - P

gitblog_00124的博客 470

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

LibMTL多任务学习库快速入门指南

LibMTL是一个专门为多任务学习(MTL)设计的高效开源库,它提供了多种任务加权策略和网络架构,帮助研究人员和开发者快速构建和评估多任务学习模型。本文将带您快速了解如何使用LibMTL进行多任务学习模型的训练和评估。 ## 准备工作:NYUv2数据集 在开始之前,我们需要准备一个多任务学习基准数据集。NYUv2是一个常用的室内场景理解数据集,包含三个关联任务: 1. 13类语义分割 2.

gitblog_00415的博客 605

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

为什么选择Light-Weight RefineNet:与其他语义分割模型的终极对比分析指南

在实时语义分割领域,选择合适的模型往往需要在精度和速度之间做出权衡。今天,我们将深入探讨**Light-Weight RefineNet**——这款专为实时语义分割设计的轻量级模型,并与其他主流语义分割模型进行全面对比分析。无论您是计算机视觉新手还是经验丰富的开发者,这篇文章都将为您提供完整的决策参考。 ## 🔍 什么是Light-Weight RefineNet? **Light-Weig

gitblog_00575的博客 390

多任务学习不再难:LibMTL如何用一行代码解决你的AI模型冲突?

还在为多个AI任务之间的冲突而烦恼吗?当你的模型需要同时处理语义分割、深度估计和表面法线预测时,不同任务之间总会互相干扰,导致性能下降。传统方法要么需要复杂的调参,要么干脆放弃多任务学习,回归到单任务模型的繁琐部署。 但今天,我要向你介绍一个革命性的工具——LibMTL,它能让你用**一行代码**就实现高效的多任务学习!这个基于PyTorch的开源库,已经帮助无数研究者和开发者解决了多任务学习的

gitblog_01154的博客 415
上一篇: YOLOV5中添加CBAM模块详解——原理+代码
下一篇: YOLOv5中添加SE模块详解——原理+代码
晓shuo
晓shuo 优质创作者: 人工智能技术领域 优质创作者: 人工智能技术领域
博客等级 码龄6年 4万+粉丝 113原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

晓shuo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值