RCNN代码运行
caffe中自带的代码'/caffe/example/detection.ipynb',这个代码并没有完全按照论文<Rich feature hierarchies foraccurate object detection and semantic segmentation. Ross Girshick, Jeff Donahue, TrevorDarrell, Jitendra Malik. CVPR 2014. Arxiv 2013.>中的结构来设计。论文是通过SS(selective search)得到regionpropose,将这些待检测区域resize到同一大小,通过提取Alexnet全连接层的特征,之后这个特征通过SVM来分类。显然,这样来做不是一个端到端的过程(end2end),RGB大神为什么不直接使用完整的Alexnet得到最终结果?可能的解释是:RGB大神在SVM进行分类的同时还对boundingbox进行了回归。
caffe中这个rcnn的结构是:先通过SS的方法得到regionpropose,得到的待检测区域,通过resize到同意大小,之后完全由一个Alexnet进行分类(200类),没有对bounding box 进行回归的过程,虽然论文中有提到,进行回归后,最终mAP(mean average precision)有一定的提升,但这直接用过Alexnet显然是一个end2end的过程
准备工作:
1.按照要求下载SS,下载地址:https://github.com/sergeyk/selective_search_ijcv_with_python,下载好的文件夹重命名为selective_search_ijcv_with_python。一定要放在'/caffe/python/caffe'这个目录下,这是由于这个目录下的detector.py这个文件将会调用SS,不放在这个文件的话,一定要注明路径。
2.MATLAB编译selective_search_ijcv_with_python中的demo就行。运行成功的话,会看到一堆SS分割好的子图,完成就可以关闭不管了。
3.下载相应的网络结果和训练好的模型,这里用的还是Alexnet的结构和ImageNet上训练好的模型
首先打开jupyter-notebook,建立一个临时文件夹。第三行代码中的--gpu可以去掉,那就使用CPU来运行。本人屌丝,用的就是i5-2400CPU,4g内存跑的,卡了很久才跑完第一段代码。
!mkdir -p _temp
!echo`pwd`/images/fish-bike.jpg > _temp/det_input.txt
!../python/detect.py--crop_mode=selective_search--pretrained_model=../models/bvlc_reference_rcnn_ilsvrc13/bvlc_reference_rcnn_ilsvrc13.caffemodel--model_def=../models/bvlc_reference_rcnn_ilsvrc13/deploy.prototxt --gpu--raw_scale=255 _temp/det_input.txt _temp/det_output.h
如果你运行这段代码出现了一堆错误,那你只能根据提示的问题一点点的修改代码。这些错误有些是代码本来的严谨性造成的,有些是由于Python库的升级、版本的问题。下面我列举一下我修改过的代码:
1.维度不满足:代码86行
原代码:predictions=out[self.outputs[0]].squeeze(axis=(2))
修改为:predictions=out[self.outputs[0]].squeeze(axis=(2,3))
2.用int型 代码140行 177行
源代码:crop=im[window[0]:window[2],window[1]:window[3]]
修改为:crop=im[int(window[0]):int(window[2]),int(window[1]):int(window[3])]
源代码:crop[pad_y:(pad_y+crop_h),pad_x:(pad_x+crop_w)]=context_crop
修改为:crop[int{pad_y}:int((pad_y+crop_h)),int(pad_x):int((pad_x+crop_w))]=context_crop
我在上述修改后,代码没有其他什么问题。如果出现了其他什么问题,根据他的提示来进行修改。
一般的Python可能PyTables会出问题,安装下,就没什么问题了。
第二段代码按照运行我没出什么问题,这段代码将保存在det_output.h5文件的内容进行读取
第三段代码,这段代码是把det_synset_words.txt中的标签读入。我把这行代码注释掉了labels_df.sort('synset_id'),原因:
1.pd.DataFrame没有sort这个方法,只有sort_values(),因此可能是pandas的版本的原因
2.这个代码的意思是想进行排序,sort_values()这个函数不会改变labels_df的值,这样写没有意义,可以删去
第四段代码,通过图表显示,完全看不清楚图中的内容。。。
第五段代码同第三段代码,没有sort这个函数我修改为sort_values
源代码:max_s.sort(ascending=False)
修改为:max_s.sort_values(ascending=False)
第六段代码中order这个接口无法调用+,在此处还是一个值的排序,因此修改为sort_values
源代码:print(f.order(ascending=False)[:5])
修改为:print(f.sort_values(ascending=False)[:5])
这个代码有两处,两处都要进行修改。
代码运行到这,你应该可以看到这个图:
到这步,可以看到检测到了person和bicycle,显然这个车跟我们的groundtruth相差很多,这里采用一种NMS(Non-maximum suppression)的方法。这个方法解决的问题:对于同一个物体,有多个框,在这个矿中选一个最优的框,尽量与ground truth相近。
defnms_detections(dets, overlap=0.3):
x1 = dets[:, 0] #方框左上角坐标的x坐标
y1 = dets[:, 1] #方框左上角坐标的y坐标
x2 = dets[:, 2] #方框右下角坐标的x坐标
y2 = dets[:, 3] #方框右下角坐标的y坐标
ind = np.argsort(dets[:,4]) #方框中的物体判断为某类的得分score进行排序
w = x2 - x1 #方框的宽
h = y2 - y1 #方框的高
area = (w *h).astype(float) #方框的面积
pick = []
while len(ind) > 0:
i = ind[-1] #得到得分score最高的索引
pick.append(i)
ind = ind[:-1]
xx1 = np.maximum(x1[i], x1[ind])
yy1 = np.maximum(y1[i], y1[ind])
xx2 = np.minimum(x2[i], x2[ind])
yy2 =np.minimum(y2[i], y2[ind])#得到最小的框
w = np.maximum(0., xx2 - xx1)
h = np.maximum(0., yy2 - yy1)
wh = w * h #最小框的面积
o = wh / (area[i] +area[ind] - wh) #计算Iou
ind = ind[np.nonzero(o <=overlap)[0]]
return dets[pick, :]
这段代码运行后的结果:
可以看到运行后,反而觉得结果不好了。。。。。