目标检测学习 「======」 1

1. Kaggle目标检测第一名的一篇论文:Large-scale Landmark Retrieval/Recognition under a Noisy and Diverse Dataset论文地址

摘要:这篇论文篇幅比较短,主要描述了在这个比赛中的如何处理数据、建立模型、模型融合。

2. SSD目标检测代码学习

摘要:SSD的tensorflow代码实现在网上还是很多的,大同小异,选择了其中一个处在我这个阶段的新手能够看懂的tensorflow-SSD,但又能提升tensorflow能力的一份代码,就开始死抠吧。

  • 我目前的代码能力就是能够自己实现一个非模块化的CNN模型,并且知道其中每个部件的作用,但是目前盛行的slim,这种集成的模块就不太会使用,所以借此学习一下slim模块的用法;
  • 将代码中有关数据读取处理的复制下来,使用slim读取TFRecords文件;
# step1: dataset = slim.data.Data(data_sources, reader, decoder, num_samples, items_to_descriptions)
#是对一个数据集的定义,数据读取需要数据源所在的位置、阅读器、解码器. 逻辑上含有数据,实际没有
dataset = dataset_factory.get_dataset(FLAGS.dataset_name, FLAGS.dataset_split_name, FLAGS.dataset_dir)

# step2: 接下来通过datasetdataprovider可以congprovider中一条条的读取数据: 
# slim.dataset_data_provider(dataset, num_readers, reader_kwargs阅读器关键配置字典, shuffle, 
# num_epochs(每个数据源被读取的次数), common_queue_capacity,  common_queue_min,(读取数据队列的容量、最小容量)
provider = slim.dataset_data_provider.DatasetDataProvider(
                    dataset,
                    num_readers=FLAGS.num_readers,
                    common_queue_capacity=20 * FLAGS.batch_size,
                    common_queue_min=10 * FLAGS.batch_size,
                    shuffle=True)
            
# step3: provider.get()按照标签获取数,并对数据进行预处理
[image, shape, glabels, gbboxes] = provider.get(['image', 'shape',
                                                             'object/label',
                                                             'object/bbox'])
# step4: tf.train.batch(),从provider()中get()到的数据建立batch
 r = tf.train.batch(
                tf_utils.reshape_list([image, gclasses, glocalisations, gscores]),
                batch_size=FLAGS.batch_size,
                num_threads=FLAGS.num_preprocessing_threads,
                capacity=5 * FLAGS.batch_size)             
# step5: 建立prefetch_queue,然后可以使用batch_deque进行接下来的操作
batch_queue = slim.prefetch_queue.prefetch_queue(
                tf_utils.reshape_list([b_image, b_gclasses, b_glocalisations, b_gscores]),
                capacity=2 * deploy_config.num_clones)                  
  • 在网上看了很多SSD结构和论文的剖析,但只纸上谈兵的话有些抽象,因此看tensorflow代码理解,SSD主要结构是VGG,不过将后面的全连接层改成了卷积层。这部分代码需要理解的就是如何生成的predictions,localisations。
# 基于VGG16的SSD模型,使用了feat_layers相应卷积输出作为feature map,不同特征图设置的先验框的
# 数目不同,先验框的设置有大小和长宽比,其大小在论文中给出了计算公式,也有几个常用的长宽比
# feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11']
# 
predictions = []
logits = []
localisations = []
for i, layer in enumerate(feat_layers):
    with tf.variable_scope(layer + '_box'):
         p, l = ssd_multibox_layer(end_points[layer],
                                                 num_classes,
                                                 anchor_sizes[i],
                                                 anchor_ratios[i],
                                                 normalizations[i])
    predictions.append(prediction_fn(p))
    logits.append(p)
    localisations.append(l)
# 函数ssd_multibox_layer()是在feature map上进行卷积后得到最后的分类结果以及矩形框的location
  • 微修代码跑通链接里的demo:首先是下载2007VOC数据集,代码包中有pascalvoc_to_tfrecords.py文件,将py文件里面的数据存放地址等信息修改一下后运行,就能够得到数据的TFrecords文件,然后再修改train_ssd_network.py文件运行;
# tf.ConfigProto()的主要作用是配置tf.Session()的运算方式
config = tf.ConfigProto()
# log_device_placement=True,能够获取到operations和tensor能够被分派到哪个设备上运行
# allow_soft_placement=True允许TF选择任何一个存在且可用的设备来运行操作
# tf提供两种限制GPU资源使用的方法:
(1) config.gpu_options.allow_growth = True,需要多少申请多少
(2) config.gpu_options.per_process_gpu_memory_fraction = 0.4,限制GPU的使用率
slim.learning.train(train_op, # 一个‘Tensor’,被执行时更新梯度并返回损失值
          logdir,  # 将训练过程文件写入logdir
          train_step_fn = train_step, # 
          train_step_kwargs=_USE_DEFAULT,
          log_every_n_steps=1,
          graph=None,
          master='',
          is_chief=True, # 是否在主要副本上运行training
          global_step=None,
          number_of_steps=None, # 当训练global_step大于这个值时,停止训练
          init_op=_USE_DEFAULT, 
          init_feed_dict=None, 
          local_init_op=_USE_DEFAULT, 
          init_fn=None,
          ready_op=_USE_DEFAULT,
          summary_op=_USE_DEFAULT,
          save_summaries_secs=600,
          summary_writer=_USE_DEFAULT,
          startup_delay_steps=0,
          saver=None,
          save_interval_secs=600,
          sync_optimizer=None,
          session_config=None,
          session_wrapper=None,
          trace_every_n_steps=None,
          ignore_live_threads=False)

3. 图像分割

摘要: 当发现目标检测可能完成我的任务后,有小伙伴建议说可以尝试图像分割的方法。对图像分割依旧了解不多,所以就看看博客论文等学习一下。

3.1 Some Tricks

  • 图像分割是像素级别的判断,预测图像中的每一个像素所属的类别或物体。第一篇成功进行图像分割的算法是FCN(基础网络:VGG):将全连接层换成卷积层,再经过上采样后的得到原图大小的图像,相当于在原图的每个像素上做了一个分类。

  • 上采样层:反卷积Deconvolution(Transposed Convolution),卷积可以看作是矩阵相乘,虽然是反卷积但不是矩阵求逆。
    反卷积的教程
    卷积与反卷积 - 双线性插值上采样,实现feature map的扩大,作用:用于初始化反卷积的权重;不用反卷积,使用上采样+卷积;只使用上采样。(后两种用的比较多)

  • Dilated Convolution(带洞卷积or膨胀卷积)

  • Feature Pyramid(特征金字塔):将小的特征图上采样后与大一点的特征图merge在一起,这样的特征金字塔既有全局信息,也有局部信息。
    特征金字塔

  • Pyramid Pooling: 原图经过CNN卷积之后,经过不同的池化层。
    Pyramid Pooling

3.2 Mask-RCNN

  • Contributions:(1)多分支输出:同时输出了物体的bounding box, 类别和mask;(2)Binary Mask: class bounding box可以输出类别,只用binary mask判断物体在不在就可以;(3)RIOAlign
  • Multi-Target Loss包括三个问题:对ROI用FCN。
  • Binary Mask: 多类mask:softmax;二分类mask:sigmoid;
  • Roi Align:使用附近像素进行线性插值
  • RoI Pooling:图片物体对应到特征图上对应位置,可能导致物体有一定的偏移,在detection中可以使用,但在图像分割的时候有些不准确。

3.3 BiSeNet语义分割网络

摘要: 看到较多使用BiSeNet网络的语义分割模型,所以来看一下BiSeNet模型的原理等相关内容,文章链接BiSeNet.BiSeNet结构

  • BiSeNet模型设计了Spatial Path和Context Path模块,Spatial Path通过三层卷积层,得到的特征图尺寸依旧很大;Context Path利用轻量级模型和全局池化,将原图从较高的分辨率,迅速下降。我的理解是前者保留了很多平面信息和细节,而后者将图片缩小后保留了主体信息,两者都各有优劣,合并起来给模型充足信息的同时计算量等也不是很大

后记

  • 这篇博客是根据我这几天学习的路径来记录的,还有一些细节希望通过反复看博客能够琢磨出来,我的目标检测任务还没完成,所以后面会继续完善这篇blog;
  • 新晋的CV算法小白,还有很多需要锻炼和学习,如果有想一起交流或指导的可以加V哦
  • lqn935604656
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值