Merge commit 'v0.11.0-102-gb719fd7' into debian

* commit 'v0.11.0-102-gb719fd7': (1122 commits)
  Update version to 0.11.0
  Add 0.11 release notes
  Add missing 0.10 release notes
  Add @msarahan to CONTRIBUTORS.txt
  Implement appveyor builds
  FIX: Ignore exception if attempted deletion fails (fixes #817)
  Minor modification to docstring
  Moved contribution statement to CONTRIBUTORS.txt
  Mention license type
  Fix Hessian matrix eigvals
  Minor stylistic changes, removed lena test
  PEP8 fixes, License file added, tests added
  Update README and installation instructions
  Fix gh-pages under Python 3. Make robust against running twice in a row.
  improve test coverage.  Use SciPy's fourier_shift for examples.
  Incorporate fixes for complex images
  move CollectionViewer `update_image` to parent class
  fix typo artist.remove -> artists.remove
  use feature.canny
  Fix name of pil package
  ...
This commit is contained in:
Yaroslav Halchenko
2015-03-05 08:30:40 -05:00
419 changed files with 24316 additions and 7180 deletions
+1
View File
@@ -6,6 +6,7 @@ source = skimage
include = */skimage/*
omit =
*/setup.py
*/skimage/external/*
[report]
exclude_lines =
+2
View File
@@ -3,6 +3,7 @@
*#
*egg-info
*.so
*.pyd
*.bak
*.c
*.new
@@ -18,6 +19,7 @@ skimage/version.py
.coverage
doc/source/auto_examples/*.py
doc/source/auto_examples/*.txt
doc/source/auto_examples/notebook
doc/source/auto_examples/images/plot_*.png
doc/source/auto_examples/images/thumb
doc/source/auto_examples/applications/
+21 -75
View File
@@ -1,94 +1,40 @@
# vim ft=yaml
# After changing this file, check it on:
# http://lint.travis-ci.org/
# http://yaml-online-parser.appspot.com/
# See doc/travis_notes.txt for some guidelines
language: python
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/1fea29525e8b929dd7c7
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
python:
- 2.6
matrix:
include:
- python: 2.7
env:
- PYTHON=python
- PYTHONWARNINGS=all
- PYTHONX=python
- PYVER=2.x
- python: 3.2
env:
- PYTHON=python3
- PYTHONWARNINGS=all
- PYTHONX=python3
- PYVER=3.x
exclude:
- python: 2.6
virtualenv:
system_site_packages: true
- 2.6
- 2.7
- 3.2
- 3.3
- 3.4
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sudo apt-get update
- source tools/travis_before_install.sh
- sudo apt-get install $PYTHON-numpy
- wget https://raw.githubusercontent.com/numpy/numpy/master/numpy/_import_tools.py -O /home/travis/virtualenv/python3.2_with_system_site_packages/lib/python3.2/site-packages/numpy/_import_tools.py
- sudo apt-get install $PYTHON-scipy
- sudo apt-get install libfreeimage3
- if [[ $PYVER == '2.x' ]]; then
- sudo apt-get install $PYTHON-qt4;
- sudo apt-get install $PYTHON-matplotlib;
- fi
- if [[ $PYVER == '3.x' ]]; then
- sudo apt-get install $PYTHON-pyqt4;
- pip install --use-mirrors matplotlib;
- fi
- pip install pillow
- pip install cython
- pip install flake8
- pip install six
- pip install nose-cov
- pip install coveralls
- which python; python --version
- python check_bento_build.py
install:
- tools/header.py "Dependency versions"
- tools/build_versions.py
install:
- python setup.py build_ext --inplace
- python setup.py install
script:
# Matplotlib settings
- mkdir -p $HOME/.matplotlib
- touch $HOME/.matplotlib/matplotlibrc
- "echo 'backend : Agg' > $HOME/.matplotlib/matplotlibrc"
- "echo 'backend.qt4 : PyQt4' >> $HOME/.matplotlib/matplotlibrc"
# Run all tests
- if [[ $PYVER == '3.x' ]]; then
- nosetests --exe -v --with-doctest --with-cov --cov skimage --cov-config=.coveragerc skimage
- fi
- if [[ $PYVER == '2.x' ]]; then
- nosetests --exe -v --with-doctest skimage
- fi
# Run all doc examples
- export PYTHONPATH=$(pwd):$PYTHONPATH
- for f in doc/examples/*.py; do $PYTHONX "$f"; if [ $? -ne 0 ]; then exit 1; fi done
- for f in doc/examples/applications/*.py; do $PYTHONX "$f"; if [ $? -ne 0 ]; then exit 1; fi done
# Run pep8 and flake tests
- flake8 --exit-zero --exclude=test_*,six.py skimage doc/examples viewer_examples
script: tools/travis_script.sh
after_success:
- if [[ $PYVER == '3.x' ]]; then
- coveralls
- fi
- coveralls
+10 -5
View File
@@ -77,6 +77,12 @@ For a more detailed discussion, read these :doc:`detailed documents
Travis fails, you can find out why by clicking on the "failed" icon (red
cross) and inspecting the build and test log.
5. Document changes
Before merging your commits, you must add a description of your changes
to the release notes of the upcoming version in
``doc/release/release_dev.txt``.
.. note::
To reviewers: if it is not obvious, add a short explanation of what a branch
@@ -85,7 +91,7 @@ For a more detailed discussion, read these :doc:`detailed documents
Divergence between ``upstream master`` and your feature branch
..............................................................
--------------------------------------------------------------
Do *not* ever merge the main branch into yours. If GitHub indicates that the
branch of your Pull Request can no longer be merged automatically, rebase
@@ -117,8 +123,7 @@ Guidelines
* All code should have tests (see `test coverage`_ below for more details).
* All code should be documented, to the same
`standard <http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines>`_
as NumPy and SciPy.
`standard <://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt#docstring-standard>`_ as NumPy and SciPy.
* For new functionality, always add an example to the
gallery.
* No changes are ever committed without review. Ask on the
@@ -188,8 +193,8 @@ successfully passes all tests. To do so,
* Go to `Travis-CI <http://travis-ci.org/>`__ and follow the Sign In link at the top
* Go to your `profile page <https://travis-ci.org/profile>`__ and switch on your
scikit-image fork
* Go to your `profile page <https://travis-ci.org/profile>`__ and switch
on your scikit-image fork
It corresponds to steps one and two in
`Travis-CI documentation <http://about.travis-ci.org/docs/user/getting-started/>`__
+35 -2
View File
@@ -176,9 +176,42 @@
- François Orieux
Image deconvolution http://research.orieux.fr
- Vighnesh Birodkar
Blob Detection
- Axel Donath
Blob Detection
- Adam Feuer
PIL Image import and export improvements
- Rebecca Murphy
astronaut in examples
- Geoffrey French
skimage.filters.rank.windowed_histogram and plot_windowed_histogram example.
- Alexey Umnov
skimage.draw.ellipse bug fix and tests.
- Ivana Kajic
Updated description and examples in documentation for gabor filters
- Matěj Týč
Extended the image labelling implementation so it also works on 3D images.
- Salvatore Scaramuzzino
RectTool example
- Kevin Keraudren
Fix and test for feature.peak_local_max
- Jeremy Metz
Adaptation of ImageJ Autothresholder.Li, fixed Qhull error QH6228
- Mike Sarahan
Sub-pixel shift registration
- Jim Fienup, Alexander Iacchetta
In-depth review of sub-pixel shift registration
+16 -15
View File
@@ -1,11 +1,9 @@
Build Requirements
------------------
* `Python >= 2.5 <http://python.org>`__
* `Python >= 2.6 <http://python.org>`__
* `Numpy >= 1.6 <http://numpy.scipy.org/>`__
* `Cython >= 0.17 <http://www.cython.org/>`__
`Matplotlib >= 1.0 <http://matplotlib.sf.net>`__ is needed to generate the
examples in the documentation.
* `Cython >= 0.21 <http://www.cython.org/>`__
* `Six >=1.3 <https://pypi.python.org/pypi/six>`__
You can use pip to automatically install the base dependencies as follows::
@@ -13,7 +11,11 @@ You can use pip to automatically install the base dependencies as follows::
Runtime requirements
--------------------
* `SciPy >= 0.10 <http://scipy.org>`__
* `SciPy <http://scipy.org>`__
* `Matplotlib <http://matplotlib.sf.net>`__
* `NetworkX <https://networkx.github.io>`__
* `Pillow <https://pypi.python.org/pypi/Pillow>`__
(or `PIL <http://www.pythonware.com/products/pil/>`__)
Known build errors
------------------
@@ -25,11 +27,6 @@ example at ``C:\Python26\Lib\distutils\distutils.cfg``) to contain::
[build]
compiler=mingw32
Usage Requirements
------------------
* `Scipy <http://www.scipy.org/>`__
Optional Requirements
---------------------
You can use this scikit with the basic requirements listed above, but some
@@ -46,11 +43,15 @@ functionality is only available with the following installed:
The ``pyamg`` module is used for the fast `cg_mg` mode of random
walker segmentation.
* `Pillow <https://pypi.python.org/pypi/Pillow>`__
(or `PIL <http://www.pythonware.com/products/pil/>`__)
The ``Pillow`` library (or equivalently ``PIL``) is used for Input/Output.
* `Astropy <http://www.astropy.org>`__ provides FITS io capability.
* `SimpleITK <http://www.simpleitk.org/>`
Optional io plugin providing a wide variety of `formats <http://www.itk.org/Wiki/ITK_File_Formats>`__.
including specialized formats using in medical imaging.
* `imread <http://pythonhosted.org/imread/>`
Optional io plugin providing most standard `formats <http://pythonhosted.org//imread/formats.html>`__.
* `Astropy <http://www.astropy.org>`__ is required to use the FITS io plug-in.
Testing requirements
--------------------
+4
View File
@@ -14,3 +14,7 @@ doctest:
coverage:
nosetests skimage --with-coverage --cover-package=skimage
html:
pip install -q sphinx
export SPHINXOPTS=-W; make -C doc html
+61 -21
View File
@@ -1,31 +1,71 @@
Image Processing SciKit
=======================
# scikit-image: Image processing in Python
Source
------
https://github.com/scikit-image/scikit-image
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/scikit-image/scikit-image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Coverage Status](https://img.shields.io/coveralls/scikit-image/scikit-image.svg)](https://coveralls.io/r/scikit-image/scikit-image?branch=master)
Mailing List
------------
http://groups.google.com/group/scikit-image
- **Website (including documentation):** [http://scikit-image.org/](http://scikit-image.org)
- **Mailing list:** [http://groups.google.com/group/scikit-image](http://groups.google.com/group/scikit-image)
- **Source:** [https://github.com/scikit-image/scikit-image](https://github.com/scikit-image/scikit-image)
Installation from source
------------------------
Refer to DEPENDS.txt for a list of dependencies.
## Installation from binaries
The SciKit may be installed globally using
- **Debian/Ubuntu:** ``sudo apt-get install python-skimage``
- **OSX:** ``pip install scikit-image``
- **Anaconda:** ``conda install scikit-image
- **Windows:** Download [Windows binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image)
$ python setup.py install
Also see
[http://scikit-image.org/docs/dev/install.html](http://scikit-image.org/docs/dev/install.html)
or locally using
## Installation from source
$ python setup.py install --prefix=${HOME}
Install [dependencies](DEPENDS.txt) using:
If you prefer, you can use it without installing, by simply adding
this path to your PYTHONPATH variable and compiling the extensions:
```
pip install -r requirements.txt
```
$ python setup.py build_ext -i
Then, install scikit-image using:
```
$ pip install .
```
If you plan to develop the package, you may run it directly from source:
```
$ python setup.py develop # Do this once to add pkg to Python path
$ python setup.py build_ext -i # Build binary extensions
```
## License (Modified BSD)
Copyright (C) 2011, the scikit-image team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. Neither the name of skimage nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
License
-------
Please read LICENSE.txt in this directory.
+19 -4
View File
@@ -5,8 +5,15 @@ How to make a new release of ``skimage``
- Update release notes.
- To show a list of contributors and changes, run
``doc/release/contribs.py <tag of prev release>``.
1. Review and cleanup ``doc/release/release_dev.txt``
- To show a list of merges and contributors, run
``doc/release/contribs.py <tag of prev release>``.
2. Rename to ``doc/release/release_X.txt``
3. Copy ``doc/release/release_template.txt`` to
``doc/release/release_dev.txt`` for the next release.
- Update the version number in ``setup.py`` and ``bento.info`` and commit
@@ -19,6 +26,7 @@ How to make a new release of ``skimage``
place. Double check ``random.js``, otherwise the skimage.org front
page gets broken!
- Build using ``make gh-pages``.
- Update the symlink to ``stable``.
- Push upstream: ``git push origin gh-pages`` in ``doc/gh-pages``.
- Add the version number as a tag in git::
@@ -34,6 +42,15 @@ How to make a new release of ``skimage``
python setup.py register
python setup.py sdist upload
Go to https://travis-ci.org/scikit-image/scikit-image-wheels, select the
"Current" tab, and click (on the right) on the "Restart Build" icon. After
the wheels become available at http://wheels.scikit-image.org/ (approx 15
mins), execute ``tools/osx_wheel_upload.sh``. Note that, if you rebuild the
same wheels, it can take up to 15 minutes for the the files in the http
directory to update to the versions that Travis-CI uploaded. You may want to
check the timestamps in the http directory listing to check that you will get
the latest version.
- Increase the version number
- In ``setup.py``, set to ``0.Xdev``.
@@ -45,8 +62,6 @@ How to make a new release of ``skimage``
- Sync your branch with the remote repo: ``git pull``.
If you try to ``make gh-pages`` when your branch is out of sync, it
creates headaches.
- Update stable and development version numbers in
``_templates/sidebar_versions.html``.
- Add release date to ``index.rst`` under "Announcements".
- Add previous stable version documentation path to disallowed paths
in `robots.txt`
+16 -2
View File
@@ -1,5 +1,17 @@
Remember to list any API changes below in `doc/source/api_changes.txt`.
Version 0.13
------------
* Remove deprecated `None` defaults for `skimage.exposure.rescale_intensity`
* Remove deprecated `skimage.filters.canny` import in `filters/__init__.py`
file (canny is now in `skimage.feature.canny`).
* Don't forget to complete api_changes.txt.
(`GitHub discuss <https://github.com/scikit-image/scikit-image/pull/1113>`__ )
* Remove deprecated ``skimage.filter`` module.
* Remove deprecated edge filters `hsobel`, `vsobel`, `hscharr`, `vscharr`,
`hprewitt`, `vprewitt`, `roberts_positive_diagonal`,
`roberts_negative_diagonal` in `skimage/filters/edges.py`
Version 0.12
------------
* Change `label` to mark background as 0, not -1, which is consistent with
@@ -7,11 +19,13 @@ Version 0.12
* Remove `skimage.morphology.label` from `skimage.morphology.__init__`--it now
lives in `skimage.measure.label`.
* Remove deprecated `reverse_map` parameter of `skimage.transform.warp`
* Change depecrated `enforce_connectivity=False` on skimage.segmentation.slic
* Change deprecated `enforce_connectivity=False` on skimage.segmentation.slic
and set it to True as default
* Remove deprecated `skimage.measure.fit.BaseModel._params` attribute
* Remove deprecated `skimage.measure.fit.BaseModel._params`,
`skimage.transform.ProjectiveTransform._matrix`,
`skimage.transform.PolynomialTransform._params`,
`skimage.transform.PiecewiseAffineTransform.affines_*` attributes
* Remove deprecated functions `skimage.filter.denoise_*`
* Remove deprecated functions `skimage.filters.denoise_*`
* Add 3D phantom in `skimage.data`
* Add 3D test case of `skimage.feature.phase_correlate`
+68
View File
@@ -0,0 +1,68 @@
# AppVeyor.com is a Continuous Integration service to build and run tests under
# Windows
environment:
global:
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
# /E:ON and /V:ON options are not enabled in the batch script intepreter
# See: http://stackoverflow.com/a/13751649/163740
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\tools\\appveyor\\run_with_env.cmd"
matrix:
- PYTHON: "C:\\Python27_32"
PYTHON_VERSION: "2.7"
PYTHON_ARCH: "32"
- PYTHON: "C:\\Python27_64"
PYTHON_VERSION: "2.7"
PYTHON_ARCH: "64"
- PYTHON: "C:\\Python34_32"
PYTHON_VERSION: "3.4.2"
PYTHON_ARCH: "32"
- PYTHON: "C:\\Python24_64"
PYTHON_VERSION: "3.4.2"
PYTHON_ARCH: "64"
install:
# Install Python (from the official .msi of http://python.org) and pip when
# not already installed.
- "powershell ./tools/appveyor/install.ps1"
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
# Check that we have the expected version and architecture for Python
- "python --version"
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
# Install the build and runtime dependencies of the project.
- "%CMD_IN_ENV% pip install -v %WHEELHOUSE% -r tools/appveyor/requirements.txt"
- "%CMD_IN_ENV% pip install -v -r requirements.txt"
- "%CMD_IN_ENV% python setup.py bdist_wheel bdist_wininst"
- ps: "ls dist"
# Install the generated wheel package to test it
- "pip install --pre --no-index --find-links dist/ scikit-image"
# Not a .NET project, we build scikit-image in the install step instead
build: false
test_script:
# Change to a non-source folder to make sure we run the tests on the
# installed library.
- "cd C:\\"
# Use the Agg backend in Matplotlib
- echo backend:Agg > matplotlibrc
# Run unit tests with nose
- "python -c \"import nose; nose.main()\" -v -s skimage"
artifacts:
# Archive the generated wheel package in the ci.appveyor.com build report.
- path: dist\*
#on_success:
# - TODO: upload the content of dist/*.whl to a public wheelhouse
+25 -18
View File
@@ -1,5 +1,5 @@
Name: scikit-image
Version: 0.10.1
Version: 0.11.0
Summary: Image processing routines for SciPy
Url: http://scikit-image.org
DownloadUrl: http://github.com/scikit-image/scikit-image
@@ -33,22 +33,23 @@ UseBackends: Waf
Library:
Packages:
skimage, skimage.color, skimage.data, skimage.draw, skimage.exposure,
skimage.feature, skimage.filter, skimage.graph, skimage.io,
skimage.feature, skimage.filters, skimage.future, skimage.future.graph,
skimage.graph, skimage.io,
skimage.io._plugins, skimage.measure, skimage.morphology,
skimage.scripts, skimage.restoration, skimage.segmentation,
skimage.transform, skimage.util
Extension: skimage.morphology._pnpoly
Sources:
skimage/morphology/_pnpoly.pyx
Extension: skimage.io._plugins._colormixer
Sources:
skimage/io/_plugins/_colormixer.pyx
Extension: skimage.measure._pnpoly
Sources:
skimage/measure/_pnpoly.pyx
Extension: skimage.measure._find_contours_cy
Sources:
skimage/measure/_find_contours_cy.pyx
Extension: skimage.measure._moments
Extension: skimage.measure._moments_cy
Sources:
skimage/measure/_moments.pyx
skimage/measure/_moments_cy.pyx
Extension: skimage.measure._marching_cubes_cy
Sources:
skimage/measure/_marching_cubes_cy.pyx
@@ -61,9 +62,9 @@ Library:
Extension: skimage.transform._hough_transform
Sources:
skimage/transform/_hough_transform.pyx
Extension: skimage.filter._ctmf
Extension: skimage.filters._ctmf
Sources:
skimage/filter/_ctmf.pyx
skimage/filters/_ctmf.pyx
Extension: skimage.measure._ccomp
Sources:
skimage/measure/_ccomp.pyx
@@ -79,9 +80,6 @@ Library:
Extension: skimage.graph._spath
Sources:
skimage/graph/_spath.pyx
Extension: skimage.morphology.cmorph
Sources:
skimage/morphology/cmorph.pyx
Extension: skimage.graph.heap
Sources:
skimage/graph/heap.pyx
@@ -127,18 +125,18 @@ Library:
Extension: skimage._shared.geometry
Sources:
skimage/_shared/geometry.pyx
Extension: skimage.filter.rank.generic_cy
Extension: skimage.filters.rank.generic_cy
Sources:
skimage/filter/rank/generic_cy.pyx
Extension: skimage.filter.rank.percentile_cy
skimage/filters/rank/generic_cy.pyx
Extension: skimage.filters.rank.percentile_cy
Sources:
skimage/filter/rank/percentile_cy.pyx
Extension: skimage.filter.rank.core_cy
Extension: skimage.filters.rank.core_cy
Sources:
skimage/filter/rank/core_cy.pyx
Extension: skimage.filter.rank.bilateral_cy
Extension: skimage.filters.rank.bilateral_cy
Sources:
skimage/filter/rank/bilateral_cy.pyx
skimage/filters/rank/bilateral_cy.pyx
Extension: skimage.restoration._unwrap_1d
Sources:
skimage/restoration/_unwrap_1d.pyx
@@ -151,9 +149,18 @@ Library:
Extension: skimage.restoration._denoise_cy
Sources:
skimage/restoration/_denoise_cy.pyx
Extension: skimage.restoration._nl_means_denoising
Sources:
skimage/restoration/_nl_means_denoising.pyx
Extension: skimage.feature._hessian_det_appx
Sources:
skimage/exposure/_hessian_det_appx.pyx
Extension: skimage.future.graph._ncut_cy
Sources:
skimage/future/graph/_ncut_cy.pyx
Extension: skimage.external.tifffile._tifffile
Sources:
skimage/external/tifffile/_tifffile.c
Executable: skivi
Module: skimage.scripts.skivi
+2 -2
View File
@@ -4,7 +4,7 @@
# You can set these variables from the command line.
PYTHON ?= python
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SPHINXBUILD ?= python $(shell which sphinx-build)
PAPER ?=
# Internal variables.
@@ -30,7 +30,7 @@ help:
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " gitwash to update the gitwash documentation"
clean:
-rm -rf $(DEST)/*
-rm -rf source/api
+19
View File
@@ -0,0 +1,19 @@
# Building docs #
To build docs, run `make` in this directory. `make help` lists all targets.
## Requirements ##
Sphinx is needed to build doc. Install with `pip install sphinx`.
## Fixing Warnings ##
- "citation not found: R###"
$ cd doc/build; grep -rin R### .
There is probably an underscore after a reference
in the first line of a docstring (e.g. [1]_)
- "Duplicate citation R###, other instance in...""
There is probably a [2] without a [1] in one of
the docstrings
- Make sure to use pre-sphinxification paths to images
(not the _images directory)
@@ -57,7 +57,7 @@ segmentation. To do this, we first get the edges of features using the Canny
edge-detector.
"""
from skimage.filter import canny
from skimage.feature import canny
edges = canny(coins/255.)
fig, ax = plt.subplots(figsize=(4, 3))
@@ -109,7 +109,7 @@ find an elevation map using the Sobel gradient of the image.
"""
from skimage.filter import sobel
from skimage.filters import sobel
elevation_map = sobel(coins)
+23 -23
View File
@@ -62,7 +62,7 @@ randomly set to 0. The **median** filter is applied to remove the noise.
"""
from skimage.filter.rank import median
from skimage.filters.rank import median
from skimage.morphology import disk
noise = np.random.random(noisy_image.shape)
@@ -107,7 +107,7 @@ image.
"""
from skimage.filter.rank import mean
from skimage.filters.rank import mean
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[10, 7])
@@ -133,11 +133,11 @@ the central one.
.. note::
A different implementation is available for color images in
`skimage.filter.denoise_bilateral`.
`skimage.filters.denoise_bilateral`.
"""
from skimage.filter.rank import mean_bilateral
from skimage.filters.rank import mean_bilateral
noisy_image = img_as_ubyte(data.camera())
@@ -183,7 +183,7 @@ equalization emphasizes every local gray-level variations.
"""
from skimage import exposure
from skimage.filter import rank
from skimage.filters import rank
noisy_image = img_as_ubyte(data.camera())
@@ -230,7 +230,7 @@ picture.
"""
from skimage.filter.rank import autolevel
from skimage.filters.rank import autolevel
noisy_image = img_as_ubyte(data.camera())
@@ -260,7 +260,7 @@ result.
"""
from skimage.filter.rank import autolevel_percentile
from skimage.filters.rank import autolevel_percentile
image = data.camera()
@@ -298,7 +298,7 @@ otherwise by the minimum local.
"""
from skimage.filter.rank import enhance_contrast
from skimage.filters.rank import enhance_contrast
noisy_image = img_as_ubyte(data.camera())
@@ -330,7 +330,7 @@ percentile *p0* and *p1* instead of the local minimum and maximum.
"""
from skimage.filter.rank import enhance_contrast_percentile
from skimage.filters.rank import enhance_contrast_percentile
noisy_image = img_as_ubyte(data.camera())
@@ -366,19 +366,19 @@ threshold is determined by maximizing the variance between two classes of
pixels of the local neighborhood defined by a structuring element.
The example compares the local threshold with the global threshold
`skimage.filter.threshold_otsu`.
`skimage.filters.threshold_otsu`.
.. note::
Local is much slower than global thresholding. A function for global Otsu
thresholding can be found in : `skimage.filter.threshold_otsu`.
thresholding can be found in : `skimage.filters.threshold_otsu`.
.. [4] http://en.wikipedia.org/wiki/Otsu's_method
"""
from skimage.filter.rank import otsu
from skimage.filter import threshold_otsu
from skimage.filters.rank import otsu
from skimage.filters import threshold_otsu
p8 = data.page()
@@ -459,7 +459,7 @@ closing and morphological gradient.
"""
from skimage.filter.rank import maximum, minimum, gradient
from skimage.filters.rank import maximum, minimum, gradient
noisy_image = img_as_ubyte(data.camera())
@@ -511,7 +511,7 @@ images.
"""
from skimage import data
from skimage.filter.rank import entropy
from skimage.filters.rank import entropy
from skimage.morphology import disk
import numpy as np
import matplotlib.pyplot as plt
@@ -549,7 +549,7 @@ from time import time
from scipy.ndimage.filters import percentile_filter
from skimage.morphology import dilation
from skimage.filter.rank import median, maximum
from skimage.filters.rank import median, maximum
def exec_and_timeit(func):
@@ -586,7 +586,7 @@ def ndi_med(image, n):
Comparison between
* `filter.rank.maximum`
* `filters.rank.maximum`
* `morphology.dilate`
on increasing structuring element size:
@@ -610,7 +610,7 @@ ax.set_title('Performance with respect to element size')
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Element radius')
ax.plot(e_range, rec)
ax.legend(['filter.rank.maximum', 'morphology.dilate'])
ax.legend(['filters.rank.maximum', 'morphology.dilate'])
"""
@@ -638,7 +638,7 @@ ax.set_title('Performance with respect to image size')
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Image size')
ax.plot(s_range, rec)
ax.legend(['filter.rank.maximum', 'morphology.dilate'])
ax.legend(['filters.rank.maximum', 'morphology.dilate'])
"""
@@ -647,7 +647,7 @@ ax.legend(['filter.rank.maximum', 'morphology.dilate'])
Comparison between:
* `filter.rank.median`
* `filters.rank.median`
* `scipy.ndimage.percentile`
on increasing structuring element size:
@@ -669,7 +669,7 @@ rec = np.asarray(rec)
fig, ax = plt.subplots()
ax.set_title('Performance with respect to element size')
ax.plot(e_range, rec)
ax.legend(['filter.rank.median', 'scipy.ndimage.percentile'])
ax.legend(['filters.rank.median', 'scipy.ndimage.percentile'])
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Element radius')
@@ -682,7 +682,7 @@ Comparison of outcome of the three methods:
fig, ax = plt.subplots()
ax.imshow(np.hstack((rc, rndi)))
ax.set_title('filter.rank.median vs. scipy.ndimage.percentile')
ax.set_title('filters.rank.median vs. scipy.ndimage.percentile')
ax.axis('off')
"""
@@ -708,7 +708,7 @@ rec = np.asarray(rec)
fig, ax = plt.subplots()
ax.set_title('Performance with respect to image size')
ax.plot(s_range, rec)
ax.legend(['filter.rank.median', 'scipy.ndimage.percentile'])
ax.legend(['filters.rank.median', 'scipy.ndimage.percentile'])
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Image size')
+111
View File
@@ -0,0 +1,111 @@
"""
=========================================
Adapting gray-scale filters to RGB images
=========================================
There are many filters that are designed work with gray-scale images but not
color images. To simplify the process of creating functions that can adapt to
RGB images, scikit-image provides the ``adapt_rgb`` decorator.
To actually use the ``adapt_rgb`` decorator, you have to decide how you want to
adapt the RGB image for use with the gray-scale filter. There are two
pre-defined handlers:
``each_channel``
Pass each of the RGB channels to the filter one-by-one, and stitch the
results back into an RGB image.
``hsv_value``
Convert the RGB image to HSV and pass the value channel to the filter.
The filtered result is inserted back into the HSV image and converted
back to RGB.
Below, we demonstrate the use of ``adapt_rgb`` on a couple of gray-scale
filters:
"""
from skimage.color.adapt_rgb import adapt_rgb, each_channel, hsv_value
from skimage import filters
@adapt_rgb(each_channel)
def sobel_each(image):
return filters.sobel(image)
@adapt_rgb(hsv_value)
def sobel_hsv(image):
return filters.sobel(image)
"""
We can use these functions as we would normally use them, but now they work
with both gray-scale and color images. Let's plot the results with a color
image:
"""
from skimage import data
import matplotlib.pyplot as plt
image = data.lena()
fig, (ax_each, ax_hsv) = plt.subplots(ncols=2)
ax_each.imshow(sobel_each(image))
ax_hsv.imshow(sobel_hsv(image))
"""
.. image:: PLOT2RST.current_figure
Notice that the result for the value-filtered image preserves the color of the
original image, but channel filtered image combines in a more surprising way.
In other common cases, smoothing for example, the channel filtered image will
produce a better result than the value-filtered image.
You can also create your own handler functions for ``adapt_rgb``. To do so,
just create a function with the following signature::
def handler(image_filter, image, *args, **kwargs):
# Manipulate RGB image here...
image = image_filter(image, *args, **kwargs)
# Manipulate filtered image here...
return image
Note that ``adapt_rgb`` handlers are written for filters where the image is the
first argument.
As a very simple example, we can just convert any RGB image to grayscale and
then return the filtered result:
"""
from skimage.color import rgb2gray
def as_gray(image_filter, image, *args, **kwargs):
gray_image = rgb2gray(image)
return image_filter(gray_image, *args, **kwargs)
"""
It's important to create a signature that uses ``*args`` and ``**kwargs`` to
pass arguments along to the filter so that the decorated function is allowed to
have any number of positional and keyword arguments.
Finally, we can use this handler with ``adapt_rgb`` just as before:
"""
@adapt_rgb(as_gray)
def sobel_gray(image):
return filters.sobel(image)
fig, ax = plt.subplots()
ax.imshow(sobel_gray(image), cmap=plt.cm.gray)
plt.show()
"""
.. image:: PLOT2RST.current_figure
.. note::
A very simple check of the array shape is used for detecting RGB images, so
``adapt_rgb`` is not recommended for functions that support 3D volumes or
color images in non-RGB spaces.
"""
+1 -1
View File
@@ -22,7 +22,7 @@ from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
img1 = rgb2gray(data.astronaut())
tform = tf.AffineTransform(scale=(1.2, 1.2), translation=(0, -100))
img2 = tf.warp(img1, tform)
img3 = tf.rotate(img1, 25)
+29
View File
@@ -0,0 +1,29 @@
"""
Using simple NumPy operations for manipulating images
=====================================================
This script illustrates how to use basic NumPy operations, such as slicing,
masking and fancy indexing, in order to modify the pixel values of an image.
"""
import numpy as np
from skimage import data
import matplotlib.pyplot as plt
camera = data.camera()
camera[:10] = 0
mask = camera < 87
camera[mask] = 255
inds_x = np.arange(len(camera))
inds_y = (4 * inds_x) % len(camera)
camera[inds_x, inds_y] = 0
l_x, l_y = camera.shape[0], camera.shape[1]
X, Y = np.ogrid[:l_x, :l_y]
outer_disk_mask = (X - l_x / 2)**2 + (Y - l_y / 2)**2 > (l_x / 2)**2
camera[outer_disk_mask] = 0
plt.figure(figsize=(4, 4))
plt.imshow(camera, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.show()
+3 -3
View File
@@ -19,7 +19,7 @@ import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
from skimage import filter
from skimage import feature
# Generate noisy image of a square
@@ -31,8 +31,8 @@ im = ndimage.gaussian_filter(im, 4)
im += 0.2 * np.random.random(im.shape)
# Compute the Canny filter for two values of sigma
edges1 = filter.canny(im)
edges2 = filter.canny(im, sigma=3)
edges1 = feature.canny(im)
edges2 = feature.canny(im, sigma=3)
# display results
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3))
+1 -1
View File
@@ -15,7 +15,7 @@ from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
img1 = rgb2gray(data.astronaut())
tform = tf.AffineTransform(scale=(1.5, 1.5), rotation=0.5,
translation=(150, -200))
img2 = tf.warp(img1, tform)
@@ -37,16 +37,16 @@ Its size is extended by two times the larger radius.
import numpy as np
import matplotlib.pyplot as plt
from skimage import data, filter, color
from skimage import data, color
from skimage.transform import hough_circle
from skimage.feature import peak_local_max
from skimage.feature import peak_local_max, canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
# Load picture and detect edges
image = img_as_ubyte(data.coins()[0:95, 70:370])
edges = filter.canny(image, sigma=3, low_threshold=10, high_threshold=50)
edges = canny(image, sigma=3, low_threshold=10, high_threshold=50)
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(5, 2))
@@ -60,10 +60,11 @@ radii = []
for radius, h in zip(hough_radii, hough_res):
# For each radius, extract two circles
peaks = peak_local_max(h, num_peaks=2)
num_peaks = 2
peaks = peak_local_max(h, num_peaks=num_peaks)
centers.extend(peaks)
accums.extend(h[peaks[:, 0], peaks[:, 1]])
radii.extend([radius, radius])
radii.extend([radius] * num_peaks)
# Draw the most prominent 5 circles
image = color.gray2rgb(image)
@@ -106,14 +107,15 @@ References
import matplotlib.pyplot as plt
from skimage import data, filter, color
from skimage import data, color
from skimage.feature import canny
from skimage.transform import hough_ellipse
from skimage.draw import ellipse_perimeter
# Load picture, convert to grayscale and detect edges
image_rgb = data.coffee()[0:220, 160:420]
image_gray = color.rgb2gray(image_rgb)
edges = filter.canny(image_gray, sigma=2.0,
edges = canny(image_gray, sigma=2.0,
low_threshold=0.55, high_threshold=0.8)
# Perform a Hough Transform
+9 -9
View File
@@ -1,10 +1,10 @@
"""
=============================
Denoising the picture of Lena
=============================
====================
Denoising a picture
====================
In this example, we denoise a noisy version of the picture of Lena using the
total variation and bilateral denoising filter.
In this example, we denoise a noisy version of the picture of the astronaut
Eileen Collins using the total variation and bilateral denoising filter.
These algorithms typically produce "posterized" images with flat domains
separated by sharp edges. It is possible to change the degree of posterization
@@ -32,10 +32,10 @@ from skimage import data, img_as_float
from skimage.restoration import denoise_tv_chambolle, denoise_bilateral
lena = img_as_float(data.lena())
lena = lena[220:300, 220:320]
astro = img_as_float(data.astronaut())
astro = astro[220:300, 220:320]
noisy = lena + 0.6 * lena.std() * np.random.random(lena.shape)
noisy = astro + 0.6 * astro.std() * np.random.random(astro.shape)
noisy = np.clip(noisy, 0, 1)
fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5))
@@ -58,7 +58,7 @@ ax[1, 0].set_title('(more) TV')
ax[1, 1].imshow(denoise_bilateral(noisy, sigma_range=0.1, sigma_spatial=15))
ax[1, 1].axis('off')
ax[1, 1].set_title('(more) Bilateral')
ax[1, 2].imshow(lena)
ax[1, 2].imshow(astro)
ax[1, 2].axis('off')
ax[1, 2].set_title('original')
+53 -1
View File
@@ -8,10 +8,11 @@ They are discrete differentiation operators, computing an approximation of the
gradient of the image intensity function.
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage.data import camera
from skimage.filter import roberts, sobel
from skimage.filters import roberts, sobel, scharr
image = camera()
@@ -28,4 +29,55 @@ ax1.imshow(edge_sobel, cmap=plt.cm.gray)
ax1.set_title('Sobel Edge Detection')
ax1.axis('off')
plt.tight_layout()
"""
.. image:: PLOT2RST.current_figure
Different operators compute different finite-difference approximations of the
gradient. For example, the Scharr filter results in a better rotational
variance than other filters such as the Sobel filter [1]_ [2]_. The difference
between the two filters is illustrated below on an image that is the
discretization of a rotation-invariant continuous function. The discrepancy
between the two filters is stronger for regions of the image where the
direction of the gradient is close to diagonal, and for regions with high
spatial frequencies.
.. [1] http://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators
.. [2] B. Jaehne, H. Scharr, and S. Koerkel. Principles of filter design. In
Handbook of Computer Vision and Applications. Academic Press, 1999.
"""
x, y = np.ogrid[:100, :100]
# Rotation-invariant image with different spatial frequencies
img = np.exp(1j * np.hypot(x, y)**1.3 / 20.).real
edge_sobel = sobel(img)
edge_scharr = scharr(img)
fig, ((ax0, ax1), (ax2, ax3)) = plt.subplots(nrows=2, ncols=2)
ax0.imshow(edge_sobel, cmap=plt.cm.gray)
ax0.set_title('Sobel Edge Detection')
ax0.axis('off')
ax1.imshow(edge_scharr, cmap=plt.cm.gray)
ax1.set_title('Scharr Edge Detection')
ax1.axis('off')
ax2.imshow(img, cmap=plt.cm.gray)
ax2.set_title('Original image')
ax2.axis('off')
ax3.imshow(edge_scharr - edge_sobel, cmap=plt.cm.jet)
ax3.set_title('difference (Scharr - Sobel)')
ax3.axis('off')
plt.tight_layout()
plt.show()
"""
.. image:: PLOT2RST.current_figure
"""
+1 -1
View File
@@ -10,7 +10,7 @@ coded in an image.
import matplotlib.pyplot as plt
from skimage import data
from skimage.filter.rank import entropy
from skimage.filters.rank import entropy
from skimage.morphology import disk
from skimage.util import img_as_ubyte
+1 -1
View File
@@ -21,7 +21,7 @@ from scipy import ndimage as nd
from skimage import data
from skimage.util import img_as_float
from skimage.filter import gabor_kernel
from skimage.filters import gabor_kernel
def compute_feats(image, kernels):
@@ -1,7 +1,7 @@
"""
=======================================================
Gabors / Primary Visual Cortex "Simple Cells" from Lena
=======================================================
============================================================
Gabors / Primary Visual Cortex "Simple Cells" from an Image
============================================================
How to build a (bio-plausible) "sparse" dictionary (or 'codebook', or
'filterbank') for e.g. image classification without any fancy math and
@@ -10,15 +10,16 @@ with just standard python scientific libraries?
Please find below a short answer ;-)
This simple example shows how to get Gabor-like filters [1]_ using just
the famous Lena image. Gabor filters are good approximations of the
"Simple Cells" [2]_ receptive fields [3]_ found in the mammalian primary
visual cortex (V1) (for details, see e.g. the Nobel-prize winning work
of Hubel & Wiesel done in the 60s [4]_ [5]_).
a simple image. In our example, we use a photograph of the astronaut Eileen
Collins. Gabor filters are good approximations of the "Simple Cells" [2]_
receptive fields [3]_ found in the mammalian primary visual cortex (V1)
(for details, see e.g. the Nobel-prize winning work of Hubel & Wiesel done
in the 60s [4]_ [5]_).
Here we use McQueen's 'kmeans' algorithm [6]_, as a simple biologically
plausible hebbian-like learning rule and we apply it (a) to patches of
the original Lena image (retinal projection), and (b) to patches of an
LGN-like [7]_ Lena image using a simple difference of gaussians (DoG)
the original image (retinal projection), and (b) to patches of an
LGN-like [7]_ image using a simple difference of gaussians (DoG)
approximation.
Enjoy ;-) And keep in mind that getting Gabors on natural image patches
@@ -50,18 +51,18 @@ np.random.seed(42)
patch_shape = 8, 8
n_filters = 49
lena = color.rgb2gray(data.lena())
astro = color.rgb2gray(data.astronaut())
# -- filterbank1 on original Lena
patches1 = view_as_windows(lena, patch_shape)
# -- filterbank1 on original image
patches1 = view_as_windows(astro, patch_shape)
patches1 = patches1.reshape(-1, patch_shape[0] * patch_shape[1])[::8]
fb1, _ = kmeans2(patches1, n_filters, minit='points')
fb1 = fb1.reshape((-1,) + patch_shape)
fb1_montage = montage2d(fb1, rescale_intensity=True)
# -- filterbank2 LGN-like Lena
lena_dog = ndi.gaussian_filter(lena, .5) - ndi.gaussian_filter(lena, 1)
patches2 = view_as_windows(lena_dog, patch_shape)
# -- filterbank2 LGN-like image
astro_dog = ndi.gaussian_filter(astro, .5) - ndi.gaussian_filter(astro, 1)
patches2 = view_as_windows(astro_dog, patch_shape)
patches2 = patches2.reshape(-1, patch_shape[0] * patch_shape[1])[::8]
fb2, _ = kmeans2(patches2, n_filters, minit='points')
fb2 = fb2.reshape((-1,) + patch_shape)
@@ -71,17 +72,17 @@ fb2_montage = montage2d(fb2, rescale_intensity=True)
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
ax0.imshow(lena, cmap=plt.cm.gray)
ax0.set_title("Lena (original)")
ax0.imshow(astro, cmap=plt.cm.gray)
ax0.set_title("Image (original)")
ax1.imshow(fb1_montage, cmap=plt.cm.gray, interpolation='nearest')
ax1.set_title("K-means filterbank (codebook)\non Lena (original)")
ax1.set_title("K-means filterbank (codebook)\non original image")
ax2.imshow(lena_dog, cmap=plt.cm.gray)
ax2.set_title("Lena (LGN-like DoG)")
ax2.imshow(astro_dog, cmap=plt.cm.gray)
ax2.set_title("Image (LGN-like DoG)")
ax3.imshow(fb2_montage, cmap=plt.cm.gray, interpolation='nearest')
ax3.set_title("K-means filterbank (codebook)\non Lena (LGN-like DoG)")
ax3.set_title("K-means filterbank (codebook)\non LGN-like DoG image")
for ax in axes.ravel():
ax.axis('off')
+1 -1
View File
@@ -85,7 +85,7 @@ from skimage.feature import hog
from skimage import data, color, exposure
image = color.rgb2gray(data.lena())
image = color.rgb2gray(data.astronaut())
fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16),
cells_per_block=(1, 1), visualise=True)
+1 -1
View File
@@ -14,7 +14,7 @@ import numpy as np
from scipy import ndimage as nd
import matplotlib.pyplot as plt
from skimage.filter import sobel
from skimage.filters import sobel
from skimage.segmentation import slic, join_segmentations
from skimage.morphology import watershed
from skimage.color import label2rgb
+3 -2
View File
@@ -17,9 +17,10 @@ import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from skimage import data
from skimage.filter import threshold_otsu
from skimage.filters import threshold_otsu
from skimage.segmentation import clear_border
from skimage.morphology import label, closing, square
from skimage.measure import label
from skimage.morphology import closing, square
from skimage.measure import regionprops
from skimage.color import label2rgb
+1 -1
View File
@@ -58,7 +58,7 @@ References
from skimage.transform import (hough_line, hough_line_peaks,
probabilistic_hough_line)
from skimage.filter import canny
from skimage.feature import canny
from skimage import data
import numpy as np
+1 -1
View File
@@ -28,7 +28,7 @@ from skimage.util.dtype import dtype_range
from skimage.util import img_as_ubyte
from skimage import exposure
from skimage.morphology import disk
from skimage.filter import rank
from skimage.filters import rank
matplotlib.rcParams['font.size'] = 9
+1 -1
View File
@@ -20,7 +20,7 @@ import matplotlib.pyplot as plt
from skimage import data
from skimage.morphology import disk
from skimage.filter import threshold_otsu, rank
from skimage.filters import threshold_otsu, rank
from skimage.util import img_as_ubyte
+1 -1
View File
@@ -19,7 +19,7 @@ import matplotlib.pyplot as plt
from skimage.morphology import watershed, disk
from skimage import data
from skimage.filter import rank
from skimage.filters import rank
from skimage.util import img_as_ubyte
+33
View File
@@ -0,0 +1,33 @@
"""
==============
Normalized Cut
==============
This example constructs a Region Adjacency Graph (RAG) and recursively performs
a Normalized Cut on it.
References
----------
.. [1] Shi, J.; Malik, J., "Normalized cuts and image segmentation",
Pattern Analysis and Machine Intelligence,
IEEE Transactions on, vol. 22, no. 8, pp. 888-905, August 2000.
"""
from skimage import data, io, segmentation, color
from skimage.future import graph
from matplotlib import pyplot as plt
img = data.coffee()
labels1 = segmentation.slic(img, compactness=30, n_segments=400)
out1 = color.label2rgb(labels1, img, kind='avg')
g = graph.rag_mean_color(img, labels1, mode='similarity')
labels2 = graph.cut_normalized(labels1, g)
out2 = color.label2rgb(labels2, img, kind='avg')
plt.figure()
io.imshow(out1)
plt.figure()
io.imshow(out2)
io.show()
+41
View File
@@ -0,0 +1,41 @@
"""
=================================================
Non-local means denoising for preserving textures
=================================================
In this example, we denoise a detail of the astronaut image using the non-local
means filter. The non-local means algorithm replaces the value of a pixel by an
average of a selection of other pixels values: small patches centered on the
other pixels are compared to the patch centered on the pixel of interest, and
the average is performed only for pixels that have patches close to the current
patch. As a result, this algorithm can restore well textures, that would be
blurred by other denoising algoritm.
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage import data, img_as_float
from skimage.restoration import nl_means_denoising
astro = img_as_float(data.astronaut())
astro = astro[30:180, 150:300]
noisy = astro + 0.3 * np.random.random(astro.shape)
noisy = np.clip(noisy, 0, 1)
denoise = nl_means_denoising(noisy, 7, 9, 0.08)
fig, ax = plt.subplots(ncols=2, figsize=(8, 4))
ax[0].imshow(noisy)
ax[0].axis('off')
ax[0].set_title('noisy')
ax[1].imshow(denoise)
ax[1].axis('off')
ax[1].set_title('non-local means')
fig.subplots_adjust(wspace=0.02, hspace=0.2,
top=0.9, bottom=0.05, left=0, right=1)
plt.show()
+1 -1
View File
@@ -20,7 +20,7 @@ from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
img1 = rgb2gray(data.astronaut())
img2 = tf.rotate(img1, 180)
tform = tf.AffineTransform(scale=(1.3, 1.1), rotation=0.5,
translation=(0, -200))
+1 -1
View File
@@ -18,7 +18,7 @@ import matplotlib
import matplotlib.pyplot as plt
from skimage.data import camera
from skimage.filter import threshold_otsu
from skimage.filters import threshold_otsu
matplotlib.rcParams['font.size'] = 9
+1 -1
View File
@@ -92,7 +92,7 @@ is clear: Without unwrapping (lower left), the regions above and below the
masked boundary do not interact at all, resulting in an offset between the
two regions of an arbitrary integer times two pi. We could just as well have
unwrapped the regions as two separate images. With wrap around enabled for the
vertical direction (lower rigth), the situation changes: Unwrapping paths are
vertical direction (lower right), the situation changes: Unwrapping paths are
now allowed to pass from the bottom to the top of the image and vice versa, in
effect providing a way to determine the offset between the two regions.
+1 -1
View File
@@ -12,7 +12,7 @@ from skimage.transform import PiecewiseAffineTransform, warp
from skimage import data
image = data.lena()
image = data.astronaut()
rows, cols = image.shape[0], image.shape[1]
src_cols = np.linspace(0, cols, 20)
+1 -1
View File
@@ -16,7 +16,7 @@ from skimage import data
from skimage.transform import pyramid_gaussian
image = data.lena()
image = data.astronaut()
rows, cols, dim = image.shape
pyramid = tuple(pyramid_gaussian(image, downscale=2))
+7 -7
View File
@@ -4,11 +4,11 @@ Radon transform
===============
In computed tomography, the tomography reconstruction problem is to obtain
a tomographic slice image from a set of projections [1]_. A projection is formed
by drawing a set of parallel rays through the 2D object of interest, assigning
the integral of the object's contrast along each ray to a single pixel in the
projection. A single projection of a 2D object is one dimensional. To
enable computed tomography reconstruction of the object, several projections
a tomographic slice image from a set of projections [1]_. A projection is
formed by drawing a set of parallel rays through the 2D object of interest,
assigning the integral of the object's contrast along each ray to a single
pixel in the projection. A single projection of a 2D object is one dimensional.
To enable computed tomography reconstruction of the object, several projections
must be acquired, each of them corresponding to a different angle between the
rays with respect to the object. A collection of projections at several angles
is called a sinogram, which is a linear transform of the original image.
@@ -29,7 +29,7 @@ and reconstructing the original image are compared: The Filtered Back
Projection (FBP) and the Simultaneous Algebraic Reconstruction
Technique (SART).
.. seealso::
For further information on tomographic reconstruction, see
- AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging",
http://www.slaney.org/pct/pct-toc.html
@@ -65,7 +65,7 @@ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
ax1.set_title("Original")
ax1.imshow(image, cmap=plt.cm.Greys_r)
theta = np.linspace(0., 180., max(image.shape), endpoint=True)
theta = np.linspace(0., 180., max(image.shape), endpoint=False)
sinogram = radon(image, theta=theta, circle=True)
ax2.set_title("Radon transform\n(Sinogram)")
ax2.set_xlabel("Projection angle (deg)")
+81
View File
@@ -0,0 +1,81 @@
"""
=======================
Region Adjacency Graphs
=======================
This example demonstrates the use of the `merge_nodes` function of a Region
Adjacency Graph (RAG). The `RAG` class represents a undirected weighted graph
which inherits from `networkx.graph` class. When a new node is formed by
merging two nodes, the edge weight of all the edges incident on the resulting
node can be updated by a user defined function `weight_func`.
The default behaviour is to use the smaller edge weight in case of a conflict.
The example below also shows how to use a custom function to select the larger
weight instead.
"""
from skimage.future.graph import rag
import networkx as nx
from matplotlib import pyplot as plt
import numpy as np
def max_edge(g, src, dst, n):
"""Callback to handle merging nodes by choosing maximum weight.
Returns either the weight between (`src`, `n`) or (`dst`, `n`)
in `g` or the maximum of the two when both exist.
Parameters
----------
g : RAG
The graph under consideration.
src, dst : int
The vertices in `g` to be merged.
n : int
A neighbor of `src` or `dst` or both.
Returns
-------
weight : float
The weight between (`src`, `n`) or (`dst`, `n`) in `g` or the
maximum of the two when both exist.
"""
w1 = g[n].get(src, {'weight': -np.inf})['weight']
w2 = g[n].get(dst, {'weight': -np.inf})['weight']
return max(w1, w2)
def display(g, title):
"""Displays a graph with the given title."""
pos = nx.circular_layout(g)
plt.figure()
plt.title(title)
nx.draw(g, pos)
nx.draw_networkx_edge_labels(g, pos, font_size=20)
g = rag.RAG()
g.add_edge(1, 2, weight=10)
g.add_edge(2, 3, weight=20)
g.add_edge(3, 4, weight=30)
g.add_edge(4, 1, weight=40)
g.add_edge(1, 3, weight=50)
# Assigning dummy labels.
for n in g.nodes():
g.node[n]['labels'] = [n]
gc = g.copy()
display(g, "Original Graph")
g.merge_nodes(1, 3)
display(g, "Merged with default (min)")
gc.merge_nodes(1, 3, weight_func=max_edge, in_place=False)
display(gc, "Merged with max without in_place")
plt.show()
+40
View File
@@ -0,0 +1,40 @@
"""
======================================
Drawing Region Adjacency Graphs (RAGs)
======================================
This example constructs a Region Adjacency Graph (RAG) and draws it with
the `rag_draw` method.
"""
from skimage import data, segmentation
from skimage.future import graph
from matplotlib import pyplot as plt, colors
img = data.coffee()
labels = segmentation.slic(img, compactness=30, n_segments=400)
g = graph.rag_mean_color(img, labels)
out = graph.draw_rag(labels, g, img)
plt.figure()
plt.title("RAG with all edges shown in green.")
plt.imshow(out)
# The color palette used was taken from
# http://www.colorcombos.com/color-schemes/2/ColorCombo2.html
cmap = colors.ListedColormap(['#6599FF', '#ff9900'])
out = graph.draw_rag(labels, g, img, node_color="#ffde00", colormap=cmap,
thresh=30, desaturate=True)
plt.figure()
plt.title("RAG with edge weights less than 30, color "
"mapped between blue and orange.")
plt.imshow(out)
plt.figure()
plt.title("All edges drawn with cubehelix colormap")
cmap = plt.get_cmap('cubehelix')
out = graph.draw_rag(labels, g, img, colormap=cmap,
desaturate=True)
plt.imshow(out)
plt.show()
+30
View File
@@ -0,0 +1,30 @@
"""
================
RAG Thresholding
================
This example constructs a Region Adjacency Graph (RAG) and merges regions
which are similar in color. We construct a RAG and define edges as the
difference in mean color. We then join regions with similar mean color.
"""
from skimage import data, io, segmentation, color
from skimage.future import graph
from matplotlib import pyplot as plt
img = data.coffee()
labels1 = segmentation.slic(img, compactness=30, n_segments=400)
out1 = color.label2rgb(labels1, img, kind='avg')
g = graph.rag_mean_color(img, labels1)
labels2 = graph.cut_threshold(labels1, g, 29)
out2 = color.label2rgb(labels2, img, kind='avg')
plt.figure()
io.imshow(out1)
plt.figure()
io.imshow(out2)
io.show()
+75
View File
@@ -0,0 +1,75 @@
"""
===========
RAG Merging
===========
This example constructs a Region Adjacency Graph (RAG) and progressively merges
regions that are similar in color. Merging two adjacent regions produces
a new region with all the pixels from the merged regions. Regions are merged
until no highly similar region pairs remain.
"""
from skimage import data, io, segmentation, color
from skimage.future import graph
import numpy as np
def _weight_mean_color(graph, src, dst, n):
"""Callback to handle merging nodes by recomputing mean color.
The method expects that the mean color of `dst` is already computed.
Parameters
----------
graph : RAG
The graph under consideration.
src, dst : int
The vertices in `graph` to be merged.
n : int
A neighbor of `src` or `dst` or both.
Returns
-------
weight : float
The absolute difference of the mean color between node `dst` and `n`.
"""
diff = graph.node[dst]['mean color'] - graph.node[n]['mean color']
diff = np.linalg.norm(diff)
return diff
def merge_mean_color(graph, src, dst):
"""Callback called before merging two nodes of a mean color distance graph.
This method computes the mean color of `dst`.
Parameters
----------
graph : RAG
The graph under consideration.
src, dst : int
The vertices in `graph` to be merged.
"""
graph.node[dst]['total color'] += graph.node[src]['total color']
graph.node[dst]['pixel count'] += graph.node[src]['pixel count']
graph.node[dst]['mean color'] = (graph.node[dst]['total color'] /
graph.node[dst]['pixel count'])
img = data.coffee()
labels = segmentation.slic(img, compactness=30, n_segments=400)
g = graph.rag_mean_color(img, labels)
labels2 = graph.merge_hierarchical(labels, g, thresh=40, rag_copy=False,
in_place_merge=True,
merge_func=merge_mean_color,
weight_func=_weight_mean_color)
g2 = graph.rag_mean_color(img, labels2)
out = color.label2rgb(labels2, img, kind='avg')
out = segmentation.mark_boundaries(out, labels2, (0, 0, 0))
io.imshow(out)
io.show()
+1 -1
View File
@@ -23,7 +23,7 @@ import matplotlib.pyplot as plt
from skimage import data
from skimage.morphology import disk
from skimage.filter import rank
from skimage.filters import rank
image = (data.coins()).astype(np.uint16) * 16
+1 -2
View File
@@ -11,8 +11,7 @@ import matplotlib.pyplot as plt
import numpy as np
from skimage.draw import ellipse
from skimage.morphology import label
from skimage.measure import regionprops
from skimage.measure import label, regionprops
from skimage.transform import rotate
+85
View File
@@ -0,0 +1,85 @@
"""
=====================================
Cross-Correlation (Phase Correlation)
=====================================
In this example, we use phase correlation to identify the relative shift
between two similar-sized images.
The ``register_translation`` function uses cross-correlation in Fourier space,
optionally employing an upsampled matrix-multiplication DFT to achieve
arbitrary subpixel precision. [1]_
.. [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
"Efficient subpixel image registration algorithms," Optics Letters 33,
156-158 (2008).
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import register_translation
from skimage.feature.register_translation import _upsampled_dft
from scipy.ndimage.fourier import fourier_shift
image = data.camera()
shift = (-2.4, 1.32)
# (-2.4, 1.32) pixel offset relative to reference coin
offset_image = fourier_shift(np.fft.fftn(image), shift)
offset_image = np.fft.ifftn(offset_image)
print("Known offset (y, x):")
print(shift)
# pixel precision first
shift, error, diffphase = register_translation(image, offset_image)
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3))
ax1.imshow(image)
ax1.set_axis_off()
ax1.set_title('Reference image')
ax2.imshow(offset_image.real)
ax2.set_axis_off()
ax2.set_title('Offset image')
# View the output of a cross-correlation to show what the algorithm is
# doing behind the scenes
image_product = np.fft.fft2(image) * np.fft.fft2(offset_image).conj()
cc_image = np.fft.fftshift(np.fft.ifft2(image_product))
ax3.imshow(cc_image.real)
ax3.set_axis_off()
ax3.set_title("Cross-correlation")
plt.show()
print("Detected pixel offset (y, x):")
print(shift)
# subpixel precision
shift, error, diffphase = register_translation(image, offset_image, 100)
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3))
ax1.imshow(image)
ax1.set_axis_off()
ax1.set_title('Reference image')
ax2.imshow(offset_image.real)
ax2.set_axis_off()
ax2.set_title('Offset image')
# Calculate the upsampled DFT, again to show what the algorithm is doing
# behind the scenes. Constants correspond to calculated values in routine.
# See source code for details.
cc_image = _upsampled_dft(image_product, 150, 100, (shift*100)+75).conj()
ax3.imshow(cc_image.real)
ax3.set_axis_off()
ax3.set_title("Supersampled XC sub-area")
plt.show()
print("Detected subpixel offset (y, x):")
print(shift)
+7 -7
View File
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
"""
=====================
Deconvolution of Lena
Image Deconvolution
=====================
In this example, we deconvolve a noisy version of Lena using Wiener
In this example, we deconvolve a noisy version of an image using Wiener
and unsupervised Wiener algorithms. This algorithms are based on
linear models that can't restore sharp edge as much as non-linear
methods (like TV restoration) but are much faster.
@@ -34,19 +34,19 @@ import matplotlib.pyplot as plt
from skimage import color, data, restoration
lena = color.rgb2gray(data.lena())
astro = color.rgb2gray(data.astronaut())
from scipy.signal import convolve2d as conv2
psf = np.ones((5, 5)) / 25
lena = conv2(lena, psf, 'same')
lena += 0.1 * lena.std() * np.random.standard_normal(lena.shape)
astro = conv2(astro, psf, 'same')
astro += 0.1 * astro.std() * np.random.standard_normal(astro.shape)
deconvolved, _ = restoration.unsupervised_wiener(lena, psf)
deconvolved, _ = restoration.unsupervised_wiener(astro, psf)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 5))
plt.gray()
ax[0].imshow(lena, vmin=deconvolved.min(), vmax=deconvolved.max())
ax[0].imshow(astro, vmin=deconvolved.min(), vmax=deconvolved.max())
ax[0].axis('off')
ax[0].set_title('Data')
+2 -2
View File
@@ -63,12 +63,12 @@ from __future__ import print_function
import matplotlib.pyplot as plt
import numpy as np
from skimage.data import lena
from skimage.data import astronaut
from skimage.segmentation import felzenszwalb, slic, quickshift
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
img = img_as_float(lena()[::2, ::2])
img = img_as_float(astronaut()[::2, ::2])
segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50)
segments_slic = slic(img, n_segments=250, compactness=10, sigma=1)
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
+1 -1
View File
@@ -18,7 +18,7 @@ local neighborhood minus an offset value.
import matplotlib.pyplot as plt
from skimage import data
from skimage.filter import threshold_otsu, threshold_adaptive
from skimage.filters import threshold_otsu, threshold_adaptive
image = data.page()
@@ -37,7 +37,7 @@ ax2.imshow(yellow_multiplier * image)
In many cases, dealing with RGB values may not be ideal. Because of that, there
are many other `color spaces`_ in which you can represent a color image. One
popular color space is called HSV_, which represents hue (~the color),
popular color space is called HSV, which represents hue (~the color),
saturation (~colorfulness), and value (~brightness). For example, a color
(hue) might be green, but its saturation is how intense that green is---where
olive is on the low end and neon on the high end.
@@ -46,6 +46,9 @@ In some implementations, the hue in HSV goes from 0 to 360, since hues wrap
around in a circle. In scikit-image, however, hues are float values from 0 to
1, so that hue, saturation, and value all share the same scale.
.. _color spaces:
http://en.wikipedia.org/wiki/List_of_color_spaces_and_their_uses
Below, we plot a linear gradient in the hue, with the saturation and value
turned all the way up:
"""
@@ -69,6 +72,8 @@ Notice how the colors at the far left and far right are the same. That reflects
the fact that the hues wrap around like the color wheel (see HSV_ for more
info).
.. _HSV: http://en.wikipedia.org/wiki/HSL_and_HSV
Now, let's create a little utility function to take an RGB image and:
1. Transform the RGB image to HSV
@@ -116,7 +121,7 @@ thresholding. In practice, you might want to define a region for tinting based
on segmentation results or blob detection methods.
"""
from skimage.filter import rank
from skimage.filters import rank
# Square regions defined as slices over the first two dimensions.
top_left = (slice(100),) * 2
@@ -147,7 +152,4 @@ plt.show()
For coloring multiple regions, you may also be interested in
`skimage.color.label2rgb <http://scikit-image.org/docs/0.9.x/api/skimage.color.html#label2rgb>`_.
.. _color spaces:
http://en.wikipedia.org/wiki/List_of_color_spaces_and_their_uses
.. _HSV: http://en.wikipedia.org/wiki/HSL_and_HSV
"""
+6 -6
View File
@@ -7,10 +7,10 @@ This example illustrates the use of `view_as_blocks` from
`skimage.util.shape`. Block views can be incredibly useful when one
wants to perform local operations on non-overlapping image patches.
We use `lena` from `skimage.data` and virtually 'slice' it into square
We use `astronaut` from `skimage.data` and virtually 'slice' it into square
blocks. Then, on each block, we either pool the mean, the max or the
median value of that block. The results are displayed altogether, along
with a spline interpolation of order 3 rescaling of the original `lena`
with a spline interpolation of order 3 rescaling of the original `astronaut`
image.
"""
@@ -24,20 +24,20 @@ from skimage import color
from skimage.util.shape import view_as_blocks
# -- get `lena` from skimage.data in grayscale
l = color.rgb2gray(data.lena())
# -- get `astronaut` from skimage.data in grayscale
l = color.rgb2gray(data.astronaut())
# -- size of blocks
block_shape = (4, 4)
# -- see `lena` as a matrix of blocks (of shape
# -- see `astronaut` as a matrix of blocks (of shape
# `block_shape`)
view = view_as_blocks(l, block_shape)
# -- collapse the last two dimensions in one
flatten_view = view.reshape(view.shape[0], view.shape[1], -1)
# -- resampling `lena` by taking either the `mean`,
# -- resampling `astronaut` by taking either the `mean`,
# the `max` or the `median` value of each blocks.
mean_view = np.mean(flatten_view, axis=2)
max_view = np.max(flatten_view, axis=2)
+137
View File
@@ -0,0 +1,137 @@
from __future__ import division
"""
========================
Sliding window histogram
========================
Histogram matching can be used for object detection in images [1]_. This
example extracts a single coin from the `skimage.data.coins` image and uses
histogram matching to attempt to locate it within the original image.
First, a box-shaped region of the image containing the target coin is
extracted and a histogram of its greyscale values is computed.
Next, for each pixel in the test image, a histogram of the greyscale values in
a region of the image surrounding the pixel is computed.
`skimage.filters.rank.windowed_histogram` is used for this task, as it employs
an efficient sliding window based algorithm that is able to compute these
histograms quickly [2]_. The local histogram for the region surrounding each
pixel in the image is compared to that of the single coin, with a similarity
measure being computed and displayed.
The histogram of the single coin is computed using `numpy.histogram` on a box
shaped region surrounding the coin, while the sliding window histograms are
computed using a disc shaped structural element of a slightly different size.
This is done in aid of demonstrating that the technique still finds similarity
in spite of these differences.
To demonstrate the rotational invariance of the technique, the same test is
performed on a version of the coins image rotated by 45 degrees.
References
----------
.. [1] Porikli, F. "Integral Histogram: A Fast Way to Extract Histograms
in Cartesian Spaces" CVPR, 2005. Vol. 1. IEEE, 2005
.. [2] S.Perreault and P.Hebert. Median filtering in constant time.
Trans. Image Processing, 16(9):2389-2394, 2007.
"""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from skimage import data, transform
from skimage.util import img_as_ubyte
from skimage.morphology import disk
from skimage.filters import rank
matplotlib.rcParams['font.size'] = 9
def windowed_histogram_similarity(image, selem, reference_hist, n_bins):
# Compute normalized windowed histogram feature vector for each pixel
px_histograms = rank.windowed_histogram(image, selem, n_bins=n_bins)
# Reshape coin histogram to (1,1,N) for broadcast when we want to use it in
# arithmetic operations with the windowed histograms from the image
reference_hist = reference_hist.reshape((1, 1) + reference_hist.shape)
# Compute Chi squared distance metric: sum((X-Y)^2 / (X+Y));
# a measure of distance between histograms
X = px_histograms
Y = reference_hist
num = (X - Y) ** 2
denom = X + Y
denom[denom == 0] = np.infty
frac = num / denom
chi_sqr = 0.5 * np.sum(frac, axis=2)
# Generate a similarity measure. It needs to be low when distance is high
# and high when distance is low; taking the reciprocal will do this.
# Chi squared will always be >= 0, add small value to prevent divide by 0.
similarity = 1 / (chi_sqr + 1.0e-4)
return similarity
# Load the `skimage.data.coins` image
img = img_as_ubyte(data.coins())
# Quantize to 16 levels of greyscale; this way the output image will have a
# 16-dimensional feature vector per pixel
quantized_img = img // 16
# Select the coin from the 4th column, second row.
# Co-ordinate ordering: [x1,y1,x2,y2]
coin_coords = [184, 100, 228, 148] # 44 x 44 region
coin = quantized_img[coin_coords[1]:coin_coords[3],
coin_coords[0]:coin_coords[2]]
# Compute coin histogram and normalize
coin_hist, _ = np.histogram(coin.flatten(), bins=16, range=(0, 16))
coin_hist = coin_hist.astype(float) / np.sum(coin_hist)
# Compute a disk shaped mask that will define the shape of our sliding window
# Example coin is ~44px across, so make a disk 61px wide (2 * rad + 1) to be
# big enough for other coins too.
selem = disk(30)
# Compute the similarity across the complete image
similarity = windowed_histogram_similarity(quantized_img, selem, coin_hist,
coin_hist.shape[0])
# Now try a rotated image
rotated_img = img_as_ubyte(transform.rotate(img, 45.0, resize=True))
# Quantize to 16 levels as before
quantized_rotated_image = rotated_img // 16
# Similarity on rotated image
rotated_similarity = windowed_histogram_similarity(quantized_rotated_image,
selem, coin_hist,
coin_hist.shape[0])
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
axes[0, 0].imshow(quantized_img, cmap='gray')
axes[0, 0].set_title('Quantized image')
axes[0, 0].axis('off')
axes[0, 1].imshow(coin, cmap='gray')
axes[0, 1].set_title('Coin from 2nd row, 4th column')
axes[0, 1].axis('off')
axes[1, 0].imshow(img, cmap='gray')
axes[1, 0].imshow(similarity, cmap='hot', alpha=0.5)
axes[1, 0].set_title('Original image with overlaid similarity')
axes[1, 0].axis('off')
axes[1, 1].imshow(rotated_img, cmap='gray')
axes[1, 1].imshow(rotated_similarity, cmap='hot', alpha=0.5)
axes[1, 1].set_title('Rotated image with overlaid similarity')
axes[1, 1].axis('off')
plt.show()
+1 -1
View File
@@ -15,7 +15,7 @@ The file
- plot_directive.py
was derived from code in Matplotlib (http://matplotlib.sf.net/), which has the
was derived from code in Matplotlib (http://matplotlib.org), which has the
following license:
Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved.
+68 -25
View File
@@ -1,13 +1,16 @@
"""Extract reference documentation from the NumPy source tree.
"""
from __future__ import division, absolute_import, print_function
import inspect
import textwrap
import re
import pydoc
from StringIO import StringIO
from warnings import warn
import collections
import sys
class Reader(object):
"""A line-based string reader.
@@ -113,7 +116,7 @@ class NumpyDocString(object):
return self._parsed_data[key]
def __setitem__(self,key,val):
if not self._parsed_data.has_key(key):
if key not in self._parsed_data:
warn("Unknown section %s" % key)
else:
self._parsed_data[key] = val
@@ -265,13 +268,17 @@ class NumpyDocString(object):
if self._is_at_section():
return
summary = self._doc.read_to_next_empty_line()
summary_str = " ".join([s.strip() for s in summary]).strip()
if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
self['Signature'] = summary_str
if not self._is_at_section():
self['Summary'] = self._doc.read_to_next_empty_line()
else:
# If several signatures present, take the last one
while True:
summary = self._doc.read_to_next_empty_line()
summary_str = " ".join([s.strip() for s in summary]).strip()
if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
self['Signature'] = summary_str
if not self._is_at_section():
continue
break
if summary is not None:
self['Summary'] = summary
if not self._is_at_section():
@@ -328,7 +335,10 @@ class NumpyDocString(object):
if self[name]:
out += self._str_header(name)
for param,param_type,desc in self[name]:
out += ['%s : %s' % (param, param_type)]
if param_type:
out += ['%s : %s' % (param, param_type)]
else:
out += [param]
out += self._str_indent(desc)
out += ['']
return out
@@ -370,7 +380,7 @@ class NumpyDocString(object):
idx = self['index']
out = []
out += ['.. index:: %s' % idx.get('default','')]
for section, references in idx.iteritems():
for section, references in idx.items():
if section == 'default':
continue
out += [' :%s: %s' % (section, ', '.join(references))]
@@ -424,11 +434,14 @@ class FunctionDoc(NumpyDocString):
func, func_name = self.get_func()
try:
# try to read signature
argspec = inspect.getargspec(func)
if sys.version_info[0] >= 3:
argspec = inspect.getfullargspec(func)
else:
argspec = inspect.getargspec(func)
argspec = inspect.formatargspec(*argspec)
argspec = argspec.replace('*','\*')
signature = '%s%s' % (func_name, argspec)
except TypeError, e:
except TypeError as e:
signature = '%s()' % func_name
self['Signature'] = signature
@@ -450,8 +463,8 @@ class FunctionDoc(NumpyDocString):
'meth': 'method'}
if self._role:
if not roles.has_key(self._role):
print "Warning: invalid role %s" % self._role
if self._role not in roles:
print("Warning: invalid role %s" % self._role)
out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''),
func_name)
@@ -460,12 +473,18 @@ class FunctionDoc(NumpyDocString):
class ClassDoc(NumpyDocString):
extra_public_methods = ['__call__']
def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
config={}):
if not inspect.isclass(cls) and cls is not None:
raise ValueError("Expected a class or None, but got %r" % cls)
self._cls = cls
self.show_inherited_members = config.get('show_inherited_class_members',
True)
if modulename and not modulename.endswith('.'):
modulename += '.'
self._mod = modulename
@@ -478,23 +497,47 @@ class ClassDoc(NumpyDocString):
NumpyDocString.__init__(self, doc)
if config.get('show_class_members', True):
if not self['Methods']:
self['Methods'] = [(name, '', '')
for name in sorted(self.methods)]
if not self['Attributes']:
self['Attributes'] = [(name, '', '')
for name in sorted(self.properties)]
def splitlines_x(s):
if not s:
return []
else:
return s.splitlines()
for field, items in [('Methods', self.methods),
('Attributes', self.properties)]:
if not self[field]:
doc_list = []
for name in sorted(items):
try:
doc_item = pydoc.getdoc(getattr(self._cls, name))
doc_list.append((name, '', splitlines_x(doc_item)))
except AttributeError:
pass # method doesn't exist
self[field] = doc_list
@property
def methods(self):
if self._cls is None:
return []
return [name for name,func in inspect.getmembers(self._cls)
if not name.startswith('_') and callable(func)]
return [name for name, func in inspect.getmembers(self._cls)
if ((not name.startswith('_')
or name in self.extra_public_methods)
and isinstance(func, collections.Callable)
and self._is_show_member(name))]
@property
def properties(self):
if self._cls is None:
return []
return [name for name,func in inspect.getmembers(self._cls)
if not name.startswith('_') and func is None]
return [name for name, func in inspect.getmembers(self._cls)
if (not name.startswith('_') and
(func is None or isinstance(func, property) or
inspect.isgetsetdescriptor(func))
and self._is_show_member(name))]
def _is_show_member(self, name):
if self.show_inherited_members:
return True # show all class members
if name not in self._cls.__dict__:
return False # class member is inherited, we do not show it
return True
+71 -24
View File
@@ -1,11 +1,24 @@
import re, inspect, textwrap, pydoc
from __future__ import division, absolute_import, print_function
import sys, re, inspect, textwrap, pydoc
import sphinx
import collections
from docscrape import NumpyDocString, FunctionDoc, ClassDoc
if sys.version_info[0] >= 3:
sixu = lambda s: s
else:
sixu = lambda s: unicode(s, 'unicode_escape')
class SphinxDocString(NumpyDocString):
def __init__(self, docstring, config={}):
self.use_plots = config.get('use_plots', False)
NumpyDocString.__init__(self, docstring, config=config)
self.load_config(config)
def load_config(self, config):
self.use_plots = config.get('use_plots', False)
self.class_members_toctree = config.get('class_members_toctree', True)
# string conversion routines
def _str_header(self, name, symbol='`'):
@@ -33,16 +46,37 @@ class SphinxDocString(NumpyDocString):
def _str_extended_summary(self):
return self['Extended Summary'] + ['']
def _str_returns(self):
out = []
if self['Returns']:
out += self._str_field_list('Returns')
out += ['']
for param, param_type, desc in self['Returns']:
if param_type:
out += self._str_indent(['**%s** : %s' % (param.strip(),
param_type)])
else:
out += self._str_indent([param.strip()])
if desc:
out += ['']
out += self._str_indent(desc, 8)
out += ['']
return out
def _str_param_list(self, name):
out = []
if self[name]:
out += self._str_field_list(name)
out += ['']
for param,param_type,desc in self[name]:
out += self._str_indent(['**%s** : %s' % (param.strip(),
param_type)])
out += ['']
out += self._str_indent(desc,8)
for param, param_type, desc in self[name]:
if param_type:
out += self._str_indent(['**%s** : %s' % (param.strip(),
param_type)])
else:
out += self._str_indent(['**%s**' % param.strip()])
if desc:
out += ['']
out += self._str_indent(desc, 8)
out += ['']
return out
@@ -72,25 +106,36 @@ class SphinxDocString(NumpyDocString):
others = []
for param, param_type, desc in self[name]:
param = param.strip()
if not self._obj or hasattr(self._obj, param):
# Check if the referenced member can have a docstring or not
param_obj = getattr(self._obj, param, None)
if not (callable(param_obj)
or isinstance(param_obj, property)
or inspect.isgetsetdescriptor(param_obj)):
param_obj = None
if param_obj and (pydoc.getdoc(param_obj) or not desc):
# Referenced object has a docstring
autosum += [" %s%s" % (prefix, param)]
else:
others.append((param, param_type, desc))
if autosum:
out += ['.. autosummary::', ' :toctree:', '']
out += autosum
out += ['.. autosummary::']
if self.class_members_toctree:
out += [' :toctree:']
out += [''] + autosum
if others:
maxlen_0 = max([len(x[0]) for x in others])
maxlen_1 = max([len(x[1]) for x in others])
hdr = "="*maxlen_0 + " " + "="*maxlen_1 + " " + "="*10
fmt = '%%%ds %%%ds ' % (maxlen_0, maxlen_1)
n_indent = maxlen_0 + maxlen_1 + 4
out += [hdr]
maxlen_0 = max(3, max([len(x[0]) for x in others]))
hdr = sixu("=")*maxlen_0 + sixu(" ") + sixu("=")*10
fmt = sixu('%%%ds %%s ') % (maxlen_0,)
out += ['', hdr]
for param, param_type, desc in others:
out += [fmt % (param.strip(), param_type)]
out += self._str_indent(desc, n_indent)
desc = sixu(" ").join(x.strip() for x in desc).strip()
if param_type:
desc = "(%s) %s" % (param_type, desc)
out += [fmt % (param.strip(), desc)]
out += [hdr]
out += ['']
return out
@@ -127,7 +172,7 @@ class SphinxDocString(NumpyDocString):
return out
out += ['.. index:: %s' % idx.get('default','')]
for section, references in idx.iteritems():
for section, references in idx.items():
if section == 'default':
continue
elif section == 'refguide':
@@ -178,8 +223,9 @@ class SphinxDocString(NumpyDocString):
out += self._str_index() + ['']
out += self._str_summary()
out += self._str_extended_summary()
for param_list in ('Parameters', 'Returns', 'Other Parameters',
'Raises', 'Warns'):
out += self._str_param_list('Parameters')
out += self._str_returns()
for param_list in ('Other Parameters', 'Raises', 'Warns'):
out += self._str_param_list(param_list)
out += self._str_warnings()
out += self._str_see_also(func_role)
@@ -193,17 +239,18 @@ class SphinxDocString(NumpyDocString):
class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
def __init__(self, obj, doc=None, config={}):
self.use_plots = config.get('use_plots', False)
self.load_config(config)
FunctionDoc.__init__(self, obj, doc=doc, config=config)
class SphinxClassDoc(SphinxDocString, ClassDoc):
def __init__(self, obj, doc=None, func_doc=None, config={}):
self.use_plots = config.get('use_plots', False)
self.load_config(config)
ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config)
class SphinxObjDoc(SphinxDocString):
def __init__(self, obj, doc=None, config={}):
self._f = obj
self.load_config(config)
SphinxDocString.__init__(self, doc, config=config)
def get_doc_object(obj, what=None, doc=None, config={}):
@@ -212,7 +259,7 @@ def get_doc_object(obj, what=None, doc=None, config={}):
what = 'class'
elif inspect.ismodule(obj):
what = 'module'
elif callable(obj):
elif isinstance(obj, collections.Callable):
what = 'function'
else:
what = 'object'
+53 -25
View File
@@ -12,45 +12,68 @@ It will:
- Renumber references.
- Extract the signature from the docstring, if it can't be determined otherwise.
.. [1] http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard
.. [1] https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
"""
from __future__ import division, absolute_import, print_function
import sys
import re
import pydoc
import sphinx
import inspect
import collections
if sphinx.__version__ < '1.0.1':
raise RuntimeError("Sphinx 1.0.1 or newer is required")
import os, re, pydoc
from docscrape_sphinx import get_doc_object, SphinxDocString
from sphinx.util.compat import Directive
import inspect
if sys.version_info[0] >= 3:
sixu = lambda s: s
else:
sixu = lambda s: unicode(s, 'unicode_escape')
def mangle_docstrings(app, what, name, obj, options, lines,
reference_offset=[0]):
cfg = dict(use_plots=app.config.numpydoc_use_plots,
show_class_members=app.config.numpydoc_show_class_members)
cfg = dict(
use_plots=app.config.numpydoc_use_plots,
show_class_members=app.config.numpydoc_show_class_members,
show_inherited_class_members=app.config.numpydoc_show_inherited_class_members,
class_members_toctree=app.config.numpydoc_class_members_toctree,
)
if what == 'module':
# Strip top title
title_re = re.compile(ur'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*',
title_re = re.compile(sixu('^\\s*[#*=]{4,}\\n[a-z0-9 -]+\\n[#*=]{4,}\\s*'),
re.I|re.S)
lines[:] = title_re.sub(u'', u"\n".join(lines)).split(u"\n")
lines[:] = title_re.sub(sixu(''), sixu("\n").join(lines)).split(sixu("\n"))
else:
doc = get_doc_object(obj, what, u"\n".join(lines), config=cfg)
lines[:] = unicode(doc).split(u"\n")
doc = get_doc_object(obj, what, sixu("\n").join(lines), config=cfg)
if sys.version_info[0] >= 3:
doc = str(doc)
else:
doc = unicode(doc)
lines[:] = doc.split(sixu("\n"))
if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \
obj.__name__:
if hasattr(obj, '__module__'):
v = dict(full_name=u"%s.%s" % (obj.__module__, obj.__name__))
v = dict(full_name=sixu("%s.%s") % (obj.__module__, obj.__name__))
else:
v = dict(full_name=obj.__name__)
lines += [u'', u'.. htmlonly::', '']
lines += [u' %s' % x for x in
lines += [sixu(''), sixu('.. htmlonly::'), sixu('')]
lines += [sixu(' %s') % x for x in
(app.config.numpydoc_edit_link % v).split("\n")]
# replace reference numbers so that there are no duplicates
references = []
for line in lines:
line = line.strip()
m = re.match(ur'^.. \[([a-z0-9_.-])\]', line, re.I)
m = re.match(sixu('^.. \\[([a-z0-9_.-])\\]'), line, re.I)
if m:
references.append(m.group(1))
@@ -59,14 +82,14 @@ def mangle_docstrings(app, what, name, obj, options, lines,
if references:
for i, line in enumerate(lines):
for r in references:
if re.match(ur'^\d+$', r):
new_r = u"R%d" % (reference_offset[0] + int(r))
if re.match(sixu('^\\d+$'), r):
new_r = sixu("R%d") % (reference_offset[0] + int(r))
else:
new_r = u"%s%d" % (r, reference_offset[0])
lines[i] = lines[i].replace(u'[%s]_' % r,
u'[%s]_' % new_r)
lines[i] = lines[i].replace(u'.. [%s]' % r,
u'.. [%s]' % new_r)
new_r = sixu("%s%d") % (r, reference_offset[0])
lines[i] = lines[i].replace(sixu('[%s]_') % r,
sixu('[%s]_') % new_r)
lines[i] = lines[i].replace(sixu('.. [%s]') % r,
sixu('.. [%s]') % new_r)
reference_offset[0] += len(references)
@@ -77,15 +100,18 @@ def mangle_signature(app, what, name, obj, options, sig, retann):
'initializes x; see ' in pydoc.getdoc(obj.__init__))):
return '', ''
if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): return
if not (isinstance(obj, collections.Callable) or hasattr(obj, '__argspec_is_invalid_')): return
if not hasattr(obj, '__doc__'): return
doc = SphinxDocString(pydoc.getdoc(obj))
if doc['Signature']:
sig = re.sub(u"^[^(]*", u"", doc['Signature'])
return sig, u''
sig = re.sub(sixu("^[^(]*"), sixu(""), doc['Signature'])
return sig, sixu('')
def setup(app, get_doc_object_=get_doc_object):
if not hasattr(app, 'add_config_value'):
return # probably called by nose, better bail out
global get_doc_object
get_doc_object = get_doc_object_
@@ -94,6 +120,8 @@ def setup(app, get_doc_object_=get_doc_object):
app.add_config_value('numpydoc_edit_link', None, False)
app.add_config_value('numpydoc_use_plots', None, False)
app.add_config_value('numpydoc_show_class_members', True, True)
app.add_config_value('numpydoc_show_inherited_class_members', True, True)
app.add_config_value('numpydoc_class_members_toctree', True, True)
# Extra mangling domains
app.add_domain(NumpyPythonDomain)
@@ -115,7 +143,7 @@ class ManglingDomainBase(object):
self.wrap_mangling_directives()
def wrap_mangling_directives(self):
for name, objtype in self.directive_mangling_map.items():
for name, objtype in list(self.directive_mangling_map.items()):
self.directives[name] = wrap_mangling_directive(
self.directives[name], objtype)
@@ -130,6 +158,7 @@ class NumpyPythonDomain(ManglingDomainBase, PythonDomain):
'staticmethod': 'function',
'attribute': 'attribute',
}
indices = []
class NumpyCDomain(ManglingDomainBase, CDomain):
name = 'np-c'
@@ -161,4 +190,3 @@ def wrap_mangling_directive(base_directive, objtype):
return base_directive.run(self)
return directive
+56 -9
View File
@@ -66,10 +66,12 @@ Suggested CSS definitions
"""
import os
import re
import shutil
import token
import tokenize
import traceback
import itertools
import numpy as np
import matplotlib
@@ -83,7 +85,7 @@ from skimage.util.dtype import dtype_range
from notebook import Notebook
from docutils.core import publish_parts
from sphinx.domains.python import PythonDomain
LITERALINCLUDE = """
.. literalinclude:: {src_name}
@@ -132,8 +134,8 @@ GALLERY_IMAGE_TEMPLATE = """
class Path(str):
"""Path object for manipulating directory and file paths."""
def __init__(self, path):
super(Path, self).__init__(path)
def __new__(self, path):
return str.__new__(self, path)
@property
def isdir(self):
@@ -203,7 +205,7 @@ def generate_examples_and_gallery(example_dir, rst_dir, cfg):
rst_dir.makedirs()
# we create an index.rst with all examples
gallery_index = file(rst_dir.pjoin('index'+cfg.source_suffix), 'w')
gallery_index = open(rst_dir.pjoin('index'+cfg.source_suffix), 'w')
# Here we don't use an os.walk, but we recurse only twice: flat is
# better than nested.
@@ -244,7 +246,7 @@ def write_gallery(gallery_index, src_dir, rst_dir, cfg, depth=0):
print(80*'_')
return
gallery_description = file(gallery_template).read()
gallery_description = open(gallery_template).read()
gallery_index.write('\n\n%s\n\n' % gallery_description)
rst_dir.makedirs()
@@ -256,7 +258,8 @@ def write_gallery(gallery_index, src_dir, rst_dir, cfg, depth=0):
else:
sub_dir_list = src_dir.psplit()[-depth:]
sub_dir = Path('/'.join(sub_dir_list) + '/')
gallery_index.write(TOCTREE_TEMPLATE % (sub_dir + '\n '.join(ex_names)))
joiner = '\n %s' % sub_dir
gallery_index.write(TOCTREE_TEMPLATE % (sub_dir + joiner.join(ex_names)))
for src_name in examples:
@@ -332,6 +335,8 @@ def write_example(src_name, src_dir, rst_dir, cfg):
notebook_path.exists:
return
print('plot2rst: %s' % basename)
blocks = split_code_and_text_blocks(example_file)
if blocks[0][2].startswith('#!'):
blocks.pop(0) # don't add shebang line to rst file.
@@ -380,15 +385,57 @@ def write_example(src_name, src_dir, rst_dir, cfg):
# Export example to IPython notebook
nb = Notebook()
for (cell_type, _, content) in blocks:
content = content.rstrip('\n')
# Add sphinx roles to the examples, otherwise docutils
# cannot compile the ReST for the notebook
sphinx_roles = PythonDomain.roles.keys()
preamble = '\n'.join('.. role:: py:{0}(literal)\n'.format(role)
for role in sphinx_roles)
# Grab all references to inject them in cells where needed
ref_regexp = re.compile('\n(\.\. \[(\d+)\].*(?:\n[ ]{7,8}.*)+)')
math_role_regexp = re.compile(':math:`(.*?)`')
text = '\n'.join((content for (cell_type, _, content) in blocks
if cell_type != 'code'))
references = re.findall(ref_regexp, text)
for (cell_type, _, content) in blocks:
if cell_type == 'code':
nb.add_cell(content, cell_type='code')
else:
content = content.replace('"""', '')
if content.startswith('r'):
content = content.replace('r"""', '')
escaped = False
else:
content = content.replace('"""', '')
escaped = True
if not escaped:
content = content.replace("\\", "\\\\")
content = content.replace('.. seealso::', '**See also:**')
content = re.sub(math_role_regexp, r'$\1$', content)
# Remove math directive when rendering notebooks
# until we implement a smarter way of capturing and replacing
# its content
content = content.replace('.. math::', '')
if not content.strip():
continue
content = (preamble + content).rstrip('\n')
content = '\n'.join([line for line in content.split('\n') if
not line.startswith('.. image')])
# Remove reference links until we can figure out a better way to
# preserve them
for (reference, ref_id) in references:
ref_tag = '[{0}]_'.format(ref_id)
if ref_tag in content:
content = content.replace(ref_tag, ref_tag[:-1])
html = publish_parts(content, writer_name='html')['html_body']
nb.add_cell(html, cell_type='markdown')
+515 -640
View File
File diff suppressed because it is too large Load Diff
+8 -4
View File
@@ -19,7 +19,6 @@ import re
import shutil
import sys
from os import chdir as cd
from os.path import join as pjoin
from subprocess import Popen, PIPE, CalledProcessError, check_call
@@ -117,8 +116,8 @@ if __name__ == '__main__':
try:
cd(pages_dir)
status = sh2('git status | head -1')
branch = re.match('\# On branch (.*)$', status).group(1)
if branch != 'gh-pages':
branch = re.match(b'On branch (.*)$', status).group(1)
if branch != b'gh-pages':
e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir,
branch)
raise RuntimeError(e)
@@ -126,7 +125,12 @@ if __name__ == '__main__':
sh('git add .nojekyll')
sh('git add index.html')
sh('git add --all %s' % tag)
sh2('git commit -m"Updated doc release: %s"' % tag)
status = sh2('git status | tail -1')
if not re.match(b'nothing to commit', status):
sh2('git commit -m"Updated doc release: %s"' % tag)
else:
print('\n! Note: no changes to commit\n')
print('Most recent commit:')
sys.stdout.flush()
+1 -1
View File
@@ -20,7 +20,7 @@ import skimage.io as sio
from skimage import img_as_float
from skimage.color import gray2rgb, rgb2gray
from skimage.exposure import rescale_intensity
from skimage.filter import sobel
from skimage.filters import sobel
import scipy_logo
+2 -12
View File
@@ -3,11 +3,11 @@ Code used to trace Scipy logo.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.nxutils as nx
from skimage import io
from skimage import data
from skimage.measure import points_in_poly
class SymmetricAnchorPoint(object):
"""Anchor point in a parametric curve with symmetric handles
@@ -211,7 +211,7 @@ class ScipyLogo(object):
y_img, x_img = np.mgrid[:h, :w]
xy_points = np.column_stack((x_img.flat, y_img.flat))
mask = nx.points_inside_poly(xy_points, xy_poly)
mask = points_in_poly(xy_points, xy_poly)
return mask.reshape((h, w))
@@ -241,18 +241,8 @@ def plot_snake_overlay():
plt.imshow(img)
def plot_lena_overlay():
plt.figure()
logo = ScipyLogo((300, 300), 180)
logo.plot_snake_curve()
logo.plot_circle()
img = data.lena()
plt.imshow(img)
if __name__ == '__main__':
plot_scipy_trace()
plot_snake_overlay()
plot_lena_overlay()
plt.show()
+5 -2
View File
@@ -14,7 +14,7 @@ def call(cmd):
return subprocess.check_output(shlex.split(cmd), universal_newlines=True).split('\n')
tag_date = call("git show --format='%%ci' %s" % tag)[0]
print("Release %s was on %s" % (tag, tag_date))
print("Release %s was on %s\n" % (tag, tag_date))
merges = call("git log --since='%s' --merges --format='>>>%%B' --reverse" % tag_date)
merges = [m for m in merges if m.strip()]
@@ -22,7 +22,10 @@ merges = '\n'.join(merges).split('>>>')
merges = [m.split('\n')[:2] for m in merges]
merges = [m for m in merges if len(m) == 2 and m[1].strip()]
print("\nIt contained the following %d merges:\n" % len(merges))
num_commits = call("git rev-list %s..HEAD --count" % tag)[0]
print("A total of %s changes have been committed.\n" % num_commits)
print("It contained the following %d merges:\n" % len(merges))
for (merge, message) in merges:
if merge.startswith('Merge pull request #'):
PR = ' (%s)' % merge.split()[3]
+3 -3
View File
@@ -80,7 +80,7 @@ surname:
- Jaime Frio
- Jostein Bø Fløystad
- Neeraj Gangwar
- Christopher Gohlke
- Christoph Gohlke
- Michael Hansen
- Almar Klein
- Jeremy Metz
@@ -91,13 +91,13 @@ surname:
- Thomas Robitaille
- Michal Romaniuk
- Johannes L. Schönberger
- Steven Sylvester
- Steven Silvester
- Julian Taylor
- Gregor Thalhammer
- Matthew Trentacoste
- Siva Prasad Varma
- Guillem Palou Visa
- Stefan van der Walt
- Josh Warner
- Joshua Warner
- Tony S Yu
- radioxoma
+96
View File
@@ -0,0 +1,96 @@
Announcement: scikit-image 0.11.0
=================================
We're happy to announce the release of scikit-image v0.11.0!
scikit-image is an image processing toolbox for SciPy that includes algorithms
for segmentation, geometric transformations, color space manipulation,
analysis, filtering, morphology, feature detection, and more.
For more information, examples, and documentation, please visit our website:
http://scikit-image.org
Highlights
----------
For this release, we merged over 200 pull requests with bug fixes,
cleanups, improved documentation and new features. Highlights
include:
- Region Adjacency Graphs
- Color distance RAGs (#1031)
- Threshold Cut on RAGs (#1031)
- Similarity RAGs (#1080)
- Normalized Cut on RAGs (#1080)
- RAG drawing (#1087)
- Hierarchical merging (#1100)
- Sub-pixel shift registration (#1066)
- Non-local means denoising (#874)
- Sliding window histogram (#1127)
- More illuminants in color conversion (#1130)
- Handling of CMYK images (#1360)
- `stop_probability` for RANSAC (#1176)
- Li thresholding (#1376)
- Signed edge operators (#1240)
- Full ndarray support for `peak_local_max` (#1355)
- Improve conditioning of geometric transformations (#1319)
- Standardize handling of multi-image files (#1200)
- Ellipse structuring element (#1298)
- Multi-line drawing tool (#1065), line handle style (#1179)
- Point in polygon testing (#1123)
- Rotation around a specified center (#1168)
- Add `shape` option to drawing functions (#1222)
- Faster regionprops (#1351)
- `skimage.future` package (#1365)
- More robust I/O module (#1189)
API Changes
-----------
- The ``skimage.filter`` subpackage has been renamed to ``skimage.filters``.
- Some edge detectors returned values greater than 1--their results are now
appropriately scaled with a factor of ``sqrt(2)``.
Contributors to this release
----------------------------
(Listed alphabetically by last name)
- Fedor Baart
- Vighnesh Birodkar
- François Boulogne
- Nelson Brown
- Alexey Buzmakov
- Julien Coste
- Phil Elson
- Adam Feuer
- Jim Fienup
- Geoffrey French
- Emmanuelle Gouillart
- Charles Harris
- Jonathan Helmus
- Alexander Iacchetta
- Ivana Kajić
- Kevin Keraudren
- Almar Klein
- Gregory R. Lee
- Jeremy Metz
- Stuart Mumford
- Damian Nadales
- Pablo Márquez Neila
- Juan Nunez-Iglesias
- Rebecca Roisin
- Jasper St. Pierre
- Jacopo Sabbatini
- Michael Sarahan
- Salvatore Scaramuzzino
- Phil Schaf
- Johannes Schönberger
- Tim Seifert
- Arve Seljebu
- Steven Silvester
- Julian Taylor
- Matěj Týč
- Alexey Umnov
- Pratap Vardhan
- Stefan van der Walt
- Joshua Warner
- Tony S Yu
+36
View File
@@ -0,0 +1,36 @@
Announcement: scikit-image 0.X.0
================================
We're happy to announce the release of scikit-image v0.X.0!
scikit-image is an image processing toolbox for SciPy that includes algorithms
for segmentation, geometric transformations, color space manipulation,
analysis, filtering, morphology, feature detection, and more.
For more information, examples, and documentation, please visit our website:
http://scikit-image.org
New Features
------------
Improvements
------------
API Changes
-----------
Deprecations
------------
+38
View File
@@ -0,0 +1,38 @@
Announcement: scikit-image 0.X.0
================================
We're happy to announce the release of scikit-image v0.X.0!
scikit-image is an image processing toolbox for SciPy that includes algorithms
for segmentation, geometric transformations, color space manipulation,
analysis, filtering, morphology, feature detection, and more.
For more information, examples, and documentation, please visit our website:
http://scikit-image.org
New Features
------------
Improvements
------------
API Changes
-----------
Deprecations
------------
Contributors to this release
----------------------------
Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

+1 -1
View File
@@ -1,4 +1,4 @@
var versions = ['dev', '0.10.x', '0.9.x', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
var versions = ['dev', '0.11.x', '0.10.x', '0.9.x', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
function insert_version_links() {
for (i = 0; i < versions.length; i++){
+7 -1
View File
@@ -2,4 +2,10 @@
<li><a href="/download.html">Download</a></li>
<li><a href="/docs/dev/auto_examples">Gallery</a></li>
<li><a href="/docs/dev">Documentation</a></li>
<li><a href="https://github.com/scikit-image/scikit-image">Source</a></li>
<li><a href="https://github.com/scikit-image/scikit-image">
<img src="{{ pathto('_static', 1) }}/GitHub-Mark-32px.png"
style="height: 15px; width: 15px;
display: inline; float: none;
padding-bottom: 3px;">
Source</a>
</li>
+6
View File
@@ -1,3 +1,9 @@
Version 0.11
------------
- The ``skimage.filter`` subpackage has been renamed to ``skimage.filters``.
- Some edge detectors returned values greater than 1--their results are now
appropriately scaled with a factor of ``sqrt(2)``.
Version 0.10
------------
- Removed ``skimage.io.video`` functionality due to broken gstreamer bindings
+1
View File
@@ -251,6 +251,7 @@ latex_use_modindex = False
# Numpy extensions
# -----------------------------------------------------------------------------
numpydoc_show_class_members = False
numpydoc_class_members_toctree = False
# -----------------------------------------------------------------------------
# Plots
-7
View File
@@ -1,7 +0,0 @@
Table of Contents
=================
.. toctree::
/api/api
+8 -5
View File
@@ -10,7 +10,10 @@ import csv
try:
import cStringIO as StringIO
except ImportError:
import StringIO
try:
import StringIO
except:
import io as StringIO
# Missing item value
MISSING_STRING=":missing:`Not Implemented`"
@@ -74,7 +77,7 @@ def read_table_titles(reader):
break
section_titles.append(row[0])
table_names[row[0]] = names
except csv.Error, e:
except csv.Error as e:
sys.exit('line %d: %s' % (reader.line_num, e))
return section_titles,table_names
@@ -106,7 +109,7 @@ def table_row(stream,data,lengths,num_columns=None):
if num_columns is None:
num_columns = len(data)
stream.write("|")
for i in xrange(num_columns):
for i in range(num_columns):
if len(data)-1 >= i:
if len(data[i]) == 0:
entry = MISSING_STRING
@@ -145,12 +148,12 @@ def generate_table(reader,stream,table_name=None,
break
data.append([entry.expandtabs() for entry in row])
num_columns = max(num_columns,len(row))
except csv.Error, e:
except csv.Error as e:
sys.exit('line %d: %s' % (reader.line_num, e))
column_lengths = [len(MISSING_STRING)]*num_columns
for row in data:
for i in xrange(len(row)):
for i in range(len(row)):
column_lengths[i] = max(column_lengths[i],len(row[i]))
# Output table header
+3 -3
View File
@@ -4,7 +4,7 @@
Development workflow
####################
You already have your own forked copy of the scikit-image_ repository, by
You already have your own forked copy of the `scikit-image`_ repository, by
following :ref:`forking`. You have :ref:`set-up-fork`. You have configured
git by following :ref:`configure-git`. Now you are ready for some real work.
@@ -22,7 +22,7 @@ In what follows we'll refer to the upstream scikit-image ``master`` branch, as
* Name your branch for the purpose of the changes - e.g.
``bugfix-for-issue-14`` or ``refactor-database-code``.
* If you can possibly avoid it, avoid merging trunk or any other branches into
your feature branch while you are working.
your feature branch while you are working.
* If you do find yourself merging from trunk, consider :ref:`rebase-on-trunk`
* Ask on the `scikit-image mailing list`_ if you get stuck.
* Ask for code review!
@@ -81,7 +81,7 @@ what the changes in the branch are for. For example ``add-ability-to-fly``, or
git checkout my-new-feature
Generally, you will want to keep your feature branches on your public github_
fork of scikit-image_. To do this, you `git push`_ this new branch up to your
fork of `scikit-image`_. To do this, you `git push`_ this new branch up to your
github repo. Generally (if you followed the instructions in these pages, and by
default), git will have a link to your github repo, called ``origin``. You push
up to your own repo on github with::
+8 -8
View File
@@ -1,33 +1,33 @@
.. _forking:
============================================
======================================================
Making your own copy (fork) of scikit-image
============================================
======================================================
You need to do this only once. The instructions here are very similar
to the instructions at http://help.github.com/forking/ |emdash| please see
that page for more detail. We're repeating some of it here just to give the
specifics for the scikit-image_ project, and to suggest some default names.
specifics for the `scikit-image`_ project, and to suggest some default names.
Set up and configure a github account
======================================
=====================================
If you don't have a github account, go to the github page, and make one.
You then need to configure your account to allow write access |emdash| see
the ``Generating SSH keys`` help on `github help`_.
Create your own forked copy of scikit-image_
=============================================
Create your own forked copy of `scikit-image`_
======================================================
#. Log into your github account.
#. Go to the scikit-image_ github home at `scikit-image github`_.
#. Go to the `scikit-image`_ github home at `scikit-image github`_.
#. Click on the *fork* button:
.. image:: forking_button.png
Now, after a short pause and some 'Hardcore forking action', you
should find yourself at the home page for your own forked copy of scikit-image_.
should find yourself at the home page for your own forked copy of `scikit-image`_.
.. include:: links.inc
+1 -1
View File
@@ -8,7 +8,7 @@ Overview
========
================ =============
Debian / Ubuntu ``sudo apt-get install git-core``
Debian / Ubuntu ``sudo apt-get install git``
Fedora ``sudo yum install git-core``
Windows Download and install msysGit_
OS X Use the git-osx-installer_
+1 -1
View File
@@ -2,7 +2,7 @@
Introduction
==============
These pages describe a git_ and github_ workflow for the scikit-image_
These pages describe a git_ and github_ workflow for the `scikit-image`_
project.
There are several different workflows here, for different ways of
+16 -16
View File
@@ -20,27 +20,27 @@
.. _git svn crash course: http://git-scm.com/course/svn.html
.. _learn.github: http://learn.github.com/
.. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer
.. _git user manual: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
.. _git tutorial: http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html
.. _git user manual: http://schacon.github.com/git/user-manual.html
.. _git tutorial: http://schacon.github.com/git/gittutorial.html
.. _git community book: http://book.git-scm.com/
.. _git ready: http://www.gitready.com/
.. _git casts: http://www.gitcasts.com/
.. _Fernando's git page: http://www.fperez.org/py4science/git.html
.. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html
.. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/
.. _git clone: http://www.kernel.org/pub/software/scm/git/docs/git-clone.html
.. _git checkout: http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html
.. _git commit: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html
.. _git push: http://www.kernel.org/pub/software/scm/git/docs/git-push.html
.. _git pull: http://www.kernel.org/pub/software/scm/git/docs/git-pull.html
.. _git add: http://www.kernel.org/pub/software/scm/git/docs/git-add.html
.. _git status: http://www.kernel.org/pub/software/scm/git/docs/git-status.html
.. _git diff: http://www.kernel.org/pub/software/scm/git/docs/git-diff.html
.. _git log: http://www.kernel.org/pub/software/scm/git/docs/git-log.html
.. _git branch: http://www.kernel.org/pub/software/scm/git/docs/git-branch.html
.. _git remote: http://www.kernel.org/pub/software/scm/git/docs/git-remote.html
.. _git rebase: http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html
.. _git config: http://www.kernel.org/pub/software/scm/git/docs/git-config.html
.. _git clone: http://schacon.github.com/git/git-clone.html
.. _git checkout: http://schacon.github.com/git/git-checkout.html
.. _git commit: http://schacon.github.com/git/git-commit.html
.. _git push: http://schacon.github.com/git/git-push.html
.. _git pull: http://schacon.github.com/git/git-pull.html
.. _git add: http://schacon.github.com/git/git-add.html
.. _git status: http://schacon.github.com/git/git-status.html
.. _git diff: http://schacon.github.com/git/git-diff.html
.. _git log: http://schacon.github.com/git/git-log.html
.. _git branch: http://schacon.github.com/git/git-branch.html
.. _git remote: http://schacon.github.com/git/git-remote.html
.. _git rebase: http://schacon.github.com/git/git-rebase.html
.. _git config: http://schacon.github.com/git/git-config.html
.. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html
.. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html
.. _tangled working copy problem: http://tomayko.com/writings/the-thing-about-git
@@ -50,7 +50,7 @@
.. _git foundation: http://matthew-brett.github.com/pydagogue/foundation.html
.. _deleting master on github: http://matthew-brett.github.com/pydagogue/gh_delete_master.html
.. _rebase without tears: http://matthew-brett.github.com/pydagogue/rebase_without_tears.html
.. _resolving a merge: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#resolving-a-merge
.. _resolving a merge: http://schacon.github.com/git/user-manual.html#resolving-a-merge
.. _ipython git workflow: http://mail.scipy.org/pipermail/ipython-dev/2010-October/006746.html
.. other stuff
+1 -1
View File
@@ -1,7 +1,7 @@
.. _using-git:
Working with *scikit-image* source code
========================================
================================================
Contents:
+1 -1
View File
@@ -6,7 +6,7 @@
.. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel
.. numpy
.. _numpy: hhttp://numpy.scipy.org
.. _numpy: http://numpy.org
.. _`numpy github`: http://github.com/numpy/numpy
.. _`numpy mailing list`: http://mail.scipy.org/mailman/listinfo/numpy-discussion
+3 -3
View File
@@ -3,7 +3,7 @@
================
You've discovered a bug or something else you want to change
in scikit-image_ .. |emdash| excellent!
in `scikit-image`_ .. |emdash| excellent!
You've worked out a way to fix it |emdash| even better!
@@ -57,7 +57,7 @@ In detail
git config --global user.name "Your Name Comes Here"
#. If you don't already have one, clone a copy of the
scikit-image_ repository::
`scikit-image`_ repository::
git clone git://github.com/scikit-image/scikit-image.git
cd scikit-image
@@ -115,7 +115,7 @@ more feature branches, you will probably want to switch to
development mode. You can do this with the repository you
have.
Fork the scikit-image_ repository on github |emdash| :ref:`forking`.
Fork the `scikit-image`_ repository on github |emdash| :ref:`forking`.
Then::
# checkout and refresh master branch from main repo
+1 -1
View File
@@ -49,7 +49,7 @@ Linking your repository to the upstream repo
git remote add upstream git://github.com/scikit-image/scikit-image.git
``upstream`` here is just the arbitrary name we're using to refer to the
main scikit-image_ repository at `scikit-image github`_.
main `scikit-image`_ repository at `scikit-image github`_.
Note that we've used ``git://`` for the URL rather than ``git@``. The
``git://`` URL is read only. This means we that we can't accidentally
+1 -1
View File
@@ -1,5 +1,5 @@
.. scikit-image
.. _scikit-image: http://scikit-image.org
.. _`scikit-image`: http://scikit-image.org
.. _`scikit-image github`: http://github.com/scikit-image/scikit-image
.. _`scikit-image mailing list`: http://groups.google.com/group/scikit-image
+1 -1
View File
@@ -15,7 +15,7 @@ Sections
:hidden:
overview
api
api/api
api_changes
install
user_guide
+8 -17
View File
@@ -2,8 +2,9 @@ Pre-built installation
----------------------
`Windows binaries
<http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image>`__
are kindly provided by Christoph Gohlke.
<http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikit-image>`__
are kindly provided by Christoph Gohlke (note that, when upgrading,
you should first uninstall any older versions).
The latest stable release is also included as part of
`Enthought Canopy <https://www.enthought.com/products/canopy/>`__,
@@ -19,13 +20,6 @@ add Neurodebian to your system package manager, then look for
On systems that support setuptools, the package can be installed from the
`Python packaging index <http://pypi.python.org/pypi/scikit-image>`__ using
::
easy_install -U scikit-image
or
::
pip install -U scikit-image
@@ -45,13 +39,9 @@ If you do not have git installed, you can also download a zipball from
`https://github.com/scikit-image/scikit-image/zipball/master
<https://github.com/scikit-image/scikit-image/zipball/master>`_.
The SciKit can be installed globally using::
The scikit can be installed using::
python setup.py install
or locally using::
python setup.py install --prefix=${HOME}
pip install .
If you prefer, you can use it without installing, by simply adding
this path to your ``PYTHONPATH`` variable and compiling extensions
@@ -80,6 +70,7 @@ From the ``scikit-image`` source directory::
bentomaker build -j # (add -i for in-place build)
bentomaker install # (when not builing in-place)
Depending on file permissions, the install commands may need to be run as sudo.
Depending on file permissions, the install commands may need to be run as
sudo.
.. include:: ../../DEPENDS.txt
+1 -1
View File
@@ -106,7 +106,7 @@
<div class="well footer">
<small>
&copy; Copyright the scikit-image development team.
Created using <a href="http://twitter.github.com/bootstrap/">Bootstrap</a> and <a href="http://sphinx.pocoo.org/">Sphinx</a>.
Created using <a href="http://getbootstrap.com/">Bootstrap</a> and <a href="http://sphinx-doc.org/">Sphinx</a>.
</small>
</div>
</body>
@@ -1,5 +1,7 @@
body {
font-family: "Raleway";
letter-spacing: 0.02em;
font-size: 102%;
}
a {
color: #CE5C00;
@@ -10,9 +12,6 @@ select,
textarea {
font-family: "Raleway";
}
pre {
font-size: 11px;
}
h1, h2, h3, h4, h5, h6 {
clear: left;
@@ -41,12 +40,6 @@ h6 {
font-size: 13px;
line-height: 15px;
}
blockquote {
border-left: 0;
}
dt {
font-weight: normal;
}
.logo {
float: left;
@@ -57,18 +50,21 @@ dt {
}
.hero {
padding: 10px 25px;
padding: 10px 25px 15px 25px;
}
.gallery-random {
float: right;
line-height: 180px;
margin-left: 10px;
}
.gallery-random img {
max-height: 180px;
max-width: 180px;
}
.coins-sample {
float: left;
padding: 5px;
}
@@ -79,10 +75,6 @@ dt {
padding-left: 15px;
}
#current {
font-weight: bold;
}
.headerlink {
margin-left: 10px;
color: #ddd;
@@ -111,7 +103,7 @@ h6:hover .headerlink {
text-decoration: underline;
}
.ohloh-use, .gplus-use {
.gplus-use {
float: left;
margin: 0 0 10px 15px;
}
@@ -233,7 +225,14 @@ p.admonition-title {
text-align: center !important;
}
/* misc */
div.math {
text-align: center;
.summary-box {
/* Should derive width from span8 */
width: 640px;
}
.citation {
color: #3a87ad;
background-color: #d9edf7;
border-color: #bce8f1;
/* padding: 1em;*/
}
+5
View File
@@ -4,8 +4,13 @@ User Guide
.. toctree::
:maxdepth: 2
user_guide/getting_started
user_guide/numpy_images
user_guide/data_types
user_guide/transforming_image_data
user_guide/plugins
user_guide/tutorials
user_guide/getting_help
user_guide/viewer
user_guide/tutorial_parallelization
user_guide/tutorial_segmentation
+35 -7
View File
@@ -1,3 +1,4 @@
.. _data_types:
===================================
Image data types and what they mean
@@ -14,16 +15,16 @@ Data type Range
uint8 0 to 255
uint16 0 to 65535
uint32 0 to 2\ :sup:`32`
float -1 to 1
float -1 to 1 or 0 to 1
int8 -128 to 127
int16 -32768 to 32767
int32 -2\ :sup:`31` to 2\ :sup:`31` - 1
========= =================================
Note that float images are restricted to the range -1 to 1 even though the data
type itself can exceed this range; all integer dtypes, on the other hand, have
pixel intensities that can span the entire data type range. Currently, *64-bit
(u)int images are not supported*.
Note that float images should be restricted to the range -1 to 1 even though
the data type itself can exceed this range; all integer dtypes, on the other
hand, have pixel intensities that can span the entire data type range. With a
few exceptions, *64-bit (u)int images are not supported*.
Functions in ``skimage`` are designed so that they accept any of these dtypes,
but, for efficiency, *may return an image of a different dtype* (see `Output
@@ -43,9 +44,10 @@ violates these assumptions about the dtype range::
Input types
===========
Functions may choose to support only a subset of these data-types. In such
Although we aim to preserve the data range and type of input images, functions
may support only a subset of these data-types. In such
a case, the input will be converted to the required type (if possible), and
a warning message is printed to the log if a memory copy is needed. Type
a warning message printed to the log if a memory copy is needed. Type
requirements should be noted in the docstrings.
The following utility functions in the main package are available to developers
@@ -72,6 +74,32 @@ issued::
array([ 0, 128, 255], dtype=uint8)
Additionally, some functions take a ``preserve_range`` argument where a range
conversion is convenient but not necessary. For example, interpolation in
``transform.warp`` requires an image of type float, which should have a range
in [0, 1]. So, by default, input images will be rescaled to this range.
However, in some cases, the image values represent physical measurements, such
as temperature or rainfall values, that the user does not want rescaled.
With ``preserve_range=True``, the original range of the data will be
preserved, even though the output is a float image. Users must then ensure
this non-standard image is properly processed by downstream functions, which
may expect an image in [0, 1].
>>> from skimage import data
>>> from skimage.transform import rescale
>>> image = data.coins()
>>> image.dtype, image.min(), image.max(), image.shape
(dtype('uint8'), 1, 252, (303, 384))
>>> rescaled = rescale(image, 0.5)
>>> (rescaled.dtype, np.round(rescaled.min(), 4),
... np.round(rescaled.max(), 4), rescaled.shape)
(dtype('float64'), 0.0147, 0.9456, (152, 192))
>>> rescaled = rescale(image, 0.5, preserve_range=True)
>>> (rescaled.dtype, np.round(rescaled.min()),
... np.round(rescaled.max()), rescaled.shape
(dtype('float64'), 4.0, 241.0, (152, 192))
Output types
============
+43
View File
@@ -0,0 +1,43 @@
Getting started
---------------
``scikit-image`` is an image processing Python package that works with
:mod:`numpy` arrays. The package is imported as ``skimage``: ::
>>> import skimage
Most functions of ``skimage`` are found within submodules: ::
>>> from skimage import data
>>> camera = data.camera()
A list of submodules and functions is found on the `API reference
<http://scikit-image.org/docs/stable/api/api.html>`_ webpage.
Within scikit-image, images are represented as NumPy arrays, for
example 2-D arrays for grayscale 2-D images ::
>>> type(camera)
<type 'numpy.ndarray'>
>>> # An image with 512 rows and 512 columns
>>> camera.shape
(512, 512)
The :mod:`skimage.data` submodule provides a set of functions returning
example images, that can be used to get started quickly on using
scikit-image's functions: ::
>>> coins = data.coins()
>>> from skimage import filters
>>> threshold_value = filters.threshold_otsu(coins)
>>> threshold_value
107
Of course, it is also possible to load your own images as NumPy arrays
from image files, using :func:`skimage.io.imread`: ::
>>> import os
>>> filename = os.path.join(skimage.data_dir, 'moon.png')
>>> from skimage import io
>>> moon = io.imread(filename)
+258
View File
@@ -0,0 +1,258 @@
A crash course on NumPy for images
----------------------------------
Images manipulated by ``scikit-image`` are simply NumPy arrays. Hence, a
large fraction of operations on images will just consist in using NumPy::
>>> from skimage import data
>>> camera = data.camera()
>>> type(camera)
<type 'numpy.ndarray'>
Retrieving the geometry of the image and the number of pixels: ::
>>> camera.shape
(512, 512)
>>> camera.size
262144
Retrieving statistical information about gray values: ::
>>> camera.min(), camera.max()
(0, 255)
>>> camera.mean()
118.31400299072266
NumPy arrays representing images can be of different integer of float
numerical types. See :ref:`data_types` for more information about these
types and how scikit-image treats them.
NumPy indexing
--------------
NumPy indexing can be used both for looking at pixel values, and to
modify pixel values: ::
>>> # Get the value of the pixel on the 10th row and 20th column
>>> camera[10, 20]
153
>>> # Set to black the pixel on the 3rd row and 10th column
>>> camera[3, 10] = 0
Be careful: in NumPy indexing, the first dimension (``camera.shape[0]``)
corresponds to rows, while the second (``camera.shape[1]``) corresponds
to columns, with the origin (``camera[0, 0]``) on the top-left corner.
This matches matrix/linear algebra notation, but is in contrast to
Cartesian (x, y) coordinates. See `Coordinate conventions`_ below for
more details.
Beyond individual pixels, it is possible to access / modify values of
whole sets of pixels, using the different indexing possibilities of
NumPy.
Slicing::
>>> # Set to black the ten first lines
>>> camera[:10] = 0
Masking (indexing with masks of booleans)::
>>> mask = camera < 87
>>> # Set to "white" (255) pixels where mask is True
>>> camera[mask] = 255
Fancy indexing (indexing with sets of indices) ::
>>> inds_r = np.arange(len(camera))
>>> inds_c = 4 * inds_r % len(camera)
>>> camera[inds_r, inds_c] = 0
Using masks, especially, is very useful to select a set of pixels on
which to perform further manipulations. The mask can be any boolean array
of same shape as the image (or a shape broadcastable to the image shape).
This can be useful to define a region of interest, such as a
disk: ::
>>> nrows, ncols = camera.shape
>>> row, col = np.ogrid[:nrows, :ncols]
>>> cnt_row, cnt_col = nrows / 2, ncols / 2
>>> outer_disk_mask = ((row - cnt_row)**2 + (col - cnt_col)**2 <
... (nrows / 2)**2)
>>> camera[outer_disk_mask] = 0
.. image:: ../auto_examples/images/plot_camera_numpy_1.png
:width: 45%
:target: ../auto_examples/plot_camera_numpy.html
Boolean arithmetic can be used to define more complex masks: ::
>>> lower_half = row > cnt_row
>>> lower_half_disk = np.logical_and(lower_half, outer_disk_mask)
>>> camera = data.camera()
>>> camera[lower_half_disk] = 0
Color images
------------
All of the above is true of color images, too: a color image is a
NumPy array, with an additional trailing dimension for the channels:
>>> cat = data.chelsea()
>>> type(cat)
<type 'numpy.ndarray'>
>>> cat.shape
(300, 451, 3)
This shows that ``cat`` is a 300-by-451 pixel image with three
channels (red, green, and blue).
As before, we can get and set pixel values:
>>> cat[10, 20]
array([151, 129, 115], dtype=uint8)
>>> # set the pixel at row 50, column 60 to black
>>> cat[50, 60] = 0
>>> # set the pixel at row 50, column 61 to green
>>> cat[50, 61] = [0, 255, 0] # [red, green, blue]
We can also use 2D boolean masks for a 2D color image, as we did with
the grayscale image above:
.. plot::
Using a 2D mask on a 2D color image
>>> from skimage import data
>>> cat = data.chelsea()
>>> reddish = cat[:, :, 0] > 160
>>> cat[reddish] = [0, 255, 0]
>>> plt.imshow(cat)
Coordinate conventions
----------------------
Because we represent images with numpy arrays, our coordinates must
match accordingly. Two-dimensional (2D) grayscale images (such as
`camera` above) are indexed by row and columns (abbreviated to either
``row, col`` or ``r, c``), with the lowest element (0, 0) at the top-
-left corner. In various parts of the library, you will
also see ``rr`` and ``cc`` refer to lists of row and column
coordinates. We distinguish this from (x, y), which commonly denote
standard Cartesian coordinates, where x is the horizontal coordinate,
y the vertical, and the origin is on the bottom right. (Matplotlib, for
example, uses this convention.)
In the case of color (or multichannel) images, the last dimension
contains the color information and is denoted ``channel`` or ``ch``.
Finally, for 3D images, such as videos, magnetic resonance imaging
(MRI) scans, or confocal microscopy, we refer to the leading dimension
as ``plane``, abbreviated as ``pln`` or ``p``.
These conventions are summarized below:
.. table:: Dimension name and order conventions in scikit-image
========================= ========================================
Image type coordinates
========================= ========================================
2D grayscale (row, col)
2D multichannel (eg. RGB) (row, col, ch)
3D grayscale (pln, row, col)
3D multichannel (pln, row, col, ch)
========================= ========================================
Many functions in scikit-image operate on 3D images directly:
>>> im3d = np.random.rand(100, 1000, 1000)
>>> from skimage import morphology
>>> from scipy import ndimage as nd
>>> seeds = nd.label(im3d < 0.1)[0]
>>> ws = morphology.watershed(im3d, seeds)
In many cases,
the third imaging dimension has lower resolution than the other two.
Some scikit-image functions provide a ``spacing`` keyword argument
to process these images:
>>> from skimage import segmentation
>>> slics = segmentation.slic(im3d, spacing=[5, 1, 1], multichannel=False)
Other times, processing must be done plane-wise. When planes are the
leading dimension, we can use the following syntax:
>>> from skimage import filters
>>> edges = np.zeros_like(im3d)
>>> for pln, image in enumerate(im3d):
... # iterate over the leading dimension (planes)
... edges[pln] = filters.sobel(image)
Notes on array order
--------------------
Although the labeling of the axes seems arbitrary, it can have a
significant effect on speed of operations. This is because modern
processors never retrieve just one item from memory, but rather a
whole chunk of adjacent items. (This is called prefetching.)
Therefore, processing elements that are
next to each other in memory is faster than processing them
in a different order, even if the number of operations is the same:
>>> def in_order_multiply(arr, scalar):
... for plane in list(range(arr.shape[0])):
... arr[plane, :, :] *= scalar
...
>>> def out_of_order_multiply(arr, scalar):
... for plane in list(range(arr.shape[2])):
... arr[:, :, plane] *= scalar
...
>>> import time
>>> im3d = np.random.rand(100, 1024, 1024)
>>> t0 = time.time(); x = in_order_multiply(im3d, 5); t1 = time.time()
>>> print("%.2f seconds" % (t1 - t0)) # doctest: +SKIP
0.14 seconds
>>> im3d_t = np.transpose(im3d).copy() # place "planes" dimension at end
>>> im3d_t.shape
(1024, 1024, 100)
>>> s0 = time.time(); x = out_of_order_multiply(im3d, 5); s1 = time.time()
>>> print("%.2f seconds" % (s1 - s0)) doctest: +SKIP
1.18 seconds
>>> print("Speedup: %.1fx" % ((s1 - s0) / (t1 - t0))) doctest: +SKIP
Speedup: 8.6x
When the dimension you are iterating over is even larger, the
speedup is even more dramatic. It is worth thinking about this
*data locality* when writing algorithms. In particular, know that
scikit-image uses C-contiguous arrays unless otherwise specified, so
one should iterate along the last/rightmost dimension in the
innermost loop of the computation.
A note on time
--------------
Although scikit-image does not currently (0.11) provide functions to
work specifically with time-varying 3D data, our compatibility with
numpy arrays allows us to work quite naturally with a 5D array of the
shape (t, pln, row, col, ch):
>>> for timepoint in image5d: # doctest: +SKIP
... # each timepoint is a 3D multichannel image
... do_something_with(timepoint)
We can then supplement the above table as follows:
.. table:: Addendum to dimension names and orders in scikit-image
======================== ========================================
Image type coordinates
======================== ========================================
2D color video (t, row, col, ch)
3D multichannel video (t, pln, row, col, ch)
======================== ========================================
@@ -0,0 +1,172 @@
============================================
Image adjustment: transforming image content
============================================
Color manipulation
------------------
.. currentmodule:: skimage.color
Most functions for manipulating color channels are found in the submodule
:mod:`skimage.color`.
Conversion between color models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Color images can be represented using different `color spaces
<http://en.wikipedia.org/wiki/Color_space>`_. One of the most common
color spaces is the `RGB space
<http://en.wikipedia.org/wiki/RGB_color_model>`_, where an image has red,
green and blue channels. However, other color models are widely used,
such as the `HSV color model
<http://en.wikipedia.org/wiki/HSL_and_HSV>`_, where hue, saturation and
value are independent channels, or the `CMYK model
<http://en.wikipedia.org/wiki/CMYK_color_model>`_ used for printing.
:mod:`skimage.color` provides utility functions to convert images
to and from different color spaces. Integer-type arrays can be
transformed to floating-point type by the conversion operation::
>>> # bright saturated red
>>> red_pixel_rgb = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> color.rgb2hsv(red_pixel_rgb)
array([[[ 0., 1., 1.]]])
>>> # darker saturated blue
>>> dark_blue_pixel_rgb = np.array([[[0, 0, 100]]], dtype=np.uint8)
>>> color.rgb2hsv(dark_blue_pixel_rgb)
array([[[ 0.66666667, 1. , 0.39215686]]])
>>> # less saturated pink
>>> pink_pixel_rgb = np.array([[[255, 100, 255]]], dtype=np.uint8)
>>> color.rgb2hsv(pink_pixel_rgb)
array([[[ 0.83333333, 0.60784314, 1. ]]])
Conversion between color and gray values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Converting an RGB image to a grayscale image is realized with
:func:`rgb2gray` ::
>>> from skimage.color import rgb2gray
>>> from skimage import data
>>> img = data.astronaut()
>>> img_gray = rgb2gray(img)
:func:`rgb2gray` uses a non-uniform weighting of color channels, because of the
different sensitivity of the human eye to different colors. Therefore,
such a weighting ensures `luminance preservation
<http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale>`_
from RGB to grayscale::
>>> red_pixel = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> color.rgb2gray(red_pixel)
array([[ 0.2125]])
>>> green_pixel = np.array([[[0, 255, 0]]], dtype=np.uint8)
>>> color.rgb2gray(green_pixel)
array([[ 0.7154]])
Converting a grayscale image to RGB with :func:`gray2rgb` simply
duplicates the gray values over the three color channels.
Painting images with labels
~~~~~~~~~~~~~~~~~~~~~~~~~~~
:func:`label2rgb` can be used to superimpose colors on a grayscale image
using an array of labels to encode the regions to be represented with the
same color.
.. image: ../auto_examples/images/plot_join_segmentations_1.png
:target: ../auto_examples/plot_join_segmentations.html
:align: center
:width: 80%
.. topic:: Examples:
* :ref:`example_plot_tinting_grayscale_images.py`
* :ref:`example_plot_join_segmentations.py`
* :ref:`example_plot_rag_mean_color.py`
Contrast and exposure
---------------------
.. currentmodule:: skimage.exposure
Image pixels can take values determined by the ``dtype`` of the image
(see :ref:`data_types`), such as 0 to 255 for ``uint8`` images or ``[0,
1]`` for floating-point images. However, most images either have a
narrower range of values (because of poor contrast), or have most pixel
values concentrated in a subrange of the accessible values.
:mod:`skimage.exposure` provides functions that spread the intensity
values over a larger range.
A first class of methods compute a nonlinear function of the intensity,
that is independent of the pixel values of a specific image. Such methods
are often used for correcting a known non-linearity of sensors, or
receptors such as the human eye. A well-known example is `Gamma
correction <http://en.wikipedia.org/wiki/Gamma_correction>`_, implemented
in :func:`adjust_gamma`.
Other methods re-distribute pixel values according to the *histogram* of
the image. The histogram of pixel values is computed with
:func:`skimage.exposure.histogram`::
>>> image = np.array([[1, 3], [1, 1]])
>>> exposure.histogram(image)
(array([3, 0, 1]), array([1, 2, 3]))
:func:`histogram` returns the number of pixels for each value bin, and
the centers of the bins. The behavior of :func:`histogram` is therefore
slightly different from the one of :func:`np.histogram`, which returns
the boundaries of the bins.
The simplest contrast enhancement :func:`rescale_intensity` consists in
stretching pixel values to the whole allowed range, using a linear
transformation::
>>> from skimage import exposure
>>> text = data.text()
>>> text.min(), text.max()
(10, 197)
>>> better_contrast = exposure.rescale_intensity(text)
>>> better_contrast.min(), better_contrast.max()
(0, 255)
Even if an image uses the whole value range, sometimes there is very
little weight at the ends of the value range. In such a case, clipping
pixel values using percentiles of the image improves the contrast (at the
expense of some loss of information, because some pixels are saturated by
this operation)::
>>> moon = data.moon()
>>> v_min, v_max = np.percentile(moon, (0.2, 99.8))
>>> v_min, v_max
(10.0, 186.0)
>>> better_contrast = exposure.rescale_intensity(
... moon, in_range=(v_min, v_max))
The function :func:`equalize_hist` maps the cumulative distribution
function (cdf) of pixel values onto a linear cdf, ensuring that all parts
of the value range are equally represented in the image. As a result,
details are enhanced in large regions with poor contrast. As a further
refinement, histogram equalization can be performed in subregions of the
image with :func:`equalize_adapthist`, in order to correct for exposure
gradients across the image. See the example
:ref:`example_plot_equalize.py`.
.. image:: ../auto_examples/images/plot_equalize_1.png
:target: ../auto_examples/plot_equalize.html
:align: center
:width: 90%
.. topic:: Examples:
* :ref:`example_plot_equalize.py`
+61
View File
@@ -0,0 +1,61 @@
========================
How to parallelize loops
========================
In image processing, we frequently apply the same algorithm
on a large batch of images. Here is an example:
.. code-block:: python
from skimage import data, color, util
from skimage.restoration import denoise_tv_chambolle
from skimage.feature import hog
def task(image):
"""
Apply some functions and return an image.
"""
image = denoise_tv_chambolle(image[0][0], weight=0.1, multichannel=True)
fd, hog_image = hog(color.rgb2gray(image), orientations=8,
pixels_per_cell=(16, 16), cells_per_block=(1, 1),
visualise=True)
return hog_image
# Prepare images
hubble = data.hubble_deep_field()
width = 10
pics = util.view_as_windows(hubble, (width, hubble.shape[1], hubble.shape[2]), step=width)
To call the function ``task`` on each element of the list ``pics``, it is
usual to write a for loop. To measure the execution time of this loop, you can
use ipython and measure the execution time with ``%timeit``.
.. code-block:: python
def classic_loop():
for image in pics:
task(image)
%timeit classic_loop()
Another equivalent way to code this loop is to use a comprehension list which has the same efficiency.
.. code-block:: python
def comprehension_loop():
[task(image) for image in pics]
%timeit comprehension_loop()
``joblib`` is a library providing an easy way to parallelize for loops once we have a comprehension list.
The number of jobs can be specified.
.. code-block:: python
from joblib import Parallel, delayed
def joblib_loop():
Parallel(n_jobs=4)(delayed(task)(i) for i in pics)
%timeit joblib_loop()
+12 -12
View File
@@ -11,7 +11,7 @@ the coins cannot be done directly from the histogram of grey values,
because the background shares enough grey levels with the coins that a
thresholding segmentation is not sufficient.
.. image:: ../../_images/plot_coins_segmentation_1.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_1.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -26,7 +26,7 @@ Simply thresholding the image leads either to missing significant parts
of the coins, or to merging parts of the background with the
coins. This is due to the inhomogeneous lighting of the image.
.. image:: ../../_images/plot_coins_segmentation_2.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_2.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -38,11 +38,11 @@ Edge-based segmentation
Let us first try to detect edges that enclose the coins. For edge
detection, we use the `Canny detector
<http://en.wikipedia.org/wiki/Canny_edge_detector>`_ of ``skimage.filter.canny``
<http://en.wikipedia.org/wiki/Canny_edge_detector>`_ of ``skimage.feature.canny``
::
>>> from skimage.filter import canny
>>> from skimage.feature import canny
>>> edges = canny(coins/255.)
As the background is very smooth, almost all edges are found at the
@@ -53,7 +53,7 @@ boundary of the coins, or inside the coins.
>>> from scipy import ndimage
>>> fill_coins = ndimage.binary_fill_holes(edges)
.. image:: ../../_images/plot_coins_segmentation_3.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_3.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -62,7 +62,7 @@ we fill the inner part of the coins using the
``ndimage.binary_fill_holes`` function, which uses mathematical morphology
to fill the holes.
.. image:: ../../_images/plot_coins_segmentation_4.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_4.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -83,7 +83,7 @@ has not been segmented correctly at all. The reason is that the contour
that we got from the Canny detector was not completely closed, therefore
the filling function did not fill the inner part of the coin.
.. image:: ../../_images/plot_coins_segmentation_5.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_5.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -117,7 +117,7 @@ The choice of the elevation map is critical for good segmentation.
Here, the amplitude of the gradient provides a good elevation map. We
use the Sobel operator for computing the amplitude of the gradient::
>>> from skimage.filter import sobel
>>> from skimage.filters import sobel
>>> elevation_map = sobel(coins)
From the 3-D surface plot shown below, we see that high barriers effectively
@@ -128,7 +128,7 @@ separate the coins from the background.
and here is the corresponding 2-D plot:
.. image:: ../../_images/plot_coins_segmentation_6.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_6.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -139,7 +139,7 @@ extreme parts of the histogram of grey values::
>>> markers[coins < 30] = 1
>>> markers[coins > 150] = 2
.. image:: ../../_images/plot_coins_segmentation_7.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_7.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -148,7 +148,7 @@ Let us now compute the watershed transform::
>>> from skimage.morphology import watershed
>>> segmentation = watershed(elevation_map, markers)
.. image:: ../../_images/plot_coins_segmentation_8.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_8.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
@@ -165,7 +165,7 @@ We can now label all the coins one by one using ``ndimage.label``::
>>> labeled_coins, _ = ndimage.label(segmentation)
.. image:: ../../_images/plot_coins_segmentation_9.png
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_9.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
:align: center
+1
View File
@@ -5,3 +5,4 @@ Tutorials
:maxdepth: 1
tutorial_segmentation
tutorial_parallelization
+1 -1
View File
@@ -51,7 +51,7 @@ call the total-variation denoising function, ``denoise_tv_bregman``:
.. code-block:: python
from skimage.filter import denoise_tv_bregman
from skimage.filters import denoise_tv_bregman
from skimage.viewer.plugins.base import Plugin
denoise_plugin = Plugin(image_filter=denoise_tv_bregman)
+18 -15
View File
@@ -21,7 +21,7 @@ is an MIT-licensed project.
import os
import re
from types import BuiltinFunctionType
from types import BuiltinFunctionType, FunctionType
# suppress print statements (warnings for empty files)
DEBUG = True
@@ -200,7 +200,7 @@ class ApiDocWriter(object):
classes : list of str
A list of (public) class names in the module.
"""
mod = __import__(uri, fromlist=[uri])
mod = __import__(uri, fromlist=[uri.split('.')[-1]])
# find all public objects in the module.
obj_strs = [obj for obj in dir(mod) if not obj.startswith('_')]
functions = []
@@ -210,9 +210,9 @@ class ApiDocWriter(object):
if obj_str not in mod.__dict__:
continue
obj = mod.__dict__[obj_str]
# figure out if obj is a function or class
if hasattr(obj, 'func_name') or \
isinstance(obj, BuiltinFunctionType):
if isinstance(obj, FunctionType):
functions.append(obj_str)
else:
try:
@@ -279,6 +279,20 @@ class ApiDocWriter(object):
ad += '\n.. automodule:: ' + uri + '\n'
ad += '\n.. currentmodule:: ' + uri + '\n'
ad += '.. autosummary::\n\n'
for f in functions:
ad += ' ' + uri + '.' + f + '\n'
ad += '\n'
for c in classes:
ad += ' ' + uri + '.' + c + '\n'
ad += '\n'
for f in functions:
# must NOT exclude from index to keep cross-refs working
full_f = uri + '.' + f
ad += f + '\n'
ad += self.rst_section_levels[2] * len(f) + '\n'
ad += '\n.. autofunction:: ' + full_f + '\n\n'
for c in classes:
ad += '\n:class:`' + c + '`\n' \
+ self.rst_section_levels[2] * \
@@ -290,17 +304,6 @@ class ApiDocWriter(object):
' :show-inheritance:\n' \
'\n' \
' .. automethod:: __init__\n'
ad += '.. autosummary::\n\n'
for f in functions:
ad += ' ' + uri + '.' + f + '\n'
ad += '\n'
for f in functions:
# must NOT exclude from index to keep cross-refs working
full_f = uri + '.' + f
ad += f + '\n'
ad += self.rst_section_levels[2] * len(f) + '\n'
ad += '\n.. autofunction:: ' + full_f + '\n\n'
return ad
def _survives_exclude(self, matchstr, match_type):

Some files were not shown because too many files have changed in this diff Show More