结合代码分析FasterRCNN的训练数据blob准备过程

本文通过分析tf版本的Faster R-CNN代码,详细解释了训练过程中数据blob的创建步骤。从train_val.py开始,经过layer.py的RoIDataLayer类,再到minibatch.py,最终展示了如何使用opencv的resize函数进行图像放缩并利用线性插值填充。prep_im_for_blob()函数是处理每张图片的关键,将图片转换为适合网络输入的blob格式。
摘要由CSDN通过智能技术生成

采用tf版本Faster:代码如下

https://github.com/endernewton/tf-faster-rcnn

代码结构:

先给总结:

输入流入脚本的顺序:train_val.py---->layer.py---->minibatch.py

--------------------

下面是具体的每一步处理

-------------------

 

以训练为例:在lib/model/train_val.py里有如下代码:

from roi_data_layer.layer import RoIDataLayer
......
def train_model(self, sess, max_iters):#训练模型
......
  self.data_layer = RoIDataLayer(self.roidb, self.imdb.num_classes)
......
  blobs = self.data_layer.forward()
......

调用了RoIDataLayer类,RoIDataLayer实际写在roi_data_layer文件夹里的.layer.py里面。

在layer,py所定义的RoIDataLayer类里面,定义了如下一个类方法:

  def forward(self):
    """Get blobs and copy them into this layer's top blob vector."""
    blobs = self._get_next_minibatch()
    return blobs

这个forward(self)类方法又调用了RoIDataLayer的_get_next_minibatch()类方法,它代码如下:

db_inds = self._get_next_minibatch_inds()
    minibatch_db = [self._roidb[i] for i in db_inds] 
    return get_minibatch(minibatch_db, self._num_classes)

_get_next_minibatch()实际调用了roi_data_layer文件夹里的minibatch.py文件,在minibatch.py里调用的具体代码如下:

def get_minibatch(roidb, num_classes):
  """Given a roidb, construct a minibatch sampled from it."""
  im_blob, im_scales = _get_image_blob(roidb, random_scale_inds)
 ......省略

  return blobs

这个函数的的功能是给定图像数据,构建一个blob数据块。就是把数据堆叠在一起。具体实现不全是在这,调用了minibatch.py里的另一个函数,_get_image_blob(),代码很短,如下:

def _get_image_blob(roidb, scale_inds):#组合roi的Blob。
  """Builds an input blob from the images in the roidb at the specified
  scales.
  """
  num_images = len(roidb)
  processed_ims = []
  im_scales = []
  for i in range(num_images):
    im = cv2.imread(roidb[i]['image'])#opencv读入图像的顺序是BGR
    if roidb[i]['flipped']:#如果flipped打开了,对图像进行翻转
      im = im[:, ::-1, :]
    target_size = cfg.TRAIN.SCALES[scale_inds[i]]
    im, im_scale = prep_im_for_blob(im, cfg.PIXEL_MEANS, target_size,
                    cfg.TRAIN.MAX_SIZE)#处理图片
    im_scales.append(im_scale)
    processed_ims.append(im)#往仓库丢入处理好的图片

  # Create a blob to hold the input images
  blob = im_list_to_blob(processed_ims)#把处理好的图片堆叠为blob

  return blob, im_scales

功能是对每一章图片进行处理,不断的堆叠处理好的数据,得到blob,同时记录每一张输入图片被放缩的大小im_scale(组成im_scales)

具体实现调用了:prep_im_for_blob()以及im_list_to_blob()

后者的代码很简单,张开一个Blob多维数据结构,把处理好的图片一张张丢进去,代码如下:

def im_list_to_blob(ims):
  """Convert a list of images into a network input.
  将一组图像转换为网络输入
  Assumes images are already prepared (means subtracted, BGR order, ...).
  假设图像原料已经准备好:已经取均值、已经转换为BGR结构
  """
  #首先一个简短的循环,计算出来图像的最大长宽,作为Blob长宽
  max_shape = np.array([im.shape for im in ims]).max(axis=0)
  num_images = len(ims)#计算blob高
  blob = np.zeros((num_images, max_shape[0], max_shape[1], 3),#按计算出来的长宽高生成数据
                  dtype=np.float32)
	#把每一张图像丢进去
  for i in range(num_images):
    im = ims[i]
    blob[i, 0:im.shape[0], 0:im.shape[1], :] = im

  return blob

解析得很清楚了。

主要的最底层的对每一张图片的处理,主要还是prep_im_for_blob()

代码如下:

def prep_im_for_blob(im, pixel_means, target_size, max_size):
  """Mean subtract and scale an image for use in a blob."""
  im = im.astype(np.float32, copy=False)
  im -= pixel_means#去平均
  im_shape = im.shape#求形状
  im_size_min = np.min(im_shape[0:2])#求最小边
  im_size_max = np.max(im_shape[0:2])#求最大边
  im_scale = float(target_size) / float(im_size_min)#求最小边长参数/最小边
  # Prevent the biggest axis from being more than MAX_SIZE
  if np.round(im_scale * im_size_max) > max_size:
    im_scale = float(max_size) / float(im_size_max)
  im = cv2.resize(im, None, None, fx=im_scale, fy=im_scale,
                  interpolation=cv2.INTER_LINEAR)
  #说白了上面就是在求原图到输入的缩放比例。
  return im, im_scale

这是最底层的实现部分。对应的原理在前段时间写的原理前部分有说明,连接如下:

https://blog.csdn.net/gusui7202/article/details/84556740

问题:问题在于cv2对小图放大的时候,是怎么填充取值的?

放缩用的是opencv 的resize函数,采用的是线性插值。线性插值的原理如下:

------------

2018.12.6-18:00

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值