Py Faster-RCNN 下lib/datasets中的factory.py文件主要是通过数据库名字获得图像数据。刚开始看的时候觉得写的有些乱,不过我觉得作者程序结构组织上确实有些不必要的东西,初始化的东西相对固定应该放在一个文件中一次性写好还是比较好的,中间就不要在初始化了,直接变量,不过还没完全看懂作者的程序,也许这样做是很好的,可能是我和rbg大牛编程风格不一样吧,下面还是说说我在看这个程序时遇到的一些问题并做一些记录和梳理。
首先贴一份原始的factory.py代码:
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
"""Factory method for easily getting imdbs by name."""
__sets = {}
from datasets.pascal_voc import pascal_voc
from datasets.coco import coco
import numpy as np
# Set up voc_<year>_<split> using selective search "fast" mode
for year in ['2007', '2012']:
#print 'come Voc'
for split in ['train', 'val', 'trainval', 'test']:
name = 'voc_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: pascal_voc(split, year))
# Set up coco_2014_<split>
for year in ['2014']:
#print 'come Other1'
for split in ['train', 'val', 'minival', 'valminusminival']:
name = 'coco_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: coco(split, year))
# Set up coco_2015_<split>
for year in ['2015']:
#print 'come Other2'
for split in ['test', 'test-dev']:
name = 'coco_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: coco(split, year))
def get_imdb(name): #fab_2017_trainval_defect
"""Get an imdb (image database) by name."""
##print '111111111111111111111 factory get_imdb 11111111111111111111111'
#print name
if not __sets.has_key(name):
raise KeyError('Unknown dataset: {}'.format(name))
return __sets[name]()
def list_imdbs():
"""List all registered imdbs."""
return __sets.keys()
我遇到的问题有这几个:
1、factory.py 在训练主程序train_faster_rcnn_alt.py中是这样被引入的:from datasets.factory import get_imdb
而get_imdb是在train_faster_rcnn_alt.py中的这个函数:
def get_roidb(imdb_name, rpn_file=None):
imdb = get_imdb(imdb_name)## is pascal_voc object instance
#print type(imdb)
#print 'Loaded dataset `{:s}` for training'.format(imdb.name)
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD) ##'selective_search'
print 'Set proposal method: {:s}'.format(cfg.TRAIN.PROPOSAL_METHOD)
if rpn_file is not None:
imdb.config['rpn_file'] = rpn_file
roidb = get_training_roidb(imdb)
return roidb, imdb
中的第一行被调用,它想直接去获取__sets[name](),那么__sets在哪里初始化了呀,后来才发现在运行train_faster_rcnn_alt.py后factory.py代码中的这些代码:
# Set up voc_<year>_<split> using selective search "fast" mode
for year in ['2007', '2012']:
#print 'come Voc'
for split in ['train', 'val', 'trainval', 'test']:
name = 'voc_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: pascal_voc(split, year))
其实已经运行过了,不信可以加个log记录试试。
2、__sets[name] 存放的是啥,get_imdb返回的是啥,为了弄清这些我做了一个小测试:
PyTempTest2.py代码清单:
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
"""Factory method for easily getting imdbs by name."""
__sets = {}
import numpy as np
class pascal_voc(object):
def __init__(self,split,year):
self.__Str=split+str(year)
def PrintStr(self):
print self.__Str
# Set up voc_<year>_<split> using selective search "fast" mode
for year in ['2007', '2012']:
for split in ['train', 'val', 'trainval', 'test']:
name = 'voc_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: pascal_voc(split, year))
c=pascal_voc('Test',2001)
print 'type(pascal_voc(Test,2001)) is:',
print type(c)
def get_imdb(name): #fab_2017_trainval_defect
"""Get an imdb (image database) by name."""
print '111111111111111111111 factory--get_imdb 11111111111111111111111'
print 'All _sets='+str(__sets)
print '_sets values type is:',
print type(__sets.values()[0])
return __sets[name]()
def list_imdbs():
"""List all registered imdbs."""
return __sets.keys()
PyTempTest3.py代码清单:
from PyTempTest2 import get_imdb
FileName='voc_2007_train'
Imdb=get_imdb(FileName)
print 'Imdb type is :',
print type(Imdb)
print 'Imdb.PrintStr()=',
Imdb.PrintStr()
运行PyTempTest3.py得到如下结果:
type(pascal_voc(Test,2001)) is: <class 'PyTempTest2.pascal_voc'>
111111111111111111111 factory--get_imdb 11111111111111111111111
All _sets={'voc_2012_trainval': <function <lambda> at 0x7fa553136f50>, 'voc_2012_train': <function <lambda> at 0x7fa553136e60>, 'voc_2007_train': <function <lambda> at 0x7fa553136b90>, 'voc_2007_test': <function <lambda> at 0x7fa553136de8>, 'voc_2012_test': <function <lambda> at 0x7fa553138050>, 'voc_2012_val': <function <lambda> at 0x7fa553136ed8>, 'voc_2007_trainval': <function <lambda> at 0x7fa553136d70>, 'voc_2007_val': <function <lambda> at 0x7fa553136cf8>}
_sets values type is: <type 'function'>
Imdb type is : <class 'PyTempTest2.pascal_voc'>
Imdb.PrintStr()= train2007
[Finished in 0.1s]
有上述实验得知:
1、__sets[name] 存放的是lamdba函数
2、__sets[name]()返回的是__sets[name]中具体的值,这个值是一个pascal_voc类的对象,对象是具体的,因为我们前面用split year 去实例化过pascal_voc(split, year)了