Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to run this code without GPU on windows? #187

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Mask RCNN
Mask RCNN in TensorFlow
- windows 7
- tensorflow 1.4
- python 3.6

This repo attempts to reproduce this amazing work by Kaiming He et al. :
[Mask R-CNN](https://arxiv.org/abs/1703.06870)
Expand All @@ -15,7 +18,7 @@ This repo attempts to reproduce this amazing work by Kaiming He et al. :
1. Go to `./libs/datasets/pycocotools` and run `make`
2. Download [COCO](http://mscoco.org/dataset/#download) dataset, place it into `./data`, then run `python download_and_convert_data.py` to build tf-records. It takes a while.
3. Download pretrained resnet50 model, `wget http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz`, unzip it, place it into `./data/pretrained_models/`
4. Go to `./libs` and run `make`
4. Go to `./libs`, run `python cpu_setup.py install` and `python gpu_setup.py install`
5. run `python train/train.py` for training
6. There are certainly some bugs, please report them back, and let's solve them together.

Expand Down
2 changes: 1 addition & 1 deletion libs/boxes/anchor.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def generate_anchors(base_size=16, ratios=[0.5, 1, 2],
base_anchor = np.array([1, 1, base_size, base_size]) - 1
ratio_anchors = _ratio_enum(base_anchor, ratios)
anchors = np.vstack([_scale_enum(ratio_anchors[i, :], scales)
for i in xrange(ratio_anchors.shape[0])])
for i in range(ratio_anchors.shape[0])])
return anchors

def _whctrs(anchor):
Expand Down
2 changes: 1 addition & 1 deletion libs/boxes/blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def im_list_to_blob(ims):
num_images = len(ims)
blob = np.zeros((num_images, max_shape[0], max_shape[1], 3),
dtype=np.float32)
for i in xrange(num_images):
for i in range(num_images):
im = ims[i]
blob[i, 0:im.shape[0], 0:im.shape[1], :] = im

Expand Down
2 changes: 1 addition & 1 deletion libs/boxes/gprof2dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2681,7 +2681,7 @@ def parse(self):
caller = self.get_function(fn)
call = Call(callee.id)
if isinstance(value, tuple):
for i in xrange(0, len(value), 4):
for i in range(0, len(value), 4):
nc, cc, tt, ct = value[i:i+4]
if CALLS in call:
call[CALLS] += cc
Expand Down
176 changes: 176 additions & 0 deletions libs/cpu_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------

import numpy as np
import os
from os.path import join as pjoin
#from distutils.core import setup
from setuptools import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import subprocess

#change for windows, by MrX
nvcc_bin = 'nvcc.exe'
lib_dir = 'lib/x64'

def find_in_path(name, path):
"Find a file in a search path"
# Adapted fom
# http://code.activestate.com/recipes/52224-find-a-file-given-a-search-path/
for dir in path.split(os.pathsep):
binpath = pjoin(dir, name)
if os.path.exists(binpath):
return os.path.abspath(binpath)
return None


def locate_cuda():
"""Locate the CUDA environment on the system

Returns a dict with keys 'home', 'nvcc', 'include', and 'lib64'
and values giving the absolute path to each directory.

Starts by looking for the CUDAHOME env variable. If not found, everything
is based on finding 'nvcc' in the PATH.
"""

# first check if the CUDAHOME env variable is in use
if 'CUDA_PATH' in os.environ:
home = os.environ['CUDA_PATH']
print("home = %s\n" % home)
nvcc = pjoin(home, 'bin', nvcc_bin)
else:
# otherwise, search the PATH for NVCC
default_path = pjoin(os.sep, 'usr', 'local', 'cuda', 'bin')
nvcc = find_in_path(nvcc_bin, os.environ['PATH'] + os.pathsep + default_path)
if nvcc is None:
raise EnvironmentError('The nvcc binary could not be '
'located in your $PATH. Either add it to your path, or set $CUDA_PATH')
home = os.path.dirname(os.path.dirname(nvcc))
print("home = %s, nvcc = %s\n" % (home, nvcc))


cudaconfig = {'home':home, 'nvcc':nvcc,
'include': pjoin(home, 'include'),
'lib64': pjoin(home, lib_dir)}
for k, v in cudaconfig.items():
if not os.path.exists(v):
raise EnvironmentError('The CUDA %s path could not be located in %s' % (k, v))

return cudaconfig
CUDA = locate_cuda()


# Obtain the numpy include directory. This logic works across numpy versions.
try:
numpy_include = np.get_include()
except AttributeError:
numpy_include = np.get_numpy_include()


def customize_compiler_for_nvcc(self):
"""inject deep into distutils to customize how the dispatch
to gcc/nvcc works.

If you subclass UnixCCompiler, it's not trivial to get your subclass
injected in, and still have the right customizations (i.e.
distutils.sysconfig.customize_compiler) run on it. So instead of going
the OO route, I have this. Note, it's kindof like a wierd functional
subclassing going on."""

# tell the compiler it can processes .cu
#self.src_extensions.append('.cu')


# save references to the default compiler_so and _comple methods
#default_compiler_so = self.spawn
#default_compiler_so = self.rc
super = self.compile

# now redefine the _compile method. This gets executed for each
# object but distutils doesn't have the ability to change compilers
# based on source extension: we add it.
def compile(sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None):
postfix=os.path.splitext(sources[0])[1]

if postfix == '.cu':
# use the cuda for .cu files
#self.set_executable('compiler_so', CUDA['nvcc'])
# use only a subset of the extra_postargs, which are 1-1 translated
# from the extra_compile_args in the Extension class
postargs = extra_postargs['nvcc']
else:
postargs = extra_postargs['gcc']


return super(sources, output_dir, macros, include_dirs, debug, extra_preargs, postargs, depends)
# reset the default compiler_so, which we might have changed for cuda
#self.rc = default_compiler_so

# inject our redefined _compile method into the class
self.compile = compile


# run the customize_compiler
class custom_build_ext(build_ext):
def build_extensions(self):
customize_compiler_for_nvcc(self.compiler)
build_ext.build_extensions(self)


ext_modules = [
# unix _compile: obj, src, ext, cc_args, extra_postargs, pp_opts
Extension(
"boxes.cython_bbox",
sources=["boxes/bbox.pyx"],
#define_macros={'/LD'},
#extra_compile_args={'gcc': ['/link', '/DLL', '/OUT:cython_bbox.dll']},
#extra_compile_args={'gcc': ['/LD']},
extra_compile_args={'gcc': []},
include_dirs = [numpy_include]
),
Extension(
"boxes.cython_anchor",
["boxes/cython_anchor.pyx"],
extra_compile_args={'gcc': []},
include_dirs = [numpy_include]
),
Extension(
"boxes.cython_bbox_transform",
["boxes/cython_bbox_transform.pyx"],
extra_compile_args={'gcc': []},
include_dirs=[numpy_include]
),
Extension(
"boxes.cython_nms",
["boxes/nms.pyx"],
extra_compile_args={'gcc': []},
include_dirs = [numpy_include]
),
Extension(
"nms.cpu_nms",
sources=["nms/cpu_nms.pyx"],
extra_compile_args={'gcc': []},
include_dirs = [numpy_include],
),

#Extension( # just used to get nms\gpu_nms.obj
# "nms.gpu_nms",
# sources=['nms\\gpu_nms.pyx'],
# language='c++',
# extra_compile_args={'gcc': []},
# include_dirs = [numpy_include]
#),
]

setup(
name='cpu_setup',
ext_modules=ext_modules,
# inject our custom trigger
cmdclass={'build_ext': custom_build_ext},
)
20 changes: 15 additions & 5 deletions libs/datasets/coco.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
'gt_boxes': 'bounding boxes and classes of instances in this image, of shape (N, 5), each entry is (x1, y1, x2, y2)',
}

def correct_decode_raw(data, dtype):

# BUG: THERE WAS A BUG HERE, tf.decode_raw('', tf.float32) returns [0.] tensor not the [] tensor
# So we use correct_decode_raw instead of tf.decode_raw

result = tf.cond(tf.equal(data, tf.constant("")),
lambda: tf.constant([], dtype=dtype),
lambda: tf.decode_raw(data, dtype))

return result

def get_split(split_name, dataset_dir, file_pattern=None, reader=None):
if split_name not in SPLITS_TO_SIZES:
Expand Down Expand Up @@ -48,15 +58,15 @@ def get_split(split_name, dataset_dir, file_pattern=None, reader=None):
}

def _masks_decoder(keys_to_tensors):
masks = tf.decode_raw(keys_to_tensors['label/gt_masks'], tf.uint8)
masks = correct_decode_raw(keys_to_tensors['label/gt_masks'], tf.uint8)
width = tf.cast(keys_to_tensors['image/width'], tf.int32)
height = tf.cast(keys_to_tensors['image/height'], tf.int32)
instances = tf.cast(keys_to_tensors['label/num_instances'], tf.int32)
mask_shape = tf.stack([instances, height, width])
return tf.reshape(masks, mask_shape)

def _gt_boxes_decoder(keys_to_tensors):
bboxes = tf.decode_raw(keys_to_tensors['label/gt_boxes'], tf.float32)
bboxes = correct_decode_raw(keys_to_tensors['label/gt_boxes'], tf.float32)
instances = tf.cast(keys_to_tensors['label/num_instances'], tf.int32)
bboxes_shape = tf.stack([instances, 5])
return tf.reshape(bboxes, bboxes_shape)
Expand Down Expand Up @@ -117,15 +127,15 @@ def read(tfrecords_filename):
ih = tf.cast(features['image/height'], tf.int32)
iw = tf.cast(features['image/width'], tf.int32)
num_instances = tf.cast(features['label/num_instances'], tf.int32)
image = tf.decode_raw(features['image/encoded'], tf.uint8)
image = correct_decode_raw(features['image/encoded'], tf.uint8)
imsize = tf.size(image)
image = tf.cond(tf.equal(imsize, ih * iw), \
lambda: tf.image.grayscale_to_rgb(tf.reshape(image, (ih, iw, 1))), \
lambda: tf.reshape(image, (ih, iw, 3)))

gt_boxes = tf.decode_raw(features['label/gt_boxes'], tf.float32)
gt_boxes = correct_decode_raw(features['label/gt_boxes'], tf.float32)
gt_boxes = tf.reshape(gt_boxes, [num_instances, 5])
gt_masks = tf.decode_raw(features['label/gt_masks'], tf.uint8)
gt_masks = correct_decode_raw(features['label/gt_masks'], tf.uint8)
gt_masks = tf.cast(gt_masks, tf.int32)
gt_masks = tf.reshape(gt_masks, [num_instances, ih, iw])

Expand Down
14 changes: 6 additions & 8 deletions libs/datasets/pycocotools/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
from distutils.extension import Extension
import numpy as np

# To compile and install locally run "python setup.py build_ext --inplace"
# To install library to Python site-packages run "python setup.py build_ext install"

ext_modules = [
Extension(
'_mask',
sources=['./common/maskApi.c', '_mask.pyx'],
include_dirs = [np.get_include(), './common'],
extra_compile_args=['-Wno-cpp', '-Wno-unused-function', '-std=c99'],

Extension(
"_mask",
sources=['common/maskApi.c', '_mask.pyx'],
include_dirs = [np.get_include(), 'common'],
extra_compile_args={'gcc': ['/Qstd=c99']},
)
]

Expand Down
Loading