Skip to content
This repository has been archived by the owner on Jul 2, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' into add-exclude-to-style-checker
Browse files Browse the repository at this point in the history
  • Loading branch information
Hakuyume committed May 23, 2018
2 parents 3ff4096 + 59f805e commit 2d0f087
Show file tree
Hide file tree
Showing 266 changed files with 10,896 additions and 1,823 deletions.
19 changes: 13 additions & 6 deletions .travis.yml
Expand Up @@ -5,10 +5,10 @@ python:
- "2.7"
- "3.6"
env:
- CHAINER_VERSION=">=2.0" OPTIONAL_MODULES=0
- CHAINER_VERSION=">=2.0" OPTIONAL_MODULES=1
- CHAINER_VERSION="==3.0.0b1" OPTIONAL_MODULES=0
- CHAINER_VERSION="==3.0.0b1" OPTIONAL_MODULES=1
- CHAINER_VERSION=">=4.0" OPTIONAL_MODULES=0
- CHAINER_VERSION=">=4.0" OPTIONAL_MODULES=1
- CHAINER_VERSION="==5.0.0a1" OPTIONAL_MODULES=0
- CHAINER_VERSION="==5.0.0a1" OPTIONAL_MODULES=1
notifications:
email: false

Expand All @@ -28,6 +28,8 @@ install:
- conda info -a

- if [[ "$OPTIONAL_MODULES" == "1" ]]; then
export LIBRARY_PATH="$HOME/miniconda/lib:$LIBRARY_PATH";
export LD_LIBRARY_PATH="$HOME/miniconda/envs/chainercv/lib:$LD_LIBRARY_PATH";
conda env create -f environment.yml;
source activate chainercv;
else
Expand All @@ -40,12 +42,17 @@ install:
script:
- pwd
- pip install flake8
- pip install hacking
- pip install hacking==1.0.0
- pip install autopep8
- pip install mock
- pip install nose
- pip install pytest
- flake8 .
- autopep8 -r . | tee check_autopep8
- test ! -s check_autopep8
- python style_checker.py --exclude caffe_pb2.py -- .
- MPLBACKEND="agg" nosetests -a '!gpu,!slow' tests
- if [[ "$OPTIONAL_MODULES" == "1" ]]; then
MPLBACKEND="agg" mpiexec -n 2 nosetests -a '!gpu,!slow' tests;
else
MPLBACKEND="agg" nosetests -a '!gpu,!slow' tests;
fi
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2017 Yusuke Niitani
Copyright (c) 2017 Preferred Networks, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 2 additions & 2 deletions MANIFEST.in
@@ -1,2 +1,2 @@
include README.md
recursive-include chainercv *
recursive-include chainercv *.c
recursive-exclude chainercv *.pyx
142 changes: 48 additions & 94 deletions README.md
@@ -1,17 +1,28 @@
[![travis](https://travis-ci.org/chainer/chainercv.svg?branch=master)](https://travis-ci.org/chainer/chainercv)

<!--[![pypi](https://img.shields.io/pypi/v/chainercv.svg)](https://pypi.python.org/pypi/chainercv)-->
[![](docs/images/logo.png)](http://chainercv.readthedocs.io/en/stable/)

[![PyPI](https://img.shields.io/pypi/v/chainercv.svg)](https://pypi.python.org/pypi/chainercv)
[![License](https://img.shields.io/github/license/chainer/chainercv.svg)](https://github.com/chainer/chainercv/blob/master/LICENSE)
[![travis](https://travis-ci.org/chainer/chainercv.svg?branch=master)](https://travis-ci.org/chainer/chainercv)
[![Read the Docs](https://media.readthedocs.org/static/projects/badges/passing.svg)](http://chainercv.readthedocs.io/en/latest/?badge=latest)

# ChainerCV
# ChainerCV: a Library for Deep Learning in Computer Vision

ChainerCV is a collection of tools to train and run neural networks for computer vision tasks using [Chainer](https://github.com/chainer/chainer).

You can find the documentation [here](http://chainercv.readthedocs.io/en/stable/).

![Example are outputs of detection models supported by ChainerCV](https://cloud.githubusercontent.com/assets/2062128/26337670/44a2a202-3fb5-11e7-8b88-6eb9886a9915.png)
These are the outputs of the detection models supported by ChainerCV.
Supported tasks:

+ Object Detection ([tutorial](http://chainercv.readthedocs.io/en/latest/tutorial/detection.html), [Faster R-CNN](examples/faster_rcnn), [SSD](examples/ssd))
+ Semantic Segmentation ([SegNet](examples/segnet),)
+ Image Classification ([ResNet](examples/resnet), [VGG](examples/vgg))

# Guiding Principles
ChainerCV is developed under the following three guiding principles.

+ **Ease of Use** -- Implementations of computer vision networks with a cohesive and simple interface.
+ **Reproducibility** -- Training scripts that are perfect for being used as reference implementations.
+ **Compositionality** -- Tools such as data loaders and evaluation scripts that have common API.

# Installation

Expand All @@ -32,105 +43,48 @@ For additional features

+ Matplotlib
+ OpenCV

+ SciPy

Environments under Python 2.7.12 and 3.6.0 are tested.

+ The master branch will work on both the stable version (v2) and the development version (v3).
+ For users using Chainer v1, please use version `0.4.11`, which can be installed by `pip install chainercv==0.4.11`. This branch is unmaintained.


# Features

## Data conventions

ChainerCV follows the following conventions.

+ Channels of a color image are ordered as RGB. The shape of an image-array is CHW (channel, height, width).
+ Axis-dependent values follow row-column order.
+ Shape of an image is always represented as `(height, width)`.
+ Coordinates of bounding boxes are ordered as `(y_min, x_min, y_max, x_max)`. `(y_min, x_min)` and `(y_max, x_max)` are coordinates of the top left and the bottom right vertices of a bounding box respectively.
+ Coordinates of keypoints are ordered as `(y, x)`.

## Models
Currently, ChainerCV supports networks for object detection and semantic segmentation.
We are planning to support networks with different tasks in the future.
Image detection is the task of finding objects in an image and classifying the objects.
Semantic segmentation is the task of segmenting an image into pieces and assigning object labels to them.
Our implementations include:

Detection Models

+ **Faster R-CNN**
+ **Single Shot Multibox Detector (SSD)**
+ The master branch is designed to work on Chainer v4 (the stable version) and v5 (the development version).
+ The following branches are kept for the previous version of Chainer. Note that these branches are unmaintained.
+ `0.4.11` (for Chainer v1). It can be installed by `pip install chainercv==0.4.11`.
+ `0.7` (for Chainer v2). It can be installed by `pip install chainercv==0.7`.
+ `0.8` (for Chainer v3). It can be installed by `pip install chainercv==0.8`.

Semantic Segmentation
+ **SegNet**
# Data Conventions

Models for certain tasks are designed to have common interfaces.
For example, detection models support method that takes images and outputs coordinates, class labels and confidence scores of bounding boxes predicted around estimated regions of objects.
The common interface allows users to swap different models easily inside their code.
On top of that, the utilitiy codes build on top of this interface.
For example, there is an extension of `chainer.training.Trainer` called `chainercv.extensions.DetectionVisReport` that visualizes outputs during training for models that previously stated common interface.
+ Image
+ The order of color channel is RGB.
+ Shape is CHW (i.e. `(channel, height, width)`).
+ The range of values is `[0, 255]`.
+ Size is represented by row-column order (i.e. `(height, width)`).
+ Bounding Boxes
+ Shape is `(R, 4)`.
+ Coordinates are ordered as `(y_min, x_min, y_max, x_max)`. The order is the opposite of OpenCV.
+ Semantic Segmentation Image
+ Shape is `(height, weight)`.
+ The value is class id, which is in range `[0, n_class - 1]`.

ChainerCV internally downloads and stores files in a file system using Chainer's downloading mechanism to conveniently download pretrained models from the internet automatically.
The convenient interface coupled with this functionality allows users to execute algorithms in two lines of code:
# Sample Visualization

```python
from chainercv.links import FasterRCNNVGG16, SSD300
# You can use Faster R-CNN instead of SSD.
# model = FasterRCNNVGG16(pretrained_model='voc07')
model = SSD300(pretrained_model='voc0712')


# `bboxes` is a list of numpy arrays containing coordinates of boundnig boxes
# around objects. `labels` and `scores` are class ids and confidence scores for
# the boxes.
bboxes, labels, scores = model.predict(imgs) # imgs is a list of image
```
![Example are outputs of detection models supported by ChainerCV](https://cloud.githubusercontent.com/assets/2062128/26337670/44a2a202-3fb5-11e7-8b88-6eb9886a9915.png)
These are the outputs of the detection models supported by ChainerCV.

With the following commands, you can run a visualization demo.

```
$ cd examples/ssd # or cd examples/faster_rcnn
$ wget https://cloud.githubusercontent.com/assets/2062128/26187667/9cb236da-3bd5-11e7-8bcf-7dbd4302e2dc.jpg -O sample.jpg
$ python demo.py sample.jpg
```
# Citation

With the following commands, the visualizations on the top of this page can be produced.
If ChainerCV helps your research, please cite the paper for ACM Multimedia Open Source Software Competition.
Here is a BibTeX entry:

```
$ cd examples/detection
$ python visualize_models.py
```


## Transforms

ChainerCV provides functions commonly used to prepare data before feeding to a neural network.
We expect users to use these functions together with an object that supports the dataset interface (e.g. `chainer.dataset.DatasetMixin`).
Users can create a custom preprocessing pipeline by defining a function that describes a
procedure to transform the incoming data.
By decoupling preprocessing steps from dataset objects, dataset objects can be reused in a variety of preprocessing pipelines.

Here is an example where a user rescales and applies a random rotation to an image as a preprocessing step.

```python
from chainer.datasets import get_mnist
from chainer.datasets import TransformDataset
from chainercv.transforms import random_rotate

dataset, _ = get_mnist(ndim=3)

def transform(in_data):
# in_data is values returned by __getitem__ method of MNIST dataset.
img, label = in_data
img -= 0.5 # rescale to [-0.5, 0.5]
img = random_rotate(img)
return img, label
dataset = TransformDataset(dataset, transform)
img, label = dataset[0]
@inproceedings{ChainerCV2017,
author = {Niitani, Yusuke and Ogawa, Toru and Saito, Shunta and Saito, Masaki},
title = {ChainerCV: a Library for Deep Learning in Computer Vision},
booktitle = {ACM Multimedia},
year = {2017},
}
```

As found in the example, `random_rotate` is one of the transforms provided by ChainerCV. Like other transforms, this is just a
function that takes an array as input.
The preprint can be found in arXiv: https://arxiv.org/abs/1708.08169
2 changes: 2 additions & 0 deletions chainercv/__init__.py
@@ -1,7 +1,9 @@
import pkg_resources

from chainercv import chainer_experimental # NOQA
from chainercv import datasets # NOQA
from chainercv import evaluations # NOQA
from chainercv import experimental # NOQA
from chainercv import extensions # NOQA
from chainercv import functions # NOQA
from chainercv import links # NOQA
Expand Down
1 change: 1 addition & 0 deletions chainercv/chainer_experimental/__init__.py
@@ -0,0 +1 @@
from chainercv.chainer_experimental import datasets # NOQA
1 change: 1 addition & 0 deletions chainercv/chainer_experimental/datasets/__init__.py
@@ -0,0 +1 @@
from chainercv.chainer_experimental.datasets import sliceable # NOQA
6 changes: 6 additions & 0 deletions chainercv/chainer_experimental/datasets/sliceable/__init__.py
@@ -0,0 +1,6 @@
from chainercv.chainer_experimental.datasets.sliceable.sliceable_dataset import SliceableDataset # NOQA

from chainercv.chainer_experimental.datasets.sliceable.concatenated_dataset import ConcatenatedDataset # NOQA
from chainercv.chainer_experimental.datasets.sliceable.getter_dataset import GetterDataset # NOQA
from chainercv.chainer_experimental.datasets.sliceable.transform_dataset import TransformDataset # NOQA
from chainercv.chainer_experimental.datasets.sliceable.tuple_dataset import TupleDataset # NOQA
@@ -0,0 +1,45 @@
from chainercv.chainer_experimental.datasets.sliceable import SliceableDataset


class ConcatenatedDataset(SliceableDataset):
"""A sliceable version of :class:`chainer.datasets.ConcatenatedDataset`.
Here is an example.
>>> dataset_a = TupleDataset([0, 1, 2], [0, 1, 4])
>>> dataset_b = TupleDataset([3, 4, 5], [9, 16, 25])
>>>
>>> dataset = ConcatenatedDataset(dataset_a, dataset_b)
>>> dataset.slice[:, 0][:] # [0, 1, 2, 3, 4, 5]
Args:
datasets: The underlying datasets.
Each dataset should inherit
:class:`~chainercv.chainer_experimental.datasets.sliceable.Sliceabledataset`
and should have the same keys.
"""

def __init__(self, *datasets):
if len(datasets) == 0:
raise ValueError('At least one dataset is required')
self._datasets = datasets
self._keys = datasets[0].keys
for dataset in datasets[1:]:
if not dataset.keys == self._keys:
raise ValueError('All datasets should have the same keys')

def __len__(self):
return sum(len(dataset) for dataset in self._datasets)

@property
def keys(self):
return self._keys

def get_example_by_keys(self, index, key_indices):
if index < 0:
raise IndexError
for dataset in self._datasets:
if index < len(dataset):
return dataset.get_example_by_keys(index, key_indices)
index -= len(dataset)
raise IndexError
@@ -0,0 +1,97 @@
from chainercv.chainer_experimental.datasets.sliceable.sliceable_dataset \
import _as_indices
from chainercv.chainer_experimental.datasets.sliceable import SliceableDataset


class GetterDataset(SliceableDataset):
"""A sliceable dataset class that is defined with getters.
This is a dataset class with getters.
Please refer to the tutorial for more detailed explanation.
Here is an example.
>>> class SliceableLabeledImageDataset(GetterDataset):
>>> def __init__(self, pairs, root='.'):
>>> super(SliceableLabeledImageDataset, self).__init__()
>>> with open(pairs) as f:
>>> self._pairs = [l.split() for l in f]
>>> self._root = root
>>>
>>> self.add_getter('img', self.get_image)
>>> self.add_getter('label', self.get_label)
>>>
>>> def __len__(self):
>>> return len(self._pairs)
>>>
>>> def get_image(self, i):
>>> path, _ = self._pairs[i]
>>> return read_image(os.path.join(self._root, path))
>>>
>>> def get_label(self, i):
>>> _, label = self._pairs[i]
>>> return np.int32(label)
>>>
>>> dataset = SliceableLabeledImageDataset('list.txt')
>>>
>>> # get a subset with label = 0, 1, 2
>>> # no images are loaded
>>> indices = [i for i, label in
... enumerate(dataset.slice[:, 'label']) if label in {0, 1, 2}]
>>> dataset_012 = dataset.slice[indices]
"""

def __init__(self):
self._keys = []
self._getters = []
self._return_tuple = True

def __len__(self):
raise NotImplementedError

@property
def keys(self):
if self._return_tuple:
return tuple(key for key, _, _ in self._keys)
else:
return self._keys[0][0]

@keys.setter
def keys(self, keys):
self._keys = [self._keys[key_index]
for key_index in _as_indices(keys, self.keys)]
self._return_tuple = isinstance(keys, (list, tuple))

def add_getter(self, keys, getter):
"""Register a getter function
Args:
keys (int or string or tuple of strings): The number or name(s) of
data that the getter function returns.
getter (callable): A getter function that takes an index and
returns data of the corresponding example.
"""
self._getters.append(getter)
if isinstance(keys, int):
if keys == 1:
keys = None
else:
keys = (None,) * keys
if isinstance(keys, (tuple, list)):
for key_index, key in enumerate(keys):
self._keys.append((key, len(self._getters) - 1, key_index))
else:
self._keys.append((keys, len(self._getters) - 1, None))

def get_example_by_keys(self, index, key_indices):
example = []
cache = {}
for key_index in key_indices:
_, getter_index, key_index = self._keys[key_index]
if getter_index not in cache:
cache[getter_index] = self._getters[getter_index](index)
if key_index is None:
example.append(cache[getter_index])
else:
example.append(cache[getter_index][key_index])
return tuple(example)

0 comments on commit 2d0f087

Please sign in to comment.