Skip to content

Commit

Permalink
Add maskrcnn
Browse files Browse the repository at this point in the history
  • Loading branch information
iitzco committed Aug 10, 2018
1 parent 19a975f commit 0d51971
Show file tree
Hide file tree
Showing 153 changed files with 42,054 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ This index will take you to all models of the category, regardless framework

- #### Tensorflow:
- [SSD MobileNet trained on Coco](./ssd_mobilenet_v2_coco/): Blazing fast bounding boxes of 90 different classes given a color image.

## Instance Segmentation

- #### Tensorflow:
- [MaskRCNN Inception trained on COCO](./mask_rcnn_inception_v2_coco/): Segment all objects intances given a color image.
193 changes: 193 additions & 0 deletions mask_rcnn_inception_v2_coco/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
mask_rcnn_inception_v2_coco_2018_01_28/
mask_rcnn_inception_v2_coco_2018_01_28.zip

# Created by https://www.gitignore.io/api/vim,macos,linux,python,virtualenv

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

### Python Patch ###
.venv/

### Python.VirtualEnv Stack ###
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
pip-selfcheck.json

### Vim ###
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]

# Session
Session.vim

# Temporary
.netrwhist
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~

### VirtualEnv ###
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/


# End of https://www.gitignore.io/api/vim,macos,linux,python,virtualenv
47 changes: 47 additions & 0 deletions mask_rcnn_inception_v2_coco/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# MaskRCNN Inception trained on COCO

![img](imgs/result.png)

## [Link to model](https://github.com/iitzco/deepzoo/releases/download/model-upload-2/mask_rcnn_inception_v2_coco_2018_01_28.zip)

## Requirements

* tensorflow
* numpy
* matplotlib

Install them by running `pip install -r requirements.txt`

## How to run

Use `MaskRCNNModel` class from `maskrcnn.py`.

The class can be used as shown in the following example:

```python
img_path = "/path/to/my/image"

# Provide the .pb model file path
graph_path = "/path/to/downloaded/pbmodel"

# Provide the .pbtxt label map file path
label_map = "/path/to/downloaded/pbmap"

model = MaskRCNNModel(graph_path, label_map)

out = model.run(img)
img = Image.fromarray(out)
img.show()
```

> *NOTE*: the `run` method receives a numpy array with shape [H, W, C]. If you use the Image library to open the image, remember to also install `pillow`.
An image with the intance segmentation should show up.

## Customize

See `json_handler` to see how to handle the model's output.

## Model info

Provided by tensorflow in it's model zoo. Link [here](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md)
Binary file added mask_rcnn_inception_v2_coco/imgs/example.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mask_rcnn_inception_v2_coco/imgs/result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions mask_rcnn_inception_v2_coco/maskrcnn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import numpy as np
import tensorflow as tf
import json
from json import encoder
encoder.FLOAT_REPR = lambda o: format(o, '.2f')

from object_detection.utils import label_map_util
from object_detection.utils import ops as utils_ops
from object_detection.utils import visualization_utils as vis_util


class MaskRCNNModel(object):

def __init__(self, graph_path, labels_path, num_classes=90):
self.load(graph_path, labels_path, num_classes)

def load(self, graph_path, labels_path, num_classes):
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(graph_path, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')


label_map = label_map_util.load_labelmap(labels_path)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=num_classes, use_display_name=True)

self.category_index = label_map_util.create_category_index(categories)
self.graph = detection_graph
self.sess = tf.Session(graph=self.graph)

def load_nodes(self, image):
ops = self.graph.get_operations()

all_tensor_names = {output.name for op in ops for output in op.outputs}
self.tensor_dict = {}
for key in [
'num_detections', 'detection_boxes', 'detection_scores',
'detection_classes', 'detection_masks'
]:
tensor_name = key + ':0'
if tensor_name in all_tensor_names:
self.tensor_dict[key] = self.graph.get_tensor_by_name(tensor_name)

if 'detection_masks' in self.tensor_dict:
# The following processing is only for single image
detection_boxes = tf.squeeze(self.tensor_dict['detection_boxes'], [0])
detection_masks = tf.squeeze(self.tensor_dict['detection_masks'], [0])
# Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
real_num_detection = tf.cast(self.tensor_dict['num_detections'][0], tf.int32)
detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
detection_masks, detection_boxes, image.shape[0], image.shape[1])
detection_masks_reframed = tf.cast(
tf.greater(detection_masks_reframed, 0.5), tf.uint8)
# Follow the convention by adding back the batch dimension
self.tensor_dict['detection_masks'] = tf.expand_dims(
detection_masks_reframed, 0)

self.image_tensor = self.graph.get_tensor_by_name('image_tensor:0')

def _run_inference(self, image):
self.load_nodes(image)
# Run inference
output_dict = self.sess.run(self.tensor_dict, feed_dict={self.image_tensor: np.expand_dims(image, 0)})

# all outputs are float32 numpy arrays, so convert types as appropriate
output_dict['num_detections'] = int(output_dict['num_detections'][0])
output_dict['detection_classes'] = output_dict[
'detection_classes'][0].astype(np.uint8)
output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
output_dict['detection_scores'] = output_dict['detection_scores'][0]

if 'detection_masks' in output_dict:
output_dict['detection_masks'] = output_dict['detection_masks'][0]

return output_dict

def json_handler(self, image, output_dict):
boxes = output_dict['detection_boxes']
classes = output_dict['detection_classes']
scores = output_dict['detection_scores']

d = {}
l = []
for i, v in enumerate(scores):
if v > 0:
aux = {}
aux['y0'] = float("{0:.4f}".format(boxes[i][0]))
aux['x0'] = float("{0:.4f}".format(boxes[i][1]))
aux['y1'] = float("{0:.4f}".format(boxes[i][2]))
aux['x1'] = float("{0:.4f}".format(boxes[i][3]))
aux['object'] = self.category_index[classes[i]]['name']
aux['probability'] = float("{0:.4f}".format(scores[i]))
aux['mask'] = output_dict['detection_masks'].tolist()
l.append(aux)

d['data'] = l
return json.dumps(d)


def image_handler(self, image, output_dict):
vis_util.visualize_boxes_and_labels_on_image_array(
image,
output_dict['detection_boxes'],
output_dict['detection_classes'],
output_dict['detection_scores'],
self.category_index,
instance_masks=output_dict['detection_masks'],
use_normalized_coordinates=True,
line_thickness=4,
min_score_thresh=.3)

return image


def run(self, image, handler=None):
if handler is None:
handler = self.image_handler
return handler(image, self._run_inference(image))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 0d51971

Please sign in to comment.