Skip to content

Commit

Permalink
Merge pull request #2 from Austriker/python-3-support
Browse files Browse the repository at this point in the history
More work on Python 3
  • Loading branch information
Austriker committed May 26, 2016
2 parents 6b3c6a3 + 1f1eddd commit 9407198
Show file tree
Hide file tree
Showing 30 changed files with 210 additions and 179 deletions.
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# *Faster* R-CNN Fork

- This fork adds support to python 3.4
- Uses an up-to-date Caffe Version


#### Warning
This Fork is still a work in progress

This fork :
- Merged the [caffe-fast-rcnn](https://github.com/rbgirshick/caffe-fast-rcnn/tree/0dcd397b29507b8314e252e850518c5695efbb83) fork to the current Caffe version. The [PR](https://github.com/BVLC/caffe/pull/4163) is waiting to be Merged
- Add support to Python 3.4
- Not tested with Python 2.7

##### To-Do

- Detect GPU arch in setup.py
- Test with python2.7

### Disclaimer

Expand Down Expand Up @@ -97,9 +106,31 @@ If you find Faster R-CNN useful in your research, please consider citing:
**Note 2:** The `caffe` submodule needs to be on the `fast-rcnn` branch (or equivalent detached state). This will happen automatically *if you followed step 1 instructions*.

3. Build the Cython modules

Install pip packages
```sh
pip install -r requirements.txt
```

You have to check GPU arch default is sm_35

```Shell
cd $FRCN_ROOT/lib
make
# For python 2
make python2
# For python 3
make python3
```

If you want to rebuild :
```sh
make clean
# Then
make python2/python3
```

4. Build Caffe and pycaffe
Expand Down
2 changes: 1 addition & 1 deletion caffe
Submodule caffe updated from c5f996 to ad63d7
11 changes: 10 additions & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
all:
python3:
python3 setup.py build_ext --inplace
rm -rf build

python2:
python setup.py build_ext --inplace
rm -rf build

clean:
rm utils/bbox.c
rm nms/cpu_nms.c
rm nms/gpu_nms.cpp
33 changes: 17 additions & 16 deletions lib/datasets/coco.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
import numpy as np
import scipy.sparse
import scipy.io as sio
import cPickle
import six.moves.cPickle as pickle
from six.moves import range
import json
import uuid
# COCO API
Expand All @@ -36,7 +37,7 @@ def _filter_crowd_proposals(roidb, crowd_thresh):
if len(crowd_inds) == 0 or len(non_gt_inds) == 0:
continue

iscrowd = [int(True) for _ in xrange(len(crowd_inds))]
iscrowd = [int(True) for _ in range(len(crowd_inds))]
crowd_boxes = ds_utils.xyxy_to_xywh(entry['boxes'][crowd_inds, :])
non_gt_boxes = ds_utils.xyxy_to_xywh(entry['boxes'][non_gt_inds, :])
ious = COCOmask.iou(non_gt_boxes, crowd_boxes, iscrowd)
Expand Down Expand Up @@ -65,7 +66,7 @@ def __init__(self, image_set, year):
self._COCO = COCO(self._get_ann_file())
cats = self._COCO.loadCats(self._COCO.getCatIds())
self._classes = tuple(['__background__'] + [c['name'] for c in cats])
self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))
self._class_to_ind = dict(zip(self.classes, range(self.num_classes)))
self._class_to_coco_cat_id = dict(zip([c['name'] for c in cats],
self._COCO.getCatIds()))
self._image_index = self._load_image_set_index()
Expand Down Expand Up @@ -126,10 +127,8 @@ def image_path_from_index(self, index):
str(index).zfill(12) + '.jpg')
image_path = osp.join(self._data_path, 'images',
self._data_name, file_name)
assert(
osp.exists(image_path),
'Path does not exist: {}'.format(image_path)
)

assert osp.exists(image_path), 'Path does not exist: {}'.format(image_path)

return image_path

Expand All @@ -153,7 +152,7 @@ def _roidb_from_proposals(self, method):

if osp.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cPickle.load(fid)
roidb = pickle.load(fid)

print('{:s} {:s} roidb loaded from {:s}'.format(
self.name,
Expand All @@ -174,7 +173,7 @@ def _roidb_from_proposals(self, method):
else:
roidb = self._load_proposals(method, None)
with open(cache_file, 'wb') as fid:
cPickle.dump(roidb, fid, cPickle.HIGHEST_PROTOCOL)
pickle.dump(roidb, fid, pickle.HIGHEST_PROTOCOL)

print('wrote {:s} roidb to {:s}'.format(method, cache_file))

Expand All @@ -196,8 +195,10 @@ def _load_proposals(self, method, gt_roidb):
'MCG',
'selective_search',
'edge_boxes_AR',
'edge_boxes_70']
assert(method in valid_methods)
'edge_boxes_70'
]

assert method in valid_methods

print('Loading {} boxes'.format(method))

Expand Down Expand Up @@ -239,7 +240,7 @@ def gt_roidb(self):
cache_file = osp.join(self.cache_path, self.name + '_gt_roidb.pkl')
if osp.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cPickle.load(fid)
roidb = pickle.load(fid)

print('{} gt roidb loaded from {}'.format(self.name, cache_file))

Expand All @@ -249,7 +250,7 @@ def gt_roidb(self):
for index in self._image_index]

with open(cache_file, 'wb') as fid:
cPickle.dump(gt_roidb, fid, cPickle.HIGHEST_PROTOCOL)
pickle.dump(gt_roidb, fid, pickle.HIGHEST_PROTOCOL)

print('wrote gt roidb to {}'.format(cache_file))

Expand Down Expand Up @@ -329,7 +330,7 @@ def _get_thr_ind(coco_eval, thr):
ind = np.where((coco_eval.params.iouThrs > thr - 1e-5) &
(coco_eval.params.iouThrs < thr + 1e-5))[0][0]
iou_thr = coco_eval.params.iouThrs[ind]
assert(np.isclose(iou_thr, thr))
assert np.isclose(iou_thr, thr)

return ind

Expand Down Expand Up @@ -373,7 +374,7 @@ def _do_detection_eval(self, res_file, output_dir):
eval_file = osp.join(output_dir, 'detection_results.pkl')

with open(eval_file, 'wb') as fid:
cPickle.dump(coco_eval, fid, cPickle.HIGHEST_PROTOCOL)
pickle.dump(coco_eval, fid, pickle.HIGHEST_PROTOCOL)

print('Wrote COCO eval results to: {}'.format(eval_file))

Expand All @@ -392,7 +393,7 @@ def _coco_results_one_category(self, boxes, cat_id):
[{'image_id': index,
'category_id': cat_id,
'bbox': [xs[k], ys[k], ws[k], hs[k]],
'score': scores[k]} for k in xrange(dets.shape[0])])
'score': scores[k]} for k in range(dets.shape[0])])

return results

Expand Down
23 changes: 11 additions & 12 deletions lib/datasets/imdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import numpy as np
import scipy.sparse
from fast_rcnn.config import cfg
from six.moves import range


class imdb(object):
Expand Down Expand Up @@ -98,21 +99,21 @@ def evaluate_detections(self, all_boxes, output_dir=None):
def _get_widths(self):
return [
PIL.Image.open(self.image_path_at(i)).size[0]
for i in xrange(self.num_images)
for i in range(self.num_images)
]

def append_flipped_images(self):
num_images = self.num_images
widths = self._get_widths()

for i in xrange(num_images):
for i in range(num_images):
boxes = self.roidb[i]['boxes'].copy()
oldx1 = boxes[:, 0].copy()
oldx2 = boxes[:, 2].copy()
boxes[:, 0] = widths[i] - oldx2 - 1
boxes[:, 2] = widths[i] - oldx1 - 1

assert((boxes[:, 2] >= boxes[:, 0]).all())
assert (boxes[:, 2] >= boxes[:, 0]).all()

entry = {'boxes': boxes,
'gt_overlaps': self.roidb[i]['gt_overlaps'],
Expand Down Expand Up @@ -152,13 +153,13 @@ def evaluate_recall(self, candidate_boxes=None, thresholds=None,
[512**2, 1e5**2] # 512-inf
]

assert(area in areas, 'unknown area range: {}'.format(area))
assert area in areas, 'unknown area range: {}'.format(area)

area_range = area_ranges[areas[area]]
gt_overlaps = np.zeros(0)
num_pos = 0

for i in xrange(self.num_images):
for i in range(self.num_images):
# Checking for max_overlaps == 1 avoids including crowd annotations
# (...pretty hacking :/)
max_gt_overlaps = self.roidb[i]['gt_overlaps'].toarray().max(axis=1)
Expand Down Expand Up @@ -189,7 +190,7 @@ def evaluate_recall(self, candidate_boxes=None, thresholds=None,
gt_boxes.astype(np.float))

_gt_overlaps = np.zeros((gt_boxes.shape[0]))
for j in xrange(gt_boxes.shape[0]):
for j in range(gt_boxes.shape[0]):
# find which proposal box maximally covers each gt box
argmax_overlaps = overlaps.argmax(axis=0)
# and get the iou amount of coverage for each gt box
Expand Down Expand Up @@ -223,13 +224,11 @@ def evaluate_recall(self, candidate_boxes=None, thresholds=None,
'gt_overlaps': gt_overlaps}

def create_roidb_from_box_list(self, box_list, gt_roidb):
assert(
len(box_list) == self.num_images,
'Number of boxes must match number of ground-truth images'
)

assert len(box_list) == self.num_images, 'Number of boxes must match number of ground-truth images'

roidb = []
for i in xrange(self.num_images):
for i in range(self.num_images):
boxes = box_list[i]
num_boxes = boxes.shape[0]
overlaps = np.zeros((num_boxes, self.num_classes), dtype=np.float32)
Expand Down Expand Up @@ -257,7 +256,7 @@ def create_roidb_from_box_list(self, box_list, gt_roidb):
@staticmethod
def merge_roidbs(a, b):
assert len(a) == len(b)
for i in xrange(len(a)):
for i in range(len(a)):
a[i]['boxes'] = np.vstack((a[i]['boxes'], b[i]['boxes']))
a[i]['gt_classes'] = np.hstack((a[i]['gt_classes'],
b[i]['gt_classes']))
Expand Down
Loading

0 comments on commit 9407198

Please sign in to comment.