Fix setup merge conflict
@@ -22,4 +22,5 @@ doc/source/auto_examples/images/plot_*.png
|
||||
doc/source/auto_examples/images/thumb
|
||||
doc/source/auto_examples/applications/
|
||||
doc/source/_static/random.js
|
||||
|
||||
.idea/
|
||||
*.log
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# vim ft=yaml
|
||||
# travis-ci.org definition for skimage build
|
||||
#
|
||||
# We pretend to be erlang because we need can't use the python support in
|
||||
# travis-ci; it uses virtualenvs, they do not have numpy, scipy, matplotlib,
|
||||
# and it is impractical to build them
|
||||
|
||||
language: erlang
|
||||
env:
|
||||
- PYTHON=python PYSUF='' PYVER=2.7
|
||||
- PYTHON=python3 PYSUF='3' PYVER=3.2
|
||||
install:
|
||||
- sudo apt-get update # needed for python3-numpy
|
||||
- sudo apt-get install $PYTHON-dev
|
||||
- sudo apt-get install $PYTHON-numpy
|
||||
- sudo apt-get install $PYTHON-scipy
|
||||
- sudo apt-get install $PYTHON-setuptools
|
||||
- sudo apt-get install $PYTHON-nose
|
||||
- sudo easy_install$PYSUF pip
|
||||
- sudo pip-$PYVER install cython
|
||||
- sudo apt-get install libfreeimage3
|
||||
- $PYTHON setup.py build
|
||||
- sudo $PYTHON setup.py install
|
||||
script:
|
||||
# Change into an innocuous directory and find tests from installation
|
||||
- mkdir for_test
|
||||
- cd for_test
|
||||
- nosetests-$PYVER --exe -v --cover-package=skimage skimage
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
Project coordination
|
||||
|
||||
- Nicolas Pinto
|
||||
Colour spaces and filters.
|
||||
Colour spaces and filters, and image resizing.
|
||||
Shape views: ``util.shape.view_as_windows`` and ``util.shape.view_as_blocks``
|
||||
Montage helpers: ``util.montage``
|
||||
Montage helpers: ``util.montage``.
|
||||
|
||||
- Damian Eads
|
||||
Morphological operators
|
||||
@@ -73,7 +73,8 @@
|
||||
From whom we borrowed the example generation tools.
|
||||
|
||||
- Andreas Mueller
|
||||
Example data set loader.
|
||||
Example data set loader. Nosetest compatibility functions.
|
||||
Quickshift image segmentation, Felzenszwalbs fast graph based segmentation.
|
||||
|
||||
- Yaroslav Halchenko
|
||||
For sharing his expert advice on Debian packaging.
|
||||
@@ -102,8 +103,36 @@
|
||||
|
||||
- Nicolas Poilvert
|
||||
Shape views: ``util.shape.view_as_windows`` and ``util.shape.view_as_blocks``
|
||||
Image resizing.
|
||||
|
||||
- Johannes Schönberger
|
||||
Polygon, circle and ellipse drawing functions
|
||||
Adaptive thresholding
|
||||
Implementation of Matlab's `regionprops`
|
||||
Drawing functions, adaptive thresholding, regionprops, geometric
|
||||
transformations, LBPs, polygon approximations, web layout, and more.
|
||||
|
||||
- Pavel Campr
|
||||
Fixes and tests for Histograms of Oriented Gradients.
|
||||
|
||||
- Joshua Warner
|
||||
Multichannel random walker segmentation.
|
||||
|
||||
- Petter Strandmark
|
||||
Perimeter calculation in regionprops.
|
||||
|
||||
- Olivier Debeir
|
||||
Rank filters (8- and 16-bits) using sliding window.
|
||||
|
||||
- Luis Pedro Coelho
|
||||
imread plugin
|
||||
|
||||
- Steven Silvester, Karel Zuiderveld
|
||||
Adaptive Histogram Equalization
|
||||
|
||||
- Anders Boesen Lindbo Larsen
|
||||
Dense DAISY feature description, circle perimeter drawing.
|
||||
|
||||
- François Boulogne
|
||||
Andres Method for circle perimeter, ellipse perimeter drawing.
|
||||
Circular Hough Transform
|
||||
|
||||
- Thouis Jones
|
||||
Vectorized operators for arrays of 16-bit ints.
|
||||
|
||||
@@ -4,10 +4,13 @@ Build Requirements
|
||||
* `Numpy >= 1.6 <http://numpy.scipy.org/>`__
|
||||
* `Cython >= 0.15 <http://www.cython.org/>`__
|
||||
|
||||
|
||||
`Matplotlib >= 1.0 <http://matplotlib.sf.net>`__ is needed to generate the
|
||||
examples in the documentation.
|
||||
|
||||
Runtime requirements
|
||||
--------------------
|
||||
* `SciPy >= 0.10 <http://scipy.org>`__
|
||||
|
||||
Known build errors
|
||||
------------------
|
||||
On Windows, the error ``Error:unable to find vcvarsall.bat`` means that
|
||||
@@ -34,3 +37,4 @@ functionality is only available with the following installed:
|
||||
`FreeImage <http://freeimage.sf.net>`__
|
||||
The ``freeimage`` plugin provides support for reading various types of
|
||||
image file formats, including multi-page TIFFs.
|
||||
|
||||
|
||||
@@ -1,51 +1,94 @@
|
||||
Development process
|
||||
-------------------
|
||||
|
||||
:doc:`Read this overview <gitwash/index>` of how to use Git with
|
||||
``skimage``. Here's the long and short of it:
|
||||
Here's the long and short of it:
|
||||
|
||||
* Go to `https://github.com/scikits-image/scikits-image
|
||||
<http://github.com/scikits-image/scikits-image>`_ and follow the
|
||||
* Go to `https://github.com/scikit-image/scikit-image
|
||||
<http://github.com/scikit-image/scikit-image>`_ and follow the
|
||||
instructions on making your own fork.
|
||||
* Create a new branch for the feature you want to work on. Since the
|
||||
branch name will appear in the merge message, use a sensible name
|
||||
such as 'your_name-transform-speedups'.
|
||||
such as 'transform-speedups'.
|
||||
* Commit locally as you progress.
|
||||
* Push your changes back to github and create a pull request by
|
||||
clicking "request pull" in GitHub.
|
||||
* Optionally, mail the mailing list, explaining your changes.
|
||||
* Push your changes back to GitHub and create a Pull Request by
|
||||
clicking 'Pull Request' in GitHub.
|
||||
* Optionally, post on the `mailing list <http://groups.google.com/group/scikit-image>`_ to explain your changes.
|
||||
|
||||
Read these :doc:`detailed documents <gitwash/index>` on how to use Git with
|
||||
``scikit-image`` (`<http://scikit-image.org/docs/dev/gitwash/index.html>`_).
|
||||
|
||||
.. note::
|
||||
|
||||
Do *not* merge the main branch into yours. If GitHub indicates that the
|
||||
Pull Request can no longer be merged automatically, rebase onto master.
|
||||
|
||||
(If you are curious, here's a further discussion on
|
||||
the `dangers of rebasing <http://tinyurl.com/lll385>`__. Also
|
||||
see this `LWN article <http://tinyurl.com/nqcbkj>`__.)
|
||||
|
||||
* To reviewers: add a short explanation of what a branch did to the merge
|
||||
message or, if closing a bug, add "Closes gh-XXXX".
|
||||
|
||||
You may also read this summary by Fernando Perez of the IPython
|
||||
project on how they manage to keep review overhead to a minimum:
|
||||
|
||||
http://mail.scipy.org/pipermail/ipython-dev/2010-October/006746.html
|
||||
|
||||
.. note::
|
||||
|
||||
Do *not* merge the main branch into yours. You may rebase,
|
||||
as long as you are `aware of its dangers <http://tinyurl.com/lll385>`_
|
||||
(also see `LWN article <http://tinyurl.com/nqcbkj>`_).
|
||||
|
||||
* To reviewers: add a short explanation of what a branch did to the merge
|
||||
message or, if closing a bug, add "Closes gh-XXXX".
|
||||
|
||||
Guidelines
|
||||
``````````
|
||||
* All code should have tests (see "Test coverage" below for more details).
|
||||
----------
|
||||
|
||||
* 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. If possible, also add a section to the user guide.
|
||||
as NumPy and SciPy. For new functionality, always add an example to the
|
||||
gallery.
|
||||
* Follow the `Python PEPs <http://www.python.org/dev/peps/pep-0008/>`_
|
||||
where possible.
|
||||
* No major changes should be committed without review. Ask on the
|
||||
`mailing list <http://groups.google.com/group/scikits-image>`_ if
|
||||
`mailing list <http://groups.google.com/group/scikit-image>`_ if
|
||||
you get no response to your pull request.
|
||||
* Examples in the gallery should have a maximum figure width of 8 inches.
|
||||
|
||||
Stylistic Guidelines
|
||||
--------------------
|
||||
|
||||
* Use numpy data types instead of strings (``np.uint8`` instead of
|
||||
``"uint8"``).
|
||||
|
||||
* Use the following import conventions::
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
cimport numpy as cnp # in Cython code
|
||||
|
||||
* When documenting array parameters, use ``image : (M, N) ndarray``,
|
||||
``image : (M, N, 3) ndarray`` and then refer to ``M`` and ``N`` in the
|
||||
docstring.
|
||||
|
||||
* Set up your editor to remove trailing whitespace. Follow `PEP08
|
||||
<www.python.org/dev/peps/pep-0008/>`__. Check code with pyflakes / flake8.
|
||||
|
||||
* If a function name, say ``segment(...)``, has the same name as the file in
|
||||
which it is implemented, name that file ``_segment.py`` so that it can still
|
||||
be imported. All Cython files start with an underscore, e.g.
|
||||
``_some_module.pyx``.
|
||||
|
||||
* Functions should support all input image dtypes. Use utility functions such
|
||||
as ``img_as_float`` to help convert to an appropriate type. The output
|
||||
format can be whatever is most efficient. This allows us to string together
|
||||
several functions into a pipeline, e.g.::
|
||||
|
||||
hough(canny(my_image))
|
||||
|
||||
* Use `Py_ssize_t` as data type for all indexing, shape and size variables in
|
||||
C/C++ and Cython code.
|
||||
|
||||
Test coverage
|
||||
`````````````
|
||||
-------------
|
||||
|
||||
Tests for a module should ideally cover all code in that module,
|
||||
i.e. statement coverage should be at 100%.
|
||||
i.e., statement coverage should be at 100%.
|
||||
|
||||
To measure the test coverage, install
|
||||
`coverage.py <http://nedbatchelder.com/code/coverage/>`__
|
||||
@@ -63,5 +106,6 @@ detailing the test coverage::
|
||||
...
|
||||
|
||||
Bugs
|
||||
````
|
||||
Please `report bugs on Github <https://github.com/scikits-image/scikits-image/issues>`_.
|
||||
----
|
||||
|
||||
Please `report bugs on GitHub <https://github.com/scikit-image/scikit-image/issues>`_.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Unless otherwise specified by LICENSE.txt files in individual
|
||||
directories, all code is
|
||||
|
||||
Copyright (C) 2011, the scikits-image team
|
||||
Copyright (C) 2011, the scikit-image team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -3,11 +3,11 @@ Image Processing SciKit
|
||||
|
||||
Source
|
||||
------
|
||||
https://github.com/scikits-image/scikits-image
|
||||
https://github.com/scikit-image/scikit-image
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
http://groups.google.com/group/scikits-image
|
||||
http://groups.google.com/group/scikit-image
|
||||
|
||||
Installation from source
|
||||
------------------------
|
||||
@@ -29,8 +29,3 @@ this path to your PYTHONPATH variable and compiling the extensions:
|
||||
License
|
||||
-------
|
||||
Please read LICENSE.txt in this directory.
|
||||
|
||||
Contact
|
||||
-------
|
||||
Stefan van der Walt <stefan at sun.ac.za>
|
||||
|
||||
@@ -2,30 +2,89 @@ How to make a new release of ``skimage``
|
||||
========================================
|
||||
|
||||
- Update release notes.
|
||||
- Update the version number in setup.py and bento.info and commit
|
||||
|
||||
- To show a list contributors, run ``doc/release/contributors.sh <commit>``,
|
||||
where ``<commit>`` is the first commit since the previous release.
|
||||
|
||||
- Update the version number in ``setup.py`` and ``bento.info`` and commit
|
||||
|
||||
- Update the docs:
|
||||
|
||||
- Edit ``doc/source/themes/agogo/static/docversions.js`` and commit
|
||||
- Build a clean version of the docs. Run "make" in the root dir, then
|
||||
``rm build -rf; make html`` in the docs.
|
||||
- Push upstream using "make gh-pages"
|
||||
- Build a clean version of the docs. Run ``make`` in the root dir, then
|
||||
``rm -rf build; make html`` in the docs.
|
||||
- Run ``make html`` again to copy the newly generated ``random.js`` into
|
||||
place. Double check ``random.js``, otherwise the skimage.org front
|
||||
page gets broken!
|
||||
- Build using ``make gh-pages``.
|
||||
- Push upstream: ``git push`` in ``doc/gh-pages``.
|
||||
|
||||
- Add the version number as a tag in git::
|
||||
|
||||
git tag v0.6
|
||||
git tag v0.X.0
|
||||
|
||||
- Push the new meta-data to github::
|
||||
|
||||
git push --tags origin master
|
||||
git push --tags origin master
|
||||
|
||||
- Publish on PyPi:
|
||||
- Publish on PyPi::
|
||||
|
||||
python setup.py register
|
||||
python setup.py sdist upload
|
||||
python setup.py register
|
||||
python setup.py sdist upload
|
||||
|
||||
- Increase the version number in the setup.py file to ``0.Xdev``.
|
||||
- Increase the version number
|
||||
|
||||
- In ``setup.py``, set to ``0.Xdev``.
|
||||
- In ``bento.info``, set to ``0.X.dev0``.
|
||||
|
||||
- Update the web frontpage:
|
||||
The webpage is kept in a separate repo: scikits-image-web
|
||||
- ``_templates/sidebar_versions.html``
|
||||
- ``index.rst``
|
||||
The webpage is kept in a separate repo: scikit-image-web
|
||||
|
||||
- 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".
|
||||
- Build using ``make gh-pages``.
|
||||
- Push upstream: ``git push`` in ``gh-pages``.
|
||||
|
||||
- Post release notes on mailing lists, blog, G+, etc.
|
||||
|
||||
Debian
|
||||
------
|
||||
|
||||
- Tag the release as per instructions above.
|
||||
- git checkout debian
|
||||
- git merge v0.x.x
|
||||
- uscan <- not sure if this step is necessary
|
||||
- Update changelog (emacs has a good mode, requires package dpkg-dev-el)
|
||||
- C-C C-v add new version, C-c C-c timestamp / save
|
||||
- git commit -m 'Changelog entry for 0.x.x'
|
||||
- git-buildpackage -uc -us -rfakeroot
|
||||
- Sign the changes: debsign skimage_0.x.x-x_amd64.changes
|
||||
- cd ../build-area && dput mentors skimage_0.x.x-x_amd64.changes
|
||||
- The package should now be available at:
|
||||
|
||||
http://mentors.debian.net/package/skimage
|
||||
|
||||
For the last lines above to work, you need ``~/.gbp.conf``::
|
||||
|
||||
[DEFAULT]
|
||||
upstream-tag = %(version)s
|
||||
|
||||
[git-buildpackage]
|
||||
sign-tags = True
|
||||
export-dir = ../build-area/
|
||||
tarball-dir = ../tarballs/
|
||||
|
||||
As well as ``~/dput.cf``::
|
||||
|
||||
[mentors]
|
||||
fqdn = mentors.debian.net
|
||||
incoming = /upload
|
||||
method = http
|
||||
allow_unsigned_uploads = 0
|
||||
progress_indicator = 2
|
||||
# Allow uploads for UNRELEASED packages
|
||||
allowed_distributions = .*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.. role:: strike
|
||||
|
||||
|
||||
.. _howto_contribute:
|
||||
|
||||
How to contribute to ``skimage``
|
||||
@@ -14,112 +15,15 @@ How to contribute to ``skimage``
|
||||
cell_profiler
|
||||
|
||||
|
||||
Developing Open Source is great fun! Join us on the `skimage mailing
|
||||
list <http://groups.google.com/group/scikits-image>`_ and tell us which of the
|
||||
Developing Open Source is great fun! Join us on the `scikit-image mailing
|
||||
list <http://groups.google.com/group/scikit-image>`_ and tell us which of the
|
||||
following challenges you'd like to solve.
|
||||
|
||||
* Mentoring is available for those new to scientific programming in Python.
|
||||
* The technical detail of the `development process`_ is given below.
|
||||
* :doc:`How to use GitHub <gitwash/index>` when developing skimage
|
||||
* If you're looking for something to implement, you can find a list of `requested features on GitHub <https://github.com/scikit-image/scikit-image/wiki/Requested-features>`__. In addition, you can browse the `open issues on GitHub <https://github.com/scikit-image/scikit-image/issues?state=open>`__.
|
||||
* The technical detail of the `development process`_ is summed up below.
|
||||
Refer to the :doc:`gitwash <gitwash/index>` for a step-by-step tutorial.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Tasks
|
||||
-----
|
||||
|
||||
.. :doc:`gsoc2011`
|
||||
.. :doc:`coverage_table`
|
||||
|
||||
Implement Algorithms
|
||||
````````````````````
|
||||
- Graph cut segmentation
|
||||
- `Image colorization <http://www.cs.huji.ac.il/~yweiss/Colorization/>`__
|
||||
- Fast 2D convex hull (consider using CellProfiler version)
|
||||
`Algorithm overview <http://www.tcs.fudan.edu.cn/rudolf/Courses/Algorithms/Alg_cs_07w/Webprojects/Zhaobo_hull/index.html#section26>`__.
|
||||
`One free implementation
|
||||
<http://cm.bell-labs.com/cm/cs/who/clarkson/2dch.c>`_.
|
||||
[Compare against current implementation]
|
||||
- Convex hulls of objects in a labels matrix (simply adapt current convex hull
|
||||
image code--this one's low hanging fruit). Generalise this solution to also
|
||||
skeletonize objects in a labels matrix.
|
||||
|
||||
Drawing (directly on an ndarray)
|
||||
````````````````````````````````
|
||||
- Wu's algorithm for circles
|
||||
- Text rendering
|
||||
|
||||
Infrastructure
|
||||
--------------
|
||||
- :strike:`Implement a new backend system so that we may start including
|
||||
PyOpenCL-based algorithms`
|
||||
|
||||
Adapt existing code for use
|
||||
```````````````````````````
|
||||
These snippets and packages have already been written. Some need to be
|
||||
modified to work as part of the scikit, others may be lacking in documentation
|
||||
or tests.
|
||||
|
||||
* :strike:`Connected components`
|
||||
* Nadav's bilateral filtering (first compare against CellProfiler's
|
||||
code, based on http://groups.csail.mit.edu/graphics/bilagrid/bilagrid_web.pdf)
|
||||
Also see https://github.com/stefanv/scikits-image/tree/bilateral
|
||||
* 2D image warping via thin-plate splines [ask Zach Pincus]
|
||||
|
||||
Merge code provided by `CellProfiler <http://www.cellprofiler.org>`_ team
|
||||
`````````````````````````````````````````````````````````````````````````
|
||||
* Roberts filter - convolution with diagonal and anti-diagonal
|
||||
kernels to detect edges
|
||||
* Minimum enclosing circles of objects in a labels matrix
|
||||
* spur removal, thinning, thickening, and other morphological operations on
|
||||
binary images, framework for creating arbitrary morphological operations
|
||||
using a 3x3 grid.
|
||||
|
||||
Their SVN repository is read-accessible at
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler
|
||||
|
||||
The files for the above algorithms are
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/cpmorphology.py
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/filter.py
|
||||
|
||||
There are test suites for the files at
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/tests/test_cpmorphology.py
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/tests/test_filter.py
|
||||
|
||||
Quoting a message from Lee Kamentsky to Stefan van der Walt sent on
|
||||
5 August 2009::
|
||||
|
||||
We're part of the Broad Institute which is non-profit. We would be happy
|
||||
to include our algorithm code in SciPy under the BSD license since that is
|
||||
more appropriate for a library that might be integrated into a
|
||||
commercial product whereas CellProfiler needs the more stringent
|
||||
protection of GPL as an application.
|
||||
|
||||
In 2010, Vebjorn Ljosa officially released parts of the code under a
|
||||
BSD license (:doc:`cell_profiler` | `original message
|
||||
<http://groups.google.com/group/scikits-image/browse_thread/thread/c4f8fc584bfd839d>`_).
|
||||
|
||||
Thanks to Lee Kamentsky, Thouis Jones and Anne Carpenter and their colleagues
|
||||
who contributed.
|
||||
|
||||
Rework linear filters
|
||||
`````````````````````
|
||||
* Fast, SSE2 convolution (high priority) (see prototype in pull requests)
|
||||
* Should take kernel or function for parameter (currently only takes function)
|
||||
* Kernel shape should be specifiable (currently defaults to image shape)
|
||||
|
||||
io
|
||||
``
|
||||
* Update ``qt_plugin.py`` and other plugins to view collections.
|
||||
* Rewrite GTK backend using GObject Introspection for Py3K compatibility.
|
||||
* Add DICOM plugin for `GDCM <http://sourceforge.net/apps/mediawiki/gdcm>`__.
|
||||
|
||||
docs
|
||||
````
|
||||
* Add examples to the gallery
|
||||
* Write topics for the `user guide
|
||||
<http://scikits-image.org/docs/dev/user_guide.html>`_
|
||||
* Integrate BiBTeX plugin into Sphinx build
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Name: scikits-image
|
||||
Version: 0.6
|
||||
Name: scikit-image
|
||||
Version: 0.8.0
|
||||
Summary: Image processing routines for SciPy
|
||||
Url: http://scikits-image.org
|
||||
DownloadUrl: http://github.com/scikits-image/scikits-image
|
||||
Url: http://scikit-image.org
|
||||
DownloadUrl: http://github.com/scikit-image/scikit-image
|
||||
Description: Image Processing SciKit
|
||||
|
||||
Image processing algorithms for SciPy, including IO, morphology, filtering,
|
||||
warping, color manipulation, object detection, etc.
|
||||
|
||||
Please refer to the online documentation at
|
||||
http://scikits-image.org/
|
||||
http://scikit-image.org/
|
||||
Maintainer: Stefan van der Walt
|
||||
MaintainerEmail: stefan@sun.ac.za
|
||||
License: Modified BSD
|
||||
@@ -40,9 +40,6 @@ Library:
|
||||
Extension: skimage.morphology._pnpoly
|
||||
Sources:
|
||||
skimage/morphology/_pnpoly.pyx
|
||||
Extension: skimage.feature._greycomatrix
|
||||
Sources:
|
||||
skimage/feature/_greycomatrix.pyx
|
||||
Extension: skimage.feature._template
|
||||
Sources:
|
||||
skimage/feature/_template.pyx
|
||||
@@ -67,6 +64,9 @@ Library:
|
||||
Extension: skimage.filter._ctmf
|
||||
Sources:
|
||||
skimage/filter/_ctmf.pyx
|
||||
Extension: skimage.filter._denoise_cy
|
||||
Sources:
|
||||
skimage/filter/_denoise_cy.pyx
|
||||
Extension: skimage.morphology.ccomp
|
||||
Sources:
|
||||
skimage/morphology/ccomp.pyx
|
||||
@@ -76,15 +76,9 @@ Library:
|
||||
Extension: skimage.morphology._convex_hull
|
||||
Sources:
|
||||
skimage/morphology/_convex_hull.pyx
|
||||
Extension: skimage.morphology._skeletonize
|
||||
Sources:
|
||||
skimage/morphology/_skeletonize.pyx
|
||||
Extension: skimage.draw._draw
|
||||
Sources:
|
||||
skimage/draw/_draw.pyx
|
||||
Extension: skimage.transform._project
|
||||
Sources:
|
||||
skimage/transform/_project.pyx
|
||||
Extension: skimage.graph._spath
|
||||
Sources:
|
||||
skimage/graph/_spath.pyx
|
||||
@@ -94,6 +88,69 @@ Library:
|
||||
Extension: skimage.graph.heap
|
||||
Sources:
|
||||
skimage/graph/heap.pyx
|
||||
Extension: skimage.morphology._greyreconstruct
|
||||
Sources:
|
||||
skimage/morphology/_greyreconstruct.pyx
|
||||
Extension: skimage.feature.corner_cy
|
||||
Sources:
|
||||
skimage/feature/corner_cy.pyx
|
||||
Extension: skimage.feature._texture
|
||||
Sources:
|
||||
skimage/feature/_texture.pyx
|
||||
Extension: skimage._shared.transform
|
||||
Sources:
|
||||
skimage/_shared/transform.pyx
|
||||
Extension: skimage.segmentation._slic
|
||||
Sources:
|
||||
skimage/segmentation/_slic.pyx
|
||||
Extension: skimage.segmentation._quickshift
|
||||
Sources:
|
||||
skimage/segmentation/_quickshift.pyx
|
||||
Extension: skimage.morphology._skeletonize_cy
|
||||
Sources:
|
||||
skimage/morphology/_skeletonize_cy.pyx
|
||||
Extension: skimage.transform._warps_cy
|
||||
Sources:
|
||||
skimage/transform/_warps_cy.pyx
|
||||
Extension: skimage._shared.interpolation
|
||||
Sources:
|
||||
skimage/_shared/interpolation.pyx
|
||||
Extension: skimage.segmentation._felzenszwalb_cy
|
||||
Sources:
|
||||
skimage/segmentation/_felzenszwalb_cy.pyx
|
||||
Extension: skimage._shared.geometry
|
||||
Sources:
|
||||
skimage/_shared/geometry.pyx
|
||||
Extension: skimage.filter.rank._core16
|
||||
Sources:
|
||||
skimage/filter/rank/_core16.pyx
|
||||
Extension: skimage.filter.rank._crank8
|
||||
Sources:
|
||||
skimage/filter/rank/_crank8.pyx
|
||||
Extension: skimage.filter.rank._crank16
|
||||
Sources:
|
||||
skimage/filter/rank/_crank16.pyx
|
||||
Extension: skimage.filter.rank._core8
|
||||
Sources:
|
||||
skimage/filter/rank/_core8.pyx
|
||||
Extension: skimage.filter.rank.rank
|
||||
Sources:
|
||||
skimage/filter/rank/rank.pyx
|
||||
Extension: skimage.filter.rank.bilateral_rank
|
||||
Sources:
|
||||
skimage/filter/rank/bilateral_rank.pyx
|
||||
Extension: skimage.filter.rank._crank16_percentiles
|
||||
Sources:
|
||||
skimage/filter/rank/_crank16_percentiles.pyx
|
||||
Extension: skimage.filter.rank.percentile_rank
|
||||
Sources:
|
||||
skimage/filter/rank/percentile_rank.pyx
|
||||
Extension: skimage.filter.rank._crank8_percentiles
|
||||
Sources:
|
||||
skimage/filter/rank/_crank8_percentiles.pyx
|
||||
Extension: skimage.filter.rank._crank16_bilateral
|
||||
Sources:
|
||||
skimage/filter/rank/_crank16_bilateral.pyx
|
||||
|
||||
Executable: skivi
|
||||
Module: skimage.scripts.skivi
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
Check that Cython extensions in setup.py files match those in bento.info.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
RE_CYTHON = re.compile("config.add_extension\(\s*['\"]([\S]+)['\"]")
|
||||
|
||||
BENTO_TEMPLATE = """
|
||||
Extension: {module_path}
|
||||
Sources:
|
||||
{dir_path}.pyx"""
|
||||
|
||||
|
||||
def each_setup_in_pkg(top_dir):
|
||||
"""Yield path and file object for each setup.py file"""
|
||||
for dir_path, dir_names, filenames in os.walk(top_dir):
|
||||
for fname in filenames:
|
||||
if fname == 'setup.py':
|
||||
with open(os.path.join(dir_path, 'setup.py')) as f:
|
||||
yield dir_path, f
|
||||
|
||||
|
||||
def each_cy_in_setup(top_dir):
|
||||
"""Yield path for each cython extension package's setup file."""
|
||||
for dir_path, f in each_setup_in_pkg(top_dir):
|
||||
text = f.read()
|
||||
match = RE_CYTHON.findall(text)
|
||||
if match:
|
||||
for cy_file in match:
|
||||
# if cython files in different directory than setup.py
|
||||
if '.' in cy_file:
|
||||
parts = cy_file.split('.')
|
||||
cy_file = parts[-1]
|
||||
# Don't overwrite dir_path for subsequent iterations.
|
||||
path = os.path.join(dir_path, *parts[:-1])
|
||||
else:
|
||||
path = dir_path
|
||||
full_path = os.path.join(path, cy_file)
|
||||
yield full_path
|
||||
|
||||
|
||||
def each_cy_in_bento(bento_file='bento.info'):
|
||||
"""Yield path for each cython extension in bento info file."""
|
||||
with open(bento_file) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith('Extension:'):
|
||||
path = line.lstrip('Extension:').strip()
|
||||
yield path
|
||||
|
||||
|
||||
def remove_common_extensions(cy_bento, cy_setup):
|
||||
# normalize so that cy_setup and cy_bento have the same separator
|
||||
cy_setup = set(ext.replace('/', '.') for ext in cy_setup)
|
||||
cy_setup_diff = cy_setup.difference(cy_bento)
|
||||
cy_setup_diff = set(ext.replace('.', '/') for ext in cy_setup_diff)
|
||||
cy_bento_diff = cy_bento.difference(cy_setup)
|
||||
return cy_bento_diff, cy_setup_diff
|
||||
|
||||
|
||||
def print_results(cy_bento, cy_setup):
|
||||
def info(text):
|
||||
print
|
||||
print(text)
|
||||
print('-' * len(text))
|
||||
|
||||
if not (cy_bento or cy_setup):
|
||||
print "bento.info and setup.py files match."
|
||||
|
||||
if cy_bento:
|
||||
info("Extensions found in 'bento.info' but not in any 'setup.py:")
|
||||
print('\n'.join(cy_bento))
|
||||
|
||||
|
||||
if cy_setup:
|
||||
info("Extensions found in a 'setup.py' but not in any 'bento.info:")
|
||||
print('\n'.join(cy_setup))
|
||||
info("Consider adding the following to the 'bento.info' Library:")
|
||||
for dir_path in cy_setup:
|
||||
module_path = dir_path.replace('/', '.')
|
||||
print BENTO_TEMPLATE.format(module_path=module_path,
|
||||
dir_path=dir_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# All cython extensions defined in 'setup.py' files.
|
||||
cy_setup = set(each_cy_in_setup('skimage'))
|
||||
|
||||
# All cython extensions defined 'bento.info' file.
|
||||
cy_bento = set(each_cy_in_bento())
|
||||
|
||||
cy_bento, cy_setup = remove_common_extensions(cy_bento, cy_setup)
|
||||
print_results(cy_bento, cy_setup)
|
||||
@@ -77,17 +77,17 @@ qthelp:
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in build/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator build/qthelp/scikitsimage.qhcp"
|
||||
@echo "# qcollectiongenerator build/qthelp/scikitimage.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile build/qthelp/scikitsimage.qhc"
|
||||
@echo "# assistant -collectionFile build/qthelp/scikitimage.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(DEST)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/scikitsimage"
|
||||
@echo "# ln -s build/devhelp $$HOME/.local/share/devhelp/scikitsimage"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/scikitimage"
|
||||
@echo "# ln -s build/devhelp $$HOME/.local/share/devhelp/scikitimage"
|
||||
@echo "# devhelp"
|
||||
|
||||
latex:
|
||||
@@ -123,9 +123,9 @@ gh-pages:
|
||||
python gh-pages.py
|
||||
|
||||
gitwash:
|
||||
python tools/gitwash/gitwash_dumper.py source scikits-image \
|
||||
--project-url=http://scikits-image.org \
|
||||
--project-ml-url=http://groups.google.com/group/scikits-image \
|
||||
--repo-name=scikits-image \
|
||||
--github-user=scikits-image \
|
||||
python tools/gitwash/gitwash_dumper.py source scikit-image \
|
||||
--project-url=http://scikit-image.org \
|
||||
--project-ml-url=http://groups.google.com/group/scikit-image \
|
||||
--repo-name=scikit-image \
|
||||
--github-user=scikit-image \
|
||||
--source-suffix=.txt
|
||||
|
||||
@@ -90,12 +90,8 @@ plt.title('Filling the holes')
|
||||
Small spurious objects are easily removed by setting a minimum size for valid
|
||||
objects.
|
||||
"""
|
||||
|
||||
label_objects, nb_labels = ndimage.label(fill_coins)
|
||||
sizes = np.bincount(label_objects.ravel())
|
||||
mask_sizes = sizes > 20
|
||||
mask_sizes[0] = 0
|
||||
coins_cleaned = mask_sizes[label_objects]
|
||||
from skimage import morphology
|
||||
coins_cleaned = morphology.remove_small_objects(fill_coins, 21)
|
||||
|
||||
plt.figure(figsize=(4, 3))
|
||||
plt.imshow(coins_cleaned, cmap=plt.cm.gray, interpolation='nearest')
|
||||
@@ -149,8 +145,7 @@ plt.title('markers')
|
||||
Finally, we use the watershed transform to fill regions of the elevation map starting from the markers determined above:
|
||||
|
||||
"""
|
||||
from skimage.morphology import watershed
|
||||
segmentation = watershed(elevation_map, markers)
|
||||
segmentation = morphology.watershed(elevation_map, markers)
|
||||
|
||||
plt.figure(figsize=(4, 3))
|
||||
plt.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
===============================
|
||||
Using geometric transformations
|
||||
===============================
|
||||
|
||||
In this example, we will see how to use geometric transformations in the context
|
||||
of image processing.
|
||||
"""
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage import transform as tf
|
||||
|
||||
margins = dict(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
|
||||
|
||||
"""
|
||||
Basics
|
||||
======
|
||||
|
||||
Several different geometric transformation types are supported: similarity,
|
||||
affine, projective and polynomial.
|
||||
|
||||
Geometric transformations can either be created using the explicit parameters
|
||||
(e.g. scale, shear, rotation and translation) or the transformation matrix:
|
||||
|
||||
First we create a transformation using explicit parameters:
|
||||
"""
|
||||
|
||||
tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 2,
|
||||
translation=(0, 1))
|
||||
print tform._matrix
|
||||
|
||||
"""
|
||||
Alternatively you can define a transformation by the transformation matrix
|
||||
itself:
|
||||
"""
|
||||
|
||||
matrix = tform._matrix.copy()
|
||||
matrix[1, 2] = 2
|
||||
tform2 = tf.SimilarityTransform(matrix)
|
||||
|
||||
"""
|
||||
These transformation objects can then be used to apply forward and inverse
|
||||
coordinate transformations between the source and destination coordinate
|
||||
systems:
|
||||
"""
|
||||
|
||||
coord = [1, 0]
|
||||
print tform2(coord)
|
||||
print tform2.inverse(tform(coord))
|
||||
|
||||
"""
|
||||
Image warping
|
||||
=============
|
||||
|
||||
Geometric transformations can also be used to warp images:
|
||||
"""
|
||||
|
||||
text = data.text()
|
||||
|
||||
tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 4,
|
||||
translation=(text.shape[0] / 2, -100))
|
||||
|
||||
rotated = tf.warp(text, tform)
|
||||
back_rotated = tf.warp(rotated, tform.inverse)
|
||||
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3))
|
||||
fig.subplots_adjust(**margins)
|
||||
plt.gray()
|
||||
ax1.imshow(text)
|
||||
ax1.axis('off')
|
||||
ax2.imshow(rotated)
|
||||
ax2.axis('off')
|
||||
ax3.imshow(back_rotated)
|
||||
ax3.axis('off')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Parameter estimation
|
||||
====================
|
||||
|
||||
In addition to the basic functionality mentioned above you can also estimate the
|
||||
parameters of a geometric transformation using the least-squares method.
|
||||
|
||||
This can amongst other things be used for image registration or rectification,
|
||||
where you have a set of control points or homologous/corresponding points in two
|
||||
images.
|
||||
|
||||
Let's assume we want to recognize letters on a photograph which was not taken
|
||||
from the front but at a certain angle. In the simplest case of a plane paper
|
||||
surface the letters are projectively distorted. Simple matching algorithms would
|
||||
not be able to match such symbols. One solution to this problem would be to warp
|
||||
the image so that the distortion is removed and then apply a matching algorithm:
|
||||
"""
|
||||
|
||||
text = data.text()
|
||||
|
||||
src = np.array((
|
||||
(0, 0),
|
||||
(0, 50),
|
||||
(300, 50),
|
||||
(300, 0)
|
||||
))
|
||||
dst = np.array((
|
||||
(155, 15),
|
||||
(65, 40),
|
||||
(260, 130),
|
||||
(360, 95)
|
||||
))
|
||||
|
||||
tform3 = tf.ProjectiveTransform()
|
||||
tform3.estimate(src, dst)
|
||||
warped = tf.warp(text, tform3, output_shape=(50, 300))
|
||||
|
||||
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(8, 3))
|
||||
fig.subplots_adjust(**margins)
|
||||
plt.gray()
|
||||
ax1.imshow(text)
|
||||
ax1.plot(dst[:, 0], dst[:, 1], '.r')
|
||||
ax1.axis('off')
|
||||
ax2.imshow(warped)
|
||||
ax2.axis('off')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
"""
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,719 @@
|
||||
"""
|
||||
============
|
||||
Rank filters
|
||||
============
|
||||
|
||||
Rank filters are non-linear filters using the local greylevels ordering to
|
||||
compute the filtered value. This ensemble of filters share a common base: the
|
||||
local grey-level histogram extraction computed on the neighborhood of a pixel
|
||||
(defined by a 2D structuring element). If the filtered value is taken as the
|
||||
middle value of the histogram, we get the classical median filter.
|
||||
|
||||
Rank filters can be used for several purposes such as:
|
||||
|
||||
* image quality enhancement
|
||||
e.g. image smoothing, sharpening
|
||||
|
||||
* image pre-processing
|
||||
e.g. noise reduction, contrast enhancement
|
||||
|
||||
* feature extraction
|
||||
e.g. border detection, isolated point detection
|
||||
|
||||
* post-processing
|
||||
e.g. small object removal, object grouping, contour smoothing
|
||||
|
||||
Some well known filters are specific cases of rank filters [1]_ e.g.
|
||||
morphological dilation, morphological erosion, median filters.
|
||||
|
||||
The different implementation availables in `skimage` are compared.
|
||||
|
||||
In this example, we will see how to filter a greylevel image using some of the
|
||||
linear and non-linear filters availables in skimage. We use the `camera`
|
||||
image from `skimage.data`.
|
||||
|
||||
.. [1] Pierre Soille, On morphological operators based on rank filters, Pattern
|
||||
Recognition 35 (2002) 527-535.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
|
||||
ima = data.camera()
|
||||
hist = np.histogram(ima, bins=np.arange(0, 256))
|
||||
|
||||
plt.figure(figsize=(8, 3))
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray, interpolation='nearest')
|
||||
plt.axis('off')
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.plot(hist[1][:-1], hist[0], lw=2)
|
||||
plt.title('histogram of grey values')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Noise removal
|
||||
=============
|
||||
|
||||
Some noise is added to the image, 1% of pixels are randomly set to 255, 1% are
|
||||
randomly set to 0. The **median** filter is applied to remove the noise.
|
||||
|
||||
.. note::
|
||||
|
||||
there are different implementations of median filter :
|
||||
`skimage.filter.median_filter` and `skimage.filter.rank.median`
|
||||
|
||||
"""
|
||||
|
||||
noise = np.random.random(ima.shape)
|
||||
nima = data.camera()
|
||||
nima[noise > 0.99] = 255
|
||||
nima[noise < 0.01] = 0
|
||||
|
||||
from skimage.filter.rank import median
|
||||
from skimage.morphology import disk
|
||||
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
|
||||
lo = median(nima, disk(1))
|
||||
hi = median(nima, disk(5))
|
||||
ext = median(nima, disk(20))
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(nima, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('noised image')
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(lo, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('median $r=1$')
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(hi, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('median $r=5$')
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(ext, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('median $r=20$')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
The added noise is efficiently removed, as the image defaults are small (1 pixel
|
||||
wide), a small filter radius is sufficient. As the radius is increasing, objects
|
||||
with a bigger size are filtered as well, such as the camera tripod. The median
|
||||
filter is commonly used for noise removal because borders are preserved.
|
||||
|
||||
Image smoothing
|
||||
================
|
||||
|
||||
The example hereunder shows how a local **mean** smoothes the camera man image.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import mean
|
||||
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
|
||||
loc_mean = mean(nima, disk(10))
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.imshow(loc_mean, cmap=plt.cm.gray, vmin=0, vmax=255)
|
||||
plt.xlabel('local mean $r=10$')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
One may be interested in smoothing an image while preserving important borders
|
||||
(median filters already achieved this), here we use the **bilateral** filter
|
||||
that restricts the local neighborhood to pixel having a greylevel similar to
|
||||
the central one.
|
||||
|
||||
.. note::
|
||||
|
||||
a different implementation is available for color images in
|
||||
`skimage.filter.denoise_bilateral`.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import bilateral_mean
|
||||
|
||||
ima = data.camera()
|
||||
selem = disk(10)
|
||||
|
||||
bilat = bilateral_mean(ima.astype(np.uint16), disk(20), s0=10, s1=10)
|
||||
|
||||
# display results
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(bilat, cmap=plt.cm.gray)
|
||||
plt.xlabel('bilateral mean')
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(ima[200:350, 350:450], cmap=plt.cm.gray)
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(bilat[200:350, 350:450], cmap=plt.cm.gray)
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
One can see that the large continuous part of the image (e.g. sky) is smoothed
|
||||
whereas other details are preserved.
|
||||
|
||||
|
||||
Contrast enhancement
|
||||
====================
|
||||
|
||||
We compare here how the global histogram equalization is applied locally.
|
||||
|
||||
The equalized image [2]_ has a roughly linear cumulative distribution function
|
||||
for each pixel neighborhood. The local version [3]_ of the histogram
|
||||
equalization emphasizes every local greylevel variations.
|
||||
|
||||
.. [2] http://en.wikipedia.org/wiki/Histogram_equalization
|
||||
.. [3] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization
|
||||
|
||||
"""
|
||||
|
||||
from skimage import exposure
|
||||
from skimage.filter import rank
|
||||
|
||||
ima = data.camera()
|
||||
# equalize globally and locally
|
||||
glob = exposure.equalize(ima) * 255
|
||||
loc = rank.equalize(ima, disk(20))
|
||||
|
||||
# extract histogram for each image
|
||||
hist = np.histogram(ima, bins=np.arange(0, 256))
|
||||
glob_hist = np.histogram(glob, bins=np.arange(0, 256))
|
||||
loc_hist = np.histogram(loc, bins=np.arange(0, 256))
|
||||
|
||||
plt.figure(figsize=(10, 10))
|
||||
plt.subplot(321)
|
||||
plt.imshow(ima, cmap=plt.cm.gray, interpolation='nearest')
|
||||
plt.axis('off')
|
||||
plt.subplot(322)
|
||||
plt.plot(hist[1][:-1], hist[0], lw=2)
|
||||
plt.title('histogram of grey values')
|
||||
plt.subplot(323)
|
||||
plt.imshow(glob, cmap=plt.cm.gray, interpolation='nearest')
|
||||
plt.axis('off')
|
||||
plt.subplot(324)
|
||||
plt.plot(glob_hist[1][:-1], glob_hist[0], lw=2)
|
||||
plt.title('histogram of grey values')
|
||||
plt.subplot(325)
|
||||
plt.imshow(loc, cmap=plt.cm.gray, interpolation='nearest')
|
||||
plt.axis('off')
|
||||
plt.subplot(326)
|
||||
plt.plot(loc_hist[1][:-1], loc_hist[0], lw=2)
|
||||
plt.title('histogram of grey values')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
another way to maximize the number of greylevels used for an image is to apply
|
||||
a local autoleveling, i.e. here a pixel greylevel is proportionally remapped
|
||||
between local minimum and local maximum.
|
||||
|
||||
The following example shows how local autolevel enhances the camara man picture.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import autolevel
|
||||
|
||||
ima = data.camera()
|
||||
selem = disk(10)
|
||||
|
||||
auto = autolevel(ima.astype(np.uint16), disk(20))
|
||||
|
||||
# display results
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.imshow(auto, cmap=plt.cm.gray)
|
||||
plt.xlabel('local autolevel')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
This filter is very sensitive to local outlayers, see the little white spot in
|
||||
the sky left part. This is due to a local maximum which is very high comparing
|
||||
to the rest of the neighborhood. One can moderate this using the percentile
|
||||
version of the autolevel filter which uses given percentiles (one inferior,
|
||||
one superior) in place of local minimum and maximum. The example below
|
||||
illustrates how the percentile parameters influence the local autolevel result.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import percentile_autolevel
|
||||
|
||||
image = data.camera()
|
||||
|
||||
selem = disk(20)
|
||||
loc_autolevel = autolevel(image, selem=selem)
|
||||
loc_perc_autolevel0 = percentile_autolevel(image, selem=selem, p0=.00, p1=1.0)
|
||||
loc_perc_autolevel1 = percentile_autolevel(image, selem=selem, p0=.01, p1=.99)
|
||||
loc_perc_autolevel2 = percentile_autolevel(image, selem=selem, p0=.05, p1=.95)
|
||||
loc_perc_autolevel3 = percentile_autolevel(image, selem=selem, p0=.1, p1=.9)
|
||||
|
||||
fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
|
||||
ax0, ax1, ax2 = axes
|
||||
plt.gray()
|
||||
|
||||
ax0.imshow(np.hstack((image, loc_autolevel)))
|
||||
ax0.set_title('original / autolevel')
|
||||
|
||||
ax1.imshow(
|
||||
np.hstack((loc_perc_autolevel0, loc_perc_autolevel1)), vmin=0, vmax=255)
|
||||
ax1.set_title('percentile autolevel 0%,1%')
|
||||
ax2.imshow(
|
||||
np.hstack((loc_perc_autolevel2, loc_perc_autolevel3)), vmin=0, vmax=255)
|
||||
ax2.set_title('percentile autolevel 5% and 10%')
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
The morphological contrast enhancement filter replaces the central pixel by the
|
||||
local maximum if the original pixel value is closest to local maximum, otherwise
|
||||
by the minimum local.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import morph_contr_enh
|
||||
|
||||
ima = data.camera()
|
||||
|
||||
enh = morph_contr_enh(ima, disk(5))
|
||||
|
||||
# display results
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(enh, cmap=plt.cm.gray)
|
||||
plt.xlabel('local morphlogical contrast enhancement')
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(ima[200:350, 350:450], cmap=plt.cm.gray)
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(enh[200:350, 350:450], cmap=plt.cm.gray)
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
The percentile version of the local morphological contrast enhancement uses
|
||||
percentile *p0* and *p1* instead of the local minimum and maximum.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import percentile_morph_contr_enh
|
||||
|
||||
ima = data.camera()
|
||||
|
||||
penh = percentile_morph_contr_enh(ima, disk(5), p0=.1, p1=.9)
|
||||
|
||||
# display results
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(penh, cmap=plt.cm.gray)
|
||||
plt.xlabel('local percentile morphlogical\n contrast enhancement')
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(ima[200:350, 350:450], cmap=plt.cm.gray)
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(penh[200:350, 350:450], cmap=plt.cm.gray)
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Image threshold
|
||||
===============
|
||||
|
||||
The Otsu's threshold [1]_ method can be applied locally using the local
|
||||
greylevel distribution. In the example below, for each pixel, an "optimal"
|
||||
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`.
|
||||
|
||||
.. note::
|
||||
|
||||
Local thresholding is much slower than global one. There exists a function
|
||||
for global Otsu thresholding: `skimage.filter.threshold_otsu`.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import otsu
|
||||
from skimage.filter import threshold_otsu
|
||||
|
||||
p8 = data.page()
|
||||
|
||||
radius = 10
|
||||
selem = disk(radius)
|
||||
|
||||
# t_loc_otsu is an image
|
||||
t_loc_otsu = otsu(p8, selem)
|
||||
loc_otsu = p8 >= t_loc_otsu
|
||||
|
||||
# t_glob_otsu is a scalar
|
||||
t_glob_otsu = threshold_otsu(p8)
|
||||
glob_otsu = p8 >= t_glob_otsu
|
||||
|
||||
plt.figure()
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(p8, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.colorbar()
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(t_loc_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('local Otsu ($radius=%d$)' % radius)
|
||||
plt.colorbar()
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(p8 >= t_loc_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('original>=local Otsu' % t_glob_otsu)
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(glob_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('global Otsu ($t=%d$)' % t_glob_otsu)
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
The following example shows how local Otsu's threshold handles a global level
|
||||
shift applied to a synthetic image .
|
||||
|
||||
"""
|
||||
|
||||
n = 100
|
||||
theta = np.linspace(0, 10 * np.pi, n)
|
||||
x = np.sin(theta)
|
||||
m = (np.tile(x, (n, 1)) * np.linspace(0.1, 1, n) * 128 + 128).astype(np.uint8)
|
||||
|
||||
radius = 10
|
||||
t = rank.otsu(m, disk(radius))
|
||||
plt.figure()
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.imshow(m)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.imshow(m >= t, interpolation='nearest')
|
||||
plt.xlabel('local Otsu ($radius=%d$)' % radius)
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Image morphology
|
||||
================
|
||||
|
||||
Local maximum and local minimum are the base operators for greylevel
|
||||
morphology.
|
||||
|
||||
.. note::
|
||||
|
||||
`skimage.dilate` and `skimage.erode` are equivalent filters (see below for
|
||||
comparison).
|
||||
|
||||
Here is an example of the classical morphological greylevel filters: opening,
|
||||
closing and morphological gradient.
|
||||
|
||||
"""
|
||||
|
||||
from skimage.filter.rank import maximum, minimum, gradient
|
||||
|
||||
ima = data.camera()
|
||||
|
||||
closing = maximum(minimum(ima, disk(5)), disk(5))
|
||||
opening = minimum(maximum(ima, disk(5)), disk(5))
|
||||
grad = gradient(ima, disk(5))
|
||||
|
||||
# display results
|
||||
fig = plt.figure(figsize=[10, 7])
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(ima, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(closing, cmap=plt.cm.gray)
|
||||
plt.xlabel('greylevel closing')
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(opening, cmap=plt.cm.gray)
|
||||
plt.xlabel('greylevel opening')
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(grad, cmap=plt.cm.gray)
|
||||
plt.xlabel('morphological gradient')
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Feature extraction
|
||||
===================
|
||||
|
||||
Local histogram can be exploited to compute local entropy, which is related to
|
||||
the local image complexity. Entropy is computed using base 2 logarithm i.e. the
|
||||
filter returns the minimum number of bits needed to encode local greylevel
|
||||
distribution.
|
||||
|
||||
`skimage.rank.entropy` returns local entropy on a given structuring element.
|
||||
The following example shows this filter applied on 8- and 16- bit images.
|
||||
|
||||
.. note::
|
||||
|
||||
to better use the available image bit, the function returns 10x entropy for
|
||||
8-bit images and 1000x entropy for 16-bit images.
|
||||
|
||||
"""
|
||||
|
||||
from skimage import data
|
||||
from skimage.filter.rank import entropy
|
||||
from skimage.morphology import disk
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# defining a 8- and a 16-bit test images
|
||||
a8 = data.camera()
|
||||
a16 = data.camera().astype(np.uint16) * 4
|
||||
|
||||
ent8 = entropy(a8, disk(5)) # pixel value contain 10x the local entropy
|
||||
ent16 = entropy(a16, disk(5)) # pixel value contain 1000x the local entropy
|
||||
|
||||
# display results
|
||||
plt.figure(figsize=(10, 10))
|
||||
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(a8, cmap=plt.cm.gray)
|
||||
plt.xlabel('8-bit image')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(ent8, cmap=plt.cm.jet)
|
||||
plt.xlabel('entropy*10')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(a16, cmap=plt.cm.gray)
|
||||
plt.xlabel('16-bit image')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(ent16, cmap=plt.cm.jet)
|
||||
plt.xlabel('entropy*1000')
|
||||
plt.colorbar()
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Implementation
|
||||
================
|
||||
|
||||
The central part of the `skimage.rank` filters is build on a sliding window that
|
||||
update local greylevel histogram. This approach limits the algorithm complexity
|
||||
to O(n) where n is the number of image pixels. The complexity is also limited
|
||||
with respect to the structuring element size.
|
||||
|
||||
"""
|
||||
|
||||
from time import time
|
||||
|
||||
from scipy.ndimage.filters import percentile_filter
|
||||
from skimage.morphology import dilation
|
||||
from skimage.filter import median_filter
|
||||
from skimage.filter.rank import median, maximum
|
||||
|
||||
|
||||
def exec_and_timeit(func):
|
||||
"""Decorator that returns both function results and execution time."""
|
||||
def wrapper(*arg):
|
||||
t1 = time()
|
||||
res = func(*arg)
|
||||
t2 = time()
|
||||
ms = (t2 - t1) * 1000.0
|
||||
return (res, ms)
|
||||
return wrapper
|
||||
|
||||
|
||||
@exec_and_timeit
|
||||
def cr_med(image, selem):
|
||||
return median(image=image, selem=selem)
|
||||
|
||||
|
||||
@exec_and_timeit
|
||||
def cr_max(image, selem):
|
||||
return maximum(image=image, selem=selem)
|
||||
|
||||
|
||||
@exec_and_timeit
|
||||
def cm_dil(image, selem):
|
||||
return dilation(image=image, selem=selem)
|
||||
|
||||
|
||||
@exec_and_timeit
|
||||
def ctmf_med(image, radius):
|
||||
return median_filter(image=image, radius=radius)
|
||||
|
||||
|
||||
@exec_and_timeit
|
||||
def ndi_med(image, n):
|
||||
return percentile_filter(image, 50, size=n * 2 - 1)
|
||||
|
||||
"""
|
||||
|
||||
Comparison between
|
||||
|
||||
* `rank.maximum`
|
||||
* `cmorph.dilate`
|
||||
|
||||
on increasing structuring element size
|
||||
|
||||
"""
|
||||
|
||||
a = data.camera()
|
||||
|
||||
rec = []
|
||||
e_range = range(1, 20, 2)
|
||||
for r in e_range:
|
||||
elem = disk(r + 1)
|
||||
rc, ms_rc = cr_max(a, elem)
|
||||
rcm, ms_rcm = cm_dil(a, elem)
|
||||
rec.append((ms_rc, ms_rcm))
|
||||
|
||||
rec = np.asarray(rec)
|
||||
|
||||
plt.figure()
|
||||
plt.title('increasing element size')
|
||||
plt.ylabel('time (ms)')
|
||||
plt.xlabel('element radius')
|
||||
plt.plot(e_range, rec)
|
||||
plt.legend(['crank.maximum', 'cmorph.dilate'])
|
||||
|
||||
"""
|
||||
|
||||
and increasing image size
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
"""
|
||||
|
||||
r = 9
|
||||
elem = disk(r + 1)
|
||||
|
||||
rec = []
|
||||
s_range = range(100, 1000, 100)
|
||||
for s in s_range:
|
||||
a = (np.random.random((s, s)) * 256).astype('uint8')
|
||||
(rc, ms_rc) = cr_max(a, elem)
|
||||
(rcm, ms_rcm) = cm_dil(a, elem)
|
||||
rec.append((ms_rc, ms_rcm))
|
||||
|
||||
rec = np.asarray(rec)
|
||||
|
||||
plt.figure()
|
||||
plt.title('increasing image size')
|
||||
plt.ylabel('time (ms)')
|
||||
plt.xlabel('image size')
|
||||
plt.plot(s_range, rec)
|
||||
plt.legend(['crank.maximum', 'cmorph.dilate'])
|
||||
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Comparison between:
|
||||
|
||||
* `rank.median`
|
||||
* `ctmf.median_filter`
|
||||
* `ndimage.percentile`
|
||||
|
||||
on increasing structuring element size
|
||||
|
||||
"""
|
||||
|
||||
a = data.camera()
|
||||
|
||||
rec = []
|
||||
e_range = range(2, 30, 4)
|
||||
for r in e_range:
|
||||
elem = disk(r + 1)
|
||||
rc, ms_rc = cr_med(a, elem)
|
||||
rctmf, ms_rctmf = ctmf_med(a, r)
|
||||
rndi, ms_ndi = ndi_med(a, r)
|
||||
rec.append((ms_rc, ms_rctmf, ms_ndi))
|
||||
|
||||
rec = np.asarray(rec)
|
||||
|
||||
plt.figure()
|
||||
plt.title('increasing element size')
|
||||
plt.plot(e_range, rec)
|
||||
plt.legend(['rank.median', 'ctmf.median_filter', 'ndimage.percentile'])
|
||||
plt.ylabel('time (ms)')
|
||||
plt.xlabel('element radius')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
comparison of outcome of the three methods
|
||||
|
||||
"""
|
||||
|
||||
plt.figure()
|
||||
plt.imshow(np.hstack((rc, rctmf, rndi)))
|
||||
plt.xlabel('rank.median vs ctmf.median_filter vs ndimage.percentile')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
and increasing image size
|
||||
|
||||
"""
|
||||
|
||||
r = 9
|
||||
elem = disk(r + 1)
|
||||
|
||||
rec = []
|
||||
s_range = [100, 200, 500, 1000]
|
||||
for s in s_range:
|
||||
a = (np.random.random((s, s)) * 256).astype('uint8')
|
||||
(rc, ms_rc) = cr_med(a, elem)
|
||||
rctmf, ms_rctmf = ctmf_med(a, r)
|
||||
rndi, ms_ndi = ndi_med(a, r)
|
||||
rec.append((ms_rc, ms_rctmf, ms_ndi))
|
||||
|
||||
rec = np.asarray(rec)
|
||||
|
||||
plt.figure()
|
||||
plt.title('increasing image size')
|
||||
plt.plot(s_range, rec)
|
||||
plt.legend(['rank.median', 'ctmf.median_filter', 'ndimage.percentile'])
|
||||
plt.ylabel('time (ms)')
|
||||
plt.xlabel('image size')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
"""
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
==============================
|
||||
Bilateral mean
|
||||
==============================
|
||||
This example compares
|
||||
|
||||
* local mean
|
||||
* percentile mean
|
||||
* bilateral mean
|
||||
|
||||
build on the local histogram distribution
|
||||
local mean uses all pixels belonging to the structuring element to compute average gray level,
|
||||
percentile mean uses only values between percentiles p0 and p1 (here 10% and 90%),
|
||||
whereas bilateral mean uses only pixels of the structuring element having a gray level situated inside
|
||||
g-s0 and g+s1 (here g-500 and g+500).
|
||||
The filters are applied on a 16 bit image (actual bitdepth is 12bit).
|
||||
|
||||
Percentile and usual mean give here similar results, these filters smooth the complete image (background and details).
|
||||
Bilateral mean exhibits a high filtering rate for continuous area (i.e. background) while image higher frequencies
|
||||
remains untouched.
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology import disk
|
||||
import skimage.filter.rank as rank
|
||||
|
||||
a16 = (data.coins()).astype('uint16') * 16
|
||||
selem = disk(20)
|
||||
|
||||
f1 = rank.percentile_mean(a16, selem=selem, p0=.1, p1=.9)
|
||||
f2 = rank.bilateral_mean(a16, selem=selem, s0=500, s1=500)
|
||||
f3 = rank.mean(a16, selem=selem)
|
||||
|
||||
# display results
|
||||
fig, axes = plt.subplots(nrows=3, figsize=(15, 10))
|
||||
ax0, ax1, ax2 = axes
|
||||
|
||||
ax0.imshow(np.hstack((a16, f1)))
|
||||
ax0.set_title('percentile mean')
|
||||
ax1.imshow(np.hstack((a16, f2)))
|
||||
ax1.set_title('bilateral mean')
|
||||
ax2.imshow(np.hstack((a16, f3)))
|
||||
ax2.set_title('local mean')
|
||||
plt.show()
|
||||
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
========================
|
||||
Circular Hough Transform
|
||||
========================
|
||||
|
||||
The Hough transform in its simplest form is a `method to detect
|
||||
straight lines <http://en.wikipedia.org/wiki/Hough_transform>`__
|
||||
but it can also be used to detect circles.
|
||||
|
||||
In the following example, the Hough transform is used to detect
|
||||
coin positions and match their edges. We provide a range of
|
||||
plausible radii. For each radius, two circles are extracted and
|
||||
we finally keep the five most prominent candidates.
|
||||
The result shows that coin positions are well-detected.
|
||||
|
||||
|
||||
Algorithm overview
|
||||
------------------
|
||||
|
||||
Given a black circle on a white background, we first guess its
|
||||
radius (or a range of radii) to construct a new circle.
|
||||
This circle is applied on each black pixel of the original picture
|
||||
and the coordinates of this circle are voting in an accumulator.
|
||||
From this geometrical construction, the original circle center
|
||||
position receives the highest score.
|
||||
|
||||
Note that the accumulator size is built to be larger than the
|
||||
original picture in order to detect centers outside the frame.
|
||||
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.transform import hough_circle
|
||||
from skimage.feature import peak_local_max
|
||||
from skimage.draw import circle_perimeter
|
||||
|
||||
# Load picture and detect edges
|
||||
image = data.coins()[0:95, 70:370]
|
||||
edges = filter.canny(image, sigma=3, low_threshold=10, high_threshold=50)
|
||||
|
||||
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
|
||||
|
||||
# Detect two radii
|
||||
hough_radii = np.arange(15, 30, 2)
|
||||
hough_res = hough_circle(edges, hough_radii)
|
||||
|
||||
centers = []
|
||||
accums = []
|
||||
radii = []
|
||||
|
||||
for radius, h in zip(hough_radii, hough_res):
|
||||
# For each radius, extract two circles
|
||||
peaks = peak_local_max(h, num_peaks=2)
|
||||
centers.extend(peaks - hough_radii.max())
|
||||
accums.extend(h[peaks[:, 0], peaks[:, 1]])
|
||||
radii.extend([radius, radius])
|
||||
|
||||
# Draw the most prominent 5 circles
|
||||
image = color.gray2rgb(image)
|
||||
for idx in np.argsort(accums)[::-1][:5]:
|
||||
center_x, center_y = centers[idx]
|
||||
radius = radii[idx]
|
||||
cx, cy = circle_perimeter(center_y, center_x, radius)
|
||||
image[cy, cx] = (220, 20, 20)
|
||||
|
||||
ax.imshow(image, cmap=plt.cm.gray)
|
||||
plt.show()
|
||||
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
================
|
||||
Corner detection
|
||||
================
|
||||
|
||||
Detect corner points using the Harris corner detector and determine subpixel
|
||||
position of corners.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Corner_detection
|
||||
.. [2] http://en.wikipedia.org/wiki/Interest_point_detection
|
||||
|
||||
"""
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.feature import corner_harris, corner_subpix, corner_peaks
|
||||
from skimage.transform import warp, AffineTransform
|
||||
from skimage.draw import ellipse
|
||||
|
||||
tform = AffineTransform(scale=(1.3, 1.1), rotation=1, shear=0.7,
|
||||
translation=(210, 50))
|
||||
image = warp(data.checkerboard(), tform.inverse, output_shape=(350, 350))
|
||||
rr, cc = ellipse(310, 175, 10, 100)
|
||||
image[rr, cc] = 1
|
||||
image[180:230, 10:60] = 1
|
||||
image[230:280, 60:110] = 1
|
||||
|
||||
coords = corner_peaks(corner_harris(image), min_distance=5)
|
||||
coords_subpix = corner_subpix(image, coords, window_size=13)
|
||||
|
||||
plt.gray()
|
||||
plt.imshow(image, interpolation='nearest')
|
||||
plt.plot(coords[:, 1], coords[:, 0], '.b', markersize=3)
|
||||
plt.plot(coords_subpix[:, 1], coords_subpix[:, 0], '+r', markersize=15)
|
||||
plt.axis((0, 350, 350, 0))
|
||||
plt.show()
|
||||
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
===============================
|
||||
Dense DAISY feature description
|
||||
===============================
|
||||
|
||||
The DAISY local image descriptor is based on gradient orientation histograms
|
||||
similar to the SIFT descriptor. It is formulated in a way that allows for fast
|
||||
dense extraction which is useful for e.g. bag-of-features image
|
||||
representations.
|
||||
|
||||
In this example a limited number of DAISY descriptors are extracted at a large
|
||||
scale for illustrative purposes.
|
||||
"""
|
||||
|
||||
from skimage.feature import daisy
|
||||
from skimage import data
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
img = data.camera()
|
||||
descs, descs_img = daisy(img, step=180, radius=58, rings=2, histograms=6,
|
||||
orientations=8, visualize=True)
|
||||
|
||||
plt.axis('off')
|
||||
plt.imshow(descs_img)
|
||||
descs_num = descs.shape[0] * descs.shape[1]
|
||||
plt.title('%i DAISY descriptors extracted:' % descs_num)
|
||||
plt.show()
|
||||
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
=============================
|
||||
Denoising the picture of Lena
|
||||
=============================
|
||||
|
||||
In this example, we denoise a noisy version of the picture of Lena 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
|
||||
by controlling the tradeoff between denoising and faithfulness to the original
|
||||
image.
|
||||
|
||||
Total variation filter
|
||||
----------------------
|
||||
|
||||
The result of this filter is an image that has a minimal total variation norm,
|
||||
while being as close to the initial image as possible. The total variation is
|
||||
the L1 norm of the gradient of the image.
|
||||
|
||||
Bilateral filter
|
||||
----------------
|
||||
|
||||
A bilateral filter is an edge-preserving and noise reducing filter. It averages
|
||||
pixels based on their spatial closeness and radiometric similarity.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data, color, img_as_float
|
||||
from skimage.filter import denoise_tv_chambolle, denoise_bilateral
|
||||
|
||||
lena = img_as_float(data.lena())
|
||||
lena = lena[220:300, 220:320]
|
||||
|
||||
noisy = lena + 0.6 * lena.std() * np.random.random(lena.shape)
|
||||
noisy = np.clip(noisy, 0, 1)
|
||||
|
||||
fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5))
|
||||
|
||||
plt.gray()
|
||||
|
||||
ax[0, 0].imshow(noisy)
|
||||
ax[0, 0].axis('off')
|
||||
ax[0, 0].set_title('noisy')
|
||||
ax[0, 1].imshow(denoise_tv_chambolle(noisy, weight=0.1, multichannel=True))
|
||||
ax[0, 1].axis('off')
|
||||
ax[0, 1].set_title('TV')
|
||||
ax[0, 2].imshow(denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15))
|
||||
ax[0, 2].axis('off')
|
||||
ax[0, 2].set_title('Bilateral')
|
||||
|
||||
ax[1, 0].imshow(denoise_tv_chambolle(noisy, weight=0.2, multichannel=True))
|
||||
ax[1, 0].axis('off')
|
||||
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].axis('off')
|
||||
ax[1, 2].set_title('original')
|
||||
|
||||
fig.subplots_adjust(wspace=0.02, hspace=0.2,
|
||||
top=0.9, bottom=0.05, left=0, right=1)
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
===================
|
||||
Entropy
|
||||
===================
|
||||
|
||||
|
||||
"""
|
||||
from skimage import data
|
||||
from skimage.filter.rank import entropy
|
||||
from skimage.morphology import disk
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# defining a 8- and a 16-bit test images
|
||||
a8 = data.camera()
|
||||
a16 = data.camera().astype(np.uint16)*4
|
||||
|
||||
ent8 = entropy(a8,disk(5)) # pixel value contain 10x the local entropy
|
||||
ent16 = entropy(a16,disk(5)) # pixel value contain 1000x the local entropy
|
||||
|
||||
# display results
|
||||
plt.figure(figsize=(10, 10))
|
||||
|
||||
plt.subplot(2,2,1)
|
||||
plt.imshow(a8, cmap=plt.cm.gray)
|
||||
plt.xlabel('8-bit image')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2,2,2)
|
||||
plt.imshow(ent8, cmap=plt.cm.jet)
|
||||
plt.xlabel('entropy*10')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2,2,3)
|
||||
plt.imshow(a16, cmap=plt.cm.gray)
|
||||
plt.xlabel('16-bit image')
|
||||
plt.colorbar()
|
||||
|
||||
plt.subplot(2,2,4)
|
||||
plt.imshow(ent16, cmap=plt.cm.jet)
|
||||
plt.xlabel('entropy*1000')
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
@@ -18,18 +18,18 @@ that fall within the 2nd and 98th percentiles [2]_.
|
||||
|
||||
"""
|
||||
|
||||
from skimage import data
|
||||
from skimage.util.dtype import dtype_range
|
||||
from skimage import data, img_as_float
|
||||
from skimage import exposure
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def plot_img_and_hist(img, axes, bins=256):
|
||||
"""Plot an image along with its histogram and cumulative histogram.
|
||||
|
||||
"""
|
||||
img = img_as_float(img)
|
||||
ax_img, ax_hist = axes
|
||||
ax_cdf = ax_hist.twinx()
|
||||
|
||||
@@ -38,16 +38,16 @@ def plot_img_and_hist(img, axes, bins=256):
|
||||
ax_img.set_axis_off()
|
||||
|
||||
# Display histogram
|
||||
ax_hist.hist(img.ravel(), bins=bins)
|
||||
ax_hist.hist(img.ravel(), bins=bins, histtype='step', color='black')
|
||||
ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))
|
||||
ax_hist.set_xlabel('Pixel intensity')
|
||||
|
||||
xmin, xmax = dtype_range[img.dtype.type]
|
||||
ax_hist.set_xlim(xmin, xmax)
|
||||
ax_hist.set_xlim(0, 1)
|
||||
ax_hist.set_yticks([])
|
||||
|
||||
# Display cumulative distribution
|
||||
img_cdf, bins = exposure.cumulative_distribution(img, bins)
|
||||
ax_cdf.plot(bins, img_cdf, 'r')
|
||||
ax_cdf.set_yticks([])
|
||||
|
||||
return ax_img, ax_hist, ax_cdf
|
||||
|
||||
@@ -61,25 +61,33 @@ p98 = np.percentile(img, 98)
|
||||
img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
|
||||
|
||||
# Equalization
|
||||
img_eq = exposure.equalize(img)
|
||||
img_eq = exposure.equalize_hist(img)
|
||||
|
||||
# Adaptive Equalization
|
||||
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
|
||||
|
||||
# Display results
|
||||
f, axes = plt.subplots(2, 3, figsize=(8, 4))
|
||||
f, axes = plt.subplots(2, 4, figsize=(8, 4))
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
|
||||
ax_img.set_title('Low contrast image')
|
||||
|
||||
y_min, y_max = ax_hist.get_ylim()
|
||||
ax_hist.set_ylabel('Number of pixels')
|
||||
ax_hist.set_yticks(np.linspace(0, y_max, 5))
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1])
|
||||
ax_img.set_title('Contrast stretching')
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2])
|
||||
ax_img.set_title('Histogram equalization')
|
||||
ax_cdf.set_ylabel('Fraction of total intensity')
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_adapteq, axes[:, 3])
|
||||
ax_img.set_title('Adaptive equalization')
|
||||
|
||||
ax_cdf.set_ylabel('Fraction of total intensity')
|
||||
ax_cdf.set_yticks(np.linspace(0, 1, 5))
|
||||
|
||||
# prevent overlap of y-axis labels
|
||||
plt.subplots_adjust(wspace=0.4)
|
||||
plt.show()
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
"""
|
||||
===============================================================================
|
||||
Harris Corner detector
|
||||
===============================================================================
|
||||
|
||||
The Harris corner filter [1]_ detects "interest points" [2]_ using edge
|
||||
detection in multiple directions.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Corner_detection
|
||||
.. [2] http://en.wikipedia.org/wiki/Interest_point_detection
|
||||
"""
|
||||
import numpy as np
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from skimage import data, img_as_float
|
||||
from skimage.feature import harris
|
||||
|
||||
|
||||
def plot_harris_points(image, filtered_coords):
|
||||
""" plots corners found in image"""
|
||||
|
||||
plt.imshow(image)
|
||||
y, x = np.transpose(filtered_coords)
|
||||
plt.plot(x, y, 'b.')
|
||||
plt.axis('off')
|
||||
|
||||
# display results
|
||||
plt.figure(figsize=(8, 3))
|
||||
im_lena = img_as_float(data.lena())
|
||||
im_text = img_as_float(data.text())
|
||||
|
||||
filtered_coords = harris(im_lena, min_distance=4)
|
||||
|
||||
plt.axes([0, 0, 0.3, 0.95])
|
||||
plot_harris_points(im_lena, filtered_coords)
|
||||
|
||||
filtered_coords = harris(im_text, min_distance=4)
|
||||
|
||||
plt.axes([0.2, 0, 0.77, 1])
|
||||
plot_harris_points(im_text, filtered_coords)
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
===============================
|
||||
Filling holes and finding peaks
|
||||
===============================
|
||||
|
||||
In this example, we fill holes (i.e. isolated, dark spots) in an image using
|
||||
morphological reconstruction by erosion. Erosion expands the minimal values of
|
||||
the seed image until it encounters a mask image. Thus, the seed image and mask
|
||||
image represent the maximum and minimum possible values of the reconstructed
|
||||
image.
|
||||
|
||||
We start with an image containing both peaks and holes:
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.exposure import rescale_intensity
|
||||
|
||||
image = data.moon()
|
||||
# Rescale image intensity so that we can see dim features.
|
||||
image = rescale_intensity(image, in_range=(50, 200))
|
||||
|
||||
# convenience function for plotting images
|
||||
def imshow(image, **kwargs):
|
||||
plt.figure(figsize=(5, 4))
|
||||
plt.imshow(image, **kwargs)
|
||||
plt.axis('off')
|
||||
|
||||
imshow(image)
|
||||
plt.title('original image')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Now we need to create the seed image, where the minima represent the starting
|
||||
points for erosion. To fill holes, we initialize the seed image to the maximum
|
||||
value of the original image. Along the borders, however, we use the original
|
||||
values of the image. These border pixels will be the starting points for the
|
||||
erosion process. We then limit the erosion by setting the mask to the values
|
||||
of the original image.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from skimage.morphology import reconstruction
|
||||
|
||||
seed = np.copy(image)
|
||||
seed[1:-1, 1:-1] = image.max()
|
||||
mask = image
|
||||
|
||||
filled = reconstruction(seed, mask, method='erosion')
|
||||
|
||||
imshow(filled, vmin=image.min(), vmax=image.max())
|
||||
plt.title('after filling holes')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
As shown above, eroding inward from the edges removes holes, since (by
|
||||
definition) holes are surrounded by pixels of brighter value. Finally, we can
|
||||
isolate the dark regions by subtracting the reconstructed image from the
|
||||
original image.
|
||||
"""
|
||||
|
||||
imshow(image - filled)
|
||||
plt.title('holes')
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Alternatively, we can find bright spots in an image using morphological
|
||||
reconstruction by dilation. Dilation is the inverse of erosion and expands the
|
||||
*maximal* values of the seed image until it encounters a mask image. Since this
|
||||
is an inverse operation, we initialize the seed image to the minimum image
|
||||
intensity instead of the maximum. The remainder of the process is the same.
|
||||
"""
|
||||
|
||||
seed = np.copy(image)
|
||||
seed[1:-1, 1:-1] = image.min()
|
||||
rec = reconstruction(seed, mask, method='dilation')
|
||||
imshow(image - rec)
|
||||
plt.title('peaks')
|
||||
plt.show()
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
"""
|
||||
@@ -59,7 +59,7 @@ References
|
||||
|
||||
'''
|
||||
|
||||
from skimage.transform import hough, probabilistic_hough
|
||||
from skimage.transform import hough, hough_peaks, probabilistic_hough
|
||||
from skimage.filter import canny
|
||||
from skimage import data
|
||||
|
||||
@@ -81,11 +81,11 @@ h, theta, d = hough(image)
|
||||
|
||||
plt.figure(figsize=(8, 4))
|
||||
|
||||
plt.subplot(121)
|
||||
plt.subplot(131)
|
||||
plt.imshow(image, cmap=plt.cm.gray)
|
||||
plt.title('Input image')
|
||||
|
||||
plt.subplot(122)
|
||||
plt.subplot(132)
|
||||
plt.imshow(np.log(1 + h),
|
||||
extent=[np.rad2deg(theta[-1]), np.rad2deg(theta[0]),
|
||||
d[-1], d[0]],
|
||||
@@ -94,6 +94,15 @@ plt.title('Hough transform')
|
||||
plt.xlabel('Angles (degrees)')
|
||||
plt.ylabel('Distance (pixels)')
|
||||
|
||||
plt.subplot(133)
|
||||
plt.imshow(image, cmap=plt.cm.gray)
|
||||
rows, cols = image.shape
|
||||
for _, angle, dist in zip(*hough_peaks(h, theta, d)):
|
||||
y0 = (dist - 0 * np.cos(angle)) / np.sin(angle)
|
||||
y1 = (dist - cols * np.cos(angle)) / np.sin(angle)
|
||||
plt.plot((0, cols), (y0, y1), '-r')
|
||||
plt.axis((0, cols, rows, 0))
|
||||
plt.title('Detected lines')
|
||||
|
||||
# Line finding, using the Probabilistic Hough Transform
|
||||
|
||||
@@ -109,7 +118,7 @@ plt.title('Input image')
|
||||
|
||||
plt.subplot(132)
|
||||
plt.imshow(edges, cmap=plt.cm.gray)
|
||||
plt.title('Sobel edges')
|
||||
plt.title('Canny edges')
|
||||
|
||||
plt.subplot(133)
|
||||
plt.imshow(edges * 0)
|
||||
@@ -118,7 +127,6 @@ for line in lines:
|
||||
p0, p1 = line
|
||||
plt.plot((p0[0], p1[0]), (p0[1], p1[1]))
|
||||
|
||||
plt.title('Lines found with PHT')
|
||||
plt.title('Probabilistic Hough')
|
||||
plt.axis('image')
|
||||
plt.show()
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
==========================================
|
||||
Find the intersection of two segmentations
|
||||
==========================================
|
||||
|
||||
When segmenting an image, you may want to combine multiple alternative
|
||||
segmentations. The `skimage.segmentation.join_segmentations` function
|
||||
computes the join of two segmentations, in which a pixel is placed in
|
||||
the same segment if and only if it is in the same segment in _both_
|
||||
segmentations.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from scipy import ndimage as nd
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib as mpl
|
||||
|
||||
from skimage.filter import sobel
|
||||
from skimage.segmentation import slic, join_segmentations
|
||||
from skimage.morphology import watershed
|
||||
|
||||
from skimage import data
|
||||
|
||||
coins = data.coins()
|
||||
|
||||
# make segmentation using edge-detection and watershed
|
||||
edges = sobel(coins)
|
||||
markers = np.zeros_like(coins)
|
||||
foreground, background = 1, 2
|
||||
markers[coins < 30] = background
|
||||
markers[coins > 150] = foreground
|
||||
|
||||
ws = watershed(edges, markers)
|
||||
seg1 = nd.label(ws == foreground)[0]
|
||||
|
||||
# make segmentation using SLIC superpixels
|
||||
|
||||
# make the RGB equivalent of `coins`
|
||||
coins_colour = np.tile(coins[..., np.newaxis], (1, 1, 3))
|
||||
seg2 = slic(coins_colour, n_segments=30, max_iter=160, sigma=1, ratio=9,
|
||||
convert2lab=False)
|
||||
|
||||
# combine the two
|
||||
segj = join_segmentations(seg1, seg2)
|
||||
|
||||
### Display the result ###
|
||||
|
||||
# make a random colormap for a set number of values
|
||||
def random_cmap(im):
|
||||
np.random.seed(9)
|
||||
cmap_array = np.concatenate(
|
||||
(np.zeros((1, 3)), np.random.rand(np.ceil(im.max()), 3)))
|
||||
return mpl.colors.ListedColormap(cmap_array)
|
||||
|
||||
# show the segmentations
|
||||
fig, axes = plt.subplots(ncols=4, figsize=(9, 2.5))
|
||||
axes[0].imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
|
||||
axes[0].set_title('Image')
|
||||
axes[1].imshow(seg1, cmap=random_cmap(seg1), interpolation='nearest')
|
||||
axes[1].set_title('Sobel+Watershed')
|
||||
axes[2].imshow(seg2, cmap=random_cmap(seg2), interpolation='nearest')
|
||||
axes[2].set_title('SLIC superpixels')
|
||||
axes[3].imshow(segj, cmap=random_cmap(segj), interpolation='nearest')
|
||||
axes[3].set_title('Join')
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
|
||||
plt.show()
|
||||
@@ -0,0 +1,57 @@
|
||||
"""
|
||||
===================
|
||||
Label image regions
|
||||
===================
|
||||
|
||||
This example shows how to segment an image with image labelling. The following
|
||||
steps are applied:
|
||||
|
||||
1. Thresholding with automatic Otsu method
|
||||
2. Close small holes with binary closing
|
||||
3. Remove artifacts touching image border
|
||||
4. Measure image regions to filter small objects
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.patches as mpatches
|
||||
|
||||
from skimage import data
|
||||
from skimage.filter import threshold_otsu
|
||||
from skimage.segmentation import clear_border
|
||||
from skimage.morphology import label, closing, square
|
||||
from skimage.measure import regionprops
|
||||
|
||||
|
||||
image = data.coins()[50:-50, 50:-50]
|
||||
|
||||
# apply threshold
|
||||
thresh = threshold_otsu(image)
|
||||
bw = closing(image > thresh, square(3))
|
||||
|
||||
# remove artifacts connected to image border
|
||||
cleared = bw.copy()
|
||||
clear_border(cleared)
|
||||
|
||||
# label image regions
|
||||
label_image = label(cleared)
|
||||
borders = np.logical_xor(bw, cleared)
|
||||
label_image[borders] = -1
|
||||
|
||||
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
|
||||
ax.imshow(label_image, cmap='jet')
|
||||
|
||||
for region in regionprops(label_image, ['Area', 'BoundingBox']):
|
||||
|
||||
# skip small images
|
||||
if region['Area'] < 100:
|
||||
continue
|
||||
|
||||
# draw rectangle around segmented coins
|
||||
minr, minc, maxr, maxc = region['BoundingBox']
|
||||
rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
|
||||
fill=False, edgecolor='red', linewidth=2)
|
||||
ax.add_patch(rect)
|
||||
|
||||
plt.show()
|
||||
@@ -1,51 +0,0 @@
|
||||
"""
|
||||
====================================================
|
||||
Denoising the picture of Lena using total variation
|
||||
====================================================
|
||||
|
||||
In this example, we denoise a noisy version of the picture of Lena
|
||||
using the total variation denoising filter. The result of this filter
|
||||
is an image that has a minimal total variation norm, while being as
|
||||
close to the initial image as possible. The total variation is the L1
|
||||
norm of the gradient of the image, and minimizing the total variation
|
||||
typically produces "posterized" images with flat domains separated by
|
||||
sharp edges.
|
||||
|
||||
It is possible to change the degree of posterization by controlling
|
||||
the tradeoff between denoising and faithfulness to the original image.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data, color, img_as_ubyte
|
||||
from skimage.filter import tv_denoise
|
||||
|
||||
l = img_as_ubyte(color.rgb2gray(data.lena()))
|
||||
l = l[230:290, 220:320]
|
||||
|
||||
noisy = l + 0.4 * l.std() * np.random.random(l.shape)
|
||||
|
||||
tv_denoised = tv_denoise(noisy, weight=10)
|
||||
|
||||
plt.figure(figsize=(8, 2))
|
||||
|
||||
plt.subplot(131)
|
||||
plt.imshow(noisy, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('noisy', fontsize=20)
|
||||
plt.subplot(132)
|
||||
plt.imshow(tv_denoised, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('TV denoising', fontsize=20)
|
||||
|
||||
tv_denoised = tv_denoise(noisy, weight=50)
|
||||
plt.subplot(133)
|
||||
plt.imshow(tv_denoised, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('(more) TV denoising', fontsize=20)
|
||||
|
||||
plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0, left=0,
|
||||
right=1)
|
||||
plt.show()
|
||||
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
===============================================
|
||||
Local Binary Pattern for texture classification
|
||||
===============================================
|
||||
|
||||
In this example, we will see how to classify textures based on LBP (Local
|
||||
Binary Pattern). The histogram of the LBP result is a good measure to classify
|
||||
textures. For simplicity the histogram distributions are then tested against
|
||||
each other using the Kullback-Leibler-Divergence.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
import scipy.ndimage as nd
|
||||
import skimage.feature as ft
|
||||
from skimage import data
|
||||
|
||||
|
||||
# settings for LBP
|
||||
METHOD = 'uniform'
|
||||
P = 16
|
||||
R = 2
|
||||
matplotlib.rcParams['font.size'] = 9
|
||||
|
||||
|
||||
def kullback_leibler_divergence(p, q):
|
||||
p = np.asarray(p)
|
||||
q = np.asarray(q)
|
||||
filt = np.logical_and(p != 0, q != 0)
|
||||
return np.sum(p[filt] * np.log2(p[filt] / q[filt]))
|
||||
|
||||
|
||||
def match(refs, img):
|
||||
best_score = 10
|
||||
best_name = None
|
||||
lbp = ft.local_binary_pattern(img, P, R, METHOD)
|
||||
hist, _ = np.histogram(lbp, normed=True, bins=P + 2, range=(0, P + 2))
|
||||
for name, ref in refs.items():
|
||||
ref_hist, _ = np.histogram(ref, normed=True, bins=P + 2,
|
||||
range=(0, P + 2))
|
||||
score = kullback_leibler_divergence(hist, ref_hist)
|
||||
if score < best_score:
|
||||
best_score = score
|
||||
best_name = name
|
||||
return best_name
|
||||
|
||||
|
||||
brick = data.load('brick.png')
|
||||
grass = data.load('grass.png')
|
||||
wall = data.load('rough-wall.png')
|
||||
|
||||
refs = {
|
||||
'brick': ft.local_binary_pattern(brick, P, R, METHOD),
|
||||
'grass': ft.local_binary_pattern(grass, P, R, METHOD),
|
||||
'wall': ft.local_binary_pattern(wall, P, R, METHOD)
|
||||
}
|
||||
|
||||
# classify rotated textures
|
||||
print 'Rotated images matched against references using LBP:'
|
||||
print 'original: brick, rotated: 30deg, match result:',
|
||||
print match(refs, nd.rotate(brick, angle=30, reshape=False))
|
||||
print 'original: brick, rotated: 70deg, match result:',
|
||||
print match(refs, nd.rotate(brick, angle=70, reshape=False))
|
||||
print 'original: grass, rotated: 145deg, match result:',
|
||||
print match(refs, nd.rotate(grass, angle=145, reshape=False))
|
||||
|
||||
# plot histograms of LBP of textures
|
||||
fig, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots(nrows=2, ncols=3,
|
||||
figsize=(9, 6))
|
||||
plt.gray()
|
||||
|
||||
ax1.imshow(brick)
|
||||
ax1.axis('off')
|
||||
ax4.hist(refs['brick'].ravel(), normed=True, bins=P + 2, range=(0, P + 2))
|
||||
ax4.set_ylabel('Percentage')
|
||||
|
||||
ax2.imshow(grass)
|
||||
ax2.axis('off')
|
||||
ax5.hist(refs['grass'].ravel(), normed=True, bins=P + 2, range=(0, P + 2))
|
||||
ax5.set_xlabel('Uniform LBP values')
|
||||
|
||||
ax3.imshow(wall)
|
||||
ax3.axis('off')
|
||||
ax6.hist(refs['wall'].ravel(), normed=True, bins=P + 2, range=(0, P + 2))
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
===============================
|
||||
Local Histogram Equalization
|
||||
===============================
|
||||
|
||||
This examples enhances an image with low contrast, using a method called
|
||||
*local histogram equalization*, which "spreads out the most frequent intensity
|
||||
values" in an image .
|
||||
The equalized image [1]_ has a roughly linear cumulative distribution function for each pixel neighborhood.
|
||||
The local version [2]_ of the histogram equalization emphasized every local graylevel variations.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Histogram_equalization
|
||||
.. [2] http://en.wikipedia.org/wiki/Adaptive_histogram_equalization
|
||||
|
||||
"""
|
||||
|
||||
from skimage import data
|
||||
from skimage.util.dtype import dtype_range
|
||||
from skimage import exposure
|
||||
from skimage.morphology import disk
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
import numpy as np
|
||||
from skimage.filter import rank
|
||||
|
||||
|
||||
def plot_img_and_hist(img, axes, bins=256):
|
||||
"""Plot an image along with its histogram and cumulative histogram.
|
||||
|
||||
"""
|
||||
ax_img, ax_hist = axes
|
||||
ax_cdf = ax_hist.twinx()
|
||||
|
||||
# Display image
|
||||
ax_img.imshow(img, cmap=plt.cm.gray)
|
||||
ax_img.set_axis_off()
|
||||
|
||||
# Display histogram
|
||||
ax_hist.hist(img.ravel(), bins=bins)
|
||||
ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))
|
||||
ax_hist.set_xlabel('Pixel intensity')
|
||||
|
||||
xmin, xmax = dtype_range[img.dtype.type]
|
||||
ax_hist.set_xlim(xmin, xmax)
|
||||
|
||||
# Display cumulative distribution
|
||||
img_cdf, bins = exposure.cumulative_distribution(img, bins)
|
||||
ax_cdf.plot(bins, img_cdf, 'r')
|
||||
|
||||
return ax_img, ax_hist, ax_cdf
|
||||
|
||||
|
||||
# Load an example image
|
||||
img = data.moon()
|
||||
|
||||
# Contrast stretching
|
||||
p2 = np.percentile(img, 2)
|
||||
p98 = np.percentile(img, 98)
|
||||
img_rescale = exposure.equalize_hist(img)
|
||||
|
||||
# Equalization
|
||||
selem = disk(30)
|
||||
img_eq = rank.equalize(img, selem=selem)
|
||||
|
||||
|
||||
# Display results
|
||||
f, axes = plt.subplots(2, 3, figsize=(8, 4))
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
|
||||
ax_img.set_title('Low contrast image')
|
||||
ax_hist.set_ylabel('Number of pixels')
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1])
|
||||
ax_img.set_title('Global equalise')
|
||||
|
||||
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2])
|
||||
ax_img.set_title('Local equalize')
|
||||
ax_cdf.set_ylabel('Fraction of total intensity')
|
||||
|
||||
|
||||
# prevent overlap of y-axis labels
|
||||
plt.subplots_adjust(wspace=0.4)
|
||||
plt.show()
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
=====================
|
||||
Local Otsu Threshold
|
||||
=====================
|
||||
This example shows how Otsu's threshold [1]_ method can be applied locally.
|
||||
For each pixel, an "optimal" 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.
|
||||
|
||||
.. note: local threshold is much slower than global one.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
|
||||
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology.selem import disk
|
||||
import skimage.filter.rank as rank
|
||||
from skimage.filter import threshold_otsu
|
||||
|
||||
|
||||
p8 = data.page()
|
||||
|
||||
radius = 10
|
||||
selem = disk(radius)
|
||||
|
||||
loc_otsu = rank.otsu(p8, selem)
|
||||
t_glob_otsu = threshold_otsu(p8)
|
||||
glob_otsu = p8 >= t_glob_otsu
|
||||
|
||||
|
||||
plt.figure()
|
||||
plt.subplot(2, 2, 1)
|
||||
plt.imshow(p8, cmap=plt.cm.gray)
|
||||
plt.xlabel('original')
|
||||
plt.colorbar()
|
||||
plt.subplot(2, 2, 2)
|
||||
plt.imshow(loc_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('local Otsu ($radius=%d$)' % radius)
|
||||
plt.colorbar()
|
||||
plt.subplot(2, 2, 3)
|
||||
plt.imshow(p8 >= loc_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('original>=local Otsu' % t_glob_otsu)
|
||||
plt.subplot(2, 2, 4)
|
||||
plt.imshow(glob_otsu, cmap=plt.cm.gray)
|
||||
plt.xlabel('global Otsu ($t=%d$)' % t_glob_otsu)
|
||||
plt.show()
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
================================
|
||||
Markers for watershed transform
|
||||
================================
|
||||
|
||||
The watershed is a classical algorithm used for **segmentation**, that
|
||||
is, for separating different objects in an image.
|
||||
|
||||
Here a marker image is build from the region of low gradient inside the image.
|
||||
|
||||
See Wikipedia_ for more details on the algorithm.
|
||||
|
||||
.. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing)
|
||||
|
||||
"""
|
||||
|
||||
from scipy import ndimage
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage.morphology import watershed, disk
|
||||
from skimage import data
|
||||
|
||||
# original data
|
||||
from skimage.filter import rank
|
||||
|
||||
image = data.camera()
|
||||
|
||||
# denoise image
|
||||
denoised = rank.median(image, disk(2))
|
||||
|
||||
# find continuous region (low gradient) --> markers
|
||||
markers = rank.gradient(denoised, disk(5)) < 10
|
||||
markers = ndimage.label(markers)[0]
|
||||
|
||||
#local gradient
|
||||
gradient = rank.gradient(denoised, disk(2))
|
||||
|
||||
# process the watershed
|
||||
labels = watershed(gradient, markers)
|
||||
|
||||
# display results
|
||||
fig, axes = plt.subplots(ncols=4, figsize=(8, 2.7))
|
||||
ax0, ax1, ax2, ax3 = axes
|
||||
|
||||
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
|
||||
ax1.imshow(gradient, cmap=plt.cm.spectral, interpolation='nearest')
|
||||
ax2.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest')
|
||||
ax3.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
|
||||
ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest', alpha=.7)
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
|
||||
plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
|
||||
plt.show()
|
||||
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
===============================
|
||||
Piecewise Affine Transformation
|
||||
===============================
|
||||
|
||||
This example shows how to use the Piecewise Affine Transformation.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage.transform import PiecewiseAffineTransform, warp
|
||||
from skimage import data
|
||||
|
||||
|
||||
image = data.lena()
|
||||
rows, cols = image.shape[0], image.shape[1]
|
||||
|
||||
src_cols = np.linspace(0, cols, 20)
|
||||
src_rows = np.linspace(0, rows, 10)
|
||||
src_rows, src_cols = np.meshgrid(src_rows, src_cols)
|
||||
src = np.dstack([src_cols.flat, src_rows.flat])[0]
|
||||
|
||||
# add sinusoidal oscillation to row coordinates
|
||||
dst_rows = src[:, 1] - np.sin(np.linspace(0, 3 * np.pi, src.shape[0])) * 50
|
||||
dst_cols = src[:, 0]
|
||||
dst_rows *= 1.5
|
||||
dst_rows -= 1.5 * 50
|
||||
dst = np.vstack([dst_cols, dst_rows]).T
|
||||
|
||||
|
||||
tform = PiecewiseAffineTransform()
|
||||
tform.estimate(src, dst)
|
||||
|
||||
out_rows = image.shape[0] - 1.5 * 50
|
||||
out_cols = cols
|
||||
out = warp(image, tform, output_shape=(out_rows, out_cols))
|
||||
|
||||
plt.imshow(out)
|
||||
plt.plot(tform.inverse(src)[:, 0], tform.inverse(src)[:, 1], '.b')
|
||||
plt.axis((0, out_cols, out_rows, 0))
|
||||
plt.show()
|
||||
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
==================================
|
||||
Approximate and subdivide polygons
|
||||
==================================
|
||||
|
||||
This example shows how to approximate (Douglas-Peucker algorithm) and subdivide
|
||||
(B-Splines) polygonal chains.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage.draw import ellipse
|
||||
from skimage.measure import find_contours, approximate_polygon, \
|
||||
subdivide_polygon
|
||||
|
||||
|
||||
hand = np.array([[1.64516129, 1.16145833],
|
||||
[1.64516129, 1.59375 ],
|
||||
[1.35080645, 1.921875 ],
|
||||
[1.375 , 2.18229167],
|
||||
[1.68548387, 1.9375 ],
|
||||
[1.60887097, 2.55208333],
|
||||
[1.68548387, 2.69791667],
|
||||
[1.76209677, 2.56770833],
|
||||
[1.83064516, 1.97395833],
|
||||
[1.89516129, 2.75 ],
|
||||
[1.9516129 , 2.84895833],
|
||||
[2.01209677, 2.76041667],
|
||||
[1.99193548, 1.99479167],
|
||||
[2.11290323, 2.63020833],
|
||||
[2.2016129 , 2.734375 ],
|
||||
[2.25403226, 2.60416667],
|
||||
[2.14919355, 1.953125 ],
|
||||
[2.30645161, 2.36979167],
|
||||
[2.39112903, 2.36979167],
|
||||
[2.41532258, 2.1875 ],
|
||||
[2.1733871 , 1.703125 ],
|
||||
[2.07782258, 1.16666667]])
|
||||
|
||||
# subdivide polygon using 2nd degree B-Splines
|
||||
new_hand = hand.copy()
|
||||
for _ in range(5):
|
||||
new_hand = subdivide_polygon(new_hand, degree=2, preserve_ends=True)
|
||||
|
||||
# approximate subdivided polygon with Douglas-Peucker algorithm
|
||||
appr_hand = approximate_polygon(new_hand, tolerance=0.02)
|
||||
|
||||
print "Number of coordinates:", len(hand), len(new_hand), len(appr_hand)
|
||||
|
||||
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(9, 4))
|
||||
|
||||
ax1.plot(hand[:, 0], hand[:, 1])
|
||||
ax1.plot(new_hand[:, 0], new_hand[:, 1])
|
||||
ax1.plot(appr_hand[:, 0], appr_hand[:, 1])
|
||||
|
||||
|
||||
# create two ellipses in image
|
||||
img = np.zeros((800, 800), 'int32')
|
||||
rr, cc = ellipse(250, 250, 180, 230, img.shape)
|
||||
img[rr, cc] = 1
|
||||
rr, cc = ellipse(600, 600, 150, 90, img.shape)
|
||||
img[rr, cc] = 1
|
||||
|
||||
plt.gray()
|
||||
ax2.imshow(img)
|
||||
|
||||
# approximate / simplify coordinates of the two ellipses
|
||||
for contour in find_contours(img, 0):
|
||||
coords = approximate_polygon(contour, tolerance=2.5)
|
||||
ax2.plot(coords[:, 1], coords[:, 0], '-r', linewidth=2)
|
||||
coords2 = approximate_polygon(contour, tolerance=39.5)
|
||||
ax2.plot(coords2[:, 1], coords2[:, 0], '-g', linewidth=2)
|
||||
print "Number of coordinates:", len(contour), len(coords), len(coords2)
|
||||
|
||||
ax2.axis((0, 800, 0, 800))
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
====================
|
||||
Build image pyramids
|
||||
====================
|
||||
|
||||
The `pyramid_gaussian` function takes an image and yields successive images
|
||||
shrunk by a constant scale factor. Image pyramids are often used, e.g., to
|
||||
implement algorithms for denoising, texture discrimination, and scale- invariant
|
||||
detection.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.transform import pyramid_gaussian
|
||||
|
||||
|
||||
image = data.lena()
|
||||
rows, cols, dim = image.shape
|
||||
pyramid = tuple(pyramid_gaussian(image, downscale=2))
|
||||
|
||||
composite_image = np.zeros((rows, cols + cols / 2, 3), dtype=np.double)
|
||||
|
||||
composite_image[:rows, :cols, :] = pyramid[0]
|
||||
|
||||
i_row = 0
|
||||
for p in pyramid[1:]:
|
||||
n_rows, n_cols = p.shape[:2]
|
||||
composite_image[i_row:i_row + n_rows, cols:cols + n_cols] = p
|
||||
i_row += n_rows
|
||||
|
||||
plt.imshow(composite_image)
|
||||
plt.show()
|
||||
@@ -19,7 +19,6 @@ values, and use the random walker for the segmentation.
|
||||
.. [1] *Random walks for image segmentation*, Leo Grady, IEEE Trans. Pattern
|
||||
Anal. Mach. Intell. 2006 Nov; 28(11):1768-83
|
||||
"""
|
||||
print __doc__
|
||||
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
=========================
|
||||
Filtering regional maxima
|
||||
=========================
|
||||
|
||||
Here, we use morphological reconstruction to create a background image, which
|
||||
we can subtract from the original image to isolate bright features (regional
|
||||
maxima).
|
||||
|
||||
First we try reconstruction by dilation starting at the edges of the image. We
|
||||
initialize a seed image to the minimum intensity of the image, and set its
|
||||
border to be the pixel values in the original image. These maximal pixels will
|
||||
get dilated in order to reconstruct the background image.
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
from skimage import data
|
||||
from skimage import img_as_float
|
||||
from skimage.morphology import reconstruction
|
||||
from scipy.ndimage import gaussian_filter
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# Convert to float: Important for subtraction later which won't work with uint8
|
||||
image = img_as_float(data.coins())
|
||||
image = gaussian_filter(image, 1)
|
||||
|
||||
seed = np.copy(image)
|
||||
seed[1:-1, 1:-1] = image.min()
|
||||
mask = image
|
||||
|
||||
dilated = reconstruction(seed, mask, method='dilation')
|
||||
|
||||
"""
|
||||
Subtracting the dilated image leaves an image with just the coins and a flat,
|
||||
black background, as shown below.
|
||||
"""
|
||||
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 2.5))
|
||||
|
||||
ax1.imshow(image)
|
||||
ax1.set_title('original image')
|
||||
ax1.axis('off')
|
||||
|
||||
ax2.imshow(dilated, vmin=image.min(), vmax=image.max())
|
||||
ax2.set_title('dilated')
|
||||
ax2.axis('off')
|
||||
|
||||
ax3.imshow(image - dilated)
|
||||
ax3.set_title('image - dilated')
|
||||
ax3.axis('off')
|
||||
|
||||
plt.tight_layout()
|
||||
|
||||
"""
|
||||
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
Although the features (i.e. the coins) are clearly isolated, the coins
|
||||
surrounded by a bright background in the original image are dimmer in the
|
||||
subtracted image. We can attempt to correct this using a different seed image.
|
||||
|
||||
Instead of creating a seed image with maxima along the image border, we can use
|
||||
the features of the image itself to seed the reconstruction process. Here, the
|
||||
seed image is the original image minus a fixed value, ``h``.
|
||||
"""
|
||||
|
||||
h = 0.4
|
||||
seed = image - h
|
||||
dilated = reconstruction(seed, mask, method='dilation')
|
||||
hdome = image - dilated
|
||||
|
||||
"""
|
||||
To get a feel for the reconstruction process, we plot the intensity of the
|
||||
mask, seed, and dilated images along a slice of the image (indicated by red
|
||||
line).
|
||||
"""
|
||||
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 2.5))
|
||||
|
||||
yslice = 197
|
||||
|
||||
ax1.plot(mask[yslice], '0.5', label='mask')
|
||||
ax1.plot(seed[yslice], 'k', label='seed')
|
||||
ax1.plot(dilated[yslice], 'r', label='dilated')
|
||||
ax1.set_ylim(-0.2, 2)
|
||||
ax1.set_title('image slice')
|
||||
ax1.set_xticks([])
|
||||
ax1.legend()
|
||||
|
||||
ax2.imshow(dilated, vmin=image.min(), vmax=image.max())
|
||||
ax2.axhline(yslice, color='r', alpha=0.4)
|
||||
ax2.set_title('dilated')
|
||||
ax2.axis('off')
|
||||
|
||||
ax3.imshow(hdome)
|
||||
ax3.axhline(yslice, color='r', alpha=0.4)
|
||||
ax3.set_title('image - dilated')
|
||||
ax3.axis('off')
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
"""
|
||||
.. image:: PLOT2RST.current_figure
|
||||
|
||||
As you can see in the image slice, each coin is given a different baseline
|
||||
intensity in the reconstructed image; this is because we used the local
|
||||
intensity (shifted by ``h``) as a seed value. As a result, the coins in the
|
||||
subtracted image have similar pixel intensities. The final result is known as
|
||||
the h-dome of an image since this tends to isolate regional maxima of height
|
||||
``h``. This operation is particularly useful when your images are unevenly
|
||||
illuminated.
|
||||
"""
|
||||
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
====================================================
|
||||
Comparison of segmentation and superpixel algorithms
|
||||
====================================================
|
||||
|
||||
This example compares three popular low-level image segmentation methods. As
|
||||
it is difficult to obtain good segmentations, and the definition of "good"
|
||||
often depends on the application, these methods are usually used for obtaining
|
||||
an oversegmentation, also known as superpixels. These superpixels then serve as
|
||||
a basis for more sophisticated algorithms such as conditional random fields
|
||||
(CRF).
|
||||
|
||||
|
||||
Felzenszwalb's efficient graph based segmentation
|
||||
-------------------------------------------------
|
||||
This fast 2D image segmentation algorithm, proposed in [1]_ is popular in the
|
||||
computer vision community.
|
||||
The algorithm has a single ``scale`` parameter that influences the segment
|
||||
size. The actual size and number of segments can vary greatly, depending on
|
||||
local contrast.
|
||||
|
||||
.. [1] Efficient graph-based image segmentation, Felzenszwalb, P.F. and
|
||||
Huttenlocher, D.P. International Journal of Computer Vision, 2004
|
||||
|
||||
|
||||
Quickshift image segmentation
|
||||
-----------------------------
|
||||
|
||||
Quickshift is a relatively recent 2D image segmentation algorithm, based on an
|
||||
approximation of kernelized mean-shift. Therefore it belongs to the family of
|
||||
local mode-seeking algorithms and is applied to the 5D space consisting of
|
||||
color information and image location [2]_.
|
||||
|
||||
One of the benefits of quickshift is that it actually computes a
|
||||
hierarchical segmentation on multiple scales simultaneously.
|
||||
|
||||
Quickshift has two main parameters: ``sigma`` controls the scale of the local
|
||||
density approximation, ``max_dist`` selects a level in the hierarchical
|
||||
segmentation that is produced. There is also a trade-off between distance in
|
||||
color-space and distance in image-space, given by ``ratio``.
|
||||
|
||||
.. [2] Quick shift and kernel methods for mode seeking,
|
||||
Vedaldi, A. and Soatto, S.
|
||||
European Conference on Computer Vision, 2008
|
||||
|
||||
|
||||
SLIC - K-Means based image segmentation
|
||||
---------------------------------------
|
||||
This algorithm simply performs K-means in the 5d space of color information
|
||||
and image location and is therefore closely related to quickshift. As the
|
||||
clustering method is simpler, it is very efficient. It is essential for this
|
||||
algorithm to work in Lab color space to obtain good results. The algorithm
|
||||
quickly gained momentum and is now widely used. See [3] for details. The
|
||||
``ratio`` parameter trades off color-similarity and proximity, as in the case
|
||||
of Quickshift, while ``n_segments`` chooses the number of centers for kmeans.
|
||||
|
||||
.. [3] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi,
|
||||
Pascal Fua, and Sabine Suesstrunk, SLIC Superpixels Compared to
|
||||
State-of-the-art Superpixel Methods, TPAMI, May 2012.
|
||||
"""
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from skimage.data import lena
|
||||
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])
|
||||
segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50)
|
||||
segments_slic = slic(img, ratio=10, n_segments=250, sigma=1)
|
||||
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
|
||||
|
||||
print("Felzenszwalb's number of segments: %d" % len(np.unique(segments_fz)))
|
||||
print("Slic number of segments: %d" % len(np.unique(segments_slic)))
|
||||
print("Quickshift number of segments: %d" % len(np.unique(segments_quick)))
|
||||
|
||||
fig, ax = plt.subplots(1, 3)
|
||||
fig.set_size_inches(8, 3, forward=True)
|
||||
plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
|
||||
|
||||
ax[0].imshow(mark_boundaries(img, segments_fz))
|
||||
ax[0].set_title("Felzenszwalbs's method")
|
||||
ax[1].imshow(mark_boundaries(img, segments_slic))
|
||||
ax[1].set_title("SLIC")
|
||||
ax[2].imshow(mark_boundaries(img, segments_quick))
|
||||
ax[2].set_title("Quickshift")
|
||||
for a in ax:
|
||||
a.set_xticks(())
|
||||
a.set_yticks(())
|
||||
plt.show()
|
||||
@@ -13,17 +13,17 @@ This example shows how to fill several different shapes:
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage.draw import line, polygon, circle, ellipse
|
||||
from skimage.draw import line, polygon, circle, circle_perimeter, ellipse
|
||||
import numpy as np
|
||||
|
||||
|
||||
img = np.zeros((500, 500, 3), 'uint8')
|
||||
|
||||
#: draw line
|
||||
# draw line
|
||||
rr, cc = line(120, 123, 20, 400)
|
||||
img[rr,cc,0] = 255
|
||||
|
||||
#: fill polygon
|
||||
# fill polygon
|
||||
poly = np.array((
|
||||
(300, 300),
|
||||
(480, 320),
|
||||
@@ -34,13 +34,17 @@ poly = np.array((
|
||||
rr, cc = polygon(poly[:,0], poly[:,1], img.shape)
|
||||
img[rr,cc,1] = 255
|
||||
|
||||
#: fill circle
|
||||
# fill circle
|
||||
rr, cc = circle(200, 200, 100, img.shape)
|
||||
img[rr,cc,:] = (255, 255, 0)
|
||||
|
||||
#: fill ellipse
|
||||
# fill ellipse
|
||||
rr, cc = ellipse(300, 300, 100, 200, img.shape)
|
||||
img[rr,cc,2] = 255
|
||||
|
||||
# circle
|
||||
rr, cc = circle_perimeter(120, 400, 50)
|
||||
img[rr, cc, :] = (255, 0, 255)
|
||||
|
||||
plt.imshow(img)
|
||||
plt.show()
|
||||
plt.show()
|
||||
|
||||
@@ -16,7 +16,7 @@ In the case of boolean, 'True' indicates foreground, and for integer arrays,
|
||||
the foreground is 1's.
|
||||
"""
|
||||
from skimage.morphology import skeletonize
|
||||
from skimage.draw import draw
|
||||
from skimage import draw
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ See Wikipedia_ for more details on the algorithm.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage.morphology import watershed, is_local_maximum
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ To generate your own examples, add this extension to the list of
|
||||
example directory(ies) in `plot2rst_paths` (see below) points to a directory
|
||||
with examples named `plot_*.py` and include an `index.rst` file.
|
||||
|
||||
This code was adapted from scikits-image, which took it from scikits-learn.
|
||||
This code was adapted from scikit-image, which took it from scikit-learn.
|
||||
|
||||
Options
|
||||
-------
|
||||
@@ -27,9 +27,10 @@ plot2rst_rcparams : dict
|
||||
plot2rst_default_thumb : str
|
||||
Path (relative to doc root) of default thumbnail image.
|
||||
|
||||
plot2rst_thumb_scale : float
|
||||
Scale factor for thumbnail (e.g., 0.2 to scale plot to 1/5th the
|
||||
original size).
|
||||
plot2rst_thumb_shape : float
|
||||
Shape of thumbnail in pixels. The image is resized to fit within this shape
|
||||
and the excess is filled with white pixels. This fixed size ensures that
|
||||
that gallery images are displayed in a grid.
|
||||
|
||||
plot2rst_plot_tag : str
|
||||
When this tag is found in the example file, the current plot is saved and
|
||||
@@ -68,12 +69,16 @@ import os
|
||||
import shutil
|
||||
import token
|
||||
import tokenize
|
||||
import traceback
|
||||
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import image
|
||||
|
||||
from skimage import io
|
||||
from skimage import transform
|
||||
from skimage.util.dtype import dtype_range
|
||||
|
||||
|
||||
LITERALINCLUDE = """
|
||||
@@ -160,7 +165,7 @@ def setup(app):
|
||||
('../examples', 'auto_examples'), True)
|
||||
app.add_config_value('plot2rst_rcparams', {}, True)
|
||||
app.add_config_value('plot2rst_default_thumb', None, True)
|
||||
app.add_config_value('plot2rst_thumb_scale', 0.25, True)
|
||||
app.add_config_value('plot2rst_thumb_shape', (250, 300), True)
|
||||
app.add_config_value('plot2rst_plot_tag', 'PLOT2RST.current_figure', True)
|
||||
app.add_config_value('plot2rst_index_name', 'index', True)
|
||||
|
||||
@@ -243,7 +248,16 @@ def write_gallery(gallery_index, src_dir, rst_dir, cfg, depth=0):
|
||||
gallery_index.write(TOCTREE_TEMPLATE % (sub_dir + '\n '.join(ex_names)))
|
||||
|
||||
for src_name in examples:
|
||||
write_example(src_name, src_dir, rst_dir, cfg)
|
||||
|
||||
try:
|
||||
write_example(src_name, src_dir, rst_dir, cfg)
|
||||
except Exception:
|
||||
print "Exception raised while running:"
|
||||
print "%s in %s" % (src_name, src_dir)
|
||||
print '~' * 60
|
||||
traceback.print_exc()
|
||||
print '~' * 60
|
||||
continue
|
||||
|
||||
link_name = sub_dir.pjoin(src_name)
|
||||
link_name = link_name.replace(os.path.sep, '_')
|
||||
@@ -335,7 +349,8 @@ def write_example(src_name, src_dir, rst_dir, cfg):
|
||||
thumb_path = thumb_dir.pjoin(src_name[:-3] + '.png')
|
||||
first_image_file = image_dir.pjoin(figure_list[0].lstrip('/'))
|
||||
if first_image_file.exists:
|
||||
image.thumbnail(first_image_file, thumb_path, cfg.plot2rst_thumb_scale)
|
||||
first_image = io.imread(first_image_file)
|
||||
save_thumbnail(first_image, thumb_path, cfg.plot2rst_thumb_shape)
|
||||
|
||||
if not thumb_path.exists:
|
||||
if cfg.plot2rst_default_thumb is None:
|
||||
@@ -345,6 +360,28 @@ def write_example(src_name, src_dir, rst_dir, cfg):
|
||||
shutil.copy(cfg.plot2rst_default_thumb, thumb_path)
|
||||
|
||||
|
||||
def save_thumbnail(image, thumb_path, shape):
|
||||
"""Save image as a thumbnail with the specified shape.
|
||||
|
||||
The image is first resized to fit within the specified shape and then
|
||||
centered in an array of the specified shape before saving.
|
||||
"""
|
||||
rescale = min(float(w_1) / w_2 for w_1, w_2 in zip(shape, image.shape))
|
||||
small_shape = (rescale * np.asarray(image.shape[:2])).astype(int)
|
||||
small_image = transform.resize(image, small_shape)
|
||||
|
||||
if len(image.shape) == 3:
|
||||
shape = shape + (image.shape[2],)
|
||||
background_value = dtype_range[small_image.dtype.type][1]
|
||||
thumb = background_value * np.ones(shape, dtype=small_image.dtype)
|
||||
|
||||
i = (shape[0] - small_shape[0]) // 2
|
||||
j = (shape[1] - small_shape[1]) // 2
|
||||
thumb[i:i+small_shape[0], j:j+small_shape[1]] = small_image
|
||||
|
||||
io.imsave(thumb_path, thumb)
|
||||
|
||||
|
||||
def _plots_are_current(src_path, image_path):
|
||||
first_image_file = Path(image_path.format(1))
|
||||
needs_replot = (not first_image_file.exists or
|
||||
|
||||
@@ -30,7 +30,7 @@ from subprocess import Popen, PIPE, CalledProcessError, check_call
|
||||
pages_dir = 'gh-pages'
|
||||
html_dir = 'build/html'
|
||||
pdf_dir = 'build/latex'
|
||||
pages_repo = 'git@github.com:scikits-image/docs.git'
|
||||
pages_repo = 'git@github.com:scikit-image/docs.git'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Functions
|
||||
@@ -108,7 +108,7 @@ if __name__ == '__main__':
|
||||
shutil.copytree(html_dir, dest)
|
||||
# copy pdf file into tree
|
||||
#shutil.copy(pjoin(pdf_dir, 'scikits.image.pdf'), pjoin(dest, 'scikits.image.pdf'))
|
||||
|
||||
|
||||
try:
|
||||
cd(pages_dir)
|
||||
status = sh2('git status | head -1')
|
||||
@@ -117,7 +117,7 @@ if __name__ == '__main__':
|
||||
e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir,
|
||||
branch)
|
||||
raise RuntimeError(e)
|
||||
sh("touch .nojekyll")
|
||||
sh("touch .nojekyll")
|
||||
sh('git add .nojekyll')
|
||||
sh('git add index.html')
|
||||
sh('git add %s' % tag)
|
||||
@@ -131,4 +131,4 @@ if __name__ == '__main__':
|
||||
|
||||
print
|
||||
print 'Now verify the build in: %r' % dest
|
||||
print "If everything looks good, 'git push'"
|
||||
print "If everything looks good, run 'git push' inside doc/gh-pages."
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
.PHONY: logo
|
||||
|
||||
logo: green_orange_snake.png snake_logo.svg
|
||||
inkscape --export-png=scikits_image_logo.png --export-dpi=100 \
|
||||
inkscape --export-png=scikit_image_logo.png --export-dpi=100 \
|
||||
--export-area-drawing --export-background-opacity=1 \
|
||||
snake_logo.svg
|
||||
python shrink_logo.py
|
||||
|
||||
green_orange_snake.png:
|
||||
python scikits_image_logo.py --no-plot
|
||||
python scikit_image_logo.py --no-plot
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from skimage import io, transform
|
||||
|
||||
s = 0.7
|
||||
|
||||
img = io.imread('scikits_image_logo.png')
|
||||
img = io.imread('scikit_image_logo.png')
|
||||
h, w, c = img.shape
|
||||
|
||||
print "\nScaling down logo by %.1fx..." % s
|
||||
@@ -13,4 +13,4 @@ img = transform.homography(img, [[s, 0, 0],
|
||||
output_shape=(int(h*s), int(w*s), 4),
|
||||
order=3)
|
||||
|
||||
io.imsave('scikits_image_logo_small.png', img)
|
||||
io.imsave('scikit_image_logo_small.png', img)
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
y="278.58533"
|
||||
x="261.22247"
|
||||
id="tspan3152"
|
||||
sodipodi:role="line">scikits-image</tspan></text>
|
||||
sodipodi:role="line">scikit-image</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3154"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -74,9 +74,9 @@ if "%1" == "qthelp" (
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in build/qthelp, like this:
|
||||
echo.^> qcollectiongenerator build\qthelp\scikitsimage.qhcp
|
||||
echo.^> qcollectiongenerator build\qthelp\scikitimage.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile build\qthelp\scikitsimage.ghc
|
||||
echo.^> assistant -collectionFile build\qthelp\scikitimage.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
git log $1..HEAD --format='* %aN' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u
|
||||
git log $1..HEAD --format='- %aN' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
Announcement: scikits-image 0.7.0
|
||||
=================================
|
||||
|
||||
We're happy to announce the 7th version of scikits-image!
|
||||
|
||||
Scikits-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://skimage.org
|
||||
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
It's been only 3 months since scikits-image 0.6 was released, but in that short
|
||||
time, we've managed to add plenty of new features and enhancements, including
|
||||
|
||||
- Geometric image transforms
|
||||
- 3 new image segmentation routines (Felsenzwalb, Quickshift, SLIC)
|
||||
- Local binary patterns for texture characterization
|
||||
- Morphological reconstruction
|
||||
- Polygon approximation
|
||||
- CIE Lab color space conversion
|
||||
- Image pyramids
|
||||
- Multispectral support in random walker segmentation
|
||||
- Slicing, concatenation, and natural sorting of image collections
|
||||
- Perimeter and coordinates measurements in regionprops
|
||||
- An extensible image viewer based on Qt and Matplotlib, with plugins for edge
|
||||
detection, line-profiling, and viewing image collections
|
||||
|
||||
Plus, this release adds a number of bug fixes, new examples, and performance
|
||||
enhancements.
|
||||
|
||||
|
||||
Contributors to this release
|
||||
----------------------------
|
||||
|
||||
This release was only possible due to the efforts of many contributors, both
|
||||
new and old.
|
||||
|
||||
- Andreas Mueller
|
||||
- Andreas Wuerl
|
||||
- Andy Wilson
|
||||
- Brian Holt
|
||||
- Christoph Gohlke
|
||||
- Dharhas Pothina
|
||||
- Emmanuelle Gouillart
|
||||
- Guillaume Gay
|
||||
- Josh Warner
|
||||
- James Bergstra
|
||||
- Johannes Schonberger
|
||||
- Jonathan J. Helmus
|
||||
- Juan Nunez-Iglesias
|
||||
- Leon Tietz
|
||||
- Marianne Corvellec
|
||||
- Matt McCormick
|
||||
- Neil Yager
|
||||
- Nicolas Pinto
|
||||
- Nicolas Poilvert
|
||||
- Pavel Campr
|
||||
- Petter Strandmark
|
||||
- Stefan van der Walt
|
||||
- Tim Sheerman-Chase
|
||||
- Tomas Kazmar
|
||||
- Tony S Yu
|
||||
- Wei Li
|
||||
@@ -0,0 +1,71 @@
|
||||
Announcement: scikits-image 0.8.0
|
||||
=================================
|
||||
|
||||
We're happy to announce the 8th version of scikit-image!
|
||||
|
||||
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
|
||||
------------
|
||||
|
||||
- New rank filter package with many new functions and a very fast underlying
|
||||
local histogram algorithm, especially for large structuring elements
|
||||
`skimage.filter.rank.*`
|
||||
- New function for small object removal
|
||||
`skimage.morphology.remove_small_objects`
|
||||
- New circular hough transformation `skimage.transform.hough_circle`
|
||||
- New function to draw circle perimeter `skimage.draw.circle_perimeter` and
|
||||
ellipse perimeter `skimage.draw.ellipse_perimeter`
|
||||
- New dense DAISY feature descriptor `skimage.feature.daisy`
|
||||
- New bilateral filter `skimage.filter.denoise_bilateral`
|
||||
- New faster TV denoising filter based on split-Bregman algorithm
|
||||
`skimage.filter.denoise_tv_bregman`
|
||||
- New linear hough peak detection `skimage.transform.hough_peaks`
|
||||
- New Scharr edge detection `skimage.filter.scharr`
|
||||
- New geometric image scaling as convenience function
|
||||
`skimage.transform.rescale`
|
||||
- New theme for documentation and website
|
||||
- Faster median filter through vectorization `skimage.filter.median_filter`
|
||||
- Grayscale images supported for SLIC segmentation
|
||||
- Unified peak detection with more options `skimage.feature.peak_local_max`
|
||||
- `imread` can read images via URL and knows more formats `skimage.io.imread`
|
||||
|
||||
Additionally, this release adds lots of bug fixes, new examples, and
|
||||
performance enhancements.
|
||||
|
||||
|
||||
Contributors to this release
|
||||
----------------------------
|
||||
|
||||
This release was only possible due to the efforts of many contributors, both
|
||||
new and old.
|
||||
|
||||
- Adam Ginsburg
|
||||
- Anders Boesen Lindbo Larsen
|
||||
- Andreas Mueller
|
||||
- Christoph Gohlke
|
||||
- Christos Psaltis
|
||||
- Colin Lea
|
||||
- François Boulogne
|
||||
- Jan Margeta
|
||||
- Johannes Schönberger
|
||||
- Josh Warner (Mac)
|
||||
- Juan Nunez-Iglesias
|
||||
- Luis Pedro Coelho
|
||||
- Marianne Corvellec
|
||||
- Matt McCormick
|
||||
- Nicolas Pinto
|
||||
- Olivier Debeir
|
||||
- Paul Ivanov
|
||||
- Sergey Karayev
|
||||
- Stefan van der Walt
|
||||
- Steven Silvester
|
||||
- Thouis (Ray) Jones
|
||||
- Tony S Yu
|
||||
@@ -1,144 +0,0 @@
|
||||
/* This CSS stylesheet is no longer used. Edit agogo.css instead. */
|
||||
|
||||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: {{ theme_bodyfont }};
|
||||
font-size: 100%;
|
||||
background-color: {{ theme_footerbgcolor }};
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: {{ theme_sidebarbgcolor }};
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: {{ theme_bgcolor }};
|
||||
color: {{ theme_textcolor }};
|
||||
padding: 0 20px 30px 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
{%- if theme_rightsidebar|tobool %}
|
||||
div.bodywrapper {
|
||||
margin: 0 230px 0 0;
|
||||
}
|
||||
{%- endif %}
|
||||
|
||||
div.footer {
|
||||
color: {{ theme_footertextcolor }};
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: {{ theme_footertextcolor }};
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: {{ theme_relbarbgcolor }};
|
||||
line-height: 30px;
|
||||
color: {{ theme_relbartextcolor }};
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: {{ theme_relbarlinkcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
{%- if theme_stickysidebar|tobool %}
|
||||
top: 30px;
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
{%- endif %}
|
||||
{%- if theme_rightsidebar|tobool %}
|
||||
float: right;
|
||||
{%- if theme_stickysidebar|tobool %}
|
||||
right: 0;
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
{%- if theme_stickysidebar|tobool %}
|
||||
/* this is nice, but it it leads to hidden headings when jumping
|
||||
to an anchor */
|
||||
/*
|
||||
div.related {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
margin-top: 30px;
|
||||
}
|
||||
*/
|
||||
{%- endif %}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-family: {{ theme_headfont }};
|
||||
color: {{ theme_sidebartextcolor }};
|
||||
font-size: 1.4em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: {{ theme_sidebartextcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: {{ theme_headfont }};
|
||||
color: {{ theme_sidebartextcolor }};
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: {{ theme_sidebartextcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
color: {{ theme_sidebartextcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: {{ theme_sidebarlinkcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid {{ theme_sidebarlinkcolor }};
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
function insert_version_links() {
|
||||
var labels = ['dev', '0.6', '0.5', '0.4', '0.3'];
|
||||
|
||||
document.write('<ul class="versions">\n');
|
||||
var labels = ['dev', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
|
||||
|
||||
for (i = 0; i < labels.length; i++){
|
||||
open_list = '<li>'
|
||||
@@ -14,7 +12,6 @@ function insert_version_links() {
|
||||
document.write(open_list);
|
||||
document.write('<a href="URL">skimage VERSION</a> </li>\n'
|
||||
.replace('VERSION', labels[i])
|
||||
.replace('URL', 'http://scikits-image.org/docs/' + labels[i]));
|
||||
.replace('URL', 'http://scikit-image.org/docs/' + labels[i]));
|
||||
}
|
||||
document.write('</ul>\n');
|
||||
}
|
||||
|
Before Width: | Height: | Size: 32 KiB |
@@ -1,6 +0,0 @@
|
||||
{% extends "!layout.html" %}
|
||||
{% block rootrellink %}
|
||||
<li><a href={{ pathto('index') }}>scikits-image home</a> »</li>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
{% if pagename != 'index' %}
|
||||
|
||||
{%- if display_toc %}
|
||||
<h3>Contents</h3>
|
||||
{{ toc }}
|
||||
{%- endif %}
|
||||
{%- if display_toc %}
|
||||
<h4 class="sidebar-box-heading">Contents</h4>
|
||||
<div class="well sidebar-box toc">
|
||||
{{ toc|replace('<ul>', '<ul class="nav nav-list">') }}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<li><a href="/">Home</a></li>
|
||||
<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>
|
||||
@@ -1,12 +1,22 @@
|
||||
{%- block navigation %}
|
||||
|
||||
{% if pagename != 'index' %}
|
||||
<h3>Navigation</h3>
|
||||
<p>
|
||||
<a href="{{ pathto(master_doc) }}">Documentation Home</a>
|
||||
</p>
|
||||
<p> </p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{%- endblock %}
|
||||
<h4 class="sidebar-box-heading">{{ _('Navigation') }}</h4>
|
||||
<div class="well sidebar-box">
|
||||
<ul class="nav nav-list">
|
||||
<li><a href="{{ pathto(master_doc) }}">Documentation Home</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{%- if prev %}
|
||||
<h4 class="sidebar-box-heading">{{ _('Previous topic') }}</h4>
|
||||
<div class="well sidebar-box">
|
||||
<ul class="nav nav-list">
|
||||
<li><a href="{{ prev.link|e }}" title="{{ _('previous chapter') }}">{{ prev.title }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<h4 class="sidebar-box-heading">{{ _('Next topic') }}</h4>
|
||||
<div class="well sidebar-box">
|
||||
<ul class="nav nav-list">
|
||||
<li><a href="{{ next.link|e }}" title="{{ _('next chapter') }}">{{ next.title }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{%- block versions %}
|
||||
|
||||
<h3>Version</h3>
|
||||
|
||||
<script type="text/javascript">
|
||||
insert_version_links();
|
||||
</script>
|
||||
|
||||
{%- endblock %}
|
||||
<h4 class="sidebar-box-heading">{{ _('Versions') }}</h4>
|
||||
<div class="well sidebar-box">
|
||||
<ul class="nav nav-list">
|
||||
<script src="{{ pathto('_static/', 1) }}docversions.js"></script>
|
||||
<script type="text/javascript">
|
||||
insert_version_links();
|
||||
</script>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ CellProfiler BSD license announcement
|
||||
::
|
||||
|
||||
From: Vebjorn Ljosa
|
||||
To: scikits-image@googlegroups.com
|
||||
To: scikit-image@googlegroups.com
|
||||
Date: June 3, 2010
|
||||
|
||||
We have changed the license of some parts of CellProfiler from GNU GPL
|
||||
|
||||
@@ -26,7 +26,8 @@ sys.path.append(os.path.join(curpath, '..', 'ext'))
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.pngmath', 'numpydoc',
|
||||
'sphinx.ext.autosummary', 'plot_directive', 'plot2rst']
|
||||
'sphinx.ext.autosummary', 'plot_directive', 'plot2rst',
|
||||
'sphinx.ext.intersphinx']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -42,7 +43,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'skimage'
|
||||
copyright = u'2011, the scikits-image team'
|
||||
copyright = u'2011, the scikit-image team'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -102,8 +103,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'agogo'
|
||||
html_style = 'agogo.css'
|
||||
html_theme = 'scikit-image'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -120,10 +120,6 @@ html_title = 'skimage v%s docs' % version
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
html_logo = "scikits_image_logo_small.png"
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
@@ -146,9 +142,7 @@ html_static_path = ['_static']
|
||||
html_sidebars = {
|
||||
'**': ['navigation.html',
|
||||
'localtoc.html',
|
||||
'relations.html',
|
||||
'versions.html',
|
||||
'searchbox.html'],
|
||||
'versions.html'],
|
||||
}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
@@ -182,7 +176,7 @@ html_sidebars = {
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'scikitsimagedoc'
|
||||
htmlhelp_basename = 'scikitimagedoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -196,7 +190,7 @@ htmlhelp_basename = 'scikitsimagedoc'
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('contents', 'scikitsimage.tex', u'The Image Scikit Documentation',
|
||||
('contents', 'scikitimage.tex', u'The Image Scikit Documentation',
|
||||
u'SciPy Developers', 'manual'),
|
||||
]
|
||||
|
||||
@@ -220,8 +214,7 @@ latex_documents = [
|
||||
# -----------------------------------------------------------------------------
|
||||
# Numpy extensions
|
||||
# -----------------------------------------------------------------------------
|
||||
# Make numpydoc to generate plots for example sections
|
||||
#numpydoc_use_plots = True
|
||||
numpydoc_show_class_members = False
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Plots
|
||||
@@ -256,3 +249,13 @@ plot2rst_index_name = 'README'
|
||||
plot2rst_rcparams = {'image.cmap' : 'gray',
|
||||
'image.interpolation' : 'none'}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# intersphinx
|
||||
# -----------------------------------------------------------------------------
|
||||
_python_doc_base = 'http://docs.python.org/2.7'
|
||||
intersphinx_mapping = {
|
||||
_python_doc_base: None,
|
||||
'http://docs.scipy.org/doc/numpy': None,
|
||||
'http://docs.scipy.org/doc/scipy/reference': None,
|
||||
'http://scikit-learn.org/stable': None
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
Development workflow
|
||||
####################
|
||||
|
||||
You already have your own forked copy of the scikits-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.
|
||||
|
||||
Workflow summary
|
||||
================
|
||||
|
||||
In what follows we'll refer to the upstream scikits-image ``master`` branch, as
|
||||
In what follows we'll refer to the upstream scikit-image ``master`` branch, as
|
||||
"trunk".
|
||||
|
||||
* Don't use your ``master`` branch for anything. Consider deleting it.
|
||||
@@ -22,9 +22,9 @@ In what follows we'll refer to the upstream scikits-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 `scikits-image mailing list`_ if you get stuck.
|
||||
* Ask on the `scikit-image mailing list`_ if you get stuck.
|
||||
* Ask for code review!
|
||||
|
||||
This way of working helps to keep work well organized, with readable history.
|
||||
@@ -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 scikits-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::
|
||||
@@ -150,7 +150,7 @@ Ask for your changes to be reviewed or merged
|
||||
When you are ready to ask for someone to review your code and consider a merge:
|
||||
|
||||
#. Go to the URL of your forked repo, say
|
||||
``http://github.com/your-user-name/scikits-image``.
|
||||
``http://github.com/your-user-name/scikit-image``.
|
||||
#. Use the 'Switch Branches' dropdown menu near the top left of the page to
|
||||
select the branch with your changes:
|
||||
|
||||
@@ -192,10 +192,10 @@ If you want to work on some stuff with other people, where you are all
|
||||
committing into the same repository, or even the same branch, then just
|
||||
share it via github.
|
||||
|
||||
First fork scikits-image into your account, as from :ref:`forking`.
|
||||
First fork scikit-image into your account, as from :ref:`forking`.
|
||||
|
||||
Then, go to your forked repository github page, say
|
||||
``http://github.com/your-user-name/scikits-image``
|
||||
``http://github.com/your-user-name/scikit-image``
|
||||
|
||||
Click on the 'Admin' button, and add anyone else to the repo as a
|
||||
collaborator:
|
||||
@@ -204,7 +204,7 @@ collaborator:
|
||||
|
||||
Now all those people can do::
|
||||
|
||||
git clone git@githhub.com:your-user-name/scikits-image.git
|
||||
git clone git@githhub.com:your-user-name/scikit-image.git
|
||||
|
||||
Remember that links starting with ``git@`` use the ssh protocol and are
|
||||
read-write; links starting with ``git://`` are read-only.
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
=============================
|
||||
|
||||
These are the instructions if you just want to follow the latest
|
||||
*scikits-image* source, but you don't need to do any development for now.
|
||||
*scikit-image* source, but you don't need to do any development for now.
|
||||
|
||||
The steps are:
|
||||
|
||||
* :ref:`install-git`
|
||||
* get local copy of the `scikits-image github`_ git repository
|
||||
* get local copy of the `scikit-image github`_ git repository
|
||||
* update local copy from time to time
|
||||
|
||||
Get the local copy of the code
|
||||
@@ -18,19 +18,19 @@ Get the local copy of the code
|
||||
|
||||
From the command line::
|
||||
|
||||
git clone git://github.com/scikits-image/scikits-image.git
|
||||
git clone git://github.com/scikit-image/scikit-image.git
|
||||
|
||||
You now have a copy of the code tree in the new ``scikits-image`` directory.
|
||||
You now have a copy of the code tree in the new ``scikit-image`` directory.
|
||||
|
||||
Updating the code
|
||||
=================
|
||||
|
||||
From time to time you may want to pull down the latest code. Do this with::
|
||||
|
||||
cd scikits-image
|
||||
cd scikit-image
|
||||
git pull
|
||||
|
||||
The tree in ``scikits-image`` will now have the latest changes from the initial
|
||||
The tree in ``scikit-image`` will now have the latest changes from the initial
|
||||
repository.
|
||||
|
||||
.. include:: links.inc
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
.. _forking:
|
||||
|
||||
============================================
|
||||
Making your own copy (fork) of scikits-image
|
||||
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 scikits-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
|
||||
======================================
|
||||
@@ -17,17 +17,17 @@ 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 scikits-image_
|
||||
Create your own forked copy of scikit-image_
|
||||
=============================================
|
||||
|
||||
#. Log into your github account.
|
||||
#. Go to the scikits-image_ github home at `scikits-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 scikits-image_.
|
||||
should find yourself at the home page for your own forked copy of scikit-image_.
|
||||
|
||||
.. include:: links.inc
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Introduction
|
||||
==============
|
||||
|
||||
These pages describe a git_ and github_ workflow for the scikits-image_
|
||||
These pages describe a git_ and github_ workflow for the scikit-image_
|
||||
project.
|
||||
|
||||
There are several different workflows here, for different ways of
|
||||
working with *scikits-image*.
|
||||
working with *scikit-image*.
|
||||
|
||||
This is not a comprehensive git reference, it's just a workflow for our
|
||||
own project. It's tailored to the github hosting service. You may well
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.. _using-git:
|
||||
|
||||
Working with *scikits-image* source code
|
||||
Working with *scikit-image* source code
|
||||
========================================
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -16,7 +16,7 @@ access to the upstream repo. Being a maintainer, you've got read-write access.
|
||||
It's good to have your upstream remote have a scary name, to remind you that
|
||||
it's a read-write remote::
|
||||
|
||||
git remote add upstream-rw git@github.com:scikits-image/scikits-image.git
|
||||
git remote add upstream-rw git@github.com:scikit-image/scikit-image.git
|
||||
git fetch upstream-rw
|
||||
|
||||
*******************
|
||||
@@ -29,7 +29,7 @@ Let's say you have some changes that need to go into trunk
|
||||
The changes are in some branch that you are currently on. For example, you are
|
||||
looking at someone's changes like this::
|
||||
|
||||
git remote add someone git://github.com/someone/scikits-image.git
|
||||
git remote add someone git://github.com/someone/scikit-image.git
|
||||
git fetch someone
|
||||
git branch cool-feature --track someone/cool-feature
|
||||
git checkout cool-feature
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
================
|
||||
|
||||
You've discovered a bug or something else you want to change
|
||||
in scikits-image_ .. |emdash| excellent!
|
||||
in scikit-image_ .. |emdash| excellent!
|
||||
|
||||
You've worked out a way to fix it |emdash| even better!
|
||||
|
||||
@@ -29,9 +29,9 @@ Overview
|
||||
git config --global user.email you@yourdomain.example.com
|
||||
git config --global user.name "Your Name Comes Here"
|
||||
# get the repository if you don't have it
|
||||
git clone git://github.com/scikits-image/scikits-image.git
|
||||
git clone git://github.com/scikit-image/scikit-image.git
|
||||
# make a branch for your patching
|
||||
cd scikits-image
|
||||
cd scikit-image
|
||||
git branch the-fix-im-thinking-of
|
||||
git checkout the-fix-im-thinking-of
|
||||
# hack, hack, hack
|
||||
@@ -44,7 +44,7 @@ Overview
|
||||
# make the patch files
|
||||
git format-patch -M -C master
|
||||
|
||||
Then, send the generated patch files to the `scikits-image
|
||||
Then, send the generated patch files to the `scikit-image
|
||||
mailing list`_ |emdash| where we will thank you warmly.
|
||||
|
||||
In detail
|
||||
@@ -57,10 +57,10 @@ In detail
|
||||
git config --global user.name "Your Name Comes Here"
|
||||
|
||||
#. If you don't already have one, clone a copy of the
|
||||
scikits-image_ repository::
|
||||
scikit-image_ repository::
|
||||
|
||||
git clone git://github.com/scikits-image/scikits-image.git
|
||||
cd scikits-image
|
||||
git clone git://github.com/scikit-image/scikit-image.git
|
||||
cd scikit-image
|
||||
|
||||
#. Make a 'feature branch'. This will be where you work on
|
||||
your bug fix. It's nice and safe and leaves you with
|
||||
@@ -100,7 +100,7 @@ In detail
|
||||
0001-BF-added-tests-for-Funny-bug.patch
|
||||
0002-BF-added-fix-for-Funny-bug.patch
|
||||
|
||||
Send these files to the `scikits-image mailing list`_.
|
||||
Send these files to the `scikit-image mailing list`_.
|
||||
|
||||
When you are done, to switch back to the main copy of the
|
||||
code, just return to the ``master`` branch::
|
||||
@@ -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 scikits-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
|
||||
@@ -124,7 +124,7 @@ Then::
|
||||
# rename pointer to main repository to 'upstream'
|
||||
git remote rename origin upstream
|
||||
# point your repo to default read / write to your fork on github
|
||||
git remote add origin git@github.com:your-user-name/scikits-image.git
|
||||
git remote add origin git@github.com:your-user-name/scikit-image.git
|
||||
# push up any branches you've made and want to keep
|
||||
git push origin the-fix-im-thinking-of
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ Overview
|
||||
|
||||
::
|
||||
|
||||
git clone git@github.com:your-user-name/scikits-image.git
|
||||
cd scikits-image
|
||||
git remote add upstream git://github.com/scikits-image/scikits-image.git
|
||||
git clone git@github.com:your-user-name/scikit-image.git
|
||||
cd scikit-image
|
||||
git remote add upstream git://github.com/scikit-image/scikit-image.git
|
||||
|
||||
In detail
|
||||
=========
|
||||
@@ -22,8 +22,8 @@ Clone your fork
|
||||
---------------
|
||||
|
||||
#. Clone your fork to the local computer with ``git clone
|
||||
git@github.com:your-user-name/scikits-image.git``
|
||||
#. Investigate. Change directory to your new repo: ``cd scikits-image``. Then
|
||||
git@github.com:your-user-name/scikit-image.git``
|
||||
#. Investigate. Change directory to your new repo: ``cd scikit-image``. Then
|
||||
``git branch -a`` to show you all branches. You'll get something
|
||||
like::
|
||||
|
||||
@@ -35,7 +35,7 @@ Clone your fork
|
||||
What remote repository is ``remote/origin``? Try ``git remote -v`` to
|
||||
see the URLs for the remote. They will point to your github fork.
|
||||
|
||||
Now you want to connect to the upstream `scikits-image github`_ repository, so
|
||||
Now you want to connect to the upstream `scikit-image github`_ repository, so
|
||||
you can merge in changes from trunk.
|
||||
|
||||
.. _linking-to-upstream:
|
||||
@@ -45,11 +45,11 @@ Linking your repository to the upstream repo
|
||||
|
||||
::
|
||||
|
||||
cd scikits-image
|
||||
git remote add upstream git://github.com/scikits-image/scikits-image.git
|
||||
cd scikit-image
|
||||
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 scikits-image_ repository at `scikits-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
|
||||
@@ -59,10 +59,10 @@ use it to merge into our own code.
|
||||
Just for your own satisfaction, show yourself that you now have a new
|
||||
'remote', with ``git remote -v show``, giving you something like::
|
||||
|
||||
upstream git://github.com/scikits-image/scikits-image.git (fetch)
|
||||
upstream git://github.com/scikits-image/scikits-image.git (push)
|
||||
origin git@github.com:your-user-name/scikits-image.git (fetch)
|
||||
origin git@github.com:your-user-name/scikits-image.git (push)
|
||||
upstream git://github.com/scikit-image/scikit-image.git (fetch)
|
||||
upstream git://github.com/scikit-image/scikit-image.git (push)
|
||||
origin git@github.com:your-user-name/scikit-image.git (fetch)
|
||||
origin git@github.com:your-user-name/scikit-image.git (push)
|
||||
|
||||
.. include:: links.inc
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.. scikits-image
|
||||
.. _scikits-image: http://scikits-image.org
|
||||
.. _`scikits-image github`: http://github.com/scikits-image/scikits-image
|
||||
.. scikit-image
|
||||
.. _scikit-image: http://scikit-image.org
|
||||
.. _`scikit-image github`: http://github.com/scikit-image/scikit-image
|
||||
|
||||
.. _`scikits-image mailing list`: http://groups.google.com/group/scikits-image
|
||||
.. _`scikit-image mailing list`: http://groups.google.com/group/scikit-image
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Pre-built installation
|
||||
----------------------
|
||||
|
||||
.. !! Also update scikits-image-web !!
|
||||
|
||||
`Windows binaries
|
||||
<http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image>`__
|
||||
are kindly provided by Christoph Gohlke.
|
||||
@@ -12,37 +10,37 @@ Distribution (EPD) <http://enthought.com/products/epd.php>`__ and `Python(x,y)
|
||||
<http://code.google.com/p/pythonxy/wiki/Welcome>`__.
|
||||
|
||||
On systems that support setuptools, the package can be installed from the
|
||||
`Python packaging index <http://pypi.python.org/pypi/scikits-image>`__ using
|
||||
`Python packaging index <http://pypi.python.org/pypi/scikit-image>`__ using
|
||||
|
||||
|
||||
::
|
||||
|
||||
easy_install -U scikits-image
|
||||
easy_install -U scikit-image
|
||||
|
||||
or
|
||||
|
||||
::
|
||||
|
||||
pip -U scikits-image
|
||||
pip install -U scikit-image
|
||||
|
||||
Installation from source
|
||||
------------------------
|
||||
|
||||
Obtain the source from the git-repository at
|
||||
`http://github.com/scikits-image/scikits-image
|
||||
<http://github.com/scikits-image/scikits-image>`_.
|
||||
`http://github.com/scikit-image/scikit-image
|
||||
<http://github.com/scikit-image/scikit-image>`_.
|
||||
|
||||
by running
|
||||
|
||||
::
|
||||
|
||||
git clone http://github.com/scikits-image/scikits-image.git
|
||||
git clone http://github.com/scikit-image/scikit-image.git
|
||||
|
||||
in a terminal (You will need to have git installed on your machine).
|
||||
|
||||
If you do not have git installed, you can also download a zipball from
|
||||
`https://github.com/scikits-image/scikits-image/zipball/master
|
||||
<https://github.com/scikits-image/scikits-image/zipball/master>`_.
|
||||
`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
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Image Processing SciKit
|
||||
=======================
|
||||
|
||||
The `scikits-image <http://scikits-image.org>`__ SciKit (toolkit for
|
||||
The `scikit-image <http://scikit-image.org>`__ SciKit (toolkit for
|
||||
`SciPy <http://www.scipy.org>`__) extends ``scipy.ndimage`` to provide
|
||||
a versatile set of image processing routines. It is written in the
|
||||
`Python <http://www.python.org>`_ language.
|
||||
@@ -12,15 +12,15 @@ mailing list (address provided below).
|
||||
|
||||
Homepage
|
||||
--------
|
||||
http://scikits-image.org
|
||||
http://scikit-image.org
|
||||
|
||||
Source, bugs and patches
|
||||
------------------------
|
||||
http://github.com/scikits-image/scikits-image
|
||||
http://github.com/scikit-image/scikit-image
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
http://groups.google.com/group/scikits-image
|
||||
http://groups.google.com/group/scikit-image
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
@@ -32,8 +32,8 @@ gallery_div = '''\
|
||||
examples = glob.glob(os.path.join(example_dir, 'plot_*.py'))
|
||||
|
||||
images, links = [], []
|
||||
image_url = 'http://scikits-image.org/docs/dev/_images/%s.png'
|
||||
link_url = 'http://scikits-image.org/docs/dev/auto_examples/%s.html'
|
||||
image_url = 'http://scikit-image.org/docs/dev/_images/%s.png'
|
||||
link_url = 'http://scikit-image.org/docs/dev/auto_examples/%s.html'
|
||||
|
||||
for e in examples:
|
||||
e = os.path.basename(e)
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
{#
|
||||
agogo/layout.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx layout template for the agogo theme, originally written
|
||||
by Andi Albrecht.
|
||||
|
||||
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{% extends "basic/layout.html" %}
|
||||
{% set script_files = script_files + ['_static/docversions.js'] %}
|
||||
|
||||
{% block header %}
|
||||
<div class="header-wrapper">
|
||||
<div class="header">
|
||||
{%- block headertitle %}
|
||||
|
||||
{%- if logo %}
|
||||
<div class="logo"><a href="http://scikits-image.org">
|
||||
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
|
||||
</a></div>
|
||||
{%- endif %}
|
||||
{# <h1><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></h1> #}
|
||||
{%- endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
{%- block sidebar2 %}
|
||||
{# We don't want the logo here #}
|
||||
{%- block sidebarlogo %} {% endblock %}
|
||||
{{ sidebar() }}
|
||||
{% endblock %}
|
||||
<div class="document">
|
||||
{%- block document %}
|
||||
{{ super() }}
|
||||
{%- endblock %}
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<div class="footer-wrapper">
|
||||
{{ super() }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block relbar1 %}{% endblock %}
|
||||
|
||||
{% block relbar2 %}{% endblock %}
|
||||
@@ -1,753 +0,0 @@
|
||||
/*
|
||||
* agogo.css_t
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- agogo theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
* {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
||||
div.header-wrapper {
|
||||
border-top: 0px solid #babdb6;
|
||||
padding: 1em 1em 0;
|
||||
min-height: 0px;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: {{ theme_bodyfont }};
|
||||
line-height: 1.4em;
|
||||
color: black;
|
||||
background-color: {{ theme_bgcolor }};
|
||||
}
|
||||
|
||||
|
||||
/* Page layout */
|
||||
|
||||
div.header, div.content, div.footer {
|
||||
max-width: {{ theme_pagewidth }};
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
div.header-wrapper {
|
||||
border-bottom: 0px solid #2e3436;
|
||||
}
|
||||
|
||||
|
||||
/* Default body styles */
|
||||
a {
|
||||
color: {{ theme_linkcolor }};
|
||||
}
|
||||
|
||||
div.bodywrapper a, div.footer a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: normal;
|
||||
color: {{ theme_headercolor2 }};
|
||||
margin-bottom: .8em;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: {{ theme_headercolor1 }};
|
||||
line-height: 1.1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-bottom: .5em;
|
||||
color: {{ theme_headercolor1 }};
|
||||
border-bottom: 1px solid {{ theme_headercolor1 }};
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
color: #dddddd;
|
||||
padding-left: .3em;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 2px 7px 1px 7px;
|
||||
border-left: 0.2em solid black;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dt:target, .highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
div.header {}
|
||||
|
||||
div.header h1 {
|
||||
font-family: "Trebuchet MS", Helvetica, sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 250%;
|
||||
letter-spacing: .08em;
|
||||
line-height: 70px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.header h1 a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.header h1 a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.header div.rel {
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid #AAA;
|
||||
border-bottom: 1px solid #AAA;
|
||||
border-radius: 5px;
|
||||
padding: 3px 1em;
|
||||
}
|
||||
|
||||
div.header div.rel a {
|
||||
color: {{ theme_linkcolor }};
|
||||
letter-spacing: .05em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.logo {}
|
||||
|
||||
img.logo {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Content */
|
||||
div.content-wrapper {
|
||||
background-color: white;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
div.document {
|
||||
max-width: {{ theme_documentwidth }};
|
||||
}
|
||||
|
||||
div.body {
|
||||
padding-right: 2em;
|
||||
min-width: 20em;
|
||||
overflow: hidden;
|
||||
font-size: 90%;
|
||||
text-align: {{ theme_textalign }};
|
||||
}
|
||||
|
||||
div.document ul {
|
||||
margin: 1.5em;
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
div.document dd {
|
||||
margin-left: 1.2em;
|
||||
margin-top: .4em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.document .section {
|
||||
margin-top: 1.7em;
|
||||
}
|
||||
div.document .section:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
div.document div.highlight {
|
||||
padding: 3px;
|
||||
background-color: #eeeeec;
|
||||
border-top: 2px solid #dddddd;
|
||||
border-bottom: 2px solid #dddddd;
|
||||
margin-top: .8em;
|
||||
margin-bottom: .8em;
|
||||
}
|
||||
|
||||
div.document h2 {
|
||||
margin-top: .7em;
|
||||
}
|
||||
|
||||
div.document p {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
div.document li.toctree-l1 {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.document .descname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.document .docutils.literal {
|
||||
background-color: #eeeeec;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
div.document .docutils.xref.literal {
|
||||
background-color: transparent;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
div.document blockquote {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
div.document ol {
|
||||
margin: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
/* Sidebar */
|
||||
|
||||
div.sphinxsidebar {
|
||||
width: {{ theme_sidebarwidth }};
|
||||
padding: 0 1em;
|
||||
float: right;
|
||||
font-size: .93em;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a, div.header a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover, div.header a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
color: #2e3436;
|
||||
text-transform: uppercase;
|
||||
font-size: 130%;
|
||||
letter-spacing: .1em;
|
||||
margin-bottom: .4em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
margin-bottom: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .tile {
|
||||
border: 1px solid #D1DDE2;
|
||||
border-radius: 10px;
|
||||
background-color: #E1E8EC;
|
||||
padding-left: 0.5em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin-bottom: 1.5em;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l1 a {
|
||||
display: block;
|
||||
padding: 1px;
|
||||
border: 1px solid #dddddd;
|
||||
background-color: #eeeeec;
|
||||
margin-bottom: .4em;
|
||||
padding-left: 3px;
|
||||
color: #2e3436;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l2 a {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin-left: 1em;
|
||||
border-bottom: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l3 a {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin-left: 2em;
|
||||
border-bottom: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l2:last-child a {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l1.current a {
|
||||
border-right: 5px solid {{ theme_headerlinkcolor }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar li.toctree-l1.current li.toctree-l2 a {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
div.sidebarblock {
|
||||
padding-bottom: .4em;
|
||||
border-bottom: 1px solid #AAA;
|
||||
margin-bottom: .8em;
|
||||
}
|
||||
|
||||
ul.versions li {
|
||||
color: gray;
|
||||
list-style: circle inside;
|
||||
}
|
||||
|
||||
ul.versions li#current {
|
||||
list-style: disc inside;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
div.footer-wrapper {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
border-top: 2px solid #aaa;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer, div.footer a {
|
||||
color: #888a85;
|
||||
}
|
||||
|
||||
.figure {
|
||||
float: left;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.figure img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.figure .caption {
|
||||
width: 200px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
|
||||
/* Styles copied from basic theme */
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
clear: both;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
table.contentstable, table.contentstable td, table.contentstable th {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
div.body table.contentstable p {
|
||||
margin: 0.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.contentstable a {
|
||||
text-decoration: none;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable dl, table.indextable dd {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* -- viewcode extension ---------------------------------------------------- */
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family:: {{ theme_bodyfont }};
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -3px;
|
||||
padding: 0 3px;
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
|
||||
span.strike { text-decoration: line-through; }
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: {{ theme_linkcolor }};
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: {{ theme_visitedlinkcolor }};
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: {{ theme_headfont }};
|
||||
background-color: {{ theme_headbgcolor }};
|
||||
font-weight: normal;
|
||||
color: {{ theme_headtextcolor }};
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px 20px 10px 0px;
|
||||
padding: 3px 0 3px 0px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 180%; }
|
||||
div.body h2 { font-size: 150%; }
|
||||
div.body h3 { font-size: 130%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: {{ theme_headlinkcolor }};
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: {{ theme_headlinkcolor }};
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
background-color: {{ theme_codebgcolor }};
|
||||
color: {{ theme_codetextcolor }};
|
||||
line-height: 120%;
|
||||
border: 0px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
sup {
|
||||
font-size: x-small;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
th {
|
||||
color: #333;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#api-reference ul:first-child {
|
||||
float: left;
|
||||
width: 35em;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
list-style: none;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#api-reference li {
|
||||
float: left;
|
||||
position: relative;
|
||||
margin-right: 1em;
|
||||
width: 17em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.field-list {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* ----------------- Example Gallery ----------------- */
|
||||
|
||||
.gallery {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.gallery p.caption a{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* ----------------- Coverage States ----------------- */
|
||||
span.missing{
|
||||
color: #000;
|
||||
background-color: #ff5840;
|
||||
border-color: #A77272;
|
||||
font-weight: bold;
|
||||
}
|
||||
span.partial{
|
||||
color: #806600;
|
||||
background-color: #ffc343;
|
||||
font-weight: bold;
|
||||
}
|
||||
span.done{
|
||||
color: #106600;
|
||||
background-color: #60f030;
|
||||
border-color: #4F8530;
|
||||
font-weight: bold;
|
||||
}
|
||||
span.na{
|
||||
color: #A8A8A8;
|
||||
border-color: #4F8530;
|
||||
}
|
||||
|
||||
table.coverage {
|
||||
border: solid 1px;
|
||||
}
|
||||
|
||||
td.missing-bar{
|
||||
color: #ff5840;
|
||||
background-color: #ff5840;
|
||||
border-color: #A77272;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
td.partial-bar{
|
||||
color: #ffc343;
|
||||
background-color: #ffc343;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
td.done-bar{
|
||||
color: #60f030;
|
||||
background-color: #60f030;
|
||||
border-color: #4F8530;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
td.na-bar{
|
||||
color: #FFF;
|
||||
background-color: #FFF;
|
||||
border-color: #4F8530;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Adjust doc headers such as Notes, References, etc. */
|
||||
p.rubric {
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
/* Math */
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = agogo.css
|
||||
pygments_style = tango
|
||||
|
||||
[options]
|
||||
bodyfont = "Verdana", Arial, sans-serif
|
||||
pagewidth = 70em
|
||||
documentwidth = 55em
|
||||
sidebarwidth = 14em
|
||||
bgcolor = white
|
||||
headerbg = url(bgtop.png) top left repeat-x
|
||||
footerbg = url(bgfooter.png) top left repeat-x
|
||||
linkcolor = #FC852B
|
||||
headercolor1 = #555
|
||||
headercolor2 = #555
|
||||
headerlinkcolor = #fcaf3e
|
||||
codebgcolor = #EEE
|
||||
textalign = justify
|
||||
@@ -0,0 +1,113 @@
|
||||
{#
|
||||
scikit-image/layout.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx layout template for the scikit-image theme, written by
|
||||
Johannes Schönberger.
|
||||
|
||||
#}
|
||||
|
||||
{%- set url_root = pathto('', 1) %}
|
||||
{# XXX necessary? #}
|
||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||
{%- if not embedded and docstitle %}
|
||||
{%- set titlesuffix = " — "|safe + docstitle|e %}
|
||||
{%- else %}
|
||||
{%- set titlesuffix = "" %}
|
||||
{%- endif %}
|
||||
|
||||
{%- macro script() %}
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="{{ pathto('_static/', 1) }}js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '{{ url_root }}',
|
||||
VERSION: '{{ release|e }}',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
||||
HAS_SOURCE: {{ has_source|lower }}
|
||||
};
|
||||
</script>
|
||||
{%- for scriptfile in script_files %}
|
||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro css() %}
|
||||
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
|
||||
<link href="{{ pathto('_static/', 1) }}css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="{{ pathto('_static/', 1) }}css/custom.css" rel="stylesheet" type="text/css">
|
||||
<link href="http://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" type="text/css">
|
||||
{%- for cssfile in css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{%- block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
{%- endblock %}
|
||||
{{ metatags }}
|
||||
{{ css() }}
|
||||
{{ script() }}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('genindex') %}
|
||||
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('search') %}
|
||||
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
|
||||
{%- endif %}
|
||||
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
|
||||
{%- if parents %}
|
||||
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if prev %}
|
||||
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
|
||||
{%- endif %}
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<link rel="shortcut icon" href="{{ pathto('_static/', 1) }}favicon.ico">
|
||||
{%- block extrahead %}{% endblock %}
|
||||
</head>
|
||||
<body class="container">
|
||||
<a href="http://scikit-image.org" class="logo"><img src="{{ pathto('_static/', 1) }}img/logo.png" alt=""></a>
|
||||
<div class="clearfix"></div>
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<ul class="nav">
|
||||
{% include 'navbar.html' %}
|
||||
</ul>
|
||||
<form class="navbar-form pull-right" action="{{ pathto('search') }}" method="get">
|
||||
<input type="text" class="search span3" name="q" placeholder="Search documentation ...">
|
||||
<input type="hidden" name="check_keywords" value="yes" >
|
||||
<input type="hidden" name="area" value="default" >
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span9">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
<div class="span3">
|
||||
{%- for sidebartemplate in sidebars %}
|
||||
{%- include sidebartemplate %}
|
||||
{%- endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<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>.
|
||||
</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,46 @@
|
||||
{#
|
||||
basic/search.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Template for the search page.
|
||||
|
||||
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{% extends "layout.html" %}
|
||||
{% set title = _('Search') %}
|
||||
{% set script_files = script_files + ['_static/searchtools.js'] %}
|
||||
{% set script_files = script_files + ['searchindex.js'] %}
|
||||
{% block body %}
|
||||
<h1 id="search-documentation">{{ _('Search') }}</h1>
|
||||
<div id="fallback" class="admonition warning">
|
||||
<script type="text/javascript">
|
||||
$('#fallback').hide();
|
||||
$("input.search").focus();
|
||||
</script>
|
||||
<p>
|
||||
{% trans %}Please activate JavaScript to enable the search
|
||||
functionality.{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
{% trans %}From here you can search these documents. Enter your search
|
||||
words into the box in the navigation bar and press "Enter". Note that the
|
||||
search function will automatically search for all of the words. Pages
|
||||
containing fewer words won't appear in the result list.{% endtrans %}
|
||||
</p>
|
||||
{% if search_performed %}
|
||||
{% if not search_results %}
|
||||
<p>{{ _('Your search did not match any results.') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div id="search-results">
|
||||
{% if search_results %}
|
||||
<ul>
|
||||
{% for href, caption, context in search_results %}
|
||||
<li class="well"><a href="{{ pathto(item.href) }}">{{ caption }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,224 @@
|
||||
body {
|
||||
font-family: "Raleway";
|
||||
}
|
||||
a {
|
||||
color: #CE5C00;
|
||||
}
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
textarea {
|
||||
font-family: "Raleway";
|
||||
}
|
||||
pre {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
clear: left;
|
||||
}
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
line-height: 36px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 19px;
|
||||
line-height: 21px;
|
||||
}
|
||||
h4 {
|
||||
font-size: 17px;
|
||||
line-height: 19px;
|
||||
}
|
||||
h5 {
|
||||
font-size: 15px;
|
||||
line-height: 17px;
|
||||
}
|
||||
h6 {
|
||||
font-size: 13px;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
margin: 20px 0 20px 22px;
|
||||
}
|
||||
.logo img {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10px 25px;
|
||||
}
|
||||
|
||||
.gallery-random {
|
||||
float: right;
|
||||
line-height: 180px;
|
||||
}
|
||||
.gallery-random img {
|
||||
max-height: 180px;
|
||||
}
|
||||
|
||||
.coins-sample {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.sidebar-box {
|
||||
padding: 0;
|
||||
}
|
||||
.sidebar-box-heading {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.headerlink {
|
||||
margin-left: 10px;
|
||||
color: #ddd;
|
||||
display: none;
|
||||
}
|
||||
h1:hover .headerlink,
|
||||
h2:hover .headerlink,
|
||||
h3:hover .headerlink,
|
||||
h4:hover .headerlink,
|
||||
h5:hover .headerlink,
|
||||
h6:hover .headerlink {
|
||||
display: inline;
|
||||
}
|
||||
.headerlink:hover {
|
||||
color: #CE5C00;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 30px;
|
||||
padding: 5px 10px;
|
||||
color: #999;
|
||||
}
|
||||
.footer a {
|
||||
color: #999;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ohloh-use, .gplus-use {
|
||||
float: left;
|
||||
margin: 0 0 10px 15px;
|
||||
}
|
||||
|
||||
/* Documentation */
|
||||
|
||||
/* general table settings */
|
||||
table.docutils {
|
||||
margin-bottom: 10px;
|
||||
border-color: #ccc;
|
||||
}
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 5px;
|
||||
border-color: #ccc;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.toc ul ul {
|
||||
font-size: 13px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
/* master content table */
|
||||
.contentstable.docutils, .contentstable.docutils td {
|
||||
border-color: transparent;
|
||||
}
|
||||
.contentstable.docutils .first {
|
||||
font-weight: bold;
|
||||
}
|
||||
.contentstable.docutils .last {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.docutils .label, .docutils .badge {
|
||||
background: transparent;
|
||||
text-shadow: none;
|
||||
font-size: 13px;
|
||||
padding: 5px;
|
||||
line-height: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* module summary table */
|
||||
.longtable.docutils {
|
||||
font-size: 12px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.longtable.docutils, .longtable.docutils td {
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
/* function and class description */
|
||||
dl.class, dl.function, dl.method, dl.attribute {
|
||||
border-top: 1px solid #ccc;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.descclassname {
|
||||
color: #aaa;
|
||||
font-weight: normal;
|
||||
font-family: monospace;
|
||||
}
|
||||
.descname {
|
||||
font-family: monospace;
|
||||
}
|
||||
dl.class em, dl.function em, dl.class big, dl.function big {
|
||||
font-weight: normal;
|
||||
font-family: monospace;
|
||||
}
|
||||
dl.class dd, dl.function dd {
|
||||
padding: 10px;
|
||||
}
|
||||
.docutils.field-list th {
|
||||
background-color: #eee;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
width: 100px;
|
||||
}
|
||||
.docutils.field-list td {
|
||||
padding: 10px 10px 10px 20px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
.docutils.field-list td blockquote p {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
p.rubric {
|
||||
font-weight: bold;
|
||||
font-size: 19px;
|
||||
margin: 15px 0 10px 0;
|
||||
}
|
||||
p.admonition-title {
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* example gallery */
|
||||
|
||||
.gallery {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.figure {
|
||||
float: left;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.figure img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-height: 150px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.figure .caption {
|
||||
width: 200px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,4 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = none
|
||||
pygments_style = default
|
||||
@@ -8,3 +8,4 @@ User Guide
|
||||
user_guide/plugins
|
||||
user_guide/tutorials
|
||||
user_guide/getting_help
|
||||
user_guide/viewer
|
||||
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 90 KiB |
@@ -14,13 +14,13 @@ Data type Range
|
||||
uint8 0 to 255
|
||||
uint16 0 to 65535
|
||||
uint32 0 to 2\ :sup:`32`
|
||||
float 0 to 1
|
||||
float -1 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 0 to 1 even though the data
|
||||
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*.
|
||||
@@ -71,11 +71,6 @@ issued::
|
||||
float64 to uint8
|
||||
array([ 0, 128, 255], dtype=uint8)
|
||||
|
||||
Wherever possible, functions should try to handle input without explicit
|
||||
conversion. For example, there is no need to force values to a specific type
|
||||
for doing a convolution; a plotting function, on the other hand, needs to know
|
||||
the range of the input.
|
||||
|
||||
|
||||
Output types
|
||||
============
|
||||
@@ -142,6 +137,24 @@ By default, ``rescale_intensity`` stretches the values of ``in_range`` to match
|
||||
the range of the dtype.
|
||||
|
||||
|
||||
Note about negative values
|
||||
==========================
|
||||
|
||||
People very often represent images in signed dtypes, even though they only
|
||||
manipulate the positive values of the image (e.g., using only 0-127 in an int8
|
||||
image). For this reason, conversion functions *only spread the positive values*
|
||||
of a signed dtype over the entire range of an unsigned dtype. In other words,
|
||||
negative values are clipped to 0 when converting from signed to unsigned
|
||||
dtypes. (Negative values are preserved when converting between signed dtypes.)
|
||||
To prevent this clipping behavior, you should rescale your image beforehand::
|
||||
|
||||
>>> image = exposure.rescale_intensity(img_int32, out_range=(0, 2**31 - 1))
|
||||
>>> img_uint8 = img_as_ubyte(image)
|
||||
|
||||
This behavior is symmetric: The values in an unsigned dtype are spread over
|
||||
just the positive range of a signed dtype.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
|
||||
@@ -44,13 +44,13 @@ functions include one or more examples.
|
||||
Mailing-list
|
||||
------------
|
||||
|
||||
The scikits-image mailing-list is scikits-image@googlegroups.com (users
|
||||
The scikit-image mailing-list is scikit-image@googlegroups.com (users
|
||||
should join the `Google Group
|
||||
<http://groups.google.com/group/scikits-image>`_ before posting). This
|
||||
<http://groups.google.com/group/scikit-image>`_ before posting). This
|
||||
mailing-list is shared by users and developers, and it is the right
|
||||
place to ask any question about ``skimage``, or in general, image
|
||||
processing using Python. Posting snippets of code with minimal examples
|
||||
ensures to get more relevant and focused answers.
|
||||
ensures to get more relevant and focused answers.
|
||||
|
||||
We would love to hear from how you use ``skimage`` for your work on the
|
||||
mailing-list!
|
||||
mailing-list!
|
||||
|
||||
@@ -47,10 +47,6 @@ detection, we use the `Canny detector
|
||||
|
||||
As the background is very smooth, almost all edges are found at the
|
||||
boundary of the coins, or inside the coins.
|
||||
Now that we have contours that delineate the outer boundary of the coins,
|
||||
we fill the inner part of the coins using the
|
||||
``ndimage.binary_fill_holes`` function, which uses mathematical morphology
|
||||
to fill the holes.
|
||||
|
||||
::
|
||||
|
||||
@@ -61,6 +57,15 @@ to fill the holes.
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
Now that we have contours that delineate the outer boundary of the coins,
|
||||
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
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
Most coins are well segmented out of the background. Small objects from
|
||||
the background can be easily removed using the ``ndimage.label``
|
||||
function to remove objects smaller than a small threshold.
|
||||
@@ -78,6 +83,10 @@ 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
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
Therefore, this segmentation method is not very robust: if we miss a
|
||||
single pixel of the contour of the object, we will not be able to fill
|
||||
it. Of course, we could try to dilate the contours in order to
|
||||
@@ -117,12 +126,29 @@ separate the coins from the background.
|
||||
.. image:: data/elevation_map.jpg
|
||||
:align: center
|
||||
|
||||
and here is the corresponding 2-D plot:
|
||||
|
||||
.. image:: ../../_images/plot_coins_segmentation_6.png
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
The next step is to find markers of the background and the coins based on the
|
||||
extreme parts of the histogram of grey values::
|
||||
|
||||
>>> markers = np.zeros_like(coins)
|
||||
>>> markers[coins < 30] = 1
|
||||
>>> markers[coins > 150] = 2
|
||||
|
||||
.. image:: ../../_images/plot_coins_segmentation_7.png
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
Let us now compute the watershed transform::
|
||||
|
||||
>>> from skimage.morphology import watershed
|
||||
>>> segmentation = watershed(elevation_map, markers)
|
||||
|
||||
.. image:: ../../_images/plot_coins_segmentation_4.png
|
||||
.. image:: ../../_images/plot_coins_segmentation_8.png
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
@@ -139,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_5.png
|
||||
.. image:: ../../_images/plot_coins_segmentation_9.png
|
||||
:target: ../auto_examples/applications/plot_coins_segmentation.html
|
||||
:align: center
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
Image Viewer
|
||||
============
|
||||
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
|
||||
``skimage.viewer`` provides a matplotlib_-based canvas for displaying images and
|
||||
a Qt-based GUI-toolkit, with the goal of making it easy to create interactive
|
||||
image editors. You can simply use it to display an image:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from skimage import data
|
||||
from skimage.viewer import ImageViewer
|
||||
|
||||
image = data.coins()
|
||||
viewer = ImageViewer(image)
|
||||
viewer.show()
|
||||
|
||||
Of course, you could just as easily use ``imshow`` from matplotlib_ (or
|
||||
alternatively, ``skimage.io.imshow`` which adds support for multiple
|
||||
io-plugins) to display images. The advantage of ``ImageViewer`` is that you can
|
||||
easily add plugins for manipulating images. Currently, only a few plugins are
|
||||
implemented, but it is easy to write your own. Before going into the details,
|
||||
let's see an example of how a plugin is added to the viewer:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from skimage.viewer.plugins import Canny
|
||||
|
||||
viewer = ImageViewer(image)
|
||||
viewer += Canny(view)
|
||||
viewer.show()
|
||||
|
||||
At the moment, there aren't very many plugins pre-defined, but there's a really
|
||||
simple interface for creating your own plugin. First, let's create a plugin to
|
||||
call the total-variation denoising function, ``tv_denoise``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from skimage.filter import tv_denoise
|
||||
from skimage.viewer.plugins.base import Plugin
|
||||
|
||||
denoise_plugin = Plugin(image_filter=tv_denoise)
|
||||
|
||||
.. note::
|
||||
|
||||
The ``Plugin`` assumes the first argument given to the image filter is the
|
||||
image from the image viewer. In the future, this should be changed so you
|
||||
can pass the image to a different argument of the filter function.
|
||||
|
||||
To actually interact with the filter, you have to add widgets that adjust the
|
||||
parameters of the function. Typically, that means adding a slider widget and
|
||||
connecting it to the filter parameter and the minimum and maximum values of the
|
||||
slider:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from skimage.viewer.widgets import Slider
|
||||
from skimage.viewer.widgets.history import SaveButtons
|
||||
|
||||
denoise_plugin += Slider('weight', 0.01, 0.5, update_on='release')
|
||||
denoise_plugin += SaveButtons()
|
||||
|
||||
Here, we connect a slider widget to the filter's 'weight' argument. We also
|
||||
added some buttons for saving the image to file or to the ``scikit-image``
|
||||
image stack (see ``skimage.io.push`` and ``skimage.io.pop``).
|
||||
|
||||
All that's left is to create an image viewer and add the plugin to that viewer.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
viewer = ImageViewer(image)
|
||||
viewer += denoise_plugin
|
||||
viewer.show()
|
||||
|
||||
|
||||
.. image:: data/denoise_viewer_window.png
|
||||
.. image:: data/denoise_plugin_window.png
|
||||
|
||||
|
||||
.. _matplotlib: http://matplotlib.sourceforge.net/
|
||||
|
||||
@@ -269,10 +269,6 @@ class ApiDocWriter(object):
|
||||
|
||||
ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n'
|
||||
|
||||
chap_title = uri_short
|
||||
#ad += (chap_title+'\n'+ self.rst_section_levels[1] * len(chap_title)
|
||||
# + '\n\n')
|
||||
|
||||
# Set the chapter title to read 'module' for all modules except for the
|
||||
# main packages
|
||||
if '.' in uri:
|
||||
@@ -281,21 +277,8 @@ class ApiDocWriter(object):
|
||||
title = ':mod:`' + uri_short + '`'
|
||||
ad += title + '\n' + self.rst_section_levels[1] * len(title)
|
||||
|
||||
if len(classes):
|
||||
ad += '\nInheritance diagram for ``%s``:\n\n' % uri
|
||||
ad += '.. inheritance-diagram:: %s \n' % uri
|
||||
ad += ' :parts: 3\n'
|
||||
|
||||
ad += '\n.. automodule:: ' + uri + '\n'
|
||||
ad += '\n.. currentmodule:: ' + uri + '\n'
|
||||
# multi_class = len(classes) > 1
|
||||
# multi_fx = len(functions) > 1
|
||||
# if multi_class:
|
||||
# ad += '\n' + 'Classes' + '\n' + \
|
||||
# self.rst_section_levels[2] * 7 + '\n'
|
||||
# elif len(classes) and multi_fx:
|
||||
# ad += '\n' + 'Class' + '\n' + \
|
||||
# self.rst_section_levels[2] * 5 + '\n'
|
||||
for c in classes:
|
||||
ad += '\n:class:`' + c + '`\n' \
|
||||
+ self.rst_section_levels[2] * \
|
||||
@@ -305,15 +288,8 @@ class ApiDocWriter(object):
|
||||
ad += ' :members:\n' \
|
||||
' :undoc-members:\n' \
|
||||
' :show-inheritance:\n' \
|
||||
' :inherited-members:\n' \
|
||||
'\n' \
|
||||
' .. automethod:: __init__\n'
|
||||
# if multi_fx:
|
||||
# ad += '\n' + 'Functions' + '\n' + \
|
||||
# self.rst_section_levels[2] * 9 + '\n\n'
|
||||
# elif len(functions) and multi_class:
|
||||
# ad += '\n' + 'Function' + '\n' + \
|
||||
# self.rst_section_levels[2] * 8 + '\n\n'
|
||||
ad += '.. autosummary::\n\n'
|
||||
for f in functions:
|
||||
ad += ' ' + uri + '.' + f + '\n'
|
||||
@@ -405,16 +381,9 @@ class ApiDocWriter(object):
|
||||
modules.append(package_uri)
|
||||
else:
|
||||
dirnames.remove(dirname)
|
||||
# Check filenames for modules
|
||||
for filename in filenames:
|
||||
module_name = filename[:-3]
|
||||
module_uri = '.'.join((root_uri, module_name))
|
||||
if (self._uri2path(module_uri) and
|
||||
self._survives_exclude(module_uri, 'module')):
|
||||
modules.append(module_uri)
|
||||
return sorted(modules)
|
||||
|
||||
def write_modules_api(self, modules,outdir):
|
||||
def write_modules_api(self, modules, outdir):
|
||||
# write the list
|
||||
written_modules = []
|
||||
for m in modules:
|
||||
@@ -451,14 +420,6 @@ class ApiDocWriter(object):
|
||||
os.mkdir(outdir)
|
||||
# compose list of modules
|
||||
modules = self.discover_modules()
|
||||
# group modules so we have one less level
|
||||
module_depth = max([len(item.split('.')) for item in modules])
|
||||
# modifying modules in-place, so make a copy
|
||||
for item in modules[:]:
|
||||
# Do not treat the .py files all as separate modules.
|
||||
# Like this, only the objects exported in __all__ get picked up.
|
||||
if not (len(item.split('.')) < module_depth):
|
||||
modules.remove(item)
|
||||
self.write_modules_api(modules,outdir)
|
||||
|
||||
def write_index(self, outdir, froot='gen', relative_to=None):
|
||||
|
||||
@@ -23,14 +23,17 @@ releases = OrderedDict([
|
||||
#('0.1', u'2009-10-07 13:52:19 +0200'),
|
||||
#('0.2', u'2009-11-12 14:48:45 +0200'),
|
||||
('0.3', u'2011-10-10 03:28:47 -0700'),
|
||||
('0.4', u'2011-12-03 14:31:32 -0800')])
|
||||
('0.4', u'2011-12-03 14:31:32 -0800'),
|
||||
('0.5', u'2012-02-26 21:00:51 -0800'),
|
||||
('0.6', u'2012-06-24 21:37:05 -0700')])
|
||||
|
||||
month_duration = 16
|
||||
|
||||
month_duration = 24
|
||||
|
||||
for r in releases:
|
||||
releases[r] = dateutil.parser.parse(releases[r])
|
||||
|
||||
def fetch_PRs(user='scikits-image', repo='scikits-image', state='open'):
|
||||
def fetch_PRs(user='scikit-image', repo='scikit-image', state='open'):
|
||||
params = {'state': state,
|
||||
'per_page': 100,
|
||||
'page': 1}
|
||||
|
||||
@@ -1,25 +1,32 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
descr = """Image Processing SciKit
|
||||
descr = """Image Processing SciKit
|
||||
|
||||
Image processing algorithms for SciPy, including IO, morphology, filtering,
|
||||
warping, color manipulation, object detection, etc.
|
||||
|
||||
Please refer to the online documentation at
|
||||
http://scikits-image.org/
|
||||
http://scikit-image.org/
|
||||
"""
|
||||
|
||||
DISTNAME = 'scikits-image'
|
||||
DISTNAME = 'scikit-image'
|
||||
DESCRIPTION = 'Image processing routines for SciPy'
|
||||
LONG_DESCRIPTION = descr
|
||||
MAINTAINER = 'Stefan van der Walt'
|
||||
MAINTAINER_EMAIL = 'stefan@sun.ac.za'
|
||||
URL = 'http://scikits-image.org'
|
||||
URL = 'http://scikit-image.org'
|
||||
LICENSE = 'Modified BSD'
|
||||
DOWNLOAD_URL = 'http://github.com/scikits-image/scikits-image'
|
||||
VERSION = '0.6.1'
|
||||
DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image'
|
||||
VERSION = '0.8.0'
|
||||
PYTHON_VERSION = (2, 5)
|
||||
DEPENDENCIES = {
|
||||
'numpy': (1, 6),
|
||||
'Cython': (0, 15),
|
||||
}
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import setuptools
|
||||
from numpy.distutils.core import setup
|
||||
try:
|
||||
@@ -27,6 +34,7 @@ try:
|
||||
except ImportError:
|
||||
from distutils.command.build_py import build_py
|
||||
|
||||
|
||||
def configuration(parent_package='', top_path=None):
|
||||
if os.path.exists('MANIFEST'): os.remove('MANIFEST')
|
||||
|
||||
@@ -44,6 +52,7 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def write_version_py(filename='skimage/version.py'):
|
||||
template = """# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY
|
||||
version='%s'
|
||||
@@ -57,7 +66,46 @@ version='%s'
|
||||
finally:
|
||||
vfile.close()
|
||||
|
||||
|
||||
def get_package_version(package):
|
||||
version = []
|
||||
for version_attr in ('version', 'VERSION', '__version__'):
|
||||
if hasattr(package, version_attr) \
|
||||
and isinstance(getattr(package, version_attr), str):
|
||||
version_info = getattr(package, version_attr, '')
|
||||
for part in re.split('\D+', version_info):
|
||||
try:
|
||||
version.append(int(part))
|
||||
except ValueError:
|
||||
pass
|
||||
return tuple(version)
|
||||
|
||||
|
||||
def check_requirements():
|
||||
if sys.version_info < PYTHON_VERSION:
|
||||
raise SystemExit('You need Python version %d.%d or later.' \
|
||||
% PYTHON_VERSION)
|
||||
|
||||
for package_name, min_version in DEPENDENCIES.items():
|
||||
dep_error = False
|
||||
try:
|
||||
package = __import__(package_name)
|
||||
except ImportError:
|
||||
dep_error = True
|
||||
else:
|
||||
package_version = get_package_version(package)
|
||||
if min_version > package_version:
|
||||
dep_error = True
|
||||
|
||||
if dep_error:
|
||||
raise ImportError('You need `%s` version %d.%d or later.' \
|
||||
% ((package_name, ) + min_version))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
check_requirements()
|
||||
|
||||
write_version_py()
|
||||
|
||||
setup(
|
||||
@@ -71,32 +119,31 @@ if __name__ == "__main__":
|
||||
download_url=DOWNLOAD_URL,
|
||||
version=VERSION,
|
||||
|
||||
classifiers =
|
||||
[ 'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: C',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Topic :: Scientific/Engineering',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: Unix',
|
||||
'Operating System :: MacOS',
|
||||
],
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: C',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Topic :: Scientific/Engineering',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: Unix',
|
||||
'Operating System :: MacOS',
|
||||
],
|
||||
|
||||
configuration=configuration,
|
||||
install_requires=[],
|
||||
packages=setuptools.find_packages(),
|
||||
|
||||
packages=setuptools.find_packages(exclude=['doc']),
|
||||
include_package_data=True,
|
||||
zip_safe=False, # the package can run out of an .egg file
|
||||
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'skivi = skimage.scripts.skivi:main']
|
||||
},
|
||||
'console_scripts': ['skivi = skimage.scripts.skivi:main'],
|
||||
},
|
||||
|
||||
cmdclass={'build_py': build_py},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Image Processing SciKit (Toolbox for SciPy)
|
||||
|
||||
``scikits-image`` (a.k.a. ``skimage``) is a collection of algorithms for image
|
||||
``scikit-image`` (a.k.a. ``skimage``) is a collection of algorithms for image
|
||||
processing and computer vision.
|
||||
|
||||
The main package of ``skimage`` only provides a few utilities for converting
|
||||
@@ -52,6 +52,8 @@ img_as_ubyte
|
||||
"""
|
||||
|
||||
import os.path as _osp
|
||||
import imp as _imp
|
||||
import functools as _functools
|
||||
|
||||
pkg_dir = _osp.abspath(_osp.dirname(__file__))
|
||||
data_dir = _osp.join(pkg_dir, 'data')
|
||||
@@ -61,37 +63,30 @@ try:
|
||||
except ImportError:
|
||||
__version__ = "unbuilt-dev"
|
||||
|
||||
def _setup_test(verbose=False):
|
||||
import gzip
|
||||
import functools
|
||||
|
||||
args = ['', '--exe', '-w', pkg_dir]
|
||||
if verbose:
|
||||
args.extend(['-v', '-s'])
|
||||
try:
|
||||
_imp.find_module('nose')
|
||||
except ImportError:
|
||||
def _test(verbose=False):
|
||||
"""This would invoke the skimage test suite, but nose couldn't be
|
||||
imported so the test suite can not run.
|
||||
"""
|
||||
raise ImportError("Could not load nose. Unit tests not available.")
|
||||
else:
|
||||
def _test(verbose=False):
|
||||
"""Invoke the skimage test suite."""
|
||||
import nose
|
||||
args = ['', pkg_dir, '--exe']
|
||||
if verbose:
|
||||
args.extend(['-v', '-s'])
|
||||
nose.run('skimage', argv=args)
|
||||
|
||||
try:
|
||||
import nose as _nose
|
||||
except ImportError:
|
||||
print("Could not load nose. Unit tests not available.")
|
||||
return None
|
||||
else:
|
||||
f = functools.partial(_nose.run, 'skimage', argv=args)
|
||||
f.__doc__ = 'Invoke the skimage test suite.'
|
||||
return f
|
||||
# do not use `test` as function name as this leads to a recursion problem with
|
||||
# the nose test suite
|
||||
test = _test
|
||||
test_verbose = _functools.partial(test, verbose=True)
|
||||
test_verbose.__doc__ = test.__doc__
|
||||
|
||||
test = _setup_test()
|
||||
if test is None:
|
||||
try:
|
||||
del test
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
test_verbose = _setup_test(verbose=True)
|
||||
if test_verbose is None:
|
||||
try:
|
||||
del test
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
def get_log(name=None):
|
||||
"""Return a console logger.
|
||||
@@ -120,26 +115,28 @@ def get_log(name=None):
|
||||
log = logging.getLogger(name)
|
||||
return log
|
||||
|
||||
|
||||
def _setup_log():
|
||||
"""Configure root logger.
|
||||
|
||||
"""
|
||||
import logging, sys
|
||||
import logging
|
||||
import sys
|
||||
|
||||
log = logging.getLogger()
|
||||
formatter = logging.Formatter(
|
||||
'%(name)s: %(levelname)s: %(message)s'
|
||||
)
|
||||
|
||||
try:
|
||||
handler = logging.StreamHandler(stream=sys.stdout)
|
||||
except TypeError:
|
||||
handler = logging.StreamHandler(strm=sys.stdout)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
'%(name)s: %(levelname)s: %(message)s'
|
||||
)
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
log = get_log()
|
||||
log.addHandler(handler)
|
||||
log.setLevel(logging.WARNING)
|
||||
log.propagate = False
|
||||
|
||||
_setup_log()
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import hashlib
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
|
||||
# WindowsError is not defined on unix systems
|
||||
try:
|
||||
WindowsError
|
||||
except NameError:
|
||||
WindowsError = None
|
||||
|
||||
|
||||
def cython(pyx_files, working_path=''):
|
||||
"""Use Cython to convert the given files to C.
|
||||
@@ -39,17 +45,18 @@ def cython(pyx_files, working_path=''):
|
||||
print(cmd)
|
||||
|
||||
try:
|
||||
status = subprocess.call(['cython', '-o', c_file, pyxfile])
|
||||
subprocess.call(['cython', '-o', c_file, pyxfile])
|
||||
except WindowsError:
|
||||
# On Windows cython.exe may be missing if Cython was installed
|
||||
# via distutils. Run the cython.py script instead.
|
||||
status = subprocess.call(
|
||||
subprocess.call(
|
||||
[sys.executable,
|
||||
os.path.join(os.path.dirname(sys.executable),
|
||||
'Scripts', 'cython.py'),
|
||||
'-o', c_file, pyxfile],
|
||||
shell=True)
|
||||
|
||||
|
||||
def _md5sum(f):
|
||||
m = hashlib.new('md5')
|
||||
while True:
|
||||
@@ -60,6 +67,7 @@ def _md5sum(f):
|
||||
m.update(d)
|
||||
return m.hexdigest()
|
||||
|
||||
|
||||
def _changed(filename):
|
||||
"""Compare the hash of a Cython file to the cached hash value on disk.
|
||||
|
||||
|
||||