经典目标检测YOLO系列(一)复现YOLOV1(4)VOC2007数据集的读取及预处理

经典目标检测YOLO系列(一)复现YOLOV1(4)VOC2007数据集的读取及预处理

之前,我们依据《YOLO目标检测》(ISBN:9787115627094)一书,提出了新的YOLOV1架构,并解决前向推理过程中的两个问题,继续按照此书进行YOLOV1的复现。
经典目标检测YOLO系列(一)YOLOV1的复现(1)总体架构

经典目标检测YOLO系列(一)复现YOLOV1(2)反解边界框及后处理

经典目标检测YOLO系列(一)复现YOLOV1(3)正样本的匹配及损失函数的实现

我们今天讲解下数据集的读取、数据集的预处理以及数据增强。

1、利用VOCDataset类读取数据集

对于目标检测任务而言,常用的数据集包括较小的PASCAL VOC以及较大的MS COCO。我们目前只需要了解并掌握使用较小的PASCAL VOC数据集即可,虽然COCO数据集是当下最主流的数据集之一,但其较大的数据量自然增加了训练成本。

VOC2007及2012数据集的下载(百度网盘)和介绍可以参考:

经典目标检测YOLO系列(1)YOLO-V1算法及其在VOC2007数据集上的应用

当然,作者在项目代码中,dataset/script文件中提供了用于下载VOC数据集的脚本。

1.1 VOCDataset类的实现

我们自定义VOCDataset类,继承pytorch提供的torch.utils.data.Dataset类,主要实现__getitem__函数。再利用pytorch提供的Dataloader,就可以通过调用__getitem__函数来批量读取VOC数据集图片和标签了。

VOCDataset类的初始化部分,如下方的代码所示:

# RT-ODLab\dataset\voc.pyclass VOCDataset(data.Dataset):def __init__(self, img_size     :int = 640,data_dir     :str = None,# image_sets   = [('2007', 'trainval'), ('2012', 'trainval')],image_sets   = [('2007', 'trainval')],trans_config = None,transform    = None,is_train     :bool = False,load_cache   :bool = False,):# ----------- Basic parameters -----------self.img_size = img_sizeself.image_set = image_setsself.is_train = is_trainself.target_transform = VOCAnnotationTransform()# ----------- Path parameters -----------self.root = data_dirself._annopath = osp.join('%s', 'Annotations', '%s.xml')self._imgpath = osp.join('%s', 'JPEGImages', '%s.jpg')# ----------- Data parameters -----------self.ids = list()for (year, name) in image_sets:rootpath = osp.join(self.root, 'VOC' + year)for line in open(osp.join(rootpath, 'ImageSets', 'Main', name + '.txt')):self.ids.append((rootpath, line.strip()))self.dataset_size = len(self.ids)# ----------- Transform parameters -----------self.transform = transformself.mosaic_prob = trans_config['mosaic_prob'] if trans_config else 0.0self.mixup_prob = trans_config['mixup_prob'] if trans_config else 0.0self.trans_config = trans_configprint('==============================')print('use Mosaic Augmentation: {}'.format(self.mosaic_prob))print('use Mixup Augmentation: {}'.format(self.mixup_prob))print('==============================')# ----------- Cached data -----------self.load_cache = load_cacheself.cached_datas = Noneif self.load_cache:self.cached_datas = self._load_cache()

VOCDataset类包含读取图片和标签的功能,对此,我们实现了相关的功能,如下方代码所示:

  • 通过调用pull_image和pull_anno两个函数来分别去读取图片和以XML格式保存的标签文件,load_image_target 函数最终会输出一张图片image,以及保存了该图片中的所有目标的边界框和类别信息的target。
  • 需要注意的是,当self.cached_datas不是None时,我们会从缓存了数据集所有数据的self.cached_datas中直接索引图片和对应的标签数据,而不用再从本地去读取了。
 # RT-ODLab\dataset\voc.py# ------------ Load data function ------------def load_image_target(self, index):# 读取图片和标签的功能# == 从缓存中进行加载 ==if self.cached_datas is not None:# load a datadata_item = self.cached_datas[index]image = data_item["image"]target = data_item["target"]# ==从磁盘中进行加载 ==else:        # load an image# 1、利用open-cv加载一张图像image, _ = self.pull_image(index)height, width, channels = image.shape# laod an annotation# 2、利用ET读取一张图片的标签信息(bbox以及类别信息)anno, _ = self.pull_anno(index)# guard against no boxes via resizinganno = np.array(anno).reshape(-1, 5)target = {"boxes": anno[:, :4],        # 一张图片中GT所有的bbox信息"labels": anno[:, 4],        # 一张图片中物体信息"orig_size": [height, width] # 原始图片的大小}# 返回一张图像及其标签信息return image, targetdef pull_image(self, index):# 利用opencv读取一张图片img_id = self.ids[index]# D:\\VOCdevkit\\VOC2007\\JPEGImages\\000001.jpgimage = cv2.imread(self._imgpath % img_id, cv2.IMREAD_COLOR)return image, img_iddef pull_anno(self, index):# 利用ET读取一张图片的标签信息(bbox以及类别信息)img_id = self.ids[index]# 'D:\\VOCdevkit\\VOC2007\\Annotations\\000001.xml'anno = ET.parse(self._annopath % img_id).getroot()# 解析xml文件,返回[[xmin,ymin,xmax,ymax,标签id],...]anno = self.target_transform(anno)return anno, img_id

这里作者为了实现了从缓冲中读取,实现了下面代码:

  • 代码中,将所有的图片和标签都保存在data_items变量中,注意,对于读取的每一张图片,我们都预先对其做resize操作,这是因为在后续的数据预处理环节中,我们会对原始图片先做一步resize操作,然后再去做其他的预处理操作,为了节省内存空间,这里我们就直接做好了。
  • 不过,就学习而言,我们是默认不采用这种cache方式,因为这对于设备的内存要求会很高。
    # RT-ODLab\dataset\voc.pydef _load_cache(self):data_items = []for idx in range(self.dataset_size):if idx % 2000 == 0:print("Caching images and targets : {} / {} ...".format(idx, self.dataset_size))# load a dataimage, target = self.load_image_target(idx)orig_h, orig_w, _ = image.shape# resize imager = self.img_size / max(orig_h, orig_w)if r != 1: interp = cv2.INTER_LINEARnew_size = (int(orig_w * r), int(orig_h * r))image = cv2.resize(image, new_size, interpolation=interp)img_h, img_w = image.shape[:2]# rescale bboxboxes = target["boxes"].copy()boxes[:, [0, 2]] = boxes[:, [0, 2]] / orig_w * img_wboxes[:, [1, 3]] = boxes[:, [1, 3]] / orig_h * img_htarget["boxes"] = boxesdict_item = {}dict_item["image"] = imagedict_item["target"] = targetdata_items.append(dict_item)return data_items

在实现了load_image_target函数后,我们再实现一个pull_item函数,在该函数中,我们会对读取进来的数据做预处理操作(先忽略预处理):

  • 代码中,我们会根据random.random()< self.mosaic_prob条件来决定是否读取马赛克图像,即将多张图像拼接在一起,使得拼接后的图像能拥有更丰富的目标信息。
  • 另外,我们也会根据random.random()< self.mixup_prob条件来决定是要加载混合图像,即使用混合增强(Mixup augmentation)技术随机将两张图片以加权求和的方式融合在一起。
  • 就目前的学习目标而言,我们暂时还不会使用到这两个过于强大的数据增强,因此mosaic_prob及mixup_prob默认为0。
  • 最后,外部的Dataloader就可以通过调用__getitem__函数来读取VOC数据集图片和标签了。
    # RT-ODLab\dataset\voc.pydef pull_item(self, index):# 实现一个pull_item函数,在该函数中,我们会对读取进来的数据做预处理操作if random.random() < self.mosaic_prob:# load a mosaic imagemosaic = Trueimage, target = self.load_mosaic(index)else:mosaic = False# load an image and targetimage, target = self.load_image_target(index)# MixUpif random.random() < self.mixup_prob:image, target = self.load_mixup(image, target)# augmentimage, target, deltas = self.transform(image, target, mosaic)return image, target, deltas# ------------ Basic dataset function ------------def __getitem__(self, index):image, target, deltas = self.pull_item(index)return image, target, deltasdef __len__(self):return self.dataset_size    

1.2 读取VOC数据集

1.2.1 build_dataset函数

这里,将读取VOC数据集封装为build_dataset函数,如下:

build_dataset函数:

# RT-ODLab\dataset\build.py# ------------------------------ Dataset ------------------------------
def build_dataset(args, data_cfg, trans_config, transform, is_train=True):# ------------------------- Basic parameters -------------------------data_dir = os.path.join(args.root, data_cfg['data_name'])num_classes = data_cfg['num_classes']class_names = data_cfg['class_names']class_indexs = data_cfg['class_indexs']dataset_info = {'num_classes': num_classes,'class_names': class_names,'class_indexs': class_indexs}# ------------------------- Build dataset -------------------------## VOC datasetif args.dataset == 'voc':image_sets = [('2007', 'trainval')] if is_train else [('2007', 'test')]dataset = VOCDataset(img_size     = args.img_size,data_dir     = data_dir,image_sets   = image_sets,transform    = transform,trans_config = trans_config,is_train     = is_train,load_cache   = args.load_cache)## COCO datasetelif args.dataset == 'coco':image_set = 'train2017' if is_train else 'val2017'dataset = COCODataset(img_size     = args.img_size,data_dir     = data_dir,image_set    = image_set,transform    = transform,trans_config = trans_config,is_train     = is_train,load_cache   = args.load_cache)## CrowdHuman datasetelif args.dataset == 'crowdhuman':image_set = 'train' if is_train else 'val'dataset = CrowdHumanDataset(img_size     = args.img_size,data_dir     = data_dir,image_set    = image_set,transform    = transform,trans_config = trans_config,is_train     = is_train,)## Custom datasetelif args.dataset == 'ourdataset':image_set = 'train' if is_train else 'val'dataset = OurDataset(data_dir     = data_dir,img_size     = args.img_size,image_set    = image_set,transform    = transform,trans_config = trans_config,s_train      = is_train,oad_cache    = args.load_cache)return dataset, dataset_info

1.2.2 build_dataloader函数

  • 在实现了Dataset以及数据预处理操作后,我们接下来就需要为训练中要用到的Dataloader做一些准备。
  • Dataloader的作用就是利用多线程来快速地为当前的训练迭代准备好一批数据,以便我们去做推理、标签分配和损失函数,这其中就要用到collate_fn方法,该方法的主要目的就是去将多个线程读取进来的数据处理成我们所需要的格式。
  • 默认情况下,Dataloader自带的该方法是直接将所有数据组成个更大的torch.Tensor,但这不适合于我们的数据,因为我们的标签数据是Dict,无法拼接成Tensor,因此,我们需要自己实现一个Collate函数,如下方的代码所示。
  • 这段代码的逻辑十分简单,就是从Dataloader利用多线程读取进来的一批数据batch, 分别去取出图片和标签,然后将图片组成一批数据,即torch.Tensor类型,其shape是[B, C, H, W],再将所有图片的target存放在一个List中,最后输出即可。
# RT-ODLab\utils\misc.py## collate_fn for dataloader
class CollateFunc(object):def __call__(self, batch):targets = []images = []for sample in batch:image = sample[0]target = sample[1]images.append(image)targets.append(target)images = torch.stack(images, 0) # [B, C, H, W]return images, targets
# batch为2的时候,值为下面所示:
[(tensor([[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]],[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]],[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]]]), {'boxes': tensor([[114., 295., 119., 312.],[ 29., 230., 148., 321.]]), 'labels': tensor([14., 18.]), 'orig_size': [281, 500]}, None), (tensor([[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]],[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]],[[0., 0., 0.,  ..., 0., 0., 0.],...,[0., 0., 0.,  ..., 0., 0., 0.]]]), {'boxes': tensor([[  0.,  79., 416., 362.]]), 'labels': tensor([1.]), 'orig_size': [375, 500]}, None)
]# 经过CollateFunc函数后转变为:
# images.shape:
torch.Size([2, 3, 416, 416])
# targets为:
[{'boxes': tensor([[114., 295., 119., 312.],[ 29., 230., 148., 321.]]), 'labels': tensor([14., 18.]), 'orig_size': [281, 500]}, {'boxes': tensor([[  0.,  79., 416., 362.]]), 'labels': tensor([1.]), 'orig_size': [375, 500]}
]

在写完了Collate函数后,我们就可以利用PyTorch框架提供的Dataloader来实现这部分的操作:

  • 当args.distributed=True时,我们会开启分布式训练,即所谓的“DDP”,此时我们就要构建DDP模块下的sampler,否则的话我们就构建单卡环境下的RandomSampler即可。
  • 然后构建读取一批数据的BatchSampler,其中,我们将drop_last设置为True,即当数dataloader读取到最后,发现剩下的数据数量少于我们设定的batch size,那么就丢掉这一批数据。
  • 由于每次dataloader读取完所有的数据后,即完成一次训练的epoch,内部数据会被重新打乱一次,因此这种丢弃方法不会造成负面影响。

build_dataloader函数:

# RT-ODLab\utils\misc.py# ---------------------------- For Dataset ----------------------------
## build dataloader
def build_dataloader(args, dataset, batch_size, collate_fn=None):# distributedif args.distributed:sampler = DistributedSampler(dataset)else:sampler = torch.utils.data.RandomSampler(dataset)batch_sampler_train = torch.utils.data.BatchSampler(sampler, batch_size, drop_last=True)# 读取VOC数据集dataloader = DataLoader(dataset, batch_sampler=batch_sampler_train,collate_fn=collate_fn, num_workers=args.num_workers, pin_memory=True)return dataloader

2、数据预处理

2.1 SSD风格的预处理

我们在构造VOCDataset类时候,需要传入transform,这就是数据的预处理。下面是构造transform的函数:

  • 在YOLOV1中,我们使用ssd风格数据预处理及数据增强策略,即trans_config[‘aug_type’]的值为ssd

  • 训练过程中,我们使用SSDAugmentation,即只采用SSD工作所用到的数据增强操作,包括随机裁剪、随机翻转、随机色彩空间变换、随机图像色彩变换等等。

  • 前向推理过程中,我们使用SSDBaseTransform,即前向推理过程中,只对图像做预处理操作。

  • 在YOLOV1中,我们关闭马赛克增强以及混合增强。

  • 我们可以运行dataset/voc.py文件,将数据增强后的图片可视化出来,增强的效果即可一目了然。读者可以参考下方的运行命令来查看。具体数据增强的代码实现,还请参考源码。

    python dataset/voc.py --root /data/VOCdevkit --aug_type ssd --is_train

# RT-ODLab\dataset\build.py# ------------------------------ Transform ------------------------------
def build_transform(args, trans_config, max_stride=32, is_train=False):# Modify trans_configif is_train:## mosaic prob.if args.mosaic is not None:trans_config['mosaic_prob']=args.mosaic if is_train else 0.0else:trans_config['mosaic_prob']=trans_config['mosaic_prob'] if is_train else 0.0## mixup prob.if args.mixup is not None:trans_config['mixup_prob']=args.mixup if is_train else 0.0else:trans_config['mixup_prob']=trans_config['mixup_prob']  if is_train else 0.0# Transformif trans_config['aug_type'] == 'ssd':if is_train:transform = SSDAugmentation(img_size=args.img_size,)else:transform = SSDBaseTransform(img_size=args.img_size,)trans_config['mosaic_prob'] = 0.0trans_config['mixup_prob'] = 0.0elif trans_config['aug_type'] == 'yolov5':if is_train:transform = YOLOv5Augmentation(img_size=args.img_size,trans_config=trans_config,use_ablu=trans_config['use_ablu'])else:transform = YOLOv5BaseTransform(img_size=args.img_size,max_stride=max_stride)return transform, trans_config

1.1.1 训练过程中的SSDAugmentation

  • 数据集固定,其所携带的各种信息便也就固定了下来,因此也就限定了模型的学习能力。为了扩充数据集的数量以及样本的丰富性、提高模型的鲁棒性和泛化能力,我们往往会在训练阶段对数据集已有的数据做随机的预处理操作,比如随机水平翻转、随机剪裁、色彩扰动、空间尺寸缩放等,这就是数据增强
  • 对于我们现在所要实现的YOLOv1,我们只采用SSD工作所用到的数据增强操作,包括随机裁剪、随机翻转、随机色彩空间变换、随机图像色彩变换等等。
  • 我们暂时不会用到更强大的马赛克增强、混合增强等手段。在我们实现的YOLOv1的配置文件中,我们可以看到’trans_type’: ‘ssd’ 字样,这就表明我们使用SSD风格的数据增强。
# RT-ODLab\dataset\data_augment\ssd_augment.py
# ----------------------- Main Functions -----------------------
## SSD-style Augmentation
class SSDAugmentation(object):def __init__(self, img_size=640):self.img_size = img_sizeself.augment = Compose([ConvertFromInts(),                         # 将int类型转换为float32类型PhotometricDistort(),                      # 图像颜色增强Expand(),                                  # 扩充增强RandomSampleCrop(),                        # 随机剪裁RandomHorizontalFlip(),                    # 随机水平翻转Resize(self.img_size)                      # resize操作])def __call__(self, image, target, mosaic=False):boxes = target['boxes'].copy()labels = target['labels'].copy()deltas = None# augmentimage, boxes, labels = self.augment(image, boxes, labels)# to tensorimg_tensor = torch.from_numpy(image).permute(2, 0, 1).contiguous().float()target['boxes'] = torch.from_numpy(boxes).float()target['labels'] = torch.from_numpy(labels).float()return img_tensor, target, deltas

1.1.2 前向推理过程中的SSDBaseTransform

  • 前向推理过程中,只对图像做预处理操作。

  • 首先,对于给定的一张图片image,我们调用opencv提供的cv2.resize函数将其空间尺寸变换到指定的图像尺寸,比如416x416。

    • 注意,经过这么一次操作,原始图像的长宽比通常会被改变,使得图片发生一定的畸变。大多数时候这一问题并不严重,但对于某些场景来说,这种畸变可能会破坏模型对真实世界的认识。
    • 因此,在后来的YOLO工作里,采用了保留长宽比的Resize操作。
  • 需要注意的是,我们没有在这里对图像做归一化操作,这一操作我们后在训练部分的代码中再做

  • 在完成了对图像的Resize操作后,我们也需要对相应的边界框坐标也做必要的调整,因为边界框坐标是相对于图片的,既然图片的尺寸都改变了,边界框坐标也必须做相应的比例变换。最后,我们将标签数据全部转换为torch.Tensor类型,以便后续的处理。

 # RT-ODLab\dataset\data_augment\ssd_augment.py## SSD-style valTransform
class SSDBaseTransform(object):def __init__(self, img_size):self.img_size = img_sizedef __call__(self, image, target=None, mosaic=False):deltas = None# resizeorig_h, orig_w = image.shape[:2]image = cv2.resize(image, (self.img_size, self.img_size)).astype(np.float32)# scale targetsif target is not None:boxes = target['boxes'].copy()labels = target['labels'].copy()img_h, img_w = image.shape[:2]boxes[..., [0, 2]] = boxes[..., [0, 2]] / orig_w * img_wboxes[..., [1, 3]] = boxes[..., [1, 3]] / orig_h * img_htarget['boxes'] = boxes# to tensorimg_tensor = torch.from_numpy(image).permute(2, 0, 1).contiguous().float()if target is not None:target['boxes'] = torch.from_numpy(boxes).float()target['labels'] = torch.from_numpy(labels).float()return img_tensor, target, deltas

至此,我们讲完了数据预处理操作,接下来,我们就可以在开始训练我们实现的YOLOv1模型。

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

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

相关文章

【漏洞复现】通天星CMSV6车载监控平台任意文件下载漏洞

Nx01 产品简介 深圳市通天星科技有限公司&#xff0c;是一家以从事计算机、通信和其他电子设备制造业为主的企业。通天星车载视频监控平台软件拥有多种语言版本。应用于公交车车载视频监控、校车车载视频监控、大巴车车载视频监控、物流车载监控、油品运输车载监控、警车车载视…

十七:爬虫-JS逆向(上)

1、什么是JS、JS反爬是什么&#xff1f;JS逆向是什么? JS:JS全称JavaScript是互联网上最流行的脚本语言&#xff0c;这门语言可用于HTML 和 web&#xff0c;更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。JavaScript 是一种轻量级的编程语言。JavaScript 是…

数据结构—图(上)

文章目录 12.图(上)(1).图的基本概念#1.图的基本定义#2.边的分类#3.数据结构的一些规定#4.子图#5.完全图#6.路径#7.连通性和连通分量#8.度 (2).图的存储方式#1.邻接矩阵#2.邻接表 (3).图的遍历#1.深度优先搜索(Depth First Search)i.走个迷宫ii.DFS的思想iii.代码实现 #2.广度优…

不可狗尾续貂的tail

文章目录 不可狗尾续貂的tail常规使用显示N行从第N行显示按照字符显示特别赞的一个实时更新的功能更多信息不可狗尾续貂的tail tail命令用来查看文件尾部的n行,如果没有指定的n,默认显示10行。 命令格式: $ tail [option] [filename] 参数option比较常用的如下所示: -f…

LeetCode-无重复字符的最长子串(3)

题目描述&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 代码&#xff1a; class Solution {public int lengthOfLongestSubstring(String s) {Set<Character> occnew HashSet<Character>();int lens.length();int…

解决Element-Plus中el-switch的change方法自动触发问题

下面el-switch代码片段是在el-table里使用 <el-switch v-else-if"col.prop status" v-model"scope.row.status" :active-value"0" :inactive-value"1" :before-change"beforeStatus" change"changStatus(scope.r…

Yolov5/8的小程序部署前后端实现

Yolov5/8的小程序部署前后端实现 导语本机配置硬件环境配置 前端实现后端实现总结参考文献 导语 毕设的题目与Yolo系列的图像识别相关&#xff0c;通过搜查了很多资料和实践最后完成&#xff0c;看到某些平台上居然卖300&#xff0c;觉得很离谱&#xff0c;所以决定把代码开源…

Springcloud alibab和dubbo有什么区别?

Spring Cloud Alibaba 和 Dubbo 都是为了简化企业级应用开发而生的框架&#xff0c;尤其是在分布式系统和微服务架构的背景下。 虽然他们在某些功能上有重叠&#xff0c;但各有侧重点和使用场景。 微服务架构图 首先介绍一下 Spring Cloud Alibaba&#xff1a; Spring Cloud …

C++自制小游戏《屠夫躲猫猫》

大家好&#xff0c;我是派蒙&#xff0c;我写了一个《屠夫躲猫猫》的游戏&#xff0c;下面是源代码&#xff1a; #include <stdio.h> #include <conio.h> #include<bits/stdc.h> #include<windows.h> using namespace std; string ID[1001]; string N…

Fiddler抓取https原理?

首先fiddler截获客户端浏览器发送给服务器的https请求&#xff0c; 此时还未建立握手。 第一步&#xff0c; fiddler向服务器发送请求进行握手&#xff0c; 获取到服务器的CA证书&#xff0c; 用根证书公钥进行解密&#xff0c; 验证服务器数据签名&#xff0c; 获取到服务器C…

数据结构学习 jz34 二叉树中和为某一值的路径

关键词&#xff1a;回溯 二叉树 前序遍历 路径记录 因为我没有仔细接触过二叉树的遍历过程&#xff0c;所以我是懵懵懂懂按照dfs的方法写的。没想到写对了&#xff0c;看了解答发现这叫做二叉树的前序遍历。用时29min。 这让我明白了前序遍历和dfs原来是有相同之处的。&#…

Local server not started, start with 报错python -m weditor

一、python -m weditor 如图报错 Local server not started, start with 报错 二、解决方案 右上角选择新的无痕窗口下&#xff0c;然后打开 http://localhost:17310/ 即可

2401C++,无栈协程核心概念

无栈协程本质是个可多次执行的状态机.一般使用协程的标准流程是,生成一个状态机,返回状态机的(协柄)句柄,通过控制该句柄,不断反复执行(恢复). 执行过程中,该状态机作用是:不停产生数据并写到某个地方.所以c20协程提供了协产和协中,同时,每个协程都应有个实现了产生值或中值函…

OBJECT 划分

5、Object 划分 1.PO(persistant object) 持久对象 PO 就是对应数据库中某个表中的一条记录&#xff0c;多个记录可以用 PO 的集合。 PO 中应该不包含任何对数据库的操作。 2.DO&#xff08;Domain Object&#xff09;领域对象 就是从现实世界中抽象出来的有形或无形的业务实体…

React与Vue性能对比:两大前端框架的性能

React和Vue是当今最流行的两个前端框架&#xff0c;它们在性能方面都有着出色的表现。 React的加载速度&#xff1a; 初次加载&#xff1a;由于React使用了虚拟DOM&#xff08;Virtual DOM&#xff09;技术&#xff0c;它可以通过比较虚拟DOM树与实际DOM树的差异来进行高效的…

PCIe 6.0生态业内进展分析总结-2

3.PCIe 6.0协议分析仪 (1)Keysight Keysight是德科技在2023年6月份对外宣布&#xff0c;第一款支持PCIe 6.0协议验证调试工具。 Keysight PCIe 6.0架构解决方案具备以下特点&#xff1a; 分析PCIe 6.0技术设计的数据链路/事务层 支持所有PCIe技术速率——从2.5 GT/s至64 GT/…

实验笔记之——基于COLMAP的Instant-NGP与3D Gaussian Splatting的对比

之前博客进行了COLMAP在服务器下的测试 实验笔记之——Linux实现COLMAP-CSDN博客文章浏览阅读794次&#xff0c;点赞24次&#xff0c;收藏6次。学习笔记之——NeRF SLAM&#xff08;基于神经辐射场的SLAM&#xff09;-CSDN博客NeRF 所做的任务是 Novel View Synthesis&#xf…

《PySpark大数据分析实战》-25.数据可视化图表Matplotlib介绍

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

2024-01-04 用llama.cpp部署本地llama2-7b大模型

点击 <C 语言编程核心突破> 快速C语言入门 用llama.cpp部署本地llama2-7b大模型 前言一、下载llama.cpp以及llama2-7B模型文件二、具体调用总结 使用协议: License to use Creative Commons Zero - CC0 该图片个人及商用免费&#xff0c;无需显示归属&#xff0c;但如果…

阿里通义千问「全民舞王」,一张照片就能跳《科目三》,刷爆朋友圈

这两天看朋友圈、网上都在发这种跳舞的视频。只要上传一张全身照&#xff0c;就可以生成各种跳舞的视频。 比如前段时间火爆海底捞的《科目三》&#xff0c;还有《DJ慢摇》、《鬼步舞》、《兔子舞》、甚至还有咱《秧歌舞》。 先来一睹为快&#xff01; 阿里通义千问「全民舞王…