py-faster-rcnn中demo.py代码与C++版本的代码对比: part05 Reshape

这里”C++版本的代码”是指: https://github.com/galian123/cpp_faster_rcnn_detect .

py-faster-rcnn中demo.py代码, 是指 https://github.com/rbgirshick/py-faster-rcnn/blob/master/tools/demo.py 以及
https://github.com/rbgirshick/py-faster-rcnn/tree/master/lib 目录下的一些代码.

涉及到的.py文件都是 https://github.com/rbgirshick/py-faster-rcnn/ 中的.

★ Reshape

♦ python代码

回到 py-faster-rcnn/lib/fast_rcnn/test.py, 继续分析_get_blobs()之后的代码.

demo.py 中对cfg.TEST.HAS_RPN设置了True.

def im_detect(net, im, boxes=None):
    blobs, im_scales = _get_blobs(im, boxes)
    # 由上面的代码,可以知道blobs中的'data'是image的blob, 是4维数组,
    # 维度的含义是(1, 3, 高, 宽)

    if cfg.TEST.HAS_RPN: # 执行这里
        im_blob = blobs['data']
        # 创建一个新的3维数组, 维度含义为(高, 宽, 缩放倍率)
        blobs['im_info'] = np.array(
            [[im_blob.shape[2], im_blob.shape[3], im_scales[0]]],
            dtype=np.float32)
    # reshape network inputs
    net.blobs['data'].reshape(*(blobs['data'].shape))  # 见"解释1", "解释2", "解释3"
    if cfg.TEST.HAS_RPN:
        net.blobs['im_info'].reshape(*(blobs['im_info'].shape))
    else:
        net.blobs['rois'].reshape(*(blobs['rois'].shape))
  • 解释1: net.blobs['data']的含义.

从前面的分析可知, net是Net类的实例. Net类是由boost.python定义的. 并且定义了两个属性: _blobs_blob_names. _blobs用来存储图片数据, _blob_names用来存储blob的名字,例如data, im_info, cls_prob等.
py-faster-rcnn/caffe-fast-rcnn/python/caffe/_caffe.cpp

  bp::class_<Net<Dtype>, shared_ptr<Net<Dtype> >, boost::noncopyable >("Net",
    bp::no_init)
    .def("__init__", bp::make_constructor(&Net_Init_Load))
    .add_property("_blobs", bp::make_function(&Net<Dtype>::blobs,
        bp::return_internal_reference<>()))
    .add_property("_blob_names", bp::make_function(&Net<Dtype>::blob_names,
        bp::return_value_policy<bp::copy_const_reference>()))

py-faster-rcnn/caffe-fast-rcnn/include/caffe/net.hpp

  inline const vector<string>& blob_names() const { return blob_names_; }
  inline const vector<shared_ptr<Blob<Dtype> > >& blobs() const {
    return blobs_;
  }
  vector<shared_ptr<Blob<Dtype> > > blobs_;
  vector<string> blob_names_;

Net是从 py-faster-rcnn/caffe-fast-rcnn/python/caffe/pycaffe.py 导出的,
pycaffe.py中对Net附加了一些方法(只列举部分):

Net.blobs = _Net_blobs
Net.blob_loss_weights = _Net_blob_loss_weights
Net.layer_dict = _Net_layer_dict
Net.params = _Net_params
Net.forward = _Net_forward
Net.backward = _Net_backward

Net.blobs = _Net_blobs中的_Net_blobs:

@property
def _Net_blobs(self):
    """
    An OrderedDict (bottom to top, i.e., input to output) of network
    blobs indexed by name
    """
    if not hasattr(self, '_blobs_dict'):
        self._blobs_dict = OrderedDict(zip(self._blob_names, self._blobs))
    return self._blobs_dict

所以, 使用net.blobs['data']时, 是对self._blobs_dict中的key为’data’的项(blob)赋值,
字符串’data’(key)传给了self._blob_names, 值传给了self._blobs.

  • 查看Net.blobs的信息:
>>> from caffe._caffe import Net
>>> help(Net.blobs)

Help on property:
    An OrderedDict (bottom to top, i.e., input to output) of network
    blobs indexed by name
  • net.blobs['data']的类型与 Blob<Dtype>是对应的.
>>> import caffe
>>> from caffe import Net
>>> 
>>> model = './output/faster_rcnn_end2end/voc_2007_trainval/vgg_cnn_m_1024_faster_rcnn_iter_70000.caffemodel'
>>> prototxt = 'models/pascal_voc/VGG_CNN_M_1024/faster_rcnn_end2end/test.prototxt'
>>> net = caffe.Net(prototxt, model, caffe.TEST)

>>> net.blobs['data']
<caffe._caffe.Blob object at 0x7f2511828b90>
  • 打印net.blobs
net.blobs:  OrderedDict([('data', <caffe._caffe.Blob object at 0x7fcacce06938>), ('im_info', <caffe._caffe.Blob object at 0x7fcacce069b0>), ('conv1', <caffe._caffe.Blob object at 0x7fcacce06a28>), ('norm1', <caffe._caffe.Blob object at 0x7fcacce06aa0>), ('pool1', <caffe._caffe.Blob object at 0x7fcacce06b18>), ('conv2', <caffe._caffe.Blob object at 0x7fcacce06b90>), ('norm2', <caffe._caffe.Blob object at 0x7fcacce06c08>), ('pool2', <caffe._caffe.Blob object at 0x7fcacce06c80>), ('conv3', <caffe._caffe.Blob object at 0x7fcacce06cf8>), ('conv4', <caffe._caffe.Blob object at 0x7fcacce06d70>), ('conv5', <caffe._caffe.Blob object at 0x7fcacce06de8>), ('conv5_relu5_0_split_0', <caffe._caffe.Blob object at 0x7fcacce06e60>), ('conv5_relu5_0_split_1', <caffe._caffe.Blob object at 0x7fcacce06ed8>), ('rpn/output', <caffe._caffe.Blob object at 0x7fcacce06f50>), ('rpn/output_rpn_relu/3x3_0_split_0', <caffe._caffe.Blob object at 0x7fcacce14050>), ('rpn/output_rpn_relu/3x3_0_split_1', <caffe._caffe.Blob object at 0x7fcacce140c8>), ('rpn_cls_score', <caffe._caffe.Blob object at 0x7fcacce14140>), ('rpn_bbox_pred', <caffe._caffe.Blob object at 0x7fcacce141b8>), ('rpn_cls_score_reshape', <caffe._caffe.Blob object at 0x7fcacce14230>), ('rpn_cls_prob', <caffe._caffe.Blob object at 0x7fcacce142a8>), ('rpn_cls_prob_reshape', <caffe._caffe.Blob object at 0x7fcacce14320>), ('rois', <caffe._caffe.Blob object at 0x7fcacce14398>), ('pool5', <caffe._caffe.Blob object at 0x7fcacce14410>), ('fc6', <caffe._caffe.Blob object at 0x7fcacce14488>), ('fc7', <caffe._caffe.Blob object at 0x7fcacce14500>), ('fc7_drop7_0_split_0', <caffe._caffe.Blob object at 0x7fcacce14578>), ('fc7_drop7_0_split_1', <caffe._caffe.Blob object at 0x7fcacce145f0>), ('cls_score', <caffe._caffe.Blob object at 0x7fcacce14668>), ('bbox_pred', <caffe._caffe.Blob object at 0x7fcacce146e0>), ('cls_prob', <caffe._caffe.Blob object at 0x7fcacce14758>)])
  • 解释2: net.blobs['data'].reshape(*(blobs['data'].shape))中星号 * 的含义
    举个例子:
>>> import numpy as np
>>> a = np.array([[[1], [2], [3]]])
>>> a
array([[[1],
        [2],
        [3]]])
>>> a.shape
(1, 3, 1)

>>> def f(a, b, c):
...     print a, b, c
... 
>>> f(*a.shape)
1 3 1

在函数参数中的星号, 可以使传入的元组转换成位置参数, 例如上面的例子中a.shape是(1,3,1), 不能通过f(a.shape)的方式传入(1,3,1), 需要星号的形式:f(*a.shape).

python帮助文档中的解释:

If the syntax *expression appears in the function call, expression must evaluate to an iterable. Elements from this iterable are treated as if they were additional positional arguments; if there are positional arguments x1, …, xN, and expression evaluates to a sequence y1, …, yM, this is equivalent to a call with M+N positional arguments x1, …, xN, y1, …, yM.

A consequence of this is that although the *expression syntax may appear after some keyword arguments, it is processed before the keyword arguments (and the **expression argument, if any – see below). So:

>>> def f(a, b):
...  print a, b
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2

It is unusual for both keyword arguments and the *expression syntax to be used in the same call, so in practice this confusion does not arise.

  • 解释3: net.blobs['data'].reshape()执行的是哪个函数?

由”解释1”可知, net.blobs['data']的类型为caffe._caffe.Blob对象.
所以, net.blobs['data'].reshape()执行的是caffe._caffe.Blob的函数.
caffe._caffe.Blob是caffe包(py-faster-rcnn/caffe-fast-rcnn/python/caffe目录)下的_caffe.so中实现的Blob:

 bp::class_<Blob<Dtype>, shared_ptr<Blob<Dtype> >, boost::noncopyable>(
    "Blob", bp::no_init)
    .def("reshape",           bp::raw_function(&Blob_Reshape))

net.blobs['data'].reshape()最终调用是Blob_Reshape().

Blob_Reshape()是在py-faster-rcnn/caffe-fast-rcnn/python/caffe/_caffe.cpp中.

bp::object Blob_Reshape(bp::tuple args, bp::dict kwargs) {
  if (bp::len(kwargs) > 0) {
    throw std::runtime_error("Blob.reshape takes no kwargs");
  }
  // args的内容是(blob对象地址, 1,3,高,宽), 其中(1, 3,高,宽)是一个blob的4个维度值
  Blob<Dtype>* self = bp::extract<Blob<Dtype>*>(args[0]);
  vector<int> shape(bp::len(args) - 1);
  for (int i = 1; i < bp::len(args); ++i) {// 取出(1,3,高,宽)
    shape[i - 1] = bp::extract<int>(args[i]);
  }
  self->Reshape(shape);
  // We need to explicitly return None to use bp::raw_function.
  return bp::object();
}

♦ C++代码

    net_->blob_by_name("data")->Reshape(1, 3, height, width);
    net_->Reshape();

————– 分割线 ————–
本系列文章如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值