复现PointNet++(语义分割网络):Windows + PyTorch + S3DIS语义分割 + 代码

一、平台

Windows 10

GPU RTX 3090 + CUDA 11.1 + cudnn 8.9.6

Python 3.9

Torch 1.9.1 + cu111

所用的原始代码:https://github.com/yanx27/Pointnet_Pointnet2_pytorch

二、数据

Stanford3dDataset_v1.2_Aligned_Version

三、代码

分享给有需要的人,代码质量勿喷。

对源代码进行了简化和注释。

分割结果保存成txt,或者利用 laspy 生成点云。

别问为啥在C盘,问就是2T的三星980Pro

3.1 文件组织结构

3.2 数据预处理

3.2.1 run_collect_indoor3d_data.py 生成*.npy文件

改了路径

3.2.2 indoor3d_util.py

改了路径

3.2.3 S3DISDataLoader.py

改了路径

3.3 训练 train_SematicSegmentation.py

# 参考
# https://github.com/yanx27/Pointnet_Pointnet2_pytorch
# 先在Terminal运行:python -m visdom.server
# 再运行本文件import argparse
import os
# import datetime
import logging
import importlib
import shutil
from tqdm import tqdm
import numpy as np
import time
import visdom
import torch
import warnings
warnings.filterwarnings('ignore')from dataset.S3DISDataLoader import S3DISDataset
from PointNet2 import dataProcess# PointNet
from PointNet2.pointnet_sem_seg import get_model as PNss
from PointNet2.pointnet_sem_seg import get_loss as PNloss# PointNet++
from PointNet2.pointnet2_sem_seg import get_model as PN2SS
from PointNet2.pointnet2_sem_seg import get_loss as PN2loss# True为PointNet++
PN2bool = True
# PN2bool = False# 当前文件的路径
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))# 训练输出模型的路径: PointNet
dirModel1 = ROOT_DIR + '/trainModel/pointnet_model'
if not os.path.exists(dirModel1):os.makedirs(dirModel1)
# 训练输出模型的路径
dirModel2 = ROOT_DIR + '/trainModel/PointNet2_model'
if not os.path.exists(dirModel2):os.makedirs(dirModel2)# 日志的路径
pathLog = os.path.join(ROOT_DIR, 'LOG_train.txt')# 数据集的路径
pathDataset = os.path.join(ROOT_DIR, 'dataset/stanford_indoor3d/')# 分类的类别
classNumber = 13
classes = ['ceiling', 'floor', 'wall', 'beam', 'column', 'window', 'door', 'table', 'chair', 'sofa', 'bookcase','board', 'clutter']
class2label = {cls: i for i, cls in enumerate(classes)}
seg_classes = class2label
seg_label_to_cat = {}
for i, cat in enumerate(seg_classes.keys()):seg_label_to_cat[i] = cat# 日志和输出
def log_string(str):logger.info(str)print(str)def inplace_relu(m):classname = m.__class__.__name__if classname.find('ReLU') != -1:m.inplace=Truedef parse_args():parser = argparse.ArgumentParser('Model')parser.add_argument('--pnModel', type=bool, default=True, help='True = PointNet++;False = PointNet')parser.add_argument('--batch_size', type=int, default=32, help='Batch Size during training [default: 32]')parser.add_argument('--epoch', default=320, type=int, help='Epoch to run [default: 32]')parser.add_argument('--learning_rate', default=0.001, type=float, help='Initial learning rate [default: 0.001]')parser.add_argument('--GPU', type=str, default='0', help='GPU to use [default: GPU 0]')parser.add_argument('--optimizer', type=str, default='Adam', help='Adam or SGD [default: Adam]')parser.add_argument('--decay_rate', type=float, default=1e-4, help='weight decay [default: 1e-4]')parser.add_argument('--npoint', type=int, default=4096, help='Point Number [default: 4096]')parser.add_argument('--step_size', type=int, default=10, help='Decay step for lr decay [default: every 10 epochs]')parser.add_argument('--lr_decay', type=float, default=0.7, help='Decay rate for lr decay [default: 0.7]')parser.add_argument('--test_area', type=int, default=5, help='Which area to use for test, option: 1-6 [default: 5]')return parser.parse_args()if __name__ == '__main__':# python -m visdom.servervisdomTL = visdom.Visdom()visdomTLwindow = visdomTL.line([0], [0], opts=dict(title='train_loss'))visdomVL = visdom.Visdom()visdomVLwindow = visdomVL.line([0], [0], opts=dict(title='validate_loss'))visdomTVL = visdom.Visdom(env='PointNet++')# region 创建日志文件logger = logging.getLogger("train")logger.setLevel(logging.INFO)formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')file_handler = logging.FileHandler(pathLog)file_handler.setLevel(logging.INFO)file_handler.setFormatter(formatter)logger.addHandler(file_handler)#endregion#region 超参数args = parse_args()args.pnModel = PN2boollog_string('------------ hyper-parameter ------------')log_string(args)# 指定GPUos.environ["CUDA_VISIBLE_DEVICES"] = args.GPUpointNumber = args.npointbatchSize = args.batch_size#endregion# region dataset# train datatrainData = S3DISDataset(split='train',data_root=pathDataset, num_point=pointNumber,test_area=args.test_area, block_size=1.0, sample_rate=1.0, transform=None)trainDataLoader = torch.utils.data.DataLoader(trainData, batch_size=batchSize, shuffle=True, num_workers=0,pin_memory=True, drop_last=True,worker_init_fn=lambda x: np.random.seed(x + int(time.time())))# Validation datatestData = S3DISDataset(split='test',data_root=pathDataset, num_point=pointNumber,test_area=args.test_area, block_size=1.0, sample_rate=1.0, transform=None)testDataLoader = torch.utils.data.DataLoader(testData, batch_size=batchSize, shuffle=False, num_workers=0,pin_memory=True, drop_last=True)log_string("The number of training data is: %d" % len(trainData))log_string("The number of validation data is: %d" % len(testData))weights = torch.Tensor(trainData.labelweights).cuda()#endregion# region loading model:使用预训练模型或新训练modelSS = ''criterion = ''if PN2bool:modelSS = PN2SS(classNumber).cuda()criterion = PN2loss().cuda()modelSS.apply(inplace_relu)else:modelSS = PNss(classNumber).cuda()criterion = PNloss().cuda()modelSS.apply(inplace_relu)# 权重初始化def weights_init(m):classname = m.__class__.__name__if classname.find('Conv2d') != -1:torch.nn.init.xavier_normal_(m.weight.data)torch.nn.init.constant_(m.bias.data, 0.0)elif classname.find('Linear') != -1:torch.nn.init.xavier_normal_(m.weight.data)torch.nn.init.constant_(m.bias.data, 0.0)try:path_premodel = ''if PN2bool:path_premodel = os.path.join(dirModel2, 'best_model_S3DIS.pth')else:path_premodel = os.path.join(dirModel1, 'best_model_S3DIS.pth')checkpoint = torch.load(path_premodel)start_epoch = checkpoint['epoch']# print('pretrain epoch = '+str(start_epoch))modelSS.load_state_dict(checkpoint['model_state_dict'])log_string('!!!!!!!!!! Use pretrain model')except:log_string('...... starting new training ......')start_epoch = 0modelSS = modelSS.apply(weights_init)#endregion# start_epoch = 0# modelSS = modelSS.apply(weights_init)#region 训练的参数和选项if args.optimizer == 'Adam':optimizer = torch.optim.Adam(modelSS.parameters(),lr=args.learning_rate,betas=(0.9, 0.999),eps=1e-08,weight_decay=args.decay_rate)else:optimizer = torch.optim.SGD(modelSS.parameters(), lr=args.learning_rate, momentum=0.9)def bn_momentum_adjust(m, momentum):if isinstance(m, torch.nn.BatchNorm2d) or isinstance(m, torch.nn.BatchNorm1d):m.momentum = momentumLEARNING_RATE_CLIP = 1e-5MOMENTUM_ORIGINAL = 0.1MOMENTUM_DECCAY = 0.5MOMENTUM_DECCAY_STEP = args.step_sizeglobal_epoch = 0best_iou = 0#endregionfor epoch in range(start_epoch, args.epoch):# region Train on chopped sceneslog_string('****** Epoch %d (%d/%s) ******' % (global_epoch + 1, epoch + 1, args.epoch))lr = max(args.learning_rate * (args.lr_decay ** (epoch // args.step_size)), LEARNING_RATE_CLIP)log_string('Learning rate:%f' % lr)for param_group in optimizer.param_groups:param_group['lr'] = lrmomentum = MOMENTUM_ORIGINAL * (MOMENTUM_DECCAY ** (epoch // MOMENTUM_DECCAY_STEP))if momentum < 0.01:momentum = 0.01log_string('BN momentum updated to: %f' % momentum)modelSS = modelSS.apply(lambda x: bn_momentum_adjust(x, momentum))modelSS = modelSS.train()#endregion# region 训练num_batches = len(trainDataLoader)total_correct = 0total_seen = 0loss_sum = 0for i, (points, target) in tqdm(enumerate(trainDataLoader), total=len(trainDataLoader), smoothing=0.9):# 梯度归零optimizer.zero_grad()# xyzLpoints = points.data.numpy() # ndarray = bs,4096,9(xyz rgb nxnynz)points[:, :, :3] = dataProcess.rotate_point_cloud_z(points[:, :, :3]) ## 数据处理的操作points = torch.Tensor(points) # tensor = bs,4096,9points, target = points.float().cuda(), target.long().cuda()points = points.transpose(2, 1) # tensor = bs,9,4096# 预测结果seg_pred, trans_feat = modelSS(points) # tensor = bs,4096,13  # tensor = bs,512,16seg_pred = seg_pred.contiguous().view(-1, classNumber) # tensor = (bs*4096=)点数量,13# 真实标签batch_label = target.view(-1, 1)[:, 0].cpu().data.numpy() # ndarray = (bs*4096=)点数量target = target.view(-1, 1)[:, 0] # tensor = (bs*4096=)点数量# lossloss = criterion(seg_pred, target, trans_feat, weights)loss.backward()# 优化器来更新模型的参数optimizer.step()pred_choice = seg_pred.cpu().data.max(1)[1].numpy() # ndarray = (bs*4096=)点数量correct = np.sum(pred_choice == batch_label) # 预测正确的点数量total_correct += correcttotal_seen += (batchSize * pointNumber)loss_sum += losslog_string('Training mean loss: %f' % (loss_sum / num_batches))log_string('Training accuracy: %f' % (total_correct / float(total_seen)))# drawtrainLoss = (loss_sum.item()) / num_batchesvisdomTL.line([trainLoss], [epoch+1], win=visdomTLwindow, update='append')#endregion# region 保存模型if epoch % 1 == 0:modelpath=''if PN2bool:modelpath = os.path.join(dirModel2, 'model' + str(epoch + 1) + '_S3DIS.pth')else:modelpath = os.path.join(dirModel1, 'model' + str(epoch + 1) + '_S3DIS.pth')state = {'epoch': epoch,'model_state_dict': modelSS.state_dict(),'optimizer_state_dict': optimizer.state_dict(),}torch.save(state, modelpath)logger.info('Save model...'+modelpath)#endregion# region Evaluate on chopped sceneswith torch.no_grad():num_batches = len(testDataLoader)total_correct = 0total_seen = 0loss_sum = 0labelweights = np.zeros(classNumber)total_seen_class = [0 for _ in range(classNumber)]total_correct_class = [0 for _ in range(classNumber)]total_iou_deno_class = [0 for _ in range(classNumber)]modelSS = modelSS.eval()log_string('****** Epoch Evaluation %d (%d/%s) ******' % (global_epoch + 1, epoch + 1, args.epoch))for i, (points, target) in tqdm(enumerate(testDataLoader), total=len(testDataLoader), smoothing=0.9):points = points.data.numpy() # ndarray = bs,4096,9points = torch.Tensor(points) # tensor = bs,4096,9points, target = points.float().cuda(), target.long().cuda() # tensor = bs,4096,9 # tensor = bs,4096points = points.transpose(2, 1) # tensor = bs,9,4096seg_pred, trans_feat = modelSS(points) # tensor = bs,4096,13 # tensor = bs,512,16pred_val = seg_pred.contiguous().cpu().data.numpy() # ndarray = bs,4096,13seg_pred = seg_pred.contiguous().view(-1, classNumber) # tensor = bs*4096,13batch_label = target.cpu().data.numpy() # ndarray = bs,4096target = target.view(-1, 1)[:, 0] # tensor = bs*4096loss = criterion(seg_pred, target, trans_feat, weights)loss_sum += losspred_val = np.argmax(pred_val, 2) # ndarray = bs,4096correct = np.sum((pred_val == batch_label))total_correct += correcttotal_seen += (batchSize * pointNumber)tmp, _ = np.histogram(batch_label, range(classNumber + 1))labelweights += tmpfor l in range(classNumber):total_seen_class[l] += np.sum((batch_label == l))total_correct_class[l] += np.sum((pred_val == l) & (batch_label == l))total_iou_deno_class[l] += np.sum(((pred_val == l) | (batch_label == l)))labelweights = labelweights.astype(np.float32) / np.sum(labelweights.astype(np.float32))mIoU = np.mean(np.array(total_correct_class) / (np.array(total_iou_deno_class, dtype=np.float64) + 1e-6))log_string('eval mean loss: %f' % (loss_sum / float(num_batches)))log_string('eval point avg class IoU: %f' % (mIoU))log_string('eval point accuracy: %f' % (total_correct / float(total_seen)))log_string('eval point avg class acc: %f' % (np.mean(np.array(total_correct_class) / (np.array(total_seen_class, dtype=np.float64) + 1e-6))))iou_per_class_str = '------- IoU --------\n'for l in range(classNumber):iou_per_class_str += 'class %s weight: %.3f, IoU: %.3f \n' % (seg_label_to_cat[l] + ' ' * (14 - len(seg_label_to_cat[l])), labelweights[l - 1],total_correct_class[l] / float(total_iou_deno_class[l]))log_string(iou_per_class_str)log_string('Eval mean loss: %f' % (loss_sum / num_batches))log_string('Eval accuracy: %f' % (total_correct / float(total_seen)))# drawvalLoss = (loss_sum.item()) / num_batchesvisdomVL.line([valLoss], [epoch+1], win=visdomVLwindow, update='append')# region 根据 mIoU确定最佳模型if mIoU >= best_iou:best_iou = mIoUbestmodelpath = ''if PN2bool:bestmodelpath = os.path.join(dirModel2, 'best_model_S3DIS.pth')else:bestmodelpath = os.path.join(dirModel1, 'best_model_S3DIS.pth')state = {'epoch': epoch,'class_avg_iou': mIoU,'model_state_dict': modelSS.state_dict(),'optimizer_state_dict': optimizer.state_dict(),}torch.save(state, bestmodelpath)logger.info('Save best model......'+bestmodelpath)log_string('Best mIoU: %f' % best_iou)#endregion#endregionglobal_epoch += 1# drawvisdomTVL.line(X=[epoch+1], Y=[trainLoss],name="train loss", win='line', update='append',opts=dict(showlegend=True, markers=False,title='PointNet++ train validate loss',xlabel='epoch', ylabel='loss'))visdomTVL.line(X=[epoch+1], Y=[valLoss], name="train loss", win='line', update='append')log_string('-------------------------------------------------\n\n')

3.4 预测测试 test_SematicSegmentation.py

# 参考
# https://github.com/yanx27/Pointnet_Pointnet2_pytorchimport argparse
import sys
import os
import numpy as np
import logging
from pathlib import Path
import importlib
from tqdm import tqdm
import torch
import warnings
warnings.filterwarnings('ignore')from dataset.S3DISDataLoader import ScannetDatasetWholeScene
from dataset.indoor3d_util import g_label2color# PointNet
from PointNet2.pointnet_sem_seg import get_model as PNss
# PointNet++
from PointNet2.pointnet2_sem_seg import get_model as PN2SSPN2bool = True
# PN2bool = False# region 函数:投票;日志输出;保存结果为las。
# 投票决定结果
def add_vote(vote_label_pool, point_idx, pred_label, weight):B = pred_label.shape[0]N = pred_label.shape[1]for b in range(B):for n in range(N):if weight[b, n] != 0 and not np.isinf(weight[b, n]):vote_label_pool[int(point_idx[b, n]), int(pred_label[b, n])] += 1return vote_label_pool# 日志
def log_string(str):logger.info(str)print(str)# save to LAS
import laspy
def SaveResultLAS(newLasPath, point_np, rgb_np, label1, label2):# datanewx = point_np[:, 0]newy = point_np[:, 1]newz = point_np[:, 2]newred = rgb_np[:, 0]newgreen = rgb_np[:, 1]newblue = rgb_np[:, 2]newclassification = label1newuserdata = label2minx = min(newx)miny = min(newy)minz = min(newz)# create a new headernewheader = laspy.LasHeader(point_format=3, version="1.2")newheader.scales = np.array([0.0001, 0.0001, 0.0001])newheader.offsets = np.array([minx, miny, minz])newheader.add_extra_dim(laspy.ExtraBytesParams(name="Classification", type=np.uint8))newheader.add_extra_dim(laspy.ExtraBytesParams(name="UserData", type=np.uint8))# create a Lasnewlas = laspy.LasData(newheader)newlas.x = newxnewlas.y = newynewlas.z = newznewlas.red = newrednewlas.green = newgreennewlas.blue = newbluenewlas.Classification = newclassificationnewlas.UserData = newuserdata# writenewlas.write(newLasPath)# 超参数
def parse_args():parser = argparse.ArgumentParser('Model')parser.add_argument('--pnModel', type=bool, default=True, help='True = PointNet++;False = PointNet')parser.add_argument('--batch_size', type=int, default=32, help='batch size in testing [default: 32]')parser.add_argument('--GPU', type=str, default='0', help='specify GPU device')parser.add_argument('--num_point', type=int, default=4096, help='point number [default: 4096]')parser.add_argument('--test_area', type=int, default=5, help='area for testing, option: 1-6 [default: 5]')parser.add_argument('--num_votes', type=int, default=1,help='aggregate segmentation scores with voting [default: 1]')return parser.parse_args()#endregion# 当前文件的路径
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))# 模型的路径
pathTrainModel = os.path.join(ROOT_DIR, 'trainModel/pointnet_model')
if PN2bool:pathTrainModel = os.path.join(ROOT_DIR, 'trainModel/PointNet2_model')# 结果路径
visual_dir = ROOT_DIR + '/testResultPN/'
if PN2bool:visual_dir = ROOT_DIR + '/testResultPN2/'
visual_dir = Path(visual_dir)
visual_dir.mkdir(exist_ok=True)# 日志的路径
pathLog = os.path.join(ROOT_DIR, 'LOG_test_eval.txt')# 数据集的路径
pathDataset = os.path.join(ROOT_DIR, 'dataset/stanford_indoor3d/')# 分割类别排序
classNumber = 13
classes = ['ceiling', 'floor', 'wall', 'beam', 'column', 'window', 'door', 'table', 'chair', 'sofa', 'bookcase','board', 'clutter']
class2label = {cls: i for i, cls in enumerate(classes)}
seg_classes = class2label
seg_label_to_cat = {}
for i, cat in enumerate(seg_classes.keys()):seg_label_to_cat[i] = catif __name__ == '__main__':#region LOG infologger = logging.getLogger("test_eval")logger.setLevel(logging.INFO) #日志级别:DEBUG, INFO, WARNING, ERROR, 和 CRITICALfile_handler = logging.FileHandler(pathLog)file_handler.setLevel(logging.INFO)formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')file_handler.setFormatter(formatter)logger.addHandler(file_handler)#endregion#region 超参数args = parse_args()args.pnModel = PN2boollog_string('--- hyper-parameter ---')log_string(args)os.environ["CUDA_VISIBLE_DEVICES"] = args.GPUbatchSize = args.batch_sizepointNumber = args.num_pointtestArea = args.test_areavoteNumber = args.num_votes#endregion#region ---------- 加载语义分割的模型 ----------log_string("---------- Loading sematic segmentation model ----------")ssModel = ''if PN2bool:ssModel = PN2SS(classNumber).cuda()else:ssModel = PNss(classNumber).cuda()path_model = os.path.join(pathTrainModel, 'best_model_S3DIS.pth')checkpoint = torch.load(path_model)ssModel.load_state_dict(checkpoint['model_state_dict'])ssModel = ssModel.eval()#endregion# 模型推断(inference)或评估(evaluation)阶段,不需要计算梯度,而且关闭梯度计算可以显著减少内存占用,加速计算。log_string('--- Evaluation whole scene')with torch.no_grad():# IOU 结果total_seen_class = [0 for _ in range(classNumber)]total_correct_class = [0 for _ in range(classNumber)]total_iou_deno_class = [0 for _ in range(classNumber)]# 测试区域的所有文件testDataset = ScannetDatasetWholeScene(pathDataset, split='test', test_area=testArea, block_points=pointNumber)scene_id_name = testDataset.file_listscene_id_name = [x[:-4] for x in scene_id_name] # 名称(无扩展名)testCount = len(scene_id_name)testCount = 1# 遍历需要预测的物体for batch_idx in range(testCount):log_string("Inference [%d/%d] %s ..." % (batch_idx + 1, testCount, scene_id_name[batch_idx]))# 数据whole_scene_data = testDataset.scene_points_list[batch_idx]# 真值whole_scene_label = testDataset.semantic_labels_list[batch_idx]whole_scene_labelR = np.reshape(whole_scene_label, (whole_scene_label.size, 1))# 预测标签vote_label_pool = np.zeros((whole_scene_label.shape[0], classNumber))# 同一物体多次预测for _ in tqdm(range(voteNumber), total=voteNumber):scene_data, scene_label, scene_smpw, scene_point_index = testDataset[batch_idx]num_blocks = scene_data.shape[0]s_batch_num = (num_blocks + batchSize - 1) // batchSizebatch_data = np.zeros((batchSize, pointNumber, 9))batch_label = np.zeros((batchSize, pointNumber))batch_point_index = np.zeros((batchSize, pointNumber))batch_smpw = np.zeros((batchSize, pointNumber))for sbatch in range(s_batch_num):start_idx = sbatch * batchSizeend_idx = min((sbatch + 1) * batchSize, num_blocks)real_batch_size = end_idx - start_idxbatch_data[0:real_batch_size, ...] = scene_data[start_idx:end_idx, ...]batch_label[0:real_batch_size, ...] = scene_label[start_idx:end_idx, ...]batch_point_index[0:real_batch_size, ...] = scene_point_index[start_idx:end_idx, ...]batch_smpw[0:real_batch_size, ...] = scene_smpw[start_idx:end_idx, ...]batch_data[:, :, 3:6] /= 1.0torch_data = torch.Tensor(batch_data)torch_data = torch_data.float().cuda()torch_data = torch_data.transpose(2, 1)seg_pred, _ = ssModel(torch_data)batch_pred_label = seg_pred.contiguous().cpu().data.max(2)[1].numpy()# 投票产生预测标签vote_label_pool = add_vote(vote_label_pool, batch_point_index[0:real_batch_size, ...],batch_pred_label[0:real_batch_size, ...],batch_smpw[0:real_batch_size, ...])# region  保存预测的结果# 预测标签pred_label = np.argmax(vote_label_pool, 1)pred_labelR = np.reshape(pred_label, (pred_label.size, 1))# 点云-真值-预测标签pcrgb_ll = np.hstack((whole_scene_data, whole_scene_labelR, pred_labelR))# ---------- 保存成 txt ----------pathTXT = os.path.join(visual_dir, scene_id_name[batch_idx] + '.txt')np.savetxt(pathTXT, pcrgb_ll, fmt='%f', delimiter='\t')log_string('save:' + pathTXT)# ---------- 保存成 las ----------pathLAS = os.path.join(visual_dir, scene_id_name[batch_idx] + '.las')SaveResultLAS(pathLAS, pcrgb_ll[:,0:3], pcrgb_ll[:,3:6], pcrgb_ll[:,6], pcrgb_ll[:,7])log_string('save:' + pathLAS)# endregion# IOU 临时结果total_seen_class_tmp = [0 for _ in range(classNumber)]total_correct_class_tmp = [0 for _ in range(classNumber)]total_iou_deno_class_tmp = [0 for _ in range(classNumber)]for l in range(classNumber):total_seen_class_tmp[l] += np.sum((whole_scene_label == l))total_correct_class_tmp[l] += np.sum((pred_label == l) & (whole_scene_label == l))total_iou_deno_class_tmp[l] += np.sum(((pred_label == l) | (whole_scene_label == l)))total_seen_class[l] += total_seen_class_tmp[l]total_correct_class[l] += total_correct_class_tmp[l]total_iou_deno_class[l] += total_iou_deno_class_tmp[l]iou_map = np.array(total_correct_class_tmp) / (np.array(total_iou_deno_class_tmp, dtype=np.float64) + 1e-6)print(iou_map)arr = np.array(total_seen_class_tmp)tmp_iou = np.mean(iou_map[arr != 0])log_string('Mean IoU of %s: %.4f' % (scene_id_name[batch_idx], tmp_iou))IoU = np.array(total_correct_class) / (np.array(total_iou_deno_class, dtype=np.float64) + 1e-6)iou_per_class_str = '----- IoU -----\n'for l in range(classNumber):iou_per_class_str += 'class %s, IoU: %.3f \n' % (seg_label_to_cat[l] + ' ' * (14 - len(seg_label_to_cat[l])),total_correct_class[l] / float(total_iou_deno_class[l]))log_string(iou_per_class_str)log_string('eval point avg class IoU: %f' % np.mean(IoU))log_string('eval whole scene point avg class acc: %f' % (np.mean(np.array(total_correct_class) / (np.array(total_seen_class, dtype=np.float64) + 1e-6))))log_string('eval whole scene point accuracy: %f' % (np.sum(total_correct_class) / float(np.sum(total_seen_class) + 1e-6)))log_string('--------------------------------------\n\n')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638361.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法专题[递归-搜索-回溯-2-DFS]

算法专题[递归-搜索-回溯-2-DFS] 一.计算布尔二叉树的值&#xff1a;1.思路一&#xff1a;2.GIF题目解析 二.求根节点到叶子节点的数字之和1.思路一&#xff1a;2.GIF题目解析 三.二叉树剪枝1.思路一&#xff1a;2.GIF题目解析 四.验证二叉搜索树1.思路一&#xff1a;2.GIF题目…

1.2 数据模型

数据模型是对现实世界数据特征的抽象&#xff0c;是现实世界的模拟 数据模型是用来描述数据、组织数据和对数据进行操作的 数据模型应满足三方面要求&#xff1a; 1 能比较真实地模拟现实世界 2 容易为人所理解 3 便于在计算机上实现 数据模型…

08. Springboot集成webmagic实现网页爬虫

目录 1、前言 2、WebMagic 3、Springboot集成Webmagic 3.1、创建Springboot&#xff0c;并引入webmagic依赖 3.2、定义PageProcessor 3.3、元素选择 3.3.1、F12查看网页元素 3.3.2、元素选择 3.3.3、注意事项 4、小结 1、前言 在信息化的时代&#xff0c;网络爬虫已…

QT的绘图系统QPainterDevice与文件系统QIODevice

QT的绘图系统&#xff08;QPainterDevice&#xff09;与文件系统&#xff08;QIODevice&#xff09; 文章目录 1、Qt 的绘图系统1、QPainter的使用2、QPen(画笔&#xff09;及QBursh&#xff08;画刷&#xff09;3、手动更新窗口4、绘图设备1、四种绘图设备的 区别2、 QBitmap3…

零食折扣店,注定昙花一现?

年终岁末&#xff0c;又到了各类休闲零食产品一年一度的销售旺季。与过去不同的是&#xff0c;近年来的休闲零食赛道正因大量零食折扣店的涌现而显得热闹非凡。 随着主打折扣、低价的零食折扣店成为消费者特别是三四线下沉市场消费者的新宠&#xff0c;资本开始涌入并快速推动…

SpringCloud之OpenFeign的学习、快速上手

1、什么是OpenFeign OpenFeign简化了Http的开发。在RestTemplate的基础上做了封装&#xff0c;在微服务中的服务调用发送网络请求起到了重要的作用&#xff0c;简化了开发&#xff0c;可以让我们跟写接口一样调其他服务。 并且OpenFeign内置了Ribbon实现负载均衡。 官方文档…

69.使用Go标准库compress/gzip压缩数据存入Redis避免BigKey

文章目录 一&#xff1a;简介二&#xff1a;Go标准库compress/gzip包介绍ConstantsVariablestype Headertype Reader 三&#xff1a;代码实践1、压缩与解压工具包2、单元测试3、为何压缩后还要用base64编码 代码地址&#xff1a; https://gitee.com/lymgoforIT/golang-trick/t…

SpringBoot3整合OpenAPI3(Swagger3)

文章目录 一、引入依赖二、使用1. OpenAPIDefinition Info2. Tag3. Operation4. Parameter5. Schema6. ApiResponse swagger2更新到3后&#xff0c;再使用方法上发生了很大的变化&#xff0c;名称也变为OpenAPI3。 官方文档 一、引入依赖 <dependency><groupId>…

深度解析Python关键字:掌握核心语法的基石(新版本35+4)

目录 关键字 keyword 关键字列表 kwlist softkwlist 关键字分类 数据类型 True、False None 运算类型 and、or、not in is 模块导入 import 辅助关键字 from、as 上下文管理 with 占位语句 pass 流程控制 if、elif、else for while break、continue…

第十回 朱贵水亭施号箭 林冲雪夜上梁山-FreeBSD/Linux 控制台基础操作

林冲被众庄客捉住&#xff0c;吊在门楼下&#xff0c;正被打时&#xff0c;柴进来了&#xff0c;赶快把林冲救下来。原来这是柴进打猎用的小庄子&#xff0c; 林冲就把火烧草料场一事跟柴进详细的说了。柴进说兄弟真是命运多磨难啊。林冲住了几日&#xff0c;恐怕连累柴进&…

Laykefu客服系统 任意文件上传漏洞复现

0x01 产品简介 Laykefu 是一款基于workerman+gatawayworker+thinkphp5搭建的全功能webim客服系统,旨在帮助企业有效管理和提供优质的客户服务。 0x02 漏洞概述 Laykefu客服系统/admin/users/upavatar.html接口处存在文件上传漏洞,而且当请求中Cookie中的”user_name“不为…

[学习笔记]刘知远团队大模型技术与交叉应用L3-Transformer_and_PLMs

RNN存在信息瓶颈的问题。 注意力机制的核心就是在decoder的每一步&#xff0c;都把encoder的所有向量提供给decoder模型。 具体的例子 先获得encoder隐向量的一个注意力分数。 注意力机制的各种变体 一&#xff1a;直接点积 二&#xff1a;中间乘以一个矩阵 三&#xff1a;…

找不到vcruntime140_1.dll无法继续执行怎么办?全面分析修复方法

当系统提示vcruntime140_1.dll文件出现错误时&#xff0c;可能会引发一系列影响计算机正常运行的问题。这个特定的动态链接库文件&#xff08;DLL&#xff09;是Microsoft Visual C Redistributable的一部分&#xff0c;对于许多基于Windows的应用程序来说至关重要。一旦vcrunt…

回归预测 | Python基于ALO-BiGRU蚁狮优化算法优化双向BiGRU多变量回归预测+适应度曲线+多个评价指标

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 ALO算法是Mirjalili于2015提出的一种新型元启发式群智能算法。由于引入了随机游走、轮盘赌策略及精英策略&#xff0c;使得 ALO 算法成为一种种群多样、寻优性能强、调节参数少、易于实现的搜索技术 python代码 优化参…

线段树详解

什么是线段树&#xff1f; 1、线段树是一棵二叉搜索树&#xff0c;它储存的是一个区间的信息。 2、每个节点以结构体的方式存储&#xff0c;结构体包含以下几个信息&#xff1a; 区间左端点、右端点&#xff1b;&#xff08;这两者必有&#xff09; 这个区间要维护的信息&…

【leetcode】移除元素

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一.暴力求解法二.使用额外数组三.原地修改数组 点击查看题目 一.暴力求解法 若我们不考虑时间复杂度…

【题目】2023年国赛信息安全管理与评估正式赛任务书-模块3 CTF

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 任务书 模块三 网络安全渗透、理论技能与职业素养 竞赛相关资源资料可在文末关注公众号获得 比赛时间及注意事项 本阶段比赛时长为180分钟&#xff0c;时间为9:00-12:00。 【注意事项】 &#xff08;1&#xf…

算法优化:LeetCode第122场双周赛解题策略与技巧

接下来会以刷常规题为主 &#xff0c;周赛的难题想要独立做出来还是有一定难度的&#xff0c;需要消耗大量时间 比赛地址 3011. 判断一个数组是否可以变为有序 public class Solution {public int minimumCost(int[] nums) {if (nums.length < 3) {// 数组长度小于3时&a…

UG制图-创建图纸的多种方法

1、2D&#xff1a;创建独立2D图纸&#xff0c;不引用任何3D模型 在UG软件中选择新建&#xff0c;或者快捷键ctrl N&#xff0c;进入新建命令&#xff0c;然后点击图纸&#xff0c;在关系中选择独立的部件&#xff0c;就创建了一个独立的图纸&#xff0c;我们可以在装配中添加…

项目管理该考哪个证书❓NPDP还是软考❓

有小伙伴在纠结是要考NPDP认证呢还是考软考呢❓ 今天小编要给大家好好说说NPDP认证❗️ &#x1f4a1;NPDP全称New Product Development Professional&#xff0c;也就是产品经理国际资格认证。 &#x1f525;NPDP是国际公认的为一的新产品开发专业认证&#xff0c;是集理论、方…