↑↑↑关注后"星标"Datawhale

每日干货 & 每月组队学习,不错过

Datawhale干货

作者:徐和鼎,浙江大学,Datawhale优秀学习者

前沿

在上节内容中,我们介绍了目标检测的基础概念,并分析了实现目标检测的常用思路,本篇文章将重点介绍在该领域的经典数据集:VOC数据集,以及使用Dataloader对其进行数据读取和预处理的全过程。

一、 目标检测数据集VOC

VOC数据集是目标检测领域最常用的标准数据集之一,几乎所有检测方向的论文,如faster_rcnn、yolo、SSD等都会给出其在VOC数据集上训练并评测的效果。本文中,我们使用VOC2007和VOC2012这两个最流行的版本作为训练和测试的数据。

1. 数据集类别

VOC数据集在类别上可以分为4大类,20小类,其类别信息下图所示。

VOC数据集目标类别划分

2. 数据集量级

VOC数量集图像和目标数量的基本信息如下图所示:

VOC数据集数据量级对比

其中,Images表示图片数量,Objects表示目标数量

3. 数据集下载

VOC官网经常上不去,确保后续实验准确且顺利的进行,已打包数据集,在Datawhale后台回复【目标检测】可直接下载,下载后放到dataset目录下解压即可。

下面是通过官网下载的步骤:

  • 进入VOC官网链接:http://host.robots.ox.ac.uk/pascal/VOC/.

  • 在下图所示区域找到历年VOC挑战赛链接,比如选择VOC2012.

    VOC官网页面
  • 在VOC2012页面,找到下图所示区域,点击下载即可。

    VOC2012数据集下载页面
  • VOC2007同理进行下载即可。

4. 数据集说明

将下载得到的压缩包解压,可以得到如图3-9所示的一系列文件夹,由于VOC数据集不仅被拿来做目标检测,也可以拿来做分割等任务,因此除了目标检测所需的文件之外,还包含分割任务所需的文件,比如SegmentationClass,SegmentationObject,这里,我们主要对目标检测任务涉及到的文件进行介绍。

VOC压缩包解压所得文件夹示例
  • JPEGImages:这个文件夹中存放所有的图片,包括训练验证测试用到的所有图片。

  • ImageSets:这个文件夹中包含三个子文件夹,Layout、Main、Segmentation;Layout文件夹中存放的是train,valid,test和train+valid数据集的文件名

  • Segmentation:文件夹中存放的是分割所用train,valid,test和train+valid数据集的文件名

  • Main:文件夹中存放的是各个类别所在图片的文件名,比如cow_val,表示valid数据集中,包含有cow类别目标的图片名称。

  • Annotations:Annotation文件夹中存放着每张图片相关的标注信息,以xml格式的文件存储,可以通过记事本或者浏览器打开,我们以000001.jpg这张图片为例说明标注文件中各个属性的含义。

猛一看去,内容又多又复杂,其实仔细研究一下,只有红框区域内的内容是我们真正需要关注的。

  • filename:图片名称

  • size:图片宽高

  • depth表示图片通道数

  • object:表示目标,包含下面两部分内容。

    首先是目标类别name为dog,pose表示目标姿势为left,truncated表示是否是一个被截断的目标,1表示是,0表示不是,在这个例子中,只露出狗头部分,所以truncated为1。difficult为0表示此目标不是一个难以识别的目标。

    然后就是目标的bbox信息,可以看到,这里是以[xmin,ymin,xmax,ymax]格式进行标注的,分别表示dog目标的左上角和右下角坐标。

  • 一张图片中有多少需要识别的目标,其xml文件中就有多少个object。上面的例子中有两个object,分别对应人和狗。

二、VOC数据集的dataloader的构建

1. 数据集准备

根据上面的介绍可以看出,VOC数据集的存储格式还是比较复杂的,为了后面训练中的读取代码更加简洁,这里我们准备了一个预处理脚本create_data_lists.py。

该脚本的作用是进行一系列的数据准备工作,主要是提前将记录标注信息的xml文件(Annotations)进行解析,并将信息整理到json文件之中,这样在运行训练脚本时,只需简单的从json文件中读取已经按想要的格式存储好的标签信息即可。

注: 这样的预处理并不是必须的,和算法或数据集本身均无关系,只是取决于开发者的代码习惯,不同检测框架的处理方法也是不一致的。

可以看到,create_data_lists.py脚本仅有几行代码,其内部调用了utils.py中的create_data_lists方法:

"""pythoncreate_data_lists
"""
from utils import create_data_listsif __name__ == '__main__':# voc07_path,voc12_path为我们训练测试所需要用到的数据集,output_folder为我们生成构建dataloader所需文件的路径# 参数中涉及的路径以个人实际路径为准,建议将数据集放到dataset目录下,和教程保持一致create_data_lists(voc07_path='../../../dataset/VOCdevkit/VOC2007',voc12_path='../../../dataset/VOCdevkit/VOC2012',output_folder='../../../dataset/VOCdevkit')

设置好对应路径后,我们运行数据集准备脚本:

tiny_detector_demo$ python create_data_lists.py

很快啊!dataset/VOCdevkit目录下就生成了若干json文件,这些文件会在后面训练中真正被用到。

不妨手动打开这些json文件,看下都记录了哪些信息。

下面来介绍一下parse_annotation函数内部都做了什么,json中又记录了哪些信息。这部分作为选学,不感兴趣可以跳过,只要你已经明确了json中记录的信息的含义。

代码阅读可以参照注释,建议配下图一起食用:

"""pythonxml文件解析
"""import json
import os
import torch
import random
import xml.etree.ElementTree as ET    #解析xml文件所用工具
import torchvision.transforms.functional as FT#GPU设置
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")# Label map
#voc_labels为VOC数据集中20类目标的类别名称
voc_labels = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable','dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')#创建label_map字典,用于存储类别和类别索引之间的映射关系。比如:{1:'aeroplane', 2:'bicycle',......}
label_map = {k: v + 1 for v, k in enumerate(voc_labels)}
#VOC数据集默认不含有20类目标中的其中一类的图片的类别为background,类别索引设置为0
label_map['background'] = 0#将映射关系倒过来,{类别名称:类别索引}
rev_label_map = {v: k for k, v in label_map.items()}  # Inverse mapping#解析xml文件,最终返回这张图片中所有目标的标注框及其类别信息,以及这个目标是否是一个difficult目标
def parse_annotation(annotation_path):#解析xmltree = ET.parse(annotation_path)root = tree.getroot()boxes = list()    #存储bboxlabels = list()    #存储bbox对应的labeldifficulties = list()    #存储bbox对应的difficult信息#遍历xml文件中所有的object,前面说了,有多少个object就有多少个目标for object in root.iter('object'):#提取每个object的difficult、label、bbox信息difficult = int(object.find('difficult').text == '1')label = object.find('name').text.lower().strip()if label not in label_map:continuebbox = object.find('bndbox')xmin = int(bbox.find('xmin').text) - 1ymin = int(bbox.find('ymin').text) - 1xmax = int(bbox.find('xmax').text) - 1ymax = int(bbox.find('ymax').text) - 1#存储boxes.append([xmin, ymin, xmax, ymax])labels.append(label_map[label])difficulties.append(difficult)#返回包含图片标注信息的字典return {'boxes': boxes, 'labels': labels, 'difficulties': difficulties}
  • 为什么得到的新坐标减1?VOC的矩形标注坐标是以1为基准的(1-based),而我们在处理图像坐标都是0起始的(0-based)。

    所以在这里才要对从xml文件中读取的xmin,ymin,xmax,ymax 统统减1将坐标变为我们做数据处理时所需要的0-based坐标。

  • 返回值的形状boxes (n,4) 的list,label (n) 的list,返回的都是标签对应的数字。difficulties (n)的list,返回的只有0或1。

    看了上面的代码如果还不太明白,试试结合这张图理解下:

xml解析流程图
"""python分别读取train和valid的图片和xml信息,创建用于训练和测试的json文件
"""
def create_data_lists(voc07_path, voc12_path, output_folder):"""Create lists of images, the bounding boxes and labels of the objects in these images, and save these to file.:param voc07_path: path to the 'VOC2007' folder:param voc12_path: path to the 'VOC2012' folder:param output_folder: folder where the JSONs must be saved"""#获取voc2007和voc2012数据集的绝对路径voc07_path = os.path.abspath(voc07_path)voc12_path = os.path.abspath(voc12_path)train_images = list()train_objects = list()n_objects = 0# Training datafor path in [voc07_path, voc12_path]:# Find IDs of images in training data#获取训练所用的train和val数据的图片idwith open(os.path.join(path, 'ImageSets/Main/trainval.txt')) as f:ids = f.read().splitlines()#根据图片id,解析图片的xml文件,获取标注信息for id in ids:# Parse annotation's XML fileobjects = parse_annotation(os.path.join(path, 'Annotations', id + '.xml'))if len(objects['boxes']) == 0:    #如果没有目标则跳过continuen_objects += len(objects)        #统计目标总数train_objects.append(objects)    #存储每张图片的标注信息到列表train_objectstrain_images.append(os.path.join(path, 'JPEGImages', id + '.jpg'))    #存储每张图片的路径到列表train_images,用于读取图片assert len(train_objects) == len(train_images)        #检查图片数量和标注信息量是否相等,相等才继续执行程序# Save to file#将训练数据的图片路径,标注信息,类别映射信息,分别保存为json文件with open(os.path.join(output_folder, 'TRAIN_images.json'), 'w') as j:json.dump(train_images, j)with open(os.path.join(output_folder, 'TRAIN_objects.json'), 'w') as j:json.dump(train_objects, j)with open(os.path.join(output_folder, 'label_map.json'), 'w') as j:json.dump(label_map, j)  # save label map tooprint('\nThere are %d training images containing a total of %d objects. Files have been saved to %s.' % (len(train_images), n_objects, os.path.abspath(output_folder)))#与Train data一样,目的是将测试数据的图片路径,标注信息,类别映射信息,分别保存为json文件,参考上面的注释理解# Test datatest_images = list()test_objects = list()n_objects = 0# Find IDs of images in the test datawith open(os.path.join(voc07_path, 'ImageSets/Main/test.txt')) as f:ids = f.read().splitlines()for id in ids:# Parse annotation's XML fileobjects = parse_annotation(os.path.join(voc07_path, 'Annotations', id + '.xml'))if len(objects) == 0:continuetest_objects.append(objects)n_objects += len(objects)test_images.append(os.path.join(voc07_path, 'JPEGImages', id + '.jpg'))assert len(test_objects) == len(test_images)# Save to filewith open(os.path.join(output_folder, 'TEST_images.json'), 'w') as j:json.dump(test_images, j)with open(os.path.join(output_folder, 'TEST_objects.json'), 'w') as j:json.dump(test_objects, j)print('\nThere are %d test images containing a total of %d objects. Files have been saved to %s.' % (len(test_images), n_objects, os.path.abspath(output_folder)))

同时加载voc07,voc12两个数据集,ids = f.read().splitlines()是把文件名以列表形式存储。设图片数量为n,每张图片中的object数为m(非固定)。

  • TRAIN_images.json 是列表,长度为n,装着是图片的绝对路径

  • TRAIN_objects.json 是列表,长度为n,装着n个字典,字典里有键

  • boxes (m,4) , label (m) , difficulties (m)    #括号里都是形状

同样,建议配图食用:

数据准备流程图(以train_dataset为例)

到这里,我们的训练数据就准备好了,接下来开始一步步构建训练所需的dataloader吧!

2. 构建dataloader

在这里,我们假设你对Pytorch的 Dataset 和 DataLoader 两个概念有最基本的了解。下面开始介绍构建dataloader的相关代码:

首先了解一下训练的时候在哪里定义了dataloader以及是如何定义的。以下是train.py中的部分代码段:

 #train_dataset和train_loader的实例化train_dataset = PascalVOCDataset(data_folder,split='train',keep_difficult=keep_difficult)train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True,collate_fn=train_dataset.collate_fn, num_workers=workers,pin_memory=True) # note that we're passing the collate function here

可以看到,首先需要实例化PascalVOCDataset类得到train_dataset,然后将train_dataset传入torch.utils.data.DataLoader,进而得到train_loader。

pin_memory就是锁页内存,创建DataLoader时,设置pin_memory=True,则意味着生成的Tensor数据最开始是属于内存中的锁页内存,这样将内存的Tensor转义到GPU的显存就会更快一些。显卡不好就不要开了。

collate_fn是如何将(C,H,W)组合成(N,C,H,W)的方式。

接下来看一下PascalVOCDataset是如何定义的。

代码位于 datasets.py 脚本中,可以看到,PascalVOCDataset继承了torch.utils.data.Dataset,然后重写了__init__ , getitem, lencollate_fn 四个方法,这也是我们在构建自己的dataset的时候需要经常做的工作,配合下面注释理解代码:

"""pythonPascalVOCDataset具体实现过程
"""
import torch
from torch.utils.data import Dataset
import json
import os
from PIL import Image
from utils import transformclass PascalVOCDataset(Dataset):"""A PyTorch Dataset class to be used in a PyTorch DataLoader to create batches."""#初始化相关变量#读取images和objects标注信息def __init__(self, data_folder, split, keep_difficult=False):""":param data_folder: folder where data files are stored:param split: split, one of 'TRAIN' or 'TEST':param keep_difficult: keep or discard objects that are considered difficult to detect?"""self.split = split.upper()    #保证输入为纯大写字母,便于匹配{'TRAIN', 'TEST'}assert self.split in {'TRAIN', 'TEST'}self.data_folder = data_folderself.keep_difficult = keep_difficult# Read data fileswith open(os.path.join(data_folder, self.split + '_images.json'), 'r') as j:self.images = json.load(j)with open(os.path.join(data_folder, self.split + '_objects.json'), 'r') as j:self.objects = json.load(j)assert len(self.images) == len(self.objects)#循环读取image及对应objects#对读取的image及objects进行tranform操作(数据增广)#返回PIL格式图像,标注框,标注框对应的类别索引,对应的difficult标志(True or False)def __getitem__(self, i):# Read image#*需要注意,在pytorch中,图像的读取要使用Image.open()读取成PIL格式,不能使用opencv#*由于Image.open()读取的图片是四通道的(RGBA),因此需要.convert('RGB')转换为RGB通道image = Image.open(self.images[i], mode='r')image = image.convert('RGB')# Read objects in this image (bounding boxes, labels, difficulties)objects = self.objects[i]boxes = torch.FloatTensor(objects['boxes'])  # (n_objects, 4)labels = torch.LongTensor(objects['labels'])  # (n_objects)difficulties = torch.ByteTensor(objects['difficulties'])  # (n_objects)# Discard difficult objects, if desired#如果self.keep_difficult为False,即不保留difficult标志为True的目标#那么这里将对应的目标删去if not self.keep_difficult:boxes = boxes[(1 - difficulties).bool()]  #uint8可以作为索引,但是转成bool去索引更好labels = labels[(1 - difficulties).bool()]difficulties = difficulties[(1 - difficulties).bool()]# Apply transformations#对读取的图片应用transformimage, boxes, labels, difficulties = transform(image, boxes, labels, difficulties, split=self.split)return image, boxes, labels, difficulties#获取图片的总数,用于计算batch数def __len__(self):return len(self.images)#我们知道,我们输入到网络中训练的数据通常是一个batch一起输入,而通过__getitem__我们只读取了一张图片及其objects信息#如何将读取的一张张图片及其object信息整合成batch的形式呢?#collate_fn就是做这个事情,#对于一个batch的images,collate_fn通过torch.stack()将其整合成4维tensor,对应的objects信息分别用一个list存储def collate_fn(self, batch):"""Since each image may have a different number of objects, we need a collate function (to be passed to the DataLoader).This describes how to combine these tensors of different sizes. We use lists.Note: this need not be defined in this Class, can be standalone.:param batch: an iterable of N sets from __getitem__():return: a tensor of images, lists of varying-size tensors of bounding boxes, labels, and difficulties"""images = list()boxes = list()labels = list()difficulties = list()for b in batch:images.append(b[0])boxes.append(b[1])labels.append(b[2])difficulties.append(b[3])#(3,224,224) -> (N,3,224,224)images = torch.stack(images, dim=0)return images, boxes, labels, difficulties  # tensor (N, 3, 224, 224), 3 lists of N tensors each

3. 关于数据增强

到这里为止,我们的dataset就算是构建好了,已经可以传给torch.utils.data.DataLoader来获得用于输入网络训练的数据了。但是不急,构建dataset中有个很重要的一步我们上面只是提及了一下,那就是transform操作(数据增强),也就是这一行代码

image, boxes, labels, difficulties = transform(image, boxes, labels, difficulties, split=self.split)

这部分比较重要,但是涉及代码稍多,对于基础较薄弱的伙伴可以作为选学内容,后面再认真读代码。你只需知道,同分类网络一样,训练目标检测网络同样需要进行数据增强,这对提升网络精度和泛化能力很有帮助。

需要注意的是,涉及位置变化的数据增强方法,同样需要对目标框进行一致的处理,因此目标检测框架的数据处理这部分的代码量通常都不小,且比较容易出bug。这里为了降低代码的难度,我们只是使用了几种比较简单的数据增强。

transform 函数的具体代码实现位于 utils.py 中,下面简单进行讲解:

"""pythontransform操作是训练模型中一项非常重要的工作,其中不仅包含数据增强以提升模型性能的相关操作,也包含如数据类型转换(PIL to Tensor)、归一化(Normalize)这些必要操作。
"""
import json
import os
import torch
import random
import xml.etree.ElementTree as ET
import torchvision.transforms.functional as FT"""
可以看到,transform分为TRAIN和TEST两种模式,以本实验为例:在TRAIN时进行的transform有:
1.以随机顺序改变图片亮度,对比度,饱和度和色相,每种都有50%的概率被执行。photometric_distort
2.扩大目标,expand
3.随机裁剪图片,random_crop
4.0.5的概率进行图片翻转,flip
*注意:a. 第一种transform属于像素级别的图像增强,目标相对于图片的位置没有改变,因此bbox坐标不需要变化。但是2,3,4,5都属于图片的几何变化,目标相对于图片的位置被改变,因此bbox坐标要进行相应变化。在TRAIN和TEST时都要进行的transform有:
1.统一图像大小到(224,224),resize
2.PIL to Tensor
3.归一化,FT.normalize()注1: resize也是一种几何变化,要知道应用数据增强策略时,哪些属于几何变化,哪些属于像素变化
注2: PIL to Tensor操作,normalize操作必须执行
"""def transform(image, boxes, labels, difficulties, split):"""Apply the transformations above.:param image: image, a PIL Image:param boxes: bounding boxes in boundary coordinates, a tensor of dimensions (n_objects, 4):param labels: labels of objects, a tensor of dimensions (n_objects):param difficulties: difficulties of detection of these objects, a tensor of dimensions (n_objects):param split: one of 'TRAIN' or 'TEST', since different sets of transformations are applied:return: transformed image, transformed bounding box coordinates, transformed labels, transformed difficulties"""#在训练和测试时使用的transform策略往往不完全相同,所以需要split变量指明是TRAIN还是TEST时的transform方法assert split in {'TRAIN', 'TEST'}# Mean and standard deviation of ImageNet data that our base VGG from torchvision was trained on# see: https://pytorch.org/docs/stable/torchvision/models.html#为了防止由于图片之间像素差异过大而导致的训练不稳定问题,图片在送入网络训练之间需要进行归一化#对所有图片各通道求mean和std来获得mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]new_image = imagenew_boxes = boxesnew_labels = labelsnew_difficulties = difficulties# Skip the following operations for evaluation/testingif split == 'TRAIN':# A series of photometric distortions in random order, each with 50% chance of occurrence, as in Caffe reponew_image = photometric_distort(new_image)# Convert PIL image to Torch tensornew_image = FT.to_tensor(new_image)# Expand image (zoom out) with a 50% chance - helpful for training detection of small objects# Fill surrounding space with the mean of ImageNet data that our base VGG was trained onif random.random() < 0.5:new_image, new_boxes = expand(new_image, boxes, filler=mean)# Randomly crop image (zoom in)new_image, new_boxes, new_labels, new_difficulties = random_crop(new_image, new_boxes, new_labels,new_difficulties)# Convert Torch tensor to PIL imagenew_image = FT.to_pil_image(new_image)# Flip image with a 50% chanceif random.random() < 0.5:new_image, new_boxes = flip(new_image, new_boxes)# Resize image to (224, 224) - this also converts absolute boundary coordinates to their fractional formnew_image, new_boxes = resize(new_image, new_boxes, dims=(224, 224))# Convert PIL image to Torch tensornew_image = FT.to_tensor(new_image)# Normalize by mean and standard deviation of ImageNet data that our base VGG was trained onnew_image = FT.normalize(new_image, mean=mean, std=std)return new_image, new_boxes, new_labels, new_difficulties

TRAIN transform的步骤:

  • 颜色变化、to_tensor(变形(CHW),归一化,pil变tensor)

  • 创建一个背景并把图放上去(等效缩小图片)

  • 随机裁剪图片(丢失了部分框)

  • 转为pil、随机左右翻转、resize(这里面对boxes做了归一化处理)

  • 再变tensor、标准化处理

4. 构建DataLoader

至此,我们已经将VOC数据转换成了dataset,接下来可以用来创建dataloader,这部分pytorch已经帮我们实现好了,我们只需将创建好的dataset送入即可,注意理解相关参数。

"""pythonDataLoader
"""
#参数说明:
#在train时一般设置shufle=True打乱数据顺序,增强模型的鲁棒性
#num_worker表示读取数据时的线程数,一般根据自己设备配置确定(如果是windows系统,建议设默认值0,防止出错)
#pin_memory,在计算机内存充足的时候设置为True可以加快内存中的tensor转换到GPU的速度,具体原因可以百度哈~
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True,collate_fn=train_dataset.collate_fn, num_workers=workers, pin_memory=True)  # note that we're passing the collate function here

小结

本文介绍了经典VOC数据集并对其进行了数据读取和预处理工作。现在,大家可以拿着这些已经处理好的数据,丢进模型里,尽情炼丹了。

参考连接:https://github.com/datawhalechina/dive-into-cv-pytorch

“整理不易,三连

目标检测的常用数据处理方法!相关推荐

  1. 【CV】目标检测的常用数据处理方法!

    作者:徐和鼎,浙江大学,Datawhale优秀学习者 前沿 在上节内容中,我们介绍了目标检测的基础概念,并分析了实现目标检测的常用思路,本篇文章将重点介绍在该领域的经典数据集:VOC数据集,以及使用D ...

  2. 目标检测---以制作yolov5的数据集为例,利用labelimg制作自己的深度学习目标检测数据集(正确方法)

    以制作yolov5的数据集为例,利用labelimg制作自己的深度学习目标检测数据集的正确方法 文章目录 前言 一.labelimg简单介绍 1 VOC标签格式,保存为xml文件. 2 yolo标签格 ...

  3. COCO目标检测数据集的读取方法与Python工具脚本

    COCO (Common Objects in COntext) 是一个大型的图像数据集,提供了目标检测.分割.看图说话等多个任务的标签.COCO的标注文件是用json格式编写的,初次接触时需要花十来 ...

  4. 目标检测算法常用Loss——DIoU GIoU CIoU

    目标检测算法常用Loss 文章目录 目标检测算法常用Loss 1. 差值平方损失 2. IoU Loss 3. GIoU Loss 4. DIoU Loss 5. CIoU Loss 6. 说明和补充 ...

  5. 登顶KITTI!Mix-Teaching:适用于单目3D目标检测的半监督方法【清华大学】

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨汽车人 来源丨自动驾驶之心 论文标题:Mix-Teaching: A Simple, Unifi ...

  6. 【CV】目标检测:常用名词与mAP评价指标的引出

    计算机视觉|机器视觉|机器学习|深度学习 编者荐语 mAP(mean average precision)是目标检测中衡量识别精度的一种重要的人为设计的评价指标.文章首先给大家介绍几种常见的目标检测领 ...

  7. 天池大赛通用目标检测的对抗攻击方法一览

    ©PaperWeekly 原创 · 作者|文永亮 学校|哈尔滨工业大学(深圳) 研究方向|时空序列预测,目标检测 赛题:1000张图,在图上贴补丁,最多不超过10个,导致检测框失效就算得分. 比赛链接 ...

  8. 目标检测多模型集成方法总结

    本文转载自AI公园. 前段时间推送了文章:难以置信的目标检测小妙招:多训练几个epochs,平均一下就能获得更好的模型 ,不少朋友对模型集成感兴趣,本文是个小总结. 作者:Vikas S Shetty ...

  9. Scale Match:国科大提出小目标检测的尺度匹配方法,用于预训练数据集处理

    点击我爱计算机视觉标星,更快获取CVML新技术 圣诞快乐- 今天分享一篇新出的论文 Scale Match for Tiny Person Detection,作者贡献了一个细小人物目标检测的数据集 ...

最新文章

  1. 搭建私有npm私库(使用verdaccio)
  2. php 未定义偏移,未定义的偏移PHP错误,尝试从文件读取
  3. tensorflow实现基于LSTM的文本分类方法
  4. LoaderManager使用详解(二)---了解LoaderManager
  5. mdp框架_强化学习:MDP(Markov Decision Process)
  6. c语言 想输入非数字是报错误,C语言上机练习5C言上机练习5.doc
  7. 操作系统【八】文件管理
  8. 【转】刨根究底字符编码之二——关键术语解释(下)
  9. MyBatis核心接口和类
  10. Matplotlib 三维图像 API
  11. 阿里面试官:LongAdder和AtomicLong哪个性能更好?我有点懵~
  12. 讯联智付:用户绑卡时“被签订”代扣协议 成借贷平台乱收费“帮凶”
  13. 如何使用imp导入dmp文件
  14. Ubuntu 如何更新软件源(阿里源、华为源、清华源等)
  15. android第三方登录appid,Android 第三方登录之支付宝登录
  16. 高德地图功能点使用整理
  17. Java——Shape类
  18. 转一次排障经历以供学习
  19. unix中嘚vim编辑器
  20. 中文词向量的下载与使用探索 (tensorflow加载词向量)

热门文章

  1. IOS tableView删除数据
  2. Your First Concordion.Net Project (Part 5)-Running Specs with Gallio
  3. Hibernate 获取某个表全部记录时 奇怪现象 (重复出现某个记录)
  4. 秦州:西瓜书 + 南瓜书 吃瓜系列 10. 集成学习(下)
  5. 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(一):扩展方法概述
  6. 【数据结构】图的深度优先遍历 广度优先遍历
  7. 压力测试 闪存_产品评测 | HPE Nimble AF全闪存系列,诠释真正的高端存储
  8. Python最常用的函数、基础语句有哪些?
  9. Twitter 禁止未经用户同意分享照片和视频
  10. 结合Flink,国内自研,大规模实时动态认知图谱平台——AbutionGraph |博文精选