SSD数据增强中的batch_sampler方法

  接上一篇博文,SSD在数据增广这一块儿做了相当多的工作,继图像变换和裁剪,接下来是对图像进行bounding box的采样,所谓的采样,即代码中的Sampler,其主要流程是根据prototxt中的每个batch_sampler中的条件分别对每张图片的样本框进行采样。现在我们来一步步分析代码。首先是void GenerateBatchSamples(const AnnotatedDatum& anno_datum, const vector<BatchSampler>& batch_samplers, vector<NormalizedBBox>* sampled_bboxes)函数,其输入为expand_datum的指针,batch_samplers_参数,输出为vector<NormalizedBBox> sampled_bboxes,先贴出该函数的代码:

在上述代码中,第一个 GroupObjectBBoxes函数是将输入的anno_datum(即某张图片)中的NormalizedBBox(label)全部存入object_bboxes中,对于每一个batch_sampler,先构造一个单位bounding box,名为unit_bbox,将unit_bbox,object_bboxes以及batch_samplers[i]同时传入GenerateSamples函数中,旨在输出在该batch_samplers[i]约束下的该张图片的采样先验框sampled_bboxes。

在GenerateSamples函数中,batch_sampler.max_trials()表示找寻找满足约束的框的最大尝试次数,当所采样的先验框数量大于batch_sampler.max_sample()的时候,停止采样。具体的采样过程在SampleBBox函数中执行,在这个函数中,首先产生一个介于sampler.min_scale()到 sampler.max_scale()之间的随机数scale,scale表示采样框的面积尺度,同时还需要产生一个sampler.min_aspect_ratio()到 sampler.max_aspect_ratio()之间的随机数aspect_ratio,这个数表示随机框长宽的比例尺度,根据这两个随机数,可以确定采样先验框的形状。w_off, h_off这两个随机数描述采样框的左上顶点(在图像上),他们的取值范围都是0到1(归一化了),这样就可以确定图像上的一个采样框,该采样框的坐标相对于unit_bbox。

在源码中作者还写了一个LocateBBox函数,其实src_bbox已经是单位化了,所以这个函数没有太多必要,主要是将采样的框归一化到src_bbox范围中来。接下来就是SatisfySampleConstraint函数,这个函数是为了验证我们所随机采样的sampled_bbox是否满足预设条件,在SatisfySampleConstraint中,又会根据batch_sampler中的sample_constraint参数确定使用哪一种检查条件,ssd中预设为min_jaccard_overlap和max_jaccard_overlap,即sample_constraint与label值的重合度,应用的策略是has_jaccard_overlap评价方式是IOU,保证采样的sampled_bbox与某个label box的IOU在min_jaccard_overlap与max_jaccard_overlap之间,具体函数

如果该采样框满足条件,即找到某个与之交并比满足约束的先验框(label box),则found++,源码参数设置的max_sample为1,即在该batch_sampler条件下,只需要找到一个满足条件的sample_box,即针对每张图片,我们需要找到batch_sampler.size()这么多个sample_box,并且把这些sample_box push到sampled_bboxes这个vector<NormalizedBBox>中,然后从这些sample_box中随机抽取一个进行Crop,即把原图像按照这个sample_box裁剪,存储到sampled_datum中,最后就是通过this->data_transformer_->Transform(sampled_datum->datum(),  &(this->transformed_data_))将sampled_datum存储到transformed_data_中,这个Transform函数将根据参数文件,选择对图像去均值,scale,crop裁剪,是否镜像处理,源码如下,如果在参数文件中有has_anno_type_这个参数,则在Transform中会稍有不一样,除了将sampled_datum存储到transformed_data_中以外,还会存储该sampled_datum这个数据的AnnotationGroup

这里的transformed_data_通过this->transformed_data_.set_cpu_data(top_data + offset);与top_data相关联,Dtype* top_data = batch->data_.mutable_cpu_data();即与batch->data_相关联。在batch_load函数的最后一部分是添加sample_bbox的AnnotationGroup,添加到top_label中,即batch->label_中。

最后,不是很理解,resize在哪里做的,因为resize参数的模式和代码中的不一样。研究了再改


针对之前留下的问题,再次调试代码,发现resize是在load_batch中的以下代码中实现的

由于在DataLayerSetUp函数中,    has_anno_type_ = anno_datum.has_type() || anno_data_param.has_anno_type();该处的has_anno_type_为true,所以执行了以上部分的代码,之前理解有误,之后会调用到这段代码:

可以看到TransformAnnotation中的do_resize为true,即在这里面做出了resize操作,把图片都resize到300*300或者500*500,但是为什么只能是这两个大小呢,还不是很明白,继续看代码

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值