在自建的数据集上训练yolov3准备(一):按照物体类别(单类&多类)快速准确下载Open Images V4数据集、保存成yolo3标注格式并用yolo_mark验证(附python脚本)。

前言


        Open Images V4是谷歌在2018年开放的一个约900万(9M)图像的数据集,被分成训练集,验证集和测试集三个部分。使用图像级标签(image-level labels),目标边界框(object bounding boxes)和视觉关系(visual relationships)进行注释。图像级标签:有近两万个不同的类具有标签,有些为人工标注,有些为机器标注。目标边界框:含在约191万(1.91M)张图像上的,针对600个类别的约1544万(15.44M)个边界框,这使其成为具有目标位置注释(object location annotations)的最大现有数据集。有分类较精细(比如人相关的就有人头、人脸、胡须、人手等等)、比较贴近生活(从乐器、电脑、书到厨具等等)和边框准确(Google的专业注释人员手动绘制了训练集上90%的方框。其他方法半自动生成剩余的10%。这些框经过人工验证,IoU> 0.7,物体上有一个完美的盒子,实际上它们是准确的(平均IoU~0.82))等特点[1]。该数据集可以将许多计算机视觉任务加速数天甚至数月。例如,如果我们想要为单个或多个对象创建一个对象检测器,我们可以只下载这些类的图像以及它们的注释并开始我们的训练过程。(本文主要针对目标检测数据集下载)

               


准备


  • ubuntu
  • 磁盘
  • python
  • awscli     

结构


    Open Images V4全部数据集约有560G,包括训练集、验证集和测试集。如图所示的库里包括图片文件(.zip)和注释文件(.csv),如下表所示。

                            

    我们先来看看注释文件(.csv),表示其数据格式:

    Class Names:

  • class-descriptions-boxable.csv - 数据集内部使用的类名到人类可理解名称的对应,例如/ m / 011k07对应Tortoise,/ m / 011q46kg对应Container,/ m / 012074对应Magpie等等。
/m/011k07Tortoise 
/m/011q46kgContainer
/m/012074Magpie 
/m/0120dhSea turtle 
/m/01226zFootball 

 

    Boxes:

        这个类型的文件包含表格所示的几项,如下表所示。

ImageIDSourceLabelNameConfidenceXMinXMaxYMinYMaxIsOccludedIsTruncatedIsGroupOfIsDepictionIsInside
000026e7ee790996freeform/m/07j7r10.0719050.1453460.2065910.39130601100
000026e7ee790996freeform/m/07j7r10.4397560.5724660.2641530.43512201100
000026e7ee790996freeform/m/07j7r10.668455100.55282501100
000062a39995e348freeform/m/015p610.2057190.8499120.154144100000
000062a39995e348freeform/m/05s2s10.1371330.37763400.88418511000
0000c64e1253d68ffreeform/m/07yv9100.9738500.04334201100
0000c64e1253d68ffreeform/m/0k4j100.5135340.3213560.68966101000
  • ImageID:这个框所在的图像。可以看到一个ID出现了一次或者多次,应该表示该图像上有多少个边框。
  • Source:表示边框是如何制作的:①freeform并且xclick是手动绘制的框。②activemil是使用方法的增强版本生成的框。
  • LabelName:框所属的对象类的MID,在class-descriptions-boxable.csv中有对应。
  • Confidence:虚拟值,始终为1。
  • XMinXMaxYMinYMax:框的坐标,在标准化图像坐标。XMin在[0,1]中,其中0是最左边的像素,1是图像中最右边的像素。Y坐标从顶部像素0到底部像素1。

   最后的五项表示属性,对于它们中的每一个,值1表示存在、0表示不存在、-1表示未知。

  • IsOccluded:表示对象被图像中的另一个对象遮挡。
  • IsTruncated:表示对象超出图像边界。
  • IsGroupOf:表示该框横跨一组对象(例如,一张鲜花或一群人)。我们要求注释者将这个标签用于超过5个实例的情况,这些情况彼此严重阻塞并且是物理接触的。
  • IsDepiction:表示对象是描绘(例如,对象的卡通或绘图,而不是真实的物理实例)。
  • IsInside:表示从对象内部拍摄的照片(例如,汽车内部或建筑物内部)。
  • test-images.csv:表示测试图像路径。
  • validation-images.csv :表示验证图像路径。
image_nameimage_url         
e0c995e9359596dd.jpghttps://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/validation/e0c995e9359596dd.jpg
110487ec7e9be60a.jpghttps://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/validation/110487ec7e9be60a.jpg
90596bf3313e72e3.jpghttps://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/validation/90596bf3313e72e3.jpg
4b3c6afd44adbe59.jpghttps://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/validation/4b3c6afd44adbe59.jpg
69248ebbbea5aa0c.jpghttps://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/validation/69248ebbbea5aa0c.jpg

        官网上还有关于Image Labels、Visual relationships等的描述,由于没有找到文件,此处就不做展开了。

        由上述可知,直接在官网下载的数据集,是按照训练集、验证集和测试集来打包的。可能有的时候我们不需要那么多数据,或者储存不了那么多数据,又或是我们的任务只是要其中的几类,这时就需要我们按照类别来下载。以目标检测为例,我们知道有边界框的类别有600类,他们的名字列表如下所示。此处要感谢learn OpenCv的作者 SUNITA NAYAK为我们提供了这个表格。篇幅有限,此处只列了前一百个,需要知道全部请访问https://www.learnopencv.com/fast-image-downloader-for-open-images-v4/

classtrainvalidationtest
Person10347211327440861
Wheel3406391139434604
Car248075938128737
Human hair234057859426301
Clothing1438128852726531
Human arm208982834125162
Human head201633786525080
Footwear744474718921205
Human body175244676920246
Man1418594565417514
Human face1037710517015536
Flower345296508915040
Mammal156154434913479
Human nose60142434112718
Human eye77233430413034
Tire122615418113177
Human hand75307412312505
Human leg71479409313334
Sports equipment44900395111992
Plant267913380811579
Tree1051344320910148
Auto part1358628988845
Woman76733728659047
Food8842227368331
Land vehicle8110826898480
Human mouth4419725057424
Girl19715524207479
Vehicle5095921057064
Dog2867519305818
Fruit2623619056215
Window50346716505091
Airplane2128510273272
Fashion accessory9102410263164
Baked goods2301010202907
Building1786349842915
Bird479219432751
Boat791139032672
Human ear177748702611
Bicycle wheel595217332018
Table856917142279
Snack373747082173
Book412806982147
Furniture385276461893
Dessert274076452092
Boy875556002031
Dress529995671581
Fish231955641422
Vehicle registration plate78525121570
Chair1324835111535
Vegetable186214961679
Fast food249914921599
Drink403234821427
Helmet165024401275
Toy709634371205
Bicycle401614031158
Jeans784733961433
Horse133683921144
Cat151833811095
Bottle40188340979
Strawberry7944326774
Cake5784326878
Suit110848321857
Houseplant22834319825
Sports uniform193963151135
Truck12135311969
Rose12053309899
Dairy8146308970
Flowerpot22760302659
Roller skates5476295723
Animal17442290882
Tableware41086285936
Bread3846277911
Ball6845266902
Glasses57946262890
Palm tree42026253620
Paddle6951253699
House136152246822
Seafood3063226689
Sculpture34533221653
Tomato6254216722
Salad3088213605
Insect8981210717
Hat13245201557
Carnivore3501200625
Human foot2237199467
Monkey3026195543
Wine15400193388
Shelf22899191563
Cabinetry9191188451
Aircraft1898186556
Drawer4414184448
Cookie4158184636
Sandal2938181393
Musical instrument16503178525
Orange6195175839
Juice2838174512
Motorcycle13382173530
Lemon1756171425
Cattle11603170450
Door19256165524

        有了这个表格,我们就可以根据自己需要的类别来进行下载,而且还知道此类别的图片数,比如我们要下载human head,那么通过脚本编写我们可以实现这个过程。而这个脚本 SUNITA NAYAK也已经实现好了,直接使用就可以。


下载


  • 安装用于管理AWS服务的统一工具——AWS命令行界面(CLI)
sudo pip3 install awscli
  • 下载boxes和class names的四各.csv文件(推荐直接点前面的链接,然后用迅雷,个人测试这样要快非常多)
wget https://storage.googleapis.com/openimages/2018_04/class-descriptions-boxable.csv
 
wget https://storage.googleapis.com/openimages/2018_04/train/train-annotations-bbox.csv
 
wget https://storage.googleapis.com/openimages/2018_04/validation/validation-annotations-bbox.csv
 
wget https://storage.googleapis.com/openimages/2018_04/test/test-annotations-bbox.csv
  • 将四个文件与脚本放在一个文件夹下,并运行脚本。名字有两个单词的用下划线连接。此处可能会有一个错误,如果发生先

       执行pip3 install tqdm再运行脚本。

python3 downloadOI.py --classes 'Cheese,Ice_cream,Cookie' --mode train

   获取脚本程序downloadOI.py请访问作者github,在次感谢作者

https://github.com/spmallick/learnopencv/blob/master/downloadOpenImages/downloadOI.py

     另外,还可以通过在命令行中将它们显式设置为0来添加可选参数以排除某些类型的图像。

        --occluded = 0      以排除被遮挡的实例。

        --truncated = 0     以排除在边界处截断的实例。

        --groupOf = 0       以排除一起表示一组对象的实例。这些实例通常包括一组5个或更多同一物理接触或遮挡的物体,例如一袋苹果。

        --depiction = 0     以排除草图或漫画的实例,而不是真实物理对象的图片。

        --inside = 0          以排除从对象内部拍摄照片的实例,例如在汽车内部

python3 downloadOI.py --classes 'Cheese,Ice_cream,Cookie' --mode train --groupOf=0 --inside=0

结果


     等........等..........等。已经一下午下了7170个文件,共49308个,估计还要下一天一夜。下载的文件包括此类目标的图片和其对应的txt文件,txt文件里是图片上所有此类目标框的坐标。脚本下载的txt文件默认的格式是class、Xmin、Xmax、Ymin、Ymax。从以下代码中得到体现:

 with open('%s/%s/%s.txt'%(run_mode,class_name,line_parts[0]),'a') as f:  
 f.write(','.join([class_name, line_parts[4], line_parts[5], line_parts[6], line_parts[7] ])+'\n')

 为了适应Yolo的label结构,<object-class> <x_center> <y_center> <width> <height>我们需要做适当改变,在SUNITA NAYAK的另一篇文章中有体现,以下代码需要做适当调整才可使用。见附录

with open('labels/%s.txt'%(lineParts[0]),'a') as f:
f.write(' '.join([str(ind),str((float(lineParts[5]) + float(lineParts[4]))/2), str((float(lineParts[7]) + float(lineParts[6]))/2), str(float(lineParts[5])-float(lineParts[4])),str(float(lineParts[7])-float(lineParts[6]))])+'\n')





 

                                       

        这是txt文件里的信息,妥妥的yolo格式:

        2 0.7209375 0.5066665 0.556875 0.608333
        5 0.146875 0.7058335 0.115 0.401667

        导入yolo_mask标注工具,可以看到下载的标注格式是符合yolo的,成功。

         


参考


https://storage.googleapis.com/openimages/web/factsfigures.html

https://www.learnopencv.com/fast-image-downloader-for-open-images-v4/

https://www.learnopencv.com/training-yolov3-deep-learning-based-custom-object-detector/

https://blog.csdn.net/wulala789/article/details/80646618


附录(代码为引用、并修改)


#Author : Sunita Nayak, Big Vision LLC

#### Usage example: python3 downloadOI.py --classes 'Ice_cream,Cookie' --mode train

import argparse
import csv
import subprocess
import os
from tqdm import tqdm
import multiprocessing
from multiprocessing import Pool as thread_pool

cpu_count = multiprocessing.cpu_count()

parser = argparse.ArgumentParser(description='Download Class specific images from OpenImagesV4')
parser.add_argument("--mode", help="Dataset category - train, validation or test", required=True)
parser.add_argument("--classes", help="Names of object classes to be downloaded", required=True)
parser.add_argument("--nthreads", help="Number of threads to use", required=False, type=int, default=cpu_count*2)
parser.add_argument("--occluded", help="Include occluded images", required=False, type=int, default=1)
parser.add_argument("--truncated", help="Include truncated images", required=False, type=int, default=1)
parser.add_argument("--groupOf", help="Include groupOf images", required=False, type=int, default=1)
parser.add_argument("--depiction", help="Include depiction images", required=False, type=int, default=1)
parser.add_argument("--inside", help="Include inside images", required=False, type=int, default=1)

args = parser.parse_args()

run_mode = args.mode

threads = args.nthreads

classes = []
for class_name in args.classes.split(','):
    classes.append(class_name)

with open('./class-descriptions-boxable.csv', mode='r') as infile:
    reader = csv.reader(infile)
    dict_list = {rows[1]:rows[0] for rows in reader}

subprocess.run(['rm', '-rf', 'labels'])
subprocess.run([ 'mkdir', 'labels'])

subprocess.run(['rm', '-rf', 'JPEGImages'])
subprocess.run([ 'mkdir', 'JPEGImages'])

pool = thread_pool(threads)
commands = []
cnt = 0

for ind in range(0, len(classes)):
    
    class_name = classes[ind]
    print("Class "+str(ind) + " : " + class_name)
    
    subprocess.run([ 'mkdir', run_mode+'/'+class_name])

    command = "grep "+dict_list[class_name.replace('_', ' ')] + " ./" + run_mode + "-annotations-bbox.csv"
    class_annotations = subprocess.run(command.split(), stdout=subprocess.PIPE).stdout.decode('utf-8')
    class_annotations = class_annotations.splitlines()

    for line in class_annotations:

        line_parts = line.split(',')
        
        #IsOccluded,IsTruncated,IsGroupOf,IsDepiction,IsInside
        if (args.occluded==0 and int(line_parts[8])>0):
            print("Skipped %s",line_parts[0])
            continue
        if (args.truncated==0 and int(line_parts[9])>0):
            print("Skipped %s",line_parts[0])
            continue
        if (args.groupOf==0 and int(line_parts[10])>0):
            print("Skipped %s",line_parts[0])
            continue
        if (args.depiction==0 and int(line_parts[11])>0):
            print("Skipped %s",line_parts[0])
            continue
        if (args.inside==0 and int(line_parts[12])>0):
            print("Skipped %s",line_parts[0])
            continue

        cnt = cnt + 1

        command = 'aws s3 --no-sign-request --only-show-errors cp s3://open-images-dataset/'+run_mode+'/'+line_parts[0]+'.jpg '+ 'JPEGImages'+'/'+class_name+'/'+line_parts[0]+'.jpg'
        commands.append(command)
        

        with open('labels/%s.txt'%(line_parts[0]),'a') as f:
            f.write(' '.join([str(ind), str((float(line_parts[5]) + float(line_parts[4]))/2), str((float(line_parts[7]) + float(line_parts[6]))/2), str(float(line_parts[5])-float(line_parts[4])), str(float(line_parts[7])-float(line_parts[6]))])+'\n')

print("Annotation Count : "+str(cnt))
commands = list(set(commands))
print("Number of images to be downloaded : "+str(len(commands)))

list(tqdm(pool.imap(os.system, commands), total = len(commands) ))

pool.close()
pool.join()	

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值