mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-15 11:25:53 +08:00
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:
@@ -6,6 +6,7 @@ source = skimage
|
||||
include = */skimage/*
|
||||
omit =
|
||||
*/setup.py
|
||||
*/skimage/external/*
|
||||
|
||||
[report]
|
||||
exclude_lines =
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
--------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,31 +1,71 @@
|
||||
Image Processing SciKit
|
||||
=======================
|
||||
# scikit-image: Image processing in Python
|
||||
|
||||
Source
|
||||
------
|
||||
https://github.com/scikit-image/scikit-image
|
||||
[](https://gitter.im/scikit-image/scikit-image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](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
@@ -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`
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
+22
-21
@@ -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')
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+8
-4
@@ -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()
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
------------
|
||||
|
||||
|
||||
@@ -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,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++){
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -251,6 +251,7 @@ latex_use_modindex = False
|
||||
# Numpy extensions
|
||||
# -----------------------------------------------------------------------------
|
||||
numpydoc_show_class_members = False
|
||||
numpydoc_class_members_toctree = False
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Plots
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Table of Contents
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
|
||||
/api/api
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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::
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
.. _using-git:
|
||||
|
||||
Working with *scikit-image* source code
|
||||
========================================
|
||||
================================================
|
||||
|
||||
Contents:
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -15,7 +15,7 @@ Sections
|
||||
:hidden:
|
||||
|
||||
overview
|
||||
api
|
||||
api/api
|
||||
api_changes
|
||||
install
|
||||
user_guide
|
||||
|
||||
+8
-17
@@ -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
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
<div class="well footer">
|
||||
<small>
|
||||
© 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;*/
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
============
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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()
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@ Tutorials
|
||||
:maxdepth: 1
|
||||
|
||||
tutorial_segmentation
|
||||
tutorial_parallelization
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user