下载的官方网址:http://host.robots.ox.ac.uk/pascal/voc/voc2012/index.html#devkit
PASCAL VOC 挑战赛(The PASCAL Visual Object Classes)是一个世界级的计算机视觉挑战赛。PASCAL全称Pattern Analysis, Statistical modelling and Computational Learning(模式分析、统计建模和计算学习),是一个由欧盟资助的网络组织。PASCAL VOC挑战赛主要包括下面几类:
图像分类(Object Classification)
目标检测(Object Detection)
目标分割(Object Segmentation)
动作识别(Action Classification)
etc
找到Development Kit即可进行下载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jNIcvXub-1674978186874)(C:\Users\GuoShuXian\AppData\Roaming\Typora\typora-user-images\image-20230129113748283.png)]
一共有20个类别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZXoosWH-1674978186894)(C:\Users\GuoShuXian\AppData\Roaming\Typora\typora-user-images\image-20230129112130517.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7l4Tc5Mw-1674978186896)(C:\Users\GuoShuXian\AppData\Roaming\Typora\typora-user-images\image-20230129112156244.png)]
随便打开一个annotation文件:
# 主节点
VOC2012 # 文件夹名字
2007_000187.jpg # 图片名称
# 图片大小节点
500 # 宽度
375 # 高度
3 # 深度(通道数)
1 # 该节点:该图片有没有被分割过(1和0)
flickr 网络 相片分享;
truncated 英[trʌŋˈkeɪtɪd] 美[ˈtrʌŋkeɪtɪd] adj. (版本)缩减的,删节的,截短了的; v. 截短,缩短,删节(尤指掐头或去尾);
一张图片中可以有多个检测目标
train.txt
和val.txt
对于目标检测任务,我们主要关注ImageSets\Main
下的train.txt
、val.txt
和trainval.txt
这三个文件。
下面是train.txt
和val.txt
的部分内容展示(trainval.txt
也是下面的样式):
每一行代表图像名称
2008_000008
2008_000015
2008_000019
2008_000023
2008_000028
2008_000033
2008_000036
2008_000037
2008_000041
...
train.txt
和val.txt
包含了训练时图片的名称和验证时图片的名称。
trainval.txt文件包含了训练使用的训练集和验证集。
总所周知,训练集和验证集是互斥的,那么为什么会有 trainval.txt这个文件呢?
因为我们得到结果可以去PASCAL官网进行测试,而PASCAL VOC 2012的测试集是不公开的,所以官方需要知道你在训练时使用了哪些文件,这时我们就需要提交这个文件以此在测试时可以剔除掉我们训练用过的文件。
2008_000143 -1
2008_000144 -1
2008_000148 1
2008_000151 -1
2008_000187 -1
2008_000188 -1
2008_000189 -1
2008_000191 0
2008_000192 -1
2008_000193 -1
这个文件中,除了图片的名称外,还有一列,包含三个数-1,0,1,分别表示:
-1
:图片中没有boat这个目标0
:包含boat目标,但该目标检测很困难1
:图片中有boat这个目标ImageSets/Main
的train.txt
,获取它的每一行信息(每一张图片的名称)Annotation
找到对应的.xml
文件并解析该文件,得到图片标签的信息ImageSet/JPEGImages
找到相应的图片并载入内存标注图像的软件有很多,在GitHub上有很多开源项目,比如:
https://github.com/tzutalin/labelImg
可以生成 .xml文件
https://github.com/wkentaro/labelme
主要生成json文件
为了保持和PASCAL VOC数据集一致,这里使用labelImg
pip3 install labelImg
labelImg
labelImg ./image[IMAGE_PATH] [PRE-DEFINED CLASS FILE]./class.txt
简单使用流程:
libs -> labelFile.py
文件中修改我们先将文件夹和文件准备好,如:
├── annotation
├── classes.txt
└── images
├── test_1
├── test_1.jpg
├── test_2.jpg
├── test_3.jpg
└── test_4.jpg
其中:
annotation
是标注文件夹,一会儿我们会将软件标注的结果放这里面classes.txt
是类别的信息,内容如下:dog
person
cat
tv
car
meatballs
marinara sauce
tomato soup
chicken noodle soup
french onion soup
chicken breast
ribs
pulled pork
hamburger
cavity
images
:放图片的文件夹,里面是具体需要标注的图片
# 进入文件夹
ls
annotation classes.txt images
# 打开软件 labelImg [图片文件夹路径] [标签文件]
labelImg ./images/ ./classes.txt
此时Annotation
文件夹下就有一个文件test_1.xml
,内容如下:
images # 图片所属文件夹
test_1.jpg # 图片的名字
/home/leovin/PyTorchProject/A2_object_detection/faster_rcnn/label_our_datasets/images/test_1.jpg
1032 # 图片的宽度
795 # 图片的高度
3 # 图片的深度
0
之后就可以进行其他图片的标注了。
key | action |
---|---|
Ctrl + u | 选择一个目录(文件夹)加载其中所有图片 |
Ctrl + r | 更改标注的保存目录 |
Ctrl + s | 保存本次标注 |
Ctrl + d | 复制当前的标注及标注框 |
Ctrl + Shift + d | 删除当前的图片 |
Space | 标记当前图片为验证集 |
w | 创建一个新的矩形框 |
d | 下一张图片 |
a | 上一张图片 |
del | 删除所选的矩形框 |
Ctrl + + |
放大 |
Ctrl + - |
缩放 |
↑→↓← | 微调矩形框 |
在得到自己标注好的数据后,如何得到像VOC 2012那样的train.txt文件呢?
import os
import random
def main():
random.seed(0) # 设置随机种子,保证随机结果可复现
# 给定数据集Annotation的路径
files_path = "./VOCdevkit/VOC2012/Annotations"
assert os.path.exists(files_path), "path: '{}' does not exist.".format(files_path)
# 验证集的比例
val_rate = 0.2 # 因为测试集不公开,训练:验证集=8:2
"""
for file in os.listdir(files_path)
其中os.listdir(files_path)遍历该路径下所有的文件
file就是一个一个文件
file.split(".")[0]
分割字符串并取出文件名
sorted()
排序函数
Note: 列表表达式最后得到肯定是一个list
"""
files_name = sorted([file.split(".")[0] for file in os.listdir(files_path)])
files_num = len(files_name) # 得到文件的数量
"""
random.sample(序列,k=采样个数)
可以简单理解为从某个list中随机采样k个点(且k不会重复)
返回值是一个list
>>> import random
>>> random.sample(range(0, 10), 6)
[8, 3, 7, 0, 6, 2]
random.sample(range(0, files_num), k=int(files_num*val_rate))
从0到files_num-1中随机采样files_num*val_rate个点组成一个list并返回
"""
val_index = random.sample(range(0, files_num), k=int(files_num*val_rate))
train_files = []
val_files = []
# files_name是一个list,list可以被enumerate
for index, file_name in enumerate(files_name):
if index in val_index: # 如果这张图片是采样图片,则放入验证集
val_files.append(file_name)
else:
train_files.append(file_name) # 否则放入训练集
try:
# 'x'用于创建并写入新文件
# \n 表示换行符
train_f = open("train.txt", "x")
eval_f = open("val.txt", "x")
train_f.write("\n".join(train_files))
eval_f.write("\n".join(val_files))
except FileExistsError as e:
print(e)
exit(1)
if __name__ == '__main__':
main()