Merge branch 'releases' into debian

* releases: (978 commits)
  Update release instructions for building docs
  Change to http git protocol
  Add 0.10 to docs
  Set version 0.10
  Move removal of deprated functionality by one version
  Correctly apply catch_warnings()
  Avoid circular imports
  Mention which parameters to label are optional. Simplify label deprecation.
  Fix broken and circular imports
  Update bento build
  Fix imports and suppress deprecation warnings
  Move implementation of label to measure submodule
  Move label to measure module (with deprecation). Warn that background parameter will default to 0 in v0.12.
  Fix copy/paste error in docstring.
  Change EPD link to Enthought Canopy
  Improve description of subpixel corner localization
  Comment special case when local patch around is constant
  Test invalid input for unwrap_phase
  Fix docstring of skimage.filter.rank.threshold_percentile
  Test 90deg rotation for similarity transform
  ...
This commit is contained in:
Yaroslav Halchenko
2014-06-14 07:39:49 -04:00
282 changed files with 14756 additions and 5351 deletions
+13
View File
@@ -0,0 +1,13 @@
# Configuration for coverage.py
[run]
branch = True
source = skimage
include = */skimage/*
omit =
*/setup.py
[report]
exclude_lines =
def __repr__
if __name__ == .__main__.:
+84 -32
View File
@@ -1,42 +1,94 @@
# vim ft=yaml
# travis-ci.org definition for skimage build
#
# We pretend to be erlang because we 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
# After changing this file, check it on:
# http://lint.travis-ci.org/
language: python
python:
- 2.6
matrix:
include:
- python: 2.7
env:
- PYTHON=python
- PYTHONWARNINGS=all
- PYTHONX=python
- PYVER=2.x
- python: 3.2
env:
- PYTHON=python3
- PYTHONWARNINGS=all
- PYTHONX=python3
- PYVER=3.x
exclude:
- python: 2.6
virtualenv:
system_site_packages: true
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sudo apt-get update
- sudo apt-get install $PYTHON-numpy
- wget https://raw.githubusercontent.com/numpy/numpy/master/numpy/_import_tools.py -O /home/travis/virtualenv/python3.2_with_system_site_packages/lib/python3.2/site-packages/numpy/_import_tools.py
- sudo apt-get install $PYTHON-scipy
- sudo apt-get install $PYTHON-setuptools
- sudo apt-get install $PYTHON-nose
- sudo easy_install$PYSUF pip
- sudo pip-$PYVER install cython
- sudo apt-get install libfreeimage3
- if [[ $PYVER == '2.7' ]]; then sudo apt-get install $PYTHON-matplotlib; fi
- if [[ $PYVER == '3.2' ]]; then sudo pip-$PYVER install git+git://github.com/matplotlib/matplotlib.git@v1.2.x; fi
- sudo pip-$PYVER install flake8
- $PYTHON setup.py build
- sudo $PYTHON setup.py install
- if [[ $PYVER == '2.x' ]]; then
- sudo apt-get install $PYTHON-qt4;
- sudo apt-get install $PYTHON-matplotlib;
- fi
- if [[ $PYVER == '3.x' ]]; then
- sudo apt-get install $PYTHON-pyqt4;
- pip install --use-mirrors matplotlib;
- fi
- pip install pillow
- pip install cython
- pip install flake8
- pip install six
- pip install nose-cov
- pip install coveralls
- python check_bento_build.py
install:
- tools/header.py "Dependency versions"
- tools/build_versions.py
- python setup.py build_ext --inplace
script:
# Check if setup.py's match bento.info
- $PYTHON check_bento_build.py
# Change into an innocuous directory and find tests from installation
- mkdir $HOME/.matplotlib
# Matplotlib settings
- mkdir -p $HOME/.matplotlib
- touch $HOME/.matplotlib/matplotlibrc
- "echo 'backend : Agg' > $HOME/.matplotlib/matplotlibrc"
- "echo 'backend.qt4 : PyQt4' >> $HOME/.matplotlib/matplotlibrc"
- mkdir for_test
- cd for_test
- nosetests-$PYVER --exe -v --cover-package=skimage skimage
# Change back to repository root directory and run all doc examples
- cd ..
- for f in doc/examples/*.py; do $PYTHON "$f"; if [ $? -ne 0 ]; then exit 1; fi done
- for f in doc/examples/applications/*.py; do $PYTHON "$f"; if [ $? -ne 0 ]; then exit 1; fi done
# Run all tests
- if [[ $PYVER == '3.x' ]]; then
- nosetests --exe -v --with-doctest --with-cov --cov skimage --cov-config=.coveragerc skimage
- fi
- if [[ $PYVER == '2.x' ]]; then
- nosetests --exe -v --with-doctest skimage
- fi
# Run all doc examples
- export PYTHONPATH=$(pwd):$PYTHONPATH
- for f in doc/examples/*.py; do $PYTHONX "$f"; if [ $? -ne 0 ]; then exit 1; fi done
- for f in doc/examples/applications/*.py; do $PYTHONX "$f"; if [ $? -ne 0 ]; then exit 1; fi done
# Run pep8 and flake tests
- flake8 --exit-zero --exclude=test_*,six.py skimage doc/examples viewer_examples
after_success:
- if [[ $PYVER == '3.x' ]]; then
- coveralls
- fi
+35 -7
View File
@@ -13,7 +13,7 @@ Here's the long and short of it:
git clone git@github.com:your-username/scikit-image.git
* Add upstream repository::
* Add the upstream repository::
git remote add upstream git@github.com:scikit-image/scikit-image.git
@@ -43,8 +43,8 @@ Here's the long and short of it:
git push origin transform-speedups
* Go to GitHub. The new branch will show up with a Pull Request button -
click it.
* Go to GitHub. The new branch will show up with a green Pull Request
button - click it.
* If you want, post on the `mailing list
<http://groups.google.com/group/scikit-image>`_ to explain your changes or
@@ -54,11 +54,34 @@ For a more detailed discussion, read these :doc:`detailed documents
<gitwash/index>` on how to use Git with ``scikit-image``
(`<http://scikit-image.org/docs/dev/gitwash/index.html>`_).
4. Review process:
* Reviewers (the other developers and interested community members) will
write inline and/or general comments on your Pull Request (PR) to help
you improve its implementation, documentation and style. Every single
developer working on the project has their code reviewed, and we've come
to see it as friendly conversation from which we all learn and the
overall code quality benefits. Therefore, please don't let the review
discourage you from contributing: its only aim is to improve the quality
of project, not to criticize (we are, after all, very grateful for the
time you're donating!).
* To update your pull request, make your changes on your local repository
and commit. As soon as those changes are pushed up (to the same branch as
before) the pull request will update automatically.
* `Travis-CI <http://travis-ci.org/>`__, a continuous integration service,
is triggered after each Pull Request update to build the code, run unit
tests, measure code coverage and check coding style (PEP8) of your
branch. The Travis tests must pass before your PR can be merged. If
Travis fails, you can find out why by clicking on the "failed" icon (red
cross) and inspecting the build and test log.
.. note::
To reviewers: add a short explanation of what a branch did to the merge
message and, if closing a bug, also add "Closes gh-123" where 123 is the
bug number.
To reviewers: if it is not obvious, add a short explanation of what a branch
did to the merge message and, if closing a bug, also add "Closes #123"
where 123 is the issue number.
Divergence between ``upstream master`` and your feature branch
@@ -98,7 +121,7 @@ Guidelines
as NumPy and SciPy.
* For new functionality, always add an example to the
gallery.
* No changes should be committed without review. Ask on the
* No changes are ever committed without review. Ask on the
`mailing list <http://groups.google.com/group/scikit-image>`_ if
you get no response to your pull request.
**Never merge your own pull request.**
@@ -154,6 +177,7 @@ detailing the test coverage::
skimage/filter/__init__ 1 1 100%
...
Activate Travis-CI for your fork (optional)
-------------------------------------------
@@ -174,6 +198,10 @@ It corresponds to steps one and two in
Thus, as soon as you push your code to your fork, it will trigger Travis-CI,
and you will receive an email notification when the process is done.
Every time Travis is triggered, it also calls on `Coveralls
<http://coveralls.io>`_ to inspect the current test overage.
Bugs
----
+27 -3
View File
@@ -144,17 +144,41 @@
Color separation (color deconvolution) for several stainings.
- Jostein Bø Fløystad
Reconstruction circle mode for Radon transform
Simultaneous Algebraic Reconstruction Technique for inverse Radon transform
Tomography: radon/iradon improvements and SART implementation
Phase unwrapping integration
- Matt Terry
Color difference functions
- Eugene Dvoretsky
Yen threshold implementation.
Yen, Ridler-Calvard (ISODATA) threshold implementations.
- Riaan van den Dool
skimage.io plugin: GDAL
- Fedor Morozov
Drawing: Wu's anti-aliased circle
- Michael Hansen
novice submodule
- Munther Gdeisat
Phase unwrapping implementation
- Miguel Arevallilo Herraez
Phase unwrapping implementation
- Hussein Abdul-Rahman
Phase unwrapping implementation
- Gregor Thalhammer
Phase unwrapping integration
- François Orieux
Image deconvolution http://research.orieux.fr
- Vighnesh Birodkar
Blob Detection
- Axel Donath
Blob Detection
+6
View File
@@ -46,6 +46,12 @@ functionality is only available with the following installed:
The ``pyamg`` module is used for the fast `cg_mg` mode of random
walker segmentation.
* `Pillow <https://pypi.python.org/pypi/Pillow>`__
(or <`PIL http://www.pythonware.com/products/pil/>`__)
The ``Pillow`` library (or equivalently ``PIL``) is used for Input/Output.
* `Astropy <http://www.astropy.org>`__ is required to use the FITS io plug-in.
Testing requirements
--------------------
* `Nose <https://nose.readthedocs.org/en/latest/>`__
+1 -1
View File
@@ -3,7 +3,7 @@ include setup*.py
include MANIFEST.in
include *.txt
include Makefile
recursive-include skimage *.pyx *.pxd *.pxi *.py *.c *.h *.ini *.md5 *.rst *.txt
recursive-include skimage *.pyx *.pxd *.pxi *.py *.c *.h *.ini *.md5
recursive-include skimage/data *
include doc/Makefile
+4 -1
View File
@@ -7,7 +7,10 @@ clean:
find . -name "*.so" -o -name "*.pyc" -o -name "*.pyx.md5" | xargs rm -f
test:
nosetests skimage
python -c "import skimage, sys, io; sys.exit(skimage.test_verbose())"
doctest:
python -c "import skimage, sys, io; sys.exit(skimage.doctest_verbose())"
coverage:
nosetests skimage --with-coverage --cover-package=skimage
+3 -3
View File
@@ -13,8 +13,8 @@ How to make a new release of ``skimage``
- Update the docs:
- Edit ``doc/source/_static/docversions.js`` and commit
- Build a clean version of the docs. Run ``make`` in the root dir, then
``rm -rf build; make html`` in the docs.
- Build a clean version of the docs. Run ``python setup.py install`` 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!
@@ -51,7 +51,7 @@ How to make a new release of ``skimage``
- Add previous stable version documentation path to disallowed paths
in `robots.txt`
- Build using ``make gh-pages``.
- Push upstream: ``git push`` in ``gh-pages``.
- Push upstream: ``git push origin master`` in ``gh-pages``.
- Update the development docs for the new version ``0.Xdev`` just like above
+16 -14
View File
@@ -1,15 +1,17 @@
Version 0.10
------------
* Remove deprecated functions in `skimage.filter.rank.*`
* Remove deprecated parameter `epsilon` of `skimage.viewer.LineProfile`
* Remove backwards-compatability of `skimage.measure.regionprops`
* Remove {`ratio`, `sigma`} deprecation warnings of `skimage.segmentation.slic`
* Change default mode of random_walker segmentation to 'cg_mg' > 'cg' > 'bf',
depending on which optional dependencies are available.
* Remove deprecated `out` parameter of `skimage.morphology.binary_*`
* Remove deprecated parameter `depth` in `skimage.segmentation.random_walker`
* Remove deprecated logger function in `skimage/__init__.py`
* Remove deprecated function `filter.median_filter`
* Remove deprecated `skimage.color.is_gray` and `skimage.color.is_rgb`
functions
Remember to list any API changes below in `doc/source/api_changes.txt`.
Version 0.12
------------
* Change `label` to mark background as 0, not -1, which is consistent with
SciPy's labelling.
* Remove `skimage.morphology.label` from `skimage.morphology.__init__`--it now
lives in `skimage.measure.label`.
* Remove deprecated `reverse_map` parameter of `skimage.transform.warp`
* Change depecrated `enforce_connectivity=False` on skimage.segmentation.slic
and set it to True as default
* Remove deprecated `skimage.measure.fit.BaseModel._params` attribute
* Remove deprecated `skimage.measure.fit.BaseModel._params`,
`skimage.transform.ProjectiveTransform._matrix`,
`skimage.transform.PolynomialTransform._params`,
`skimage.transform.PiecewiseAffineTransform.affines_*` attributes
* Remove deprecated functions `skimage.filter.denoise_*`
+27 -17
View File
@@ -1,5 +1,5 @@
Name: scikit-image
Version: 0.9.3
Version: 0.10.0
Summary: Image processing routines for SciPy
Url: http://scikit-image.org
DownloadUrl: http://github.com/scikit-image/scikit-image
@@ -35,19 +35,17 @@ Library:
skimage, skimage.color, skimage.data, skimage.draw, skimage.exposure,
skimage.feature, skimage.filter, skimage.graph, skimage.io,
skimage.io._plugins, skimage.measure, skimage.morphology,
skimage.scripts, skimage.segmentation, skimage.transform, skimage.util
skimage.scripts, skimage.restoration, skimage.segmentation,
skimage.transform, skimage.util
Extension: skimage.morphology._pnpoly
Sources:
skimage/morphology/_pnpoly.pyx
Extension: skimage.feature._template
Sources:
skimage/feature/_template.pyx
Extension: skimage.io._plugins._colormixer
Sources:
skimage/io/_plugins/_colormixer.pyx
Extension: skimage.measure._find_contours
Extension: skimage.measure._find_contours_cy
Sources:
skimage/measure/_find_contours.pyx
skimage/measure/_find_contours_cy.pyx
Extension: skimage.measure._moments
Sources:
skimage/measure/_moments.pyx
@@ -66,12 +64,9 @@ Library:
Extension: skimage.filter._ctmf
Sources:
skimage/filter/_ctmf.pyx
Extension: skimage.filter._denoise_cy
Extension: skimage.measure._ccomp
Sources:
skimage/filter/_denoise_cy.pyx
Extension: skimage.morphology.ccomp
Sources:
skimage/morphology/ccomp.pyx
skimage/measure/_ccomp.pyx
Extension: skimage.morphology._watershed
Sources:
skimage/morphology/_watershed.pyx
@@ -96,9 +91,12 @@ Library:
Extension: skimage.feature.censure_cy
Sources:
skimage/feature/censure_cy.pyx
Extension: skimage.feature._brief_cy
Extension: skimage.feature.orb_cy
Sources:
skimage/feature/_brief_cy.pyx
skimage/feature/orb_cy.pyx
Extension: skimage.feature.brief_cy
Sources:
skimage/feature/brief_cy.pyx
Extension: skimage.feature.corner_cy
Sources:
skimage/feature/corner_cy.pyx
@@ -123,9 +121,6 @@ Library:
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
@@ -144,6 +139,21 @@ Library:
Extension: skimage.filter.rank.bilateral_cy
Sources:
skimage/filter/rank/bilateral_cy.pyx
Extension: skimage.restoration._unwrap_1d
Sources:
skimage/restoration/_unwrap_1d.pyx
Extension: skimage.restoration._unwrap_2d
Sources:
skimage/restoration/_unwrap_2d.pyx skimage/exposure/unwrap_2d_ljmu.c
Extension: skimage.restoration._unwrap_3d
Sources:
skimage/restoration/_unwrap_3d.pyx skimage/exposure/unwrap_3d_ljmu.c
Extension: skimage.restoration._denoise_cy
Sources:
skimage/restoration/_denoise_cy.pyx
Extension: skimage.feature._hessian_det_appx
Sources:
skimage/exposure/_hessian_det_appx.pyx
Executable: skivi
Module: skimage.scripts.skivi
@@ -16,13 +16,11 @@ from skimage import data
coins = data.coins()
hist = np.histogram(coins, bins=np.arange(0, 256))
plt.figure(figsize=(8, 3))
plt.subplot(121)
plt.imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
plt.axis('off')
plt.subplot(122)
plt.plot(hist[1][:-1], hist[0], lw=2)
plt.title('histogram of grey values')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3))
ax1.imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
ax1.axis('off')
ax2.plot(hist[1][:-1], hist[0], lw=2)
ax2.set_title('histogram of grey values')
"""
.. image:: PLOT2RST.current_figure
@@ -37,17 +35,15 @@ background with the coins:
"""
plt.figure(figsize=(6, 3))
plt.subplot(121)
plt.imshow(coins > 100, cmap=plt.cm.gray, interpolation='nearest')
plt.title('coins > 100')
plt.axis('off')
plt.subplot(122)
plt.imshow(coins > 150, cmap=plt.cm.gray, interpolation='nearest')
plt.title('coins > 150')
plt.axis('off')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 3))
ax1.imshow(coins > 100, cmap=plt.cm.gray, interpolation='nearest')
ax1.set_title('coins > 100')
ax1.axis('off')
ax2.imshow(coins > 150, cmap=plt.cm.gray, interpolation='nearest')
ax2.set_title('coins > 150')
ax2.axis('off')
margins = dict(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
plt.subplots_adjust(**margins)
fig.subplots_adjust(**margins)
"""
.. image:: PLOT2RST.current_figure
@@ -64,10 +60,10 @@ edge-detector.
from skimage.filter import canny
edges = canny(coins/255.)
plt.figure(figsize=(4, 3))
plt.imshow(edges, cmap=plt.cm.gray, interpolation='nearest')
plt.axis('off')
plt.title('Canny detector')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(edges, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Canny detector')
"""
.. image:: PLOT2RST.current_figure
@@ -79,10 +75,10 @@ from scipy import ndimage
fill_coins = ndimage.binary_fill_holes(edges)
plt.figure(figsize=(4, 3))
plt.imshow(fill_coins, cmap=plt.cm.gray, interpolation='nearest')
plt.axis('off')
plt.title('Filling the holes')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(fill_coins, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Filling the holes')
"""
.. image:: PLOT2RST.current_figure
@@ -93,10 +89,10 @@ 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')
plt.axis('off')
plt.title('Removing small objects')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(coins_cleaned, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Removing small objects')
"""
.. image:: PLOT2RST.current_figure
@@ -117,10 +113,10 @@ from skimage.filter import sobel
elevation_map = sobel(coins)
plt.figure(figsize=(4, 3))
plt.imshow(elevation_map, cmap=plt.cm.jet, interpolation='nearest')
plt.axis('off')
plt.title('elevation_map')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(elevation_map, cmap=plt.cm.jet, interpolation='nearest')
ax.axis('off')
ax.set_title('elevation_map')
"""
.. image:: PLOT2RST.current_figure
@@ -133,10 +129,10 @@ markers = np.zeros_like(coins)
markers[coins < 30] = 1
markers[coins > 150] = 2
plt.figure(figsize=(4, 3))
plt.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest')
plt.axis('off')
plt.title('markers')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest')
ax.axis('off')
ax.set_title('markers')
"""
.. image:: PLOT2RST.current_figure
@@ -147,10 +143,10 @@ starting from the markers determined above:
"""
segmentation = morphology.watershed(elevation_map, markers)
plt.figure(figsize=(4, 3))
plt.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
plt.axis('off')
plt.title('segmentation')
fig, ax = plt.subplots(figsize=(4, 3))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
"""
.. image:: PLOT2RST.current_figure
@@ -166,16 +162,14 @@ segmentation = ndimage.binary_fill_holes(segmentation - 1)
labeled_coins, _ = ndimage.label(segmentation)
image_label_overlay = label2rgb(labeled_coins, image=coins)
plt.figure(figsize=(6, 3))
plt.subplot(121)
plt.imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
plt.contour(segmentation, [0.5], linewidths=1.2, colors='y')
plt.axis('off')
plt.subplot(122)
plt.imshow(image_label_overlay, interpolation='nearest')
plt.axis('off')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 3))
ax1.imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
ax1.contour(segmentation, [0.5], linewidths=1.2, colors='y')
ax1.axis('off')
ax2.imshow(image_label_overlay, interpolation='nearest')
ax2.axis('off')
plt.subplots_adjust(**margins)
fig.subplots_adjust(**margins)
"""
.. image:: PLOT2RST.current_figure
+2 -2
View File
@@ -33,14 +33,14 @@ First we create a transformation using explicit parameters:
tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 2,
translation=(0, 1))
print(tform._matrix)
print(tform.params)
"""
Alternatively you can define a transformation by the transformation matrix
itself:
"""
matrix = tform._matrix.copy()
matrix = tform.params.copy()
matrix[1, 2] = 2
tform2 = tf.SimilarityTransform(matrix)
+4 -4
View File
@@ -30,9 +30,9 @@ from skimage.data import data_dir
from skimage.util import img_as_ubyte
from skimage import io
plt.gray()
phantom = img_as_ubyte(io.imread(data_dir+'/phantom.png', as_grey=True))
plt.imshow(phantom)
fig, ax = plt.subplots()
ax.imshow(phantom, cmap=plt.cm.gray)
"""
.. image:: PLOT2RST.current_figure
@@ -43,10 +43,10 @@ Let's also define a convenience function for plotting comparisons:
def plot_comparison(original, filtered, filter_name):
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4))
ax1.imshow(original)
ax1.imshow(original, cmap=plt.cm.gray)
ax1.set_title('original')
ax1.axis('off')
ax2.imshow(filtered)
ax2.imshow(filtered, cmap=plt.cm.gray)
ax2.set_title(filter_name)
ax2.axis('off')
+161 -212
View File
@@ -44,13 +44,11 @@ from skimage import data
noisy_image = img_as_ubyte(data.camera())
hist = np.histogram(noisy_image, bins=np.arange(0, 256))
plt.figure(figsize=(8, 3))
plt.subplot(1, 2, 1)
plt.imshow(noisy_image, 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')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3))
ax1.imshow(noisy_image, interpolation='nearest', cmap=plt.cm.gray)
ax1.axis('off')
ax2.plot(hist[1][:-1], hist[0], lw=2)
ax2.set_title('Histogram of grey values')
"""
@@ -62,11 +60,6 @@ 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`
"""
from skimage.filter.rank import median
@@ -77,27 +70,24 @@ noisy_image = img_as_ubyte(data.camera())
noisy_image[noise > 0.99] = 255
noisy_image[noise < 0.01] = 0
fig = plt.figure(figsize=(10, 7))
fig, ax = plt.subplots(2, 2, figsize=(10, 7))
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 1)
plt.imshow(noisy_image, vmin=0, vmax=255)
plt.title('Noisy image')
plt.axis('off')
ax1.imshow(noisy_image, vmin=0, vmax=255, cmap=plt.cm.gray)
ax1.set_title('Noisy image')
ax1.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(median(noisy_image, disk(1)), vmin=0, vmax=255)
plt.title('Median $r=1$')
plt.axis('off')
ax2.imshow(median(noisy_image, disk(1)), vmin=0, vmax=255, cmap=plt.cm.gray)
ax2.set_title('Median $r=1$')
ax2.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(median(noisy_image, disk(5)), vmin=0, vmax=255)
plt.title('Median $r=5$')
plt.axis('off')
ax3.imshow(median(noisy_image, disk(5)), vmin=0, vmax=255, cmap=plt.cm.gray)
ax3.set_title('Median $r=5$')
ax3.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(median(noisy_image, disk(20)), vmin=0, vmax=255)
plt.title('Median $r=20$')
plt.axis('off')
ax4.imshow(median(noisy_image, disk(20)), vmin=0, vmax=255, cmap=plt.cm.gray)
ax4.set_title('Median $r=20$')
ax4.axis('off')
"""
@@ -119,19 +109,17 @@ image.
from skimage.filter.rank import mean
fig = plt.figure(figsize=[10, 7])
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[10, 7])
loc_mean = mean(noisy_image, disk(10))
plt.subplot(1, 2, 1)
plt.imshow(noisy_image, vmin=0, vmax=255)
plt.title('Original')
plt.axis('off')
ax1.imshow(noisy_image, vmin=0, vmax=255, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(loc_mean, vmin=0, vmax=255)
plt.title('Local mean $r=10$')
plt.axis('off')
ax2.imshow(loc_mean, vmin=0, vmax=255, cmap=plt.cm.gray)
ax2.set_title('Local mean $r=10$')
ax2.axis('off')
"""
@@ -149,31 +137,28 @@ the central one.
"""
from skimage.filter.rank import bilateral_mean
from skimage.filter.rank import mean_bilateral
noisy_image = img_as_ubyte(data.camera())
bilat = bilateral_mean(noisy_image.astype(np.uint16), disk(20), s0=10, s1=10)
bilat = mean_bilateral(noisy_image.astype(np.uint16), disk(20), s0=10, s1=10)
fig = plt.figure(figsize=[10, 7])
fig, ax = plt.subplots(2, 2, figsize=(10, 7))
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 1)
plt.imshow(noisy_image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
ax1.imshow(noisy_image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(bilat, cmap=plt.cm.gray)
plt.title('Bilateral mean')
plt.axis('off')
ax2.imshow(bilat, cmap=plt.cm.gray)
ax2.set_title('Bilateral mean')
ax2.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax3.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
ax3.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(bilat[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax4.imshow(bilat[200:350, 350:450], cmap=plt.cm.gray)
ax4.axis('off')
"""
@@ -203,7 +188,7 @@ from skimage.filter import rank
noisy_image = img_as_ubyte(data.camera())
# equalize globally and locally
glob = exposure.equalize(noisy_image) * 255
glob = exposure.equalize_hist(noisy_image) * 255
loc = rank.equalize(noisy_image, disk(20))
# extract histogram for each image
@@ -211,31 +196,26 @@ hist = np.histogram(noisy_image, 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))
fig, ax = plt.subplots(3, 2, figsize=(10, 10))
ax1, ax2, ax3, ax4, ax5, ax6 = ax.ravel()
plt.subplot(321)
plt.imshow(noisy_image, interpolation='nearest')
plt.axis('off')
ax1.imshow(noisy_image, interpolation='nearest', cmap=plt.cm.gray)
ax1.axis('off')
plt.subplot(322)
plt.plot(hist[1][:-1], hist[0], lw=2)
plt.title('Histogram of gray values')
ax2.plot(hist[1][:-1], hist[0], lw=2)
ax2.set_title('Histogram of gray values')
plt.subplot(323)
plt.imshow(glob, interpolation='nearest')
plt.axis('off')
ax3.imshow(glob, interpolation='nearest', cmap=plt.cm.gray)
ax3.axis('off')
plt.subplot(324)
plt.plot(glob_hist[1][:-1], glob_hist[0], lw=2)
plt.title('Histogram of gray values')
ax4.plot(glob_hist[1][:-1], glob_hist[0], lw=2)
ax4.set_title('Histogram of gray values')
plt.subplot(325)
plt.imshow(loc, interpolation='nearest')
plt.axis('off')
ax5.imshow(loc, interpolation='nearest', cmap=plt.cm.gray)
ax5.axis('off')
plt.subplot(326)
plt.plot(loc_hist[1][:-1], loc_hist[0], lw=2)
plt.title('Histogram of gray values')
ax6.plot(loc_hist[1][:-1], loc_hist[0], lw=2)
ax6.set_title('Histogram of gray values')
"""
@@ -256,17 +236,15 @@ noisy_image = img_as_ubyte(data.camera())
auto = autolevel(noisy_image.astype(np.uint16), disk(20))
fig = plt.figure(figsize=[10, 7])
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[10, 7])
plt.subplot(1, 2, 1)
plt.imshow(noisy_image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
ax1.imshow(noisy_image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(auto, cmap=plt.cm.gray)
plt.title('Local autolevel')
plt.axis('off')
ax2.imshow(auto, cmap=plt.cm.gray)
ax2.set_title('Local autolevel')
ax2.axis('off')
"""
@@ -297,7 +275,7 @@ fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
ax0, ax1, ax2 = axes
plt.gray()
ax0.imshow(np.hstack((image, loc_autolevel)))
ax0.imshow(np.hstack((image, loc_autolevel)), cmap=plt.cm.gray)
ax0.set_title('Original / auto-level')
ax1.imshow(
@@ -326,24 +304,22 @@ noisy_image = img_as_ubyte(data.camera())
enh = enhance_contrast(noisy_image, disk(5))
fig = plt.figure(figsize=[10, 7])
plt.subplot(2, 2, 1)
plt.imshow(noisy_image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
fig, ax = plt.subplots(2, 2, figsize=[10, 7])
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 3)
plt.imshow(enh, cmap=plt.cm.gray)
plt.title('Local morphological contrast enhancement')
plt.axis('off')
ax1.imshow(noisy_image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax2.imshow(enh, cmap=plt.cm.gray)
ax2.set_title('Local morphological contrast enhancement')
ax2.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(enh[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax3.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
ax3.axis('off')
ax4.imshow(enh[200:350, 350:450], cmap=plt.cm.gray)
ax4.axis('off')
"""
@@ -360,24 +336,22 @@ noisy_image = img_as_ubyte(data.camera())
penh = enhance_contrast_percentile(noisy_image, disk(5), p0=.1, p1=.9)
fig = plt.figure(figsize=[10, 7])
plt.subplot(2, 2, 1)
plt.imshow(noisy_image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
fig, ax = plt.subplots(2, 2, figsize=[10, 7])
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 3)
plt.imshow(penh, cmap=plt.cm.gray)
plt.title('Local percentile morphological\n contrast enhancement')
plt.axis('off')
ax1.imshow(noisy_image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax2.imshow(penh, cmap=plt.cm.gray)
ax2.set_title('Local percentile morphological\n contrast enhancement')
ax2.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(penh[200:350, 350:450], cmap=plt.cm.gray)
plt.axis('off')
ax3.imshow(noisy_image[200:350, 350:450], cmap=plt.cm.gray)
ax3.axis('off')
ax4.imshow(penh[200:350, 350:450], cmap=plt.cm.gray)
ax4.axis('off')
"""
@@ -419,29 +393,24 @@ loc_otsu = p8 >= t_loc_otsu
t_glob_otsu = threshold_otsu(p8)
glob_otsu = p8 >= t_glob_otsu
plt.figure()
fig, ax = plt.subplots(2, 2)
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 1)
plt.imshow(p8, cmap=plt.cm.gray)
plt.title('Original')
plt.colorbar()
plt.axis('off')
fig.colorbar(ax1.imshow(p8, cmap=plt.cm.gray), ax=ax1)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(t_loc_otsu, cmap=plt.cm.gray)
plt.title('Local Otsu ($r=%d$)' % radius)
plt.colorbar()
plt.axis('off')
fig.colorbar(ax2.imshow(t_loc_otsu, cmap=plt.cm.gray), ax=ax2)
ax2.set_title('Local Otsu ($r=%d$)' % radius)
ax2.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(p8 >= t_loc_otsu, cmap=plt.cm.gray)
plt.title('Original >= local Otsu' % t_glob_otsu)
plt.axis('off')
ax3.imshow(p8 >= t_loc_otsu, cmap=plt.cm.gray)
ax3.set_title('Original >= local Otsu' % t_glob_otsu)
ax3.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(glob_otsu, cmap=plt.cm.gray)
plt.title('Global Otsu ($t=%d$)' % t_glob_otsu)
plt.axis('off')
ax4.imshow(glob_otsu, cmap=plt.cm.gray)
ax4.set_title('Global Otsu ($t=%d$)' % t_glob_otsu)
ax4.axis('off')
"""
@@ -460,17 +429,15 @@ 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()
fig, (ax1, ax2) = plt.subplots(1, 2)
plt.subplot(1, 2, 1)
plt.imshow(m)
plt.title('Original')
plt.axis('off')
ax1.imshow(m)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(m >= t, interpolation='nearest')
plt.title('Local Otsu ($r=%d$)' % radius)
plt.axis('off')
ax2.imshow(m >= t, interpolation='nearest')
ax2.set_title('Local Otsu ($r=%d$)' % radius)
ax2.axis('off')
"""
@@ -501,27 +468,24 @@ opening = minimum(maximum(noisy_image, disk(5)), disk(5))
grad = gradient(noisy_image, disk(5))
# display results
fig = plt.figure(figsize=[10, 7])
fig, ax = plt.subplots(2, 2, figsize=[10, 7])
ax1, ax2, ax3, ax4 = ax.ravel()
plt.subplot(2, 2, 1)
plt.imshow(noisy_image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
ax1.imshow(noisy_image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(closing, cmap=plt.cm.gray)
plt.title('Gray-level closing')
plt.axis('off')
ax2.imshow(closing, cmap=plt.cm.gray)
ax2.set_title('Gray-level closing')
ax2.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(opening, cmap=plt.cm.gray)
plt.title('Gray-level opening')
plt.axis('off')
ax3.imshow(opening, cmap=plt.cm.gray)
ax3.set_title('Gray-level opening')
ax3.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(grad, cmap=plt.cm.gray)
plt.title('Morphological gradient')
plt.axis('off')
ax4.imshow(grad, cmap=plt.cm.gray)
ax4.set_title('Morphological gradient')
ax4.axis('off')
"""
@@ -554,19 +518,15 @@ import matplotlib.pyplot as plt
image = data.camera()
plt.figure(figsize=(10, 4))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Image')
plt.colorbar()
plt.axis('off')
fig.colorbar(ax1.imshow(image, cmap=plt.cm.gray), ax=ax1)
ax1.set_title('Image')
ax1.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(entropy(image, disk(5)), cmap=plt.cm.jet)
plt.title('Entropy')
plt.colorbar()
plt.axis('off')
fig.colorbar(ax2.imshow(entropy(image, disk(5)), cmap=plt.cm.jet), ax=ax2)
ax2.set_title('Entropy')
ax2.axis('off')
"""
@@ -589,7 +549,6 @@ 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
@@ -619,11 +578,6 @@ 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)
@@ -651,12 +605,12 @@ for r in e_range:
rec = np.asarray(rec)
plt.figure()
plt.title('Performance with respect to element size')
plt.ylabel('Time (ms)')
plt.title('Element radius')
plt.plot(e_range, rec)
plt.legend(['filter.rank.maximum', 'morphology.dilate'])
fig, ax = plt.subplots()
ax.set_title('Performance with respect to element size')
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Element radius')
ax.plot(e_range, rec)
ax.legend(['filter.rank.maximum', 'morphology.dilate'])
"""
@@ -679,12 +633,12 @@ for s in s_range:
rec = np.asarray(rec)
plt.figure()
plt.title('Performance with respect to image size')
plt.ylabel('Time (ms)')
plt.title('Image size')
plt.plot(s_range, rec)
plt.legend(['filter.rank.maximum', 'morphology.dilate'])
fig, ax = plt.subplots()
ax.set_title('Performance with respect to image size')
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Image size')
ax.plot(s_range, rec)
ax.legend(['filter.rank.maximum', 'morphology.dilate'])
"""
@@ -694,7 +648,6 @@ plt.legend(['filter.rank.maximum', 'morphology.dilate'])
Comparison between:
* `filter.rank.median`
* `filter.median_filter`
* `scipy.ndimage.percentile`
on increasing structuring element size:
@@ -708,19 +661,17 @@ 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.append((ms_rc, ms_ndi))
rec = np.asarray(rec)
plt.figure()
plt.title('Performance with respect to element size')
plt.plot(e_range, rec)
plt.legend(['filter.rank.median', 'filter.median_filter',
'scipy.ndimage.percentile'])
plt.ylabel('Time (ms)')
plt.title('Element radius')
fig, ax = plt.subplots()
ax.set_title('Performance with respect to element size')
ax.plot(e_range, rec)
ax.legend(['filter.rank.median', 'scipy.ndimage.percentile'])
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Element radius')
"""
.. image:: PLOT2RST.current_figure
@@ -729,10 +680,10 @@ Comparison of outcome of the three methods:
"""
plt.figure()
plt.imshow(np.hstack((rc, rctmf, rndi)))
plt.title('filter.rank.median vs filtermedian_filter vs scipy.ndimage.percentile')
plt.axis('off')
fig, ax = plt.subplots()
ax.imshow(np.hstack((rc, rndi)))
ax.set_title('filter.rank.median vs. scipy.ndimage.percentile')
ax.axis('off')
"""
.. image:: PLOT2RST.current_figure
@@ -749,19 +700,17 @@ s_range = [100, 200, 500, 1000]
for s in s_range:
a = (np.random.random((s, s)) * 256).astype(np.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.append((ms_rc, ms_ndi))
rec = np.asarray(rec)
plt.figure()
plt.title('Performance with respect to image size')
plt.plot(s_range, rec)
plt.legend(['filter.rank.median', 'filter.median_filter',
'scipy.ndimage.percentile'])
plt.ylabel('Time (ms)')
plt.title('Image size')
fig, ax = plt.subplots()
ax.set_title('Performance with respect to image size')
ax.plot(s_range, rec)
ax.legend(['filter.rank.median', 'scipy.ndimage.percentile'])
ax.set_ylabel('Time (ms)')
ax.set_xlabel('Image size')
"""
.. image:: PLOT2RST.current_figure
+73
View File
@@ -0,0 +1,73 @@
"""
==============
Blob Detection
==============
Blobs are bright on dark or dark on bright regions in an image. In
this example, blobs are detected using 3 algorithms. The image used
in this case is the Hubble eXtreme Deep Field. Each bright dot in the
image is a star or a galaxy.
Laplacian of Gaussian (LoG)
-----------------------------
This is the most accurate and slowest approach. It computes the Laplacian
of Gaussian images with successively increasing standard deviation and
stacks them up in a cube. Blobs are local maximas in this cube. Detecting
larger blobs is especially slower because of larger kernel sizes during
convolution. Only bright blobs on dark backgrounds are detected. See
:py:meth:`skimage.feature.blob_log` for usage.
Difference of Gaussian (DoG)
----------------------------
This is a faster approximation of LoG approach. In this case the image is
blurred with increasing standard deviations and the difference between
two successively blurred images are stacked up in a cube. This method
suffers from the same disadvantage as LoG approach for detecting larger
blobs. Blobs are again assumed to be bright on dark. See
:py:meth:`skimage.feature.blob_dog` for usage.
Determinant of Hessian (DoH)
----------------------------
This is the fastest approach. It detects blobs by finding maximas in the
matrix of the Determinant of Hessian of the image. The detection speed is
independent of the size of blobs as internally the implementation uses
box filters instead of convolutions. Bright on dark as well as dark on
bright blobs are detected. The downside is that small blobs (<3px) are not
detected accurately. See :py:meth:`skimage.feature.blob_doh` for usage.
"""
from matplotlib import pyplot as plt
from skimage import data
from skimage.feature import blob_dog, blob_log, blob_doh
from math import sqrt
from skimage.color import rgb2gray
image = data.hubble_deep_field()[0:500, 0:500]
image_gray = rgb2gray(image)
blobs_log = blob_log(image_gray, max_sigma=30, num_sigma=10, threshold=.1)
# Compute radii in the 3rd column.
blobs_log[:, 2] = blobs_log[:, 2] * sqrt(2)
blobs_dog = blob_dog(image_gray, max_sigma=30, threshold=.1)
blobs_dog[:, 2] = blobs_dog[:, 2] * sqrt(2)
blobs_doh = blob_doh(image_gray, max_sigma=30, threshold=.01)
blobs_list = [blobs_log, blobs_dog, blobs_doh]
colors = ['yellow', 'lime', 'red']
titles = ['Laplacian of Gaussian', 'Difference of Gaussian',
'Determinant of Hessian']
sequence = zip(blobs_list, colors, titles)
for blobs, color, title in sequence:
fig, ax = plt.subplots(1, 1)
ax.set_title(title)
ax.imshow(image, interpolation='nearest')
for blob in blobs:
y, x, r = blob
c = plt.Circle((x, y), r, color=color, linewidth=2, fill=False)
ax.add_patch(c)
plt.show()
+61
View File
@@ -0,0 +1,61 @@
"""
=======================
BRIEF binary descriptor
=======================
This example demonstrates the BRIEF binary description algorithm.
The descriptor consists of relatively few bits and can be computed using
a set of intensity difference tests. The short binary descriptor results
in low memory footprint and very efficient matching based on the Hamming
distance metric.
BRIEF does not provide rotation-invariance. Scale-invariance can be achieved by
detecting and extracting features at different scales.
"""
from skimage import data
from skimage import transform as tf
from skimage.feature import (match_descriptors, corner_peaks, corner_harris,
plot_matches, BRIEF)
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
tform = tf.AffineTransform(scale=(1.2, 1.2), translation=(0, -100))
img2 = tf.warp(img1, tform)
img3 = tf.rotate(img1, 25)
keypoints1 = corner_peaks(corner_harris(img1), min_distance=5)
keypoints2 = corner_peaks(corner_harris(img2), min_distance=5)
keypoints3 = corner_peaks(corner_harris(img3), min_distance=5)
extractor = BRIEF()
extractor.extract(img1, keypoints1)
keypoints1 = keypoints1[extractor.mask]
descriptors1 = extractor.descriptors
extractor.extract(img2, keypoints2)
keypoints2 = keypoints2[extractor.mask]
descriptors2 = extractor.descriptors
extractor.extract(img3, keypoints3)
keypoints3 = keypoints3[extractor.mask]
descriptors3 = extractor.descriptors
matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True)
matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True)
fig, ax = plt.subplots(nrows=2, ncols=1)
plt.gray()
plot_matches(ax[0], img1, img2, keypoints1, keypoints2, matches12)
ax[0].axis('off')
plot_matches(ax[1], img1, img3, keypoints1, keypoints3, matches13)
ax[1].axis('off')
plt.show()
+11 -14
View File
@@ -35,24 +35,21 @@ edges1 = filter.canny(im)
edges2 = filter.canny(im, sigma=3)
# display results
plt.figure(figsize=(8, 3))
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3))
plt.subplot(131)
plt.imshow(im, cmap=plt.cm.jet)
plt.axis('off')
plt.title('noisy image', fontsize=20)
ax1.imshow(im, cmap=plt.cm.jet)
ax1.axis('off')
ax1.set_title('noisy image', fontsize=20)
plt.subplot(132)
plt.imshow(edges1, cmap=plt.cm.gray)
plt.axis('off')
plt.title('Canny filter, $\sigma=1$', fontsize=20)
ax2.imshow(edges1, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('Canny filter, $\sigma=1$', fontsize=20)
plt.subplot(133)
plt.imshow(edges2, cmap=plt.cm.gray)
plt.axis('off')
plt.title('Canny filter, $\sigma=3$', fontsize=20)
ax3.imshow(edges2, cmap=plt.cm.gray)
ax3.axis('off')
ax3.set_title('Canny filter, $\sigma=3$', fontsize=20)
plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
bottom=0.02, left=0.02, right=0.98)
plt.show()
+43
View File
@@ -0,0 +1,43 @@
"""
========================
CENSURE feature detector
========================
The CENSURE feature detector is a scale-invariant center-surround detector
(CENSURE) that claims to outperform other detectors and is capable of real-time
implementation.
"""
from skimage import data
from skimage import transform as tf
from skimage.feature import CENSURE
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
tform = tf.AffineTransform(scale=(1.5, 1.5), rotation=0.5,
translation=(150, -200))
img2 = tf.warp(img1, tform)
detector = CENSURE()
fig, ax = plt.subplots(nrows=1, ncols=2)
plt.gray()
detector.detect(img1)
ax[0].imshow(img1)
ax[0].axis('off')
ax[0].scatter(detector.keypoints[:, 1], detector.keypoints[:, 0],
2 ** detector.scales, facecolors='none', edgecolors='r')
detector.detect(img2)
ax[1].imshow(img2)
ax[1].axis('off')
ax[1].scatter(detector.keypoints[:, 1], detector.keypoints[:, 0],
2 ** detector.scales, facecolors='none', edgecolors='r')
plt.show()
@@ -48,7 +48,7 @@ from skimage.util import img_as_ubyte
image = img_as_ubyte(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))
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(5, 2))
# Detect two radii
hough_radii = np.arange(15, 30, 2)
@@ -77,6 +77,8 @@ ax.imshow(image, cmap=plt.cm.gray)
"""
.. image:: PLOT2RST.current_figure
Ellipse detection
=================
@@ -137,7 +139,7 @@ image_rgb[cy, cx] = (0, 0, 255)
edges = color.gray2rgb(edges)
edges[cy, cx] = (250, 0, 0)
fig2, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(10, 6))
fig2, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(8, 4))
ax1.set_title('Original picture')
ax1.imshow(image_rgb)
@@ -146,3 +148,8 @@ ax2.set_title('Edge (white) and result (red)')
ax2.imshow(edges)
plt.show()
"""
.. image:: PLOT2RST.current_figure
"""
+6 -5
View File
@@ -29,12 +29,13 @@ r = np.sin(np.exp((np.sin(x)**3 + np.cos(y)**2)))
contours = measure.find_contours(r, 0.8)
# Display the image and plot all contours found
plt.imshow(r, interpolation='nearest')
fig, ax = plt.subplots()
ax.imshow(r, interpolation='nearest', cmap=plt.cm.gray)
for n, contour in enumerate(contours):
plt.plot(contour[:, 1], contour[:, 0], linewidth=2)
ax.plot(contour[:, 1], contour[:, 0], linewidth=2)
plt.axis('image')
plt.xticks([])
plt.yticks([])
ax.axis('image')
ax.set_xticks([])
ax.set_yticks([])
plt.show()
+5 -7
View File
@@ -40,11 +40,9 @@ image[chull] += 1
# [ 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
fig = plt.subplots(figsize=(10, 6))
plt.subplot(1, 2, 1)
plt.title('Original picture')
plt.imshow(original_image, cmap=plt.cm.gray, interpolation='nearest')
plt.subplot(1, 2, 2)
plt.title('Transformed picture')
plt.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 6))
ax1.set_title('Original picture')
ax1.imshow(original_image, cmap=plt.cm.gray, interpolation='nearest')
ax2.set_title('Transformed picture')
ax2.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
plt.show()
+5 -5
View File
@@ -29,9 +29,9 @@ 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))
fig, ax = plt.subplots()
ax.imshow(image, interpolation='nearest', cmap=plt.cm.gray)
ax.plot(coords[:, 1], coords[:, 0], '.b', markersize=3)
ax.plot(coords_subpix[:, 1], coords_subpix[:, 0], '+r', markersize=15)
ax.axis((0, 350, 350, 0))
plt.show()
+4 -3
View File
@@ -20,8 +20,9 @@ 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)
fig, ax = plt.subplots()
ax.axis('off')
ax.imshow(descs_img)
descs_num = descs.shape[0] * descs.shape[1]
plt.title('%i DAISY descriptors extracted:' % descs_num)
ax.set_title('%i DAISY descriptors extracted:' % descs_num)
plt.show()
+1 -1
View File
@@ -29,7 +29,7 @@ import numpy as np
import matplotlib.pyplot as plt
from skimage import data, img_as_float
from skimage.filter import denoise_tv_chambolle, denoise_bilateral
from skimage.restoration import denoise_tv_chambolle, denoise_bilateral
lena = img_as_float(data.lena())
+2 -2
View File
@@ -22,11 +22,11 @@ fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 4))
img0 = ax0.imshow(image, cmap=plt.cm.gray)
ax0.set_title('Image')
ax0.axis('off')
plt.colorbar(img0, ax=ax0)
fig.colorbar(img0, ax=ax0)
img1 = ax1.imshow(entropy(image, disk(5)), cmap=plt.cm.jet)
ax1.set_title('Entropy')
ax1.axis('off')
plt.colorbar(img1, ax=ax1)
fig.colorbar(img1, ax=ax1)
plt.show()
+8 -4
View File
@@ -17,6 +17,8 @@ that fall within the 2nd and 98th percentiles [2]_.
.. [2] http://homepages.inf.ed.ac.uk/rbf/HIPR2/stretch.htm
"""
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
@@ -24,6 +26,9 @@ from skimage import data, img_as_float
from skimage import exposure
matplotlib.rcParams['font.size'] = 8
def plot_img_and_hist(img, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.
@@ -55,8 +60,7 @@ def plot_img_and_hist(img, axes, bins=256):
img = data.moon()
# Contrast stretching
p2 = np.percentile(img, 2)
p98 = np.percentile(img, 98)
p2, p98 = np.percentile(img, (2, 98))
img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
# Equalization
@@ -66,7 +70,7 @@ img_eq = exposure.equalize_hist(img)
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
# Display results
f, axes = plt.subplots(2, 4, figsize=(8, 4))
fig, axes = plt.subplots(nrows=2, ncols=4, figsize=(8, 5))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
ax_img.set_title('Low contrast image')
@@ -88,5 +92,5 @@ 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)
fig.subplots_adjust(wspace=0.4)
plt.show()
+4 -7
View File
@@ -24,9 +24,6 @@ from skimage.util import img_as_float
from skimage.filter import gabor_kernel
matplotlib.rcParams['font.size'] = 9
def compute_feats(image, kernels):
feats = np.zeros((len(kernels), 2), dtype=np.double)
for k, kernel in enumerate(kernels):
@@ -104,24 +101,24 @@ for theta in (0, 1):
# Save kernel and the power image for each image
results.append((kernel, [power(img, kernel) for img in images]))
fig, axes = plt.subplots(nrows=5, ncols=4, figsize=(9, 6))
fig, axes = plt.subplots(nrows=5, ncols=4, figsize=(5, 6))
plt.gray()
fig.suptitle('Image responses for Gabor filter kernels', fontsize=15)
fig.suptitle('Image responses for Gabor filter kernels', fontsize=12)
axes[0][0].axis('off')
# Plot original images
for label, img, ax in zip(image_names, images, axes[0][1:]):
ax.imshow(img)
ax.set_title(label)
ax.set_title(label, fontsize=9)
ax.axis('off')
for label, (kernel, powers), ax_row in zip(kernel_params, results, axes[1:]):
# Plot Gabor kernel
ax = ax_row[0]
ax.imshow(np.real(kernel), interpolation='nearest')
ax.set_ylabel(label)
ax.set_ylabel(label, fontsize=7)
ax.set_xticks([])
ax.set_yticks([])
+33 -32
View File
@@ -53,44 +53,45 @@ for i, patch in enumerate(grass_patches + sky_patches):
ys.append(greycoprops(glcm, 'correlation')[0, 0])
# create the figure
plt.figure(figsize=(8, 8))
fig = plt.figure(figsize=(8, 8))
# display original image with locations of patches
ax = fig.add_subplot(3, 2, 1)
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
for (y, x) in grass_locations:
ax.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'gs')
for (y, x) in sky_locations:
ax.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'bs')
ax.set_xlabel('Original Image')
ax.set_xticks([])
ax.set_yticks([])
ax.axis('image')
# for each patch, plot (dissimilarity, correlation)
ax = fig.add_subplot(3, 2, 2)
ax.plot(xs[:len(grass_patches)], ys[:len(grass_patches)], 'go',
label='Grass')
ax.plot(xs[len(grass_patches):], ys[len(grass_patches):], 'bo',
label='Sky')
ax.set_xlabel('GLCM Dissimilarity')
ax.set_ylabel('GLVM Correlation')
ax.legend()
# display the image patches
for i, patch in enumerate(grass_patches):
plt.subplot(3, len(grass_patches), len(grass_patches) * 1 + i + 1)
plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
plt.xlabel('Grass %d' % (i + 1))
ax = fig.add_subplot(3, len(grass_patches), len(grass_patches)*1 + i + 1)
ax.imshow(patch, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
ax.set_xlabel('Grass %d' % (i + 1))
for i, patch in enumerate(sky_patches):
plt.subplot(3, len(grass_patches), len(grass_patches) * 2 + i + 1)
plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
plt.xlabel('Sky %d' % (i + 1))
ax = fig.add_subplot(3, len(sky_patches), len(sky_patches)*2 + i + 1)
ax.imshow(patch, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
ax.set_xlabel('Sky %d' % (i + 1))
# display original image with locations of patches
plt.subplot(3, 2, 1)
plt.imshow(image, cmap=plt.cm.gray, interpolation='nearest',
vmin=0, vmax=255)
for (y, x) in grass_locations:
plt.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'gs')
for (y, x) in sky_locations:
plt.plot(x + PATCH_SIZE / 2, y + PATCH_SIZE / 2, 'bs')
plt.xlabel('Original Image')
plt.xticks([])
plt.yticks([])
plt.axis('image')
# for each patch, plot (dissimilarity, correlation)
plt.subplot(3, 2, 2)
plt.plot(xs[:len(grass_patches)], ys[:len(grass_patches)], 'go',
label='Grass')
plt.plot(xs[len(grass_patches):], ys[len(grass_patches):], 'bo',
label='Sky')
plt.xlabel('GLCM Dissimilarity')
plt.ylabel('GLVM Correlation')
plt.legend()
# display the patches and plot
plt.suptitle('Grey level co-occurrence matrix features', fontsize=14)
fig.suptitle('Grey level co-occurrence matrix features', fontsize=14)
plt.show()
+7 -7
View File
@@ -90,16 +90,16 @@ image = color.rgb2gray(data.lena())
fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16),
cells_per_block=(1, 1), visualise=True)
plt.figure(figsize=(8, 4))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
plt.subplot(121).set_axis_off()
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Input image')
ax1.axis('off')
ax1.imshow(image, cmap=plt.cm.gray)
ax1.set_title('Input image')
# Rescale histogram for better display
hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 0.02))
plt.subplot(122).set_axis_off()
plt.imshow(hog_image_rescaled, cmap=plt.cm.gray)
plt.title('Histogram of Oriented Gradients')
ax2.axis('off')
ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray)
ax2.set_title('Histogram of Oriented Gradients')
plt.show()
+10 -12
View File
@@ -22,13 +22,13 @@ image = data.moon()
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')
def imshow(image, title, **kwargs):
fig, ax = plt.subplots(figsize=(5, 4))
ax.imshow(image, **kwargs)
ax.axis('off')
ax.set_title(title)
imshow(image)
plt.title('original image')
imshow(image, 'Original image')
"""
.. image:: PLOT2RST.current_figure
@@ -50,8 +50,7 @@ mask = image
filled = reconstruction(seed, mask, method='erosion')
imshow(filled, vmin=image.min(), vmax=image.max())
plt.title('after filling holes')
imshow(filled, 'after filling holes',vmin=image.min(), vmax=image.max())
"""
.. image:: PLOT2RST.current_figure
@@ -62,8 +61,8 @@ isolate the dark regions by subtracting the reconstructed image from the
original image.
"""
imshow(image - filled)
plt.title('holes')
imshow(image - filled, 'holes')
# plt.title('holes')
"""
.. image:: PLOT2RST.current_figure
@@ -78,8 +77,7 @@ 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')
imshow(image - rec, 'peaks')
plt.show()
"""
+4 -4
View File
@@ -61,10 +61,10 @@ h = rescale_intensity(ihc_hed[:, :, 0], out_range=(0, 1))
d = rescale_intensity(ihc_hed[:, :, 2], out_range=(0, 1))
zdh = np.dstack((np.zeros_like(h), d, h))
plt.figure()
plt.imshow(zdh)
plt.title("Stain separated image (rescaled)")
plt.axis('off')
fig, ax = plt.subplots()
ax.imshow(zdh)
ax.set_title("Stain separated image (rescaled)")
ax.axis('off')
plt.show()
"""
+1 -1
View File
@@ -58,5 +58,5 @@ 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)
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
plt.show()
+3 -3
View File
@@ -43,14 +43,14 @@ image_label_overlay = label2rgb(label_image, image=image)
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
ax.imshow(image_label_overlay)
for region in regionprops(label_image, ['Area', 'BoundingBox']):
for region in regionprops(label_image):
# skip small images
if region['Area'] < 100:
if region.area < 100:
continue
# draw rectangle around segmented coins
minr, minc, maxr, maxc = region['BoundingBox']
minr, minc, maxr, maxc = region.bbox
rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
fill=False, edgecolor='red', linewidth=2)
ax.add_patch(rect)
+25 -26
View File
@@ -77,30 +77,30 @@ image[idx, idx] = 255
h, theta, d = hough_line(image)
plt.figure(figsize=(8, 4))
fig, ax = plt.subplots(1, 3, figsize=(8, 4))
plt.subplot(131)
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Input image')
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].set_title('Input image')
ax[0].axis('image')
plt.subplot(132)
plt.imshow(np.log(1 + h),
ax[1].imshow(np.log(1 + h),
extent=[np.rad2deg(theta[-1]), np.rad2deg(theta[0]),
d[-1], d[0]],
cmap=plt.cm.gray, aspect=1/1.5)
plt.title('Hough transform')
plt.xlabel('Angles (degrees)')
plt.ylabel('Distance (pixels)')
ax[1].set_title('Hough transform')
ax[1].set_xlabel('Angles (degrees)')
ax[1].set_ylabel('Distance (pixels)')
ax[1].axis('image')
plt.subplot(133)
plt.imshow(image, cmap=plt.cm.gray)
ax[2].imshow(image, cmap=plt.cm.gray)
rows, cols = image.shape
for _, angle, dist in zip(*hough_line_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')
ax[2].plot((0, cols), (y0, y1), '-r')
ax[2].axis((0, cols, rows, 0))
ax[2].set_title('Detected lines')
ax[2].axis('image')
# Line finding, using the Probabilistic Hough Transform
@@ -108,23 +108,22 @@ image = data.camera()
edges = canny(image, 2, 1, 25)
lines = probabilistic_hough_line(edges, threshold=10, line_length=5, line_gap=3)
plt.figure(figsize=(8, 3))
fig2, ax = plt.subplots(1, 3, figsize=(8, 3))
plt.subplot(131)
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Input image')
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].set_title('Input image')
ax[0].axis('image')
plt.subplot(132)
plt.imshow(edges, cmap=plt.cm.gray)
plt.title('Canny edges')
ax[1].imshow(edges, cmap=plt.cm.gray)
ax[1].set_title('Canny edges')
ax[1].axis('image')
plt.subplot(133)
plt.imshow(edges * 0)
ax[2].imshow(edges * 0)
for line in lines:
p0, p1 = line
plt.plot((p0[0], p1[0]), (p0[1], p1[1]))
ax[2].plot((p0[0], p1[0]), (p0[1], p1[1]))
plt.title('Probabilistic Hough')
plt.axis('image')
ax[2].set_title('Probabilistic Hough')
ax[2].axis('image')
plt.show()
+7 -5
View File
@@ -20,6 +20,7 @@ References
"""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from skimage import data
@@ -30,6 +31,9 @@ from skimage.morphology import disk
from skimage.filter import rank
matplotlib.rcParams['font.size'] = 9
def plot_img_and_hist(img, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.
@@ -59,9 +63,7 @@ def plot_img_and_hist(img, axes, bins=256):
# Load an example image
img = img_as_ubyte(data.moon())
# Contrast stretching
p2 = np.percentile(img, 2)
p98 = np.percentile(img, 98)
# Global equalize
img_rescale = exposure.equalize_hist(img)
# Equalization
@@ -70,7 +72,7 @@ img_eq = rank.equalize(img, selem=selem)
# Display results
f, axes = plt.subplots(2, 3, figsize=(8, 4))
fig, axes = plt.subplots(2, 3, figsize=(8, 5))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
ax_img.set_title('Low contrast image')
@@ -85,5 +87,5 @@ ax_cdf.set_ylabel('Fraction of total intensity')
# prevent overlap of y-axis labels
plt.subplots_adjust(wspace=0.4)
fig.subplots_adjust(wspace=0.4)
plt.show()
+30 -20
View File
@@ -15,6 +15,7 @@ The example compares the local threshold with the global threshold.
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
"""
import matplotlib
import matplotlib.pyplot as plt
from skimage import data
@@ -23,29 +24,38 @@ from skimage.filter import threshold_otsu, rank
from skimage.util import img_as_ubyte
p8 = img_as_ubyte(data.page())
matplotlib.rcParams['font.size'] = 9
radius = 10
img = img_as_ubyte(data.page())
radius = 15
selem = disk(radius)
loc_otsu = rank.otsu(p8, selem)
t_glob_otsu = threshold_otsu(p8)
glob_otsu = p8 >= t_glob_otsu
local_otsu = rank.otsu(img, selem)
threshold_global_otsu = threshold_otsu(img)
global_otsu = img >= threshold_global_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)
fig, ax = plt.subplots(2, 2, figsize=(8, 5))
ax1, ax2, ax3, ax4 = ax.ravel()
fig.colorbar(ax1.imshow(img, cmap=plt.cm.gray),
ax=ax1, orientation='horizontal')
ax1.set_title('Original')
ax1.axis('off')
fig.colorbar(ax2.imshow(local_otsu, cmap=plt.cm.gray),
ax=ax2, orientation='horizontal')
ax2.set_title('Local Otsu (radius=%d)' % radius)
ax2.axis('off')
ax3.imshow(img >= local_otsu, cmap=plt.cm.gray)
ax3.set_title('Original >= Local Otsu' % threshold_global_otsu)
ax3.axis('off')
ax4.imshow(global_otsu, cmap=plt.cm.gray)
ax4.set_title('Global Otsu (threshold = %d)' % threshold_global_otsu)
ax4.axis('off')
plt.show()
+1 -1
View File
@@ -51,5 +51,5 @@ 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)
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
plt.show()
+12 -18
View File
@@ -27,7 +27,8 @@ from matplotlib import pyplot as plt
from skimage import data
from skimage.util import img_as_float
from skimage.feature import corner_harris, corner_subpix, corner_peaks
from skimage.feature import (corner_harris, corner_subpix, corner_peaks,
plot_matches)
from skimage.transform import warp, AffineTransform
from skimage.exposure import rescale_intensity
from skimage.color import rgb2gray
@@ -71,7 +72,7 @@ def gaussian_weights(window_ext, sigma=1):
def match_corner(coord, window_ext=5):
r, c = np.round(coord)
r, c = np.round(coord).astype(np.intp)
window_orig = img_orig[r-window_ext:r+window_ext+1,
c-window_ext:c+window_ext+1, :]
@@ -117,28 +118,21 @@ print(tform.scale, tform.translation, tform.rotation)
print(model.scale, model.translation, model.rotation)
print(model_robust.scale, model_robust.translation, model_robust.rotation)
# visualize correspondences
img_combined = np.concatenate((img_orig_gray, img_warped_gray), axis=1)
# visualize correspondence
fig, ax = plt.subplots(nrows=2, ncols=1)
plt.gray()
ax[0].imshow(img_combined, interpolation='nearest')
inlier_idxs = np.nonzero(inliers)[0]
plot_matches(ax[0], img_orig_gray, img_warped_gray, src, dst,
np.column_stack((inlier_idxs, inlier_idxs)), matches_color='b')
ax[0].axis('off')
ax[0].axis((0, 400, 200, 0))
ax[0].set_title('Correct correspondences')
ax[1].imshow(img_combined, interpolation='nearest')
outlier_idxs = np.nonzero(outliers)[0]
plot_matches(ax[1], img_orig_gray, img_warped_gray, src, dst,
np.column_stack((outlier_idxs, outlier_idxs)), matches_color='r')
ax[1].axis('off')
ax[1].axis((0, 400, 200, 0))
ax[1].set_title('Faulty correspondences')
for ax_idx, (m, color) in enumerate(((inliers, 'g'), (outliers, 'r'))):
ax[ax_idx].plot((src[m, 1], dst[m, 1] + 200), (src[m, 0], dst[m, 0]), '-',
color=color)
ax[ax_idx].plot(src[m, 1], src[m, 0], '.', markersize=10, color=color)
ax[ax_idx].plot(dst[m, 1] + 200, dst[m, 0], '.', markersize=10,
color=color)
plt.show()
+7 -9
View File
@@ -55,14 +55,12 @@ skel, distance = medial_axis(data, return_distance=True)
# Distance to the background for pixels of the skeleton
dist_on_skel = distance * skel
plt.figure(figsize=(8, 4))
plt.subplot(121)
plt.imshow(data, cmap=plt.cm.gray, interpolation='nearest')
plt.axis('off')
plt.subplot(122)
plt.imshow(dist_on_skel, cmap=plt.cm.spectral, interpolation='nearest')
plt.contour(data, [0.5], colors='w')
plt.axis('off')
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(data, cmap=plt.cm.gray, interpolation='nearest')
ax1.axis('off')
ax2.imshow(dist_on_skel, cmap=plt.cm.spectral, interpolation='nearest')
ax2.contour(data, [0.5], colors='w')
ax2.axis('off')
plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
plt.show()
+56
View File
@@ -0,0 +1,56 @@
"""
==========================================
ORB feature detector and binary descriptor
==========================================
This example demonstrates the ORB feature detection and binary description
algorithm. It uses an oriented FAST detection method and the rotated BRIEF
descriptors.
Unlike BRIEF, ORB is comparatively scale- and rotation-invariant while still
employing the very efficient Hamming distance metric for matching. As such, it
is preferred for real-time applications.
"""
from skimage import data
from skimage import transform as tf
from skimage.feature import (match_descriptors, corner_harris,
corner_peaks, ORB, plot_matches)
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
img1 = rgb2gray(data.lena())
img2 = tf.rotate(img1, 180)
tform = tf.AffineTransform(scale=(1.3, 1.1), rotation=0.5,
translation=(0, -200))
img3 = tf.warp(img1, tform)
descriptor_extractor = ORB(n_keypoints=200)
descriptor_extractor.detect_and_extract(img1)
keypoints1 = descriptor_extractor.keypoints
descriptors1 = descriptor_extractor.descriptors
descriptor_extractor.detect_and_extract(img2)
keypoints2 = descriptor_extractor.keypoints
descriptors2 = descriptor_extractor.descriptors
descriptor_extractor.detect_and_extract(img3)
keypoints3 = descriptor_extractor.keypoints
descriptors3 = descriptor_extractor.descriptors
matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True)
matches13 = match_descriptors(descriptors1, descriptors3, cross_check=True)
fig, ax = plt.subplots(nrows=2, ncols=1)
plt.gray()
plot_matches(ax[0], img1, img2, keypoints1, keypoints2, matches12)
ax[0].axis('off')
plot_matches(ax[1], img1, img3, keypoints1, keypoints3, matches13)
ax[1].axis('off')
plt.show()
+14 -13
View File
@@ -14,30 +14,31 @@ the intra-class variance.
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
"""
import matplotlib
import matplotlib.pyplot as plt
from skimage.data import camera
from skimage.filter import threshold_otsu
matplotlib.rcParams['font.size'] = 9
image = camera()
thresh = threshold_otsu(image)
binary = image > thresh
plt.figure(figsize=(8, 2.5))
plt.subplot(1, 3, 1)
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 2.5))
ax1.imshow(image, cmap=plt.cm.gray)
ax1.set_title('Original')
ax1.axis('off')
plt.subplot(1, 3, 2, aspect='equal')
plt.hist(image)
plt.title('Histogram')
plt.axvline(thresh, color='r')
ax2.hist(image)
ax2.set_title('Histogram')
ax2.axvline(thresh, color='r')
plt.subplot(1, 3, 3)
plt.imshow(binary, cmap=plt.cm.gray)
plt.title('Thresholded')
plt.axis('off')
ax3.imshow(binary, cmap=plt.cm.gray)
ax3.set_title('Thresholded')
ax3.axis('off')
plt.show()
+14 -16
View File
@@ -25,25 +25,23 @@ image_max = ndimage.maximum_filter(im, size=20, mode='constant')
coordinates = peak_local_max(im, min_distance=20)
# display results
plt.figure(figsize=(8, 3))
plt.subplot(131)
plt.imshow(im, cmap=plt.cm.gray)
plt.axis('off')
plt.title('Original')
fig, ax = plt.subplots(1, 3, figsize=(8, 3))
ax1, ax2, ax3 = ax.ravel()
ax1.imshow(im, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('Original')
plt.subplot(132)
plt.imshow(image_max, cmap=plt.cm.gray)
plt.axis('off')
plt.title('Maximum filter')
ax2.imshow(image_max, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('Maximum filter')
plt.subplot(133)
plt.imshow(im, cmap=plt.cm.gray)
plt.autoscale(False)
plt.plot([p[1] for p in coordinates], [p[0] for p in coordinates], 'r.')
plt.axis('off')
plt.title('Peak local max')
ax3.imshow(im, cmap=plt.cm.gray)
ax3.autoscale(False)
ax3.plot(coordinates[:, 1], coordinates[:, 0], 'r.')
ax3.axis('off')
ax3.set_title('Peak local max')
plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
bottom=0.02, left=0.02, right=0.98)
plt.show()
+106
View File
@@ -0,0 +1,106 @@
"""
================
Phase Unwrapping
================
Some signals can only be observed modulo 2*pi, and this can also apply to
two- and three dimensional images. In these cases phase unwrapping is
needed to recover the underlying, unwrapped signal. In this example we will
demonstrate an algorithm [1]_ implemented in ``skimage`` at work for such a
problem. One-, two- and three dimensional images can all be unwrapped using
skimage. Here we will demonstrate phase unwrapping in the two dimensional case.
"""
import numpy as np
from matplotlib import pyplot as plt
from skimage import data, img_as_float, color, exposure
from skimage.restoration import unwrap_phase
# Load an image as a floating-point grayscale
image = color.rgb2gray(img_as_float(data.chelsea()))
# Scale the image to [0, 4*pi]
image = exposure.rescale_intensity(image, out_range=(0, 4 * np.pi))
# Create a phase-wrapped image in the interval [-pi, pi)
image_wrapped = np.angle(np.exp(1j * image))
# Perform phase unwrapping
image_unwrapped = unwrap_phase(image_wrapped)
fig, ax = plt.subplots(2, 2)
ax1, ax2, ax3, ax4 = ax.ravel()
fig.colorbar(ax1.imshow(image, cmap='gray', vmin=0, vmax=4 * np.pi), ax=ax1)
ax1.set_title('Original')
fig.colorbar(ax2.imshow(image_wrapped, cmap='gray', vmin=-np.pi, vmax=np.pi), ax=ax2)
ax2.set_title('Wrapped phase')
fig.colorbar(ax3.imshow(image_unwrapped, cmap='gray'), ax=ax3)
ax3.set_title('After phase unwrapping')
fig.colorbar(ax4.imshow(image_unwrapped - image, cmap='gray'), ax=ax4)
ax4.set_title('Unwrapped minus original')
"""
.. image:: PLOT2RST.current_figure
The unwrapping procedure accepts masked arrays, and can also optionally
assume cyclic boundaries to connect edges of an image. In the example below,
we study a simple phase ramp which has been split in two by masking
a row of the image.
"""
# Create a simple ramp
image = np.ones((100, 100)) * np.linspace(0, 8 * np.pi, 100).reshape((-1, 1))
# Mask the image to split it in two horizontally
mask = np.zeros_like(image, dtype=np.bool)
mask[image.shape[0] // 2, :] = True
image_wrapped = np.ma.array(np.angle(np.exp(1j * image)), mask=mask)
# Unwrap image without wrap around
image_unwrapped_no_wrap_around = unwrap_phase(image_wrapped,
wrap_around=(False, False))
# Unwrap with wrap around enabled for the 0th dimension
image_unwrapped_wrap_around = unwrap_phase(image_wrapped,
wrap_around=(True, False))
fig, ax = plt.subplots(2, 2)
ax1, ax2, ax3, ax4 = ax.ravel()
fig.colorbar(ax1.imshow(np.ma.array(image, mask=mask), cmap='jet'), ax=ax1)
ax1.set_title('Original')
fig.colorbar(ax2.imshow(image_wrapped, cmap='jet', vmin=-np.pi, vmax=np.pi),
ax=ax2)
ax2.set_title('Wrapped phase')
fig.colorbar(ax3.imshow(image_unwrapped_no_wrap_around, cmap='jet'),
ax=ax3)
ax3.set_title('Unwrapped without wrap_around')
fig.colorbar(ax4.imshow(image_unwrapped_wrap_around, cmap='jet'), ax=ax4)
ax4.set_title('Unwrapped with wrap_around')
plt.show()
"""
.. image:: PLOT2RST.current_figure
In the figures above, the masked row can be seen as a white line across
the image. The difference between the two unwrapped images in the bottom row
is clear: Without unwrapping (lower left), the regions above and below the
masked boundary do not interact at all, resulting in an offset between the
two regions of an arbitrary integer times two pi. We could just as well have
unwrapped the regions as two separate images. With wrap around enabled for the
vertical direction (lower rigth), the situation changes: Unwrapping paths are
now allowed to pass from the bottom to the top of the image and vice versa, in
effect providing a way to determine the offset between the two regions.
References
----------
.. [1] Miguel Arevallilo Herraez, David R. Burton, Michael J. Lalor,
and Munther A. Gdeisat, "Fast two-dimensional phase-unwrapping
algorithm based on sorting by reliability following a noncontinuous
path", Journal Applied Optics, Vol. 41, No. 35, pp. 7437, 2002
"""
+4 -3
View File
@@ -35,7 +35,8 @@ 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))
fig, ax = plt.subplots()
ax.imshow(out)
ax.plot(tform.inverse(src)[:, 0], tform.inverse(src)[:, 1], '.b')
ax.axis((0, out_cols, out_rows, 0))
plt.show()
+2 -1
View File
@@ -30,5 +30,6 @@ for p in pyramid[1:]:
composite_image[i_row:i_row + n_rows, cols:cols + n_cols] = p
i_row += n_rows
plt.imshow(composite_image)
fig, ax = plt.subplots()
ax.imshow(composite_image)
plt.show()
+23 -31
View File
@@ -60,22 +60,20 @@ from skimage.transform import radon, rescale
image = imread(data_dir + "/phantom.png", as_grey=True)
image = rescale(image, scale=0.4)
plt.figure(figsize=(8, 4.5))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
plt.subplot(121)
plt.title("Original")
plt.imshow(image, cmap=plt.cm.Greys_r)
ax1.set_title("Original")
ax1.imshow(image, cmap=plt.cm.Greys_r)
theta = np.linspace(0., 180., max(image.shape), endpoint=True)
sinogram = radon(image, theta=theta, circle=True)
plt.subplot(122)
plt.title("Radon transform\n(Sinogram)")
plt.xlabel("Projection angle (deg)")
plt.ylabel("Projection position (pixels)")
plt.imshow(sinogram, cmap=plt.cm.Greys_r,
ax2.set_title("Radon transform\n(Sinogram)")
ax2.set_xlabel("Projection angle (deg)")
ax2.set_ylabel("Projection position (pixels)")
ax2.imshow(sinogram, cmap=plt.cm.Greys_r,
extent=(0, 180, 0, sinogram.shape[0]), aspect='auto')
plt.subplots_adjust(hspace=0.4, wspace=0.5)
fig.subplots_adjust(hspace=0.4, wspace=0.5)
plt.show()
"""
@@ -103,13 +101,11 @@ error = reconstruction_fbp - image
print('FBP rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2)))
imkwargs = dict(vmin=-0.2, vmax=0.2)
plt.figure(figsize=(8, 4.5))
plt.subplot(121)
plt.title("Reconstruction\nFiltered back projection")
plt.imshow(reconstruction_fbp, cmap=plt.cm.Greys_r)
plt.subplot(122)
plt.title("Reconstruction error\nFiltered back projection")
plt.imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
ax1.set_title("Reconstruction\nFiltered back projection")
ax1.imshow(reconstruction_fbp, cmap=plt.cm.Greys_r)
ax2.set_title("Reconstruction error\nFiltered back projection")
ax2.imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)
plt.show()
"""
@@ -156,14 +152,12 @@ error = reconstruction_sart - image
print('SART (1 iteration) rms reconstruction error: %.3g'
% np.sqrt(np.mean(error**2)))
plt.figure(figsize=(8, 8.5))
plt.subplot(221)
plt.title("Reconstruction\nSART")
plt.imshow(reconstruction_sart, cmap=plt.cm.Greys_r)
plt.subplot(222)
plt.title("Reconstruction error\nSART")
plt.imshow(reconstruction_sart - image, cmap=plt.cm.Greys_r, **imkwargs)
fig, ax = plt.subplots(2, 2, figsize=(8, 8.5))
ax1, ax2, ax3, ax4 = ax.ravel()
ax1.set_title("Reconstruction\nSART")
ax1.imshow(reconstruction_sart, cmap=plt.cm.Greys_r)
ax2.set_title("Reconstruction error\nSART")
ax2.imshow(reconstruction_sart - image, cmap=plt.cm.Greys_r, **imkwargs)
# Run a second iteration of SART by supplying the reconstruction
# from the first iteration as an initial estimate
@@ -173,12 +167,10 @@ error = reconstruction_sart2 - image
print('SART (2 iterations) rms reconstruction error: %.3g'
% np.sqrt(np.mean(error**2)))
plt.subplot(223)
plt.title("Reconstruction\nSART, 2 iterations")
plt.imshow(reconstruction_sart2, cmap=plt.cm.Greys_r)
plt.subplot(224)
plt.title("Reconstruction error\nSART, 2 iterations")
plt.imshow(reconstruction_sart2 - image, cmap=plt.cm.Greys_r, **imkwargs)
ax3.set_title("Reconstruction\nSART, 2 iterations")
ax3.imshow(reconstruction_sart2, cmap=plt.cm.Greys_r)
ax4.set_title("Reconstruction error\nSART, 2 iterations")
ax4.imshow(reconstruction_sart2 - image, cmap=plt.cm.Greys_r, **imkwargs)
plt.show()
"""
+11 -14
View File
@@ -58,20 +58,17 @@ markers[data > 1.3] = 2
labels = random_walker(data, markers, beta=10, mode='bf')
# Plot results
plt.figure(figsize=(8, 3.2))
plt.subplot(131)
plt.imshow(data, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.title('Noisy data')
plt.subplot(132)
plt.imshow(markers, cmap='hot', interpolation='nearest')
plt.axis('off')
plt.title('Markers')
plt.subplot(133)
plt.imshow(labels, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.title('Segmentation')
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 3.2))
ax1.imshow(data, cmap='gray', interpolation='nearest')
ax1.axis('off')
ax1.set_title('Noisy data')
ax2.imshow(markers, cmap='hot', interpolation='nearest')
ax2.axis('off')
ax2.set_title('Markers')
ax3.imshow(labels, cmap='gray', interpolation='nearest')
ax3.axis('off')
ax3.set_title('Segmentation')
plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
right=1)
plt.show()
+8 -7
View File
@@ -45,11 +45,12 @@ line_x = np.arange(-250, 250)
line_y = model.predict_y(line_x)
line_y_robust = model_robust.predict_y(line_x)
plt.plot(data[inliers, 0], data[inliers, 1], '.b', alpha=0.6,
label='Inlier data')
plt.plot(data[outliers, 0], data[outliers, 1], '.r', alpha=0.6,
label='Outlier data')
plt.plot(line_x, line_y, '-k', label='Line model from all data')
plt.plot(line_x, line_y_robust, '-b', label='Robust line model')
plt.legend(loc='lower left')
fig, ax = plt.subplots()
ax.plot(data[inliers, 0], data[inliers, 1], '.b', alpha=0.6,
label='Inlier data')
ax.plot(data[outliers, 0], data[outliers, 1], '.r', alpha=0.6,
label='Outlier data')
ax.plot(line_x, line_y, '-k', label='Line model from all data')
ax.plot(line_x, line_y_robust, '-b', label='Robust line model')
ax.legend(loc='lower left')
plt.show()
+2 -2
View File
@@ -50,7 +50,7 @@ ax3.imshow(image - dilated)
ax3.set_title('image - dilated')
ax3.axis('off')
plt.tight_layout()
fig.tight_layout()
"""
@@ -98,7 +98,7 @@ ax3.axhline(yslice, color='r', alpha=0.4)
ax3.set_title('image - dilated')
ax3.axis('off')
plt.tight_layout()
fig.tight_layout()
plt.show()
"""
+7 -7
View File
@@ -26,7 +26,8 @@ image = rotate(image, angle=15, order=0)
label_img = label(image)
regions = regionprops(label_img)
plt.imshow(image)
fig, ax = plt.subplots()
ax.imshow(image, cmap=plt.cm.gray)
for props in regions:
y0, x0 = props.centroid
@@ -36,15 +37,14 @@ for props in regions:
x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length
y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length
plt.plot((x0, x1), (y0, y1), '-r', linewidth=2.5)
plt.plot((x0, x2), (y0, y2), '-r', linewidth=2.5)
plt.plot(x0, y0, '.g', markersize=15)
ax.plot((x0, x1), (y0, y1), '-r', linewidth=2.5)
ax.plot((x0, x2), (y0, y2), '-r', linewidth=2.5)
ax.plot(x0, y0, '.g', markersize=15)
minr, minc, maxr, maxc = props.bbox
bx = (minc, maxc, maxc, minc, minc)
by = (minr, minr, maxr, maxr, minr)
plt.plot(bx, by, '-b', linewidth=2.5)
ax.plot(bx, by, '-b', linewidth=2.5)
plt.gray()
plt.axis((0, 600, 600, 0))
ax.axis((0, 600, 600, 0))
plt.show()
+60
View File
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
"""
=====================
Deconvolution of Lena
=====================
In this example, we deconvolve a noisy version of Lena using Wiener
and unsupervised Wiener algorithms. This algorithms are based on
linear models that can't restore sharp edge as much as non-linear
methods (like TV restoration) but are much faster.
Wiener filter
-------------
The inverse filter based on the PSF (Point Spread Function),
the prior regularisation (penalisation of high frequency) and the
tradeoff between the data and prior adequacy. The regularization
parameter must be hand tuned.
Unsupervised Wiener
-------------------
This algorithm has a self-tuned regularisation parameters based on
data learning. This is not common and based on the following
publication. The algorithm is based on a iterative Gibbs sampler that
draw alternatively samples of posterior conditionnal law of the image,
the noise power and the image frequency power.
.. [1] François Orieux, Jean-François Giovannelli, and Thomas
Rodet, "Bayesian estimation of regularization and point
spread function parameters for Wiener-Hunt deconvolution",
J. Opt. Soc. Am. A 27, 1593-1607 (2010)
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage import color, data, restoration
lena = color.rgb2gray(data.lena())
from scipy.signal import convolve2d as conv2
psf = np.ones((5, 5)) / 25
lena = conv2(lena, psf, 'same')
lena += 0.1 * lena.std() * np.random.standard_normal(lena.shape)
deconvolved, _ = restoration.unsupervised_wiener(lena, psf)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 5))
plt.gray()
ax[0].imshow(lena, vmin=deconvolved.min(), vmax=deconvolved.max())
ax[0].axis('off')
ax[0].set_title('Data')
ax[1].imshow(deconvolved)
ax[1].axis('off')
ax[1].set_title('Self tuned restoration')
fig.subplots_adjust(wspace=0.02, hspace=0.2,
top=0.9, bottom=0.05, left=0, right=1)
plt.show()
+3 -3
View File
@@ -51,7 +51,7 @@ 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
``compactness`` 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,
@@ -70,7 +70,7 @@ 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_slic = slic(img, n_segments=250, compactness=10, 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)))
@@ -79,7 +79,7 @@ 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)
fig.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")
+11 -12
View File
@@ -4,11 +4,17 @@ Shapes
======
This example shows how to draw several different shapes:
* line
* Bezier curve
* polygon
* circle
* ellipse
- line
- Bezier curve
- polygon
- circle
- ellipse
Anti-aliased drawing for:
- line
- circle
"""
import math
@@ -69,13 +75,6 @@ ax1.imshow(img)
ax1.set_title('No anti-aliasing')
ax1.axis('off')
"""
Anti-aliased drawing for:
* line
* circle
"""
from skimage.draw import line_aa, circle_perimeter_aa
+8 -10
View File
@@ -47,19 +47,17 @@ image[circle2] = 0
skeleton = skeletonize(image)
# display results
plt.figure(figsize=(8, 4.5))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))
plt.subplot(121)
plt.imshow(image, cmap=plt.cm.gray)
plt.axis('off')
plt.title('original', fontsize=20)
ax1.imshow(image, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('original', fontsize=20)
plt.subplot(122)
plt.imshow(skeleton, cmap=plt.cm.gray)
plt.axis('off')
plt.title('skeleton', fontsize=20)
ax2.imshow(skeleton, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('skeleton', fontsize=20)
plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.98,
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.98,
bottom=0.02, left=0.02, right=0.98)
plt.show()
+5 -1
View File
@@ -22,12 +22,16 @@ but with very different mean structural similarity indices.
"""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from skimage import data, img_as_float
from skimage.measure import structural_similarity as ssim
matplotlib.rcParams['font.size'] = 9
img = img_as_float(data.camera())
rows, cols = img.shape
@@ -41,7 +45,7 @@ def mse(x, y):
img_noise = img + noise
img_const = img + abs(noise)
f, (ax0, ax1, ax2) = plt.subplots(1, 3)
fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(8, 4))
mse_none = mse(img, img)
ssim_none = ssim(img, img, dynamic_range=img.max() - img.min())
+1 -1
View File
@@ -74,7 +74,7 @@ from skimage.transform import swirl
image = data.checkerboard()
swirled = swirl(image, rotation=0, strength=10, radius=120, order=2)
f, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 3))
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 3))
ax0.imshow(image, cmap=plt.cm.gray, interpolation='none')
ax0.axis('off')
@@ -0,0 +1,153 @@
"""
=========================
Tinting gray-scale images
=========================
It can be useful to artificially tint an image with some color, either to
highlight particular regions of an image or maybe just to liven up a grayscale
image. This example demonstrates image-tinting by scaling RGB values and by
adjusting colors in the HSV color-space.
In 2D, color images are often represented in RGB---3 layers of 2D arrays, where
the 3 layers represent (R)ed, (G)reen and (B)lue channels of the image. The
simplest way of getting a tinted image is to set each RGB channel to the
grayscale image scaled by a different multiplier for each channel. For example,
multiplying the green and blue channels by 0 leaves only the red channel and
produces a bright red image. Similarly, zeroing-out the blue channel leaves
only the red and green channels, which combine to form yellow.
"""
import matplotlib.pyplot as plt
from skimage import data
from skimage import color
from skimage import img_as_float
grayscale_image = img_as_float(data.camera()[::2, ::2])
image = color.gray2rgb(grayscale_image)
red_multiplier = [1, 0, 0]
yellow_multiplier = [1, 1, 0]
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4))
ax1.imshow(red_multiplier * image)
ax2.imshow(yellow_multiplier * image)
"""
.. image:: PLOT2RST.current_figure
In many cases, dealing with RGB values may not be ideal. Because of that, there
are many other `color spaces`_ in which you can represent a color image. One
popular color space is called HSV_, which represents hue (~the color),
saturation (~colorfulness), and value (~brightness). For example, a color
(hue) might be green, but its saturation is how intense that green is---where
olive is on the low end and neon on the high end.
In some implementations, the hue in HSV goes from 0 to 360, since hues wrap
around in a circle. In scikit-image, however, hues are float values from 0 to
1, so that hue, saturation, and value all share the same scale.
Below, we plot a linear gradient in the hue, with the saturation and value
turned all the way up:
"""
import numpy as np
hue_gradient = np.linspace(0, 1)
hsv = np.ones(shape=(1, len(hue_gradient), 3), dtype=float)
hsv[:, :, 0] = hue_gradient
all_hues = color.hsv2rgb(hsv)
fig, ax = plt.subplots(figsize=(5, 2))
# Set image extent so hues go from 0 to 1 and the image is a nice aspect ratio.
ax.imshow(all_hues, extent=(0, 1, 0, 0.2))
ax.set_axis_off()
"""
.. image:: PLOT2RST.current_figure
Notice how the colors at the far left and far right are the same. That reflects
the fact that the hues wrap around like the color wheel (see HSV_ for more
info).
Now, let's create a little utility function to take an RGB image and:
1. Transform the RGB image to HSV
2. Set the hue and saturation
3. Transform the HSV image back to RGB
"""
def colorize(image, hue, saturation=1):
""" Add color of the given hue to an RGB image.
By default, set the saturation to 1 so that the colors pop!
"""
hsv = color.rgb2hsv(image)
hsv[:, :, 1] = saturation
hsv[:, :, 0] = hue
return color.hsv2rgb(hsv)
"""
Notice that we need to bump up the saturation; images with zero saturation are
grayscale, so we need to a non-zero value to actually see the color we've set.
Using the function above, we plot six images with a linear gradient in the hue
and a non-zero saturation:
"""
hue_rotations = np.linspace(0, 1, 6)
fig, axes = plt.subplots(nrows=2, ncols=3)
for ax, hue in zip(axes.flat, hue_rotations):
# Turn down the saturation to give it that vintage look.
tinted_image = colorize(image, hue, saturation=0.3)
ax.imshow(tinted_image, vmin=0, vmax=1)
ax.set_axis_off()
fig.tight_layout()
"""
.. image:: PLOT2RST.current_figure
You can combine this tinting effect with numpy slicing and fancy-indexing to
selectively tint your images. In the example below, we set the hue of some
rectangles using slicing and scale the RGB values of some pixels found by
thresholding. In practice, you might want to define a region for tinting based
on segmentation results or blob detection methods.
"""
from skimage.filter import rank
# Square regions defined as slices over the first two dimensions.
top_left = (slice(100),) * 2
bottom_right = (slice(-100, None),) * 2
sliced_image = image.copy()
sliced_image[top_left] = colorize(image[top_left], 0.82, saturation=0.5)
sliced_image[bottom_right] = colorize(image[bottom_right], 0.5, saturation=0.5)
# Create a mask selecting regions with interesting texture.
noisy = rank.entropy(grayscale_image, np.ones((9, 9)))
textured_regions = noisy > 4
# Note that using `colorize` here is a bit more difficult, since `rgb2hsv`
# expects an RGB image (height x width x channel), but fancy-indexing returns
# a set of RGB pixels (# pixels x channel).
masked_image = image.copy()
masked_image[textured_regions, :] *= red_multiplier
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4))
ax1.imshow(sliced_image)
ax2.imshow(masked_image)
plt.show()
"""
.. image:: PLOT2RST.current_figure
For coloring multiple regions, you may also be interested in
`skimage.color.label2rgb <http://scikit-image.org/docs/0.9.x/api/skimage.color.html#label2rgb>`_.
.. _color spaces:
http://en.wikipedia.org/wiki/List_of_color_spaces_and_their_uses
.. _HSV: http://en.wikipedia.org/wiki/HSL_and_HSV
"""
+1 -1
View File
@@ -60,5 +60,5 @@ ax2.imshow(max_view, cmap=cm.Greys_r)
ax3.set_title("Block view with\n local median pooling")
ax3.imshow(median_view, cmap=cm.Greys_r)
plt.subplots_adjust(hspace=0.4, wspace=0.4)
fig.subplots_adjust(hspace=0.4, wspace=0.4)
plt.show()
+1 -1
View File
@@ -61,6 +61,6 @@ ax2.set_title('Separated objects')
for ax in axes:
ax.axis('off')
plt.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
right=1)
plt.show()
+7 -6
View File
@@ -9,7 +9,6 @@ import pydoc
from StringIO import StringIO
from warnings import warn
class Reader(object):
"""A line-based string reader.
@@ -233,7 +232,8 @@ class NumpyDocString(object):
current_func = None
if ',' in line:
for func in line.split(','):
push_item(func, [])
if func.strip():
push_item(func, [])
elif line.strip():
current_func = line
elif current_func is not None:
@@ -284,8 +284,8 @@ class NumpyDocString(object):
for (section,content) in self._read_sections():
if not section.startswith('..'):
section = ' '.join([s.capitalize() for s in section.split(' ')])
if section in ('Parameters', 'Attributes', 'Methods',
'Returns', 'Raises', 'Warns'):
if section in ('Parameters', 'Returns', 'Raises', 'Warns',
'Other Parameters', 'Attributes', 'Methods'):
self[section] = self._parse_param_list(content)
elif section.startswith('.. index::'):
self['index'] = self._parse_index(section, content)
@@ -370,7 +370,7 @@ class NumpyDocString(object):
idx = self['index']
out = []
out += ['.. index:: %s' % idx.get('default','')]
for section, references in idx.items():
for section, references in idx.iteritems():
if section == 'default':
continue
out += [' :%s: %s' % (section, ', '.join(references))]
@@ -381,7 +381,8 @@ class NumpyDocString(object):
out += self._str_signature()
out += self._str_summary()
out += self._str_extended_summary()
for param_list in ('Parameters','Returns','Raises'):
for param_list in ('Parameters', 'Returns', 'Other Parameters',
'Raises', 'Warns'):
out += self._str_param_list(param_list)
out += self._str_section('Warnings')
out += self._str_see_also(func_role)
+3 -3
View File
@@ -2,7 +2,6 @@ import re, inspect, textwrap, pydoc
import sphinx
from docscrape import NumpyDocString, FunctionDoc, ClassDoc
class SphinxDocString(NumpyDocString):
def __init__(self, docstring, config={}):
self.use_plots = config.get('use_plots', False)
@@ -128,7 +127,7 @@ class SphinxDocString(NumpyDocString):
return out
out += ['.. index:: %s' % idx.get('default','')]
for section, references in idx.items():
for section, references in idx.iteritems():
if section == 'default':
continue
elif section == 'refguide':
@@ -179,7 +178,8 @@ class SphinxDocString(NumpyDocString):
out += self._str_index() + ['']
out += self._str_summary()
out += self._str_extended_summary()
for param_list in ('Parameters', 'Returns', 'Raises'):
for param_list in ('Parameters', 'Returns', 'Other Parameters',
'Raises', 'Warns'):
out += self._str_param_list(param_list)
out += self._str_warnings()
out += self._str_see_also(func_role)
+126
View File
@@ -0,0 +1,126 @@
__all__ = ['python_to_notebook', 'Notebook']
import json
import copy
import warnings
# Skeleton notebook in JSON format
skeleton_nb = """{
"metadata": {
"name":""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"%matplotlib inline"
],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}"""
class Notebook(object):
"""
Notebook object for building an IPython notebook cell-by-cell.
"""
def __init__(self):
# cell type code
self.cell_code = {
'cell_type': 'code',
'collapsed': False,
'input': [
'# Code Goes Here'
],
'language': 'python',
'metadata': {},
'outputs': []
}
# cell type markdown
self.cell_md = {
'cell_type': 'markdown',
'metadata': {},
'source': [
'Markdown Goes Here'
]
}
self.template = json.loads(skeleton_nb)
self.cell_type = {'input': self.cell_code, 'source': self.cell_md}
self.valuetype_to_celltype = {'code': 'input', 'markdown': 'source'}
def add_cell(self, value, cell_type='code'):
"""Add a notebook cell.
Parameters
----------
value : str
Cell content.
cell_type : {'code', 'markdown'}
Type of content (default is 'code').
"""
if cell_type in ['markdown', 'code']:
key = self.valuetype_to_celltype[cell_type]
cells = self.template['worksheets'][0]['cells']
cells.append(copy.deepcopy(self.cell_type[key]))
# assign value to the last cell
cells[-1][key] = value
else:
warnings.warn('Ignoring unsupported cell type (%s)' % cell_type)
def json(self):
"""Return a JSON representation of the notebook.
Returns
-------
str
JSON notebook.
"""
return json.dumps(self.template, indent=2)
def test_notebook_basic():
nb = Notebook()
assert(json.loads(nb.json()) == json.loads(skeleton_nb))
def test_notebook_add():
nb = Notebook()
str1 = 'hello world'
str2 = 'f = lambda x: x * x'
nb.add_cell(str1, cell_type='markdown')
nb.add_cell(str2, cell_type='code')
d = json.loads(nb.json())
cells = d['worksheets'][0]['cells']
values = [c['input'] if c['cell_type'] == 'code' else c['source']
for c in cells]
assert values[1] == str1
assert values[2] == str2
assert cells[1]['cell_type'] == 'markdown'
assert cells[2]['cell_type'] == 'code'
if __name__ == "__main__":
import numpy.testing as npt
npt.run_module_suite()
+38 -2
View File
@@ -80,6 +80,10 @@ from skimage import io
from skimage import transform
from skimage.util.dtype import dtype_range
from notebook import Notebook
from docutils.core import publish_parts
LITERALINCLUDE = """
.. literalinclude:: {src_name}
@@ -94,6 +98,13 @@ CODE_LINK = """
"""
NOTEBOOK_LINK = """
**IPython Notebook:** :download:`download <{0}>`
(generated using ``skimage`` |version|)
"""
TOCTREE_TEMPLATE = """
.. toctree::
:hidden:
@@ -305,16 +316,20 @@ def write_example(src_name, src_dir, rst_dir, cfg):
image_dir = rst_dir.pjoin('images')
thumb_dir = image_dir.pjoin('thumb')
notebook_dir = rst_dir.pjoin('notebook')
image_dir.makedirs()
thumb_dir.makedirs()
notebook_dir.makedirs()
base_image_name = os.path.splitext(src_name)[0]
image_path = image_dir.pjoin(base_image_name + '_{0}.png')
basename, py_ext = os.path.splitext(src_name)
rst_path = rst_dir.pjoin(basename + cfg.source_suffix)
notebook_path = notebook_dir.pjoin(basename + '.ipynb')
if _plots_are_current(src_path, image_path) and rst_path.exists:
if _plots_are_current(src_path, image_path) and rst_path.exists and \
notebook_path.exists:
return
blocks = split_code_and_text_blocks(example_file)
@@ -341,8 +356,11 @@ def write_example(src_name, src_dir, rst_dir, cfg):
example_rst += LITERALINCLUDE.format(**code_info)
example_rst += CODE_LINK.format(src_name)
ipnotebook_name = src_name.replace('.py', '.ipynb')
ipnotebook_name = './notebook/' + ipnotebook_name
example_rst += NOTEBOOK_LINK.format(ipnotebook_name)
f = open(rst_path,'w')
f = open(rst_path, 'w')
f.write(example_rst)
f.flush()
@@ -359,6 +377,24 @@ def write_example(src_name, src_dir, rst_dir, cfg):
else:
shutil.copy(cfg.plot2rst_default_thumb, thumb_path)
# Export example to IPython notebook
nb = Notebook()
for (cell_type, _, content) in blocks:
content = content.rstrip('\n')
if cell_type == 'code':
nb.add_cell(content, cell_type='code')
else:
content = content.replace('"""', '')
content = '\n'.join([line for line in content.split('\n') if
not line.startswith('.. image')])
html = publish_parts(content, writer_name='html')['html_body']
nb.add_cell(html, cell_type='markdown')
with open(notebook_path, 'w') as f:
f.write(nb.json())
def save_thumbnail(image, thumb_path, shape):
"""Save image as a thumbnail with the specified shape.
Regular → Executable
+7 -6
View File
@@ -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:scikit-image/docs.git'
pages_repo = 'https://github.com/scikit-image/docs.git'
#-----------------------------------------------------------------------------
# Functions
@@ -86,13 +86,14 @@ if __name__ == '__main__':
if l.startswith('VERSION'):
tag = l.split("'")[1]
# Rename to, e.g., 0.9.x
tag = '.'.join(tag.split('.')[:-1] + ['x'])
if "dev" in tag:
tag = "dev"
else:
# Rename e.g. 0.9.0 to 0.9.x
tag = '.'.join(tag.split('.')[:-1] + ['x'])
break
if "dev" in tag:
tag = "dev"
startdir = os.getcwd()
if not os.path.exists(pages_dir):
@@ -124,7 +125,7 @@ if __name__ == '__main__':
sh("touch .nojekyll")
sh('git add .nojekyll')
sh('git add index.html')
sh('git add %s' % tag)
sh('git add --all %s' % tag)
sh2('git commit -m"Updated doc release: %s"' % tag)
print('Most recent commit:')
+8 -9
View File
@@ -5,16 +5,16 @@ import string
import shlex
if len(sys.argv) != 2:
print "Usage: ./contributors.py tag-of-previous-release"
print("Usage: ./contributors.py tag-of-previous-release")
sys.exit(-1)
tag = sys.argv[1]
def call(cmd):
return subprocess.check_output(shlex.split(cmd)).split('\n')
return subprocess.check_output(shlex.split(cmd), universal_newlines=True).split('\n')
tag_date = call("git show --format='%%ci' %s" % tag)[0]
print "Release %s was on %s" % (tag, tag_date)
print("Release %s was on %s" % (tag, tag_date))
merges = call("git log --since='%s' --merges --format='>>>%%B' --reverse" % tag_date)
merges = [m for m in merges if m.strip()]
@@ -22,27 +22,26 @@ merges = '\n'.join(merges).split('>>>')
merges = [m.split('\n')[:2] for m in merges]
merges = [m for m in merges if len(m) == 2 and m[1].strip()]
print "\nIt contained the following %d merges:" % len(merges)
print
print("\nIt contained the following %d merges:\n" % len(merges))
for (merge, message) in merges:
if merge.startswith('Merge pull request #'):
PR = ' (%s)' % merge.split()[3]
else:
PR = ''
print '- ' + message + PR
print('- ' + message + PR)
print "\nMade by the following committers [alphabetical by last name]:\n"
print("\nMade by the following committers [alphabetical by last name]:\n")
authors = call("git log --since='%s' --format=%%aN" % tag_date)
authors = [a.strip() for a in authors if a.strip()]
def key(author):
author = [v for v in author.split() if v[0] in string.letters]
author = [v for v in author.split() if v[0] in string.ascii_letters]
return author[-1]
authors = sorted(set(authors), key=key)
for a in authors:
print '-', a
print('- ' + a)
+1 -1
View File
@@ -1,4 +1,4 @@
var versions = ['dev', '0.9.x', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
var versions = ['dev', '0.10.x', '0.9.x', '0.8.0', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
function insert_version_links() {
for (i = 0; i < versions.length; i++){
+4 -1
View File
@@ -1,3 +1,7 @@
Version 0.10
------------
- Removed ``skimage.io.video`` functionality due to broken gstreamer bindings
Version 0.9
-----------
- No longer wrap ``imread`` output in an ``Image`` class
@@ -20,4 +24,3 @@ Version 0.3
- Remove ``as_grey``, ``dtype`` keyword from ImageCollection
- Remove ``dtype`` from imread
- Generalise ImageCollection to accept a load_func
+3 -3
View File
@@ -5,9 +5,9 @@ Pre-built installation
<http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image>`__
are kindly provided by Christoph Gohlke.
The latest stable release is also included as part of the `Enthought Python
Distribution (EPD) <http://enthought.com/products/epd.php>`__, `Python(x,y)
<http://code.google.com/p/pythonxy/wiki/Welcome>`__ and
The latest stable release is also included as part of
`Enthought Canopy <https://www.enthought.com/products/canopy/>`__,
`Python(x,y) <http://code.google.com/p/pythonxy/wiki/Welcome>`__ and
`Anaconda <https://store.continuum.io/cshop/anaconda/>`__.
On Debian and Ubuntu, a Debian package ``python-skimage`` can be found in
+5 -1
View File
@@ -134,7 +134,11 @@ dtype range::
Here, the ``in_range`` argument is set to the maximum range for a 10-bit image.
By default, ``rescale_intensity`` stretches the values of ``in_range`` to match
the range of the dtype.
the range of the dtype. ``rescale_intensity`` also accepts strings as inputs
to ``in_range`` and ``out_range``, so the example above could also be written
as::
>>> image = exposure.rescale_intensity(img10bit, in_range='uint10')
Note about negative values
+23 -10
View File
@@ -24,26 +24,37 @@ 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:
let's see an example of how a pre-defined plugin is added to the viewer:
.. code-block:: python
from skimage.viewer.plugins import Canny
from skimage.viewer.plugins.lineprofile import LineProfile
viewer = ImageViewer(image)
viewer += Canny(view)
viewer.show()
viewer += LineProfile(viewer)
overlay, data = viewer.show()[0]
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``:
The viewer's ``show()`` method returns a list of tuples, one for each attached
plugin. Each tuple contains two elements: an overlay of the same shape as the
input image, and a data field (which may be ``None``). A plugin class documents
its return value in its ``output`` method.
In this example, only one plugin is attached, so the list returned by ``show``
will have length 1. We extract the single tuple and bind its ``overlay`` and
``data`` elements to individual variables. Here, ``overlay`` contains an image
of the line drawn on the viewer, and ``data`` contains the 1-dimensional
intensity profile along that line.
At the moment, there are not many plugins pre-defined, but there is a really
simple interface for creating your own plugin. First, let us create a plugin to
call the total-variation denoising function, ``denoise_tv_bregman``:
.. code-block:: python
from skimage.filter import tv_denoise
from skimage.filter import denoise_tv_bregman
from skimage.viewer.plugins.base import Plugin
denoise_plugin = Plugin(image_filter=tv_denoise)
denoise_plugin = Plugin(image_filter=denoise_tv_bregman)
.. note::
@@ -74,8 +85,10 @@ All that's left is to create an image viewer and add the plugin to that viewer.
viewer = ImageViewer(image)
viewer += denoise_plugin
viewer.show()
denoised = viewer.show()[0][0]
Here, we access only the overlay returned by the plugin, which contains the
filtered image for the last used setting of ``weight``.
.. image:: data/denoise_viewer_window.png
.. image:: data/denoise_plugin_window.png
+1 -1
View File
@@ -1,6 +1,6 @@
These files were obtained from
http://groups.google.com/group/sphinx-dev/browse_thread/thread/595ef2eff60084c5/
https://www.mail-archive.com/sphinx-dev@googlegroups.com/msg02472.html
and were released under a BSD/MIT license by Fernando Perez, Matthew Brett and
the PyMVPA guys.
+1
View File
@@ -1,3 +1,4 @@
cython>=0.17
matplotlib>=1.0
numpy>=1.6
six>=1.3.0
+7 -2
View File
@@ -17,13 +17,18 @@ MAINTAINER_EMAIL = 'stefan@sun.ac.za'
URL = 'http://scikit-image.org'
LICENSE = 'Modified BSD'
DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image'
VERSION = '0.9.3'
VERSION = '0.10.0'
PYTHON_VERSION = (2, 5)
DEPENDENCIES = {
'numpy': (1, 6),
'Cython': (0, 17),
'six': (1, 3),
}
# Only require Cython if we have a developer checkout
if VERSION.endswith('dev'):
DEPENDENCIES['Cython'] = (0, 17)
import os
import sys
+46 -41
View File
@@ -14,27 +14,34 @@ color
data
Test images and example data.
draw
Image drawing primitives (lines, text, etc.).
Drawing primitives (lines, text, etc.) that operate on NumPy arrays.
exposure
Image intensity adjustment (e.g., histogram equalization).
Image intensity adjustment, e.g., histogram equalization, etc.
feature
Feature detection (e.g. texture analysis, corners, etc.).
Feature detection and extraction, e.g., texture analysis corners, etc.
filter
Sharpening, edge finding, denoising, etc.
Sharpening, edge finding, rank filters, thresholding, etc.
graph
Graph-theoretic operations, e.g. dynamic programming (shortest paths).
Graph-theoretic operations, e.g., shortest paths.
io
Reading, saving, and displaying images and video.
measure
Measurement of image properties, e.g., similarity and contours.
morphology
Morphological operations, e.g. opening or skeletonization.
Morphological operations, e.g., opening or skeletonization.
novice
Simplified interface for teaching purposes.
restoration
Restoration algorithms, e.g., deconvolution algorithms, denoising, etc.
segmentation
Splitting an image into self-similar regions.
Partitioning an image into multiple regions.
transform
Geometric and other transforms, e.g. rotation or the Radon transform.
Geometric and other transforms, e.g., rotation or the Radon transform.
util
Generic utilities.
viewer
A simple graphical user interface for visualizing results and exploring
parameters.
Utility Functions
-----------------
@@ -52,6 +59,7 @@ img_as_ubyte
import os.path as _osp
import imp as _imp
import functools as _functools
import warnings as _warnings
from skimage._shared.utils import deprecated as _deprecated
pkg_dir = _osp.abspath(_osp.dirname(__file__))
@@ -68,24 +76,48 @@ try:
_imp.find_module('nose')
except ImportError:
def _test(verbose=False):
"""This would invoke the skimage test suite, but nose couldn't be
"""This would run all unit tests, but nose couldn't be
imported so the test suite can not run.
"""
raise ImportError("Could not load nose. Unit tests not available.")
def _doctest(verbose=False):
"""This would run all doc tests, but nose couldn't be
imported so the test suite can not run.
"""
raise ImportError("Could not load nose. Doctests not available.")
else:
def _test(verbose=False):
"""Invoke the skimage test suite."""
def _test(doctest=False, verbose=False):
"""Run all unit tests."""
import nose
args = ['', pkg_dir, '--exe']
args = ['', pkg_dir, '--exe', '--ignore-files=^_test']
if verbose:
args.extend(['-v', '-s'])
nose.run('skimage', argv=args)
if doctest:
args.extend(['--with-doctest', '--ignore-files=^\.',
'--ignore-files=^setup\.py$$', '--ignore-files=test'])
# Make sure warnings do not break the doc tests
with _warnings.catch_warnings():
_warnings.simplefilter("ignore")
success = nose.run('skimage', argv=args)
else:
success = nose.run('skimage', argv=args)
# Return sys.exit code
if success:
return 0
else:
return 1
# 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__
doctest = _functools.partial(test, doctest=True)
doctest.__doc__ = doctest.__doc__
doctest_verbose = _functools.partial(test, doctest=True, verbose=True)
doctest_verbose.__doc__ = doctest.__doc__
class _Log(Warning):
@@ -105,10 +137,9 @@ class _FakeLog(object):
"""
self._name = name
import warnings
warnings.simplefilter("always", _Log)
self._warnings = warnings
self._warnings = _warnings
def _warn(self, msg, wtype):
self._warnings.warn('%s: %s' % (wtype, msg), _Log)
@@ -137,30 +168,4 @@ class _FakeLog(object):
pass
@_deprecated()
def get_log(name=None):
"""Return a console logger.
Output may be sent to the logger using the `debug`, `info`, `warning`,
`error` and `critical` methods.
Parameters
----------
name : str
Name of the log.
References
----------
.. [1] Logging facility for Python,
http://docs.python.org/library/logging.html
"""
if name is None:
name = 'skimage'
else:
name = 'skimage.' + name
return _FakeLog(name)
from .util.dtype import *
+3 -21
View File
@@ -3,7 +3,6 @@ import os
import hashlib
import subprocess
# WindowsError is not defined on unix systems
try:
WindowsError
@@ -26,7 +25,7 @@ def cython(pyx_files, working_path=''):
return
try:
import Cython
from Cython.Build import cythonize
except ImportError:
# If cython is not found, we do nothing -- the build will make use of
# the distributed .c files
@@ -39,24 +38,7 @@ def cython(pyx_files, working_path=''):
if not _changed(pyxfile):
continue
c_file = pyxfile[:-4] + '.c'
# run cython compiler
cmd = 'cython -o %s %s' % (c_file, pyxfile)
print(cmd)
try:
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.
subprocess.call(
[sys.executable,
os.path.join(os.path.dirname(sys.executable),
'Scripts', 'cython.py'),
'-o', c_file, pyxfile],
shell=True)
cythonize(pyxfile)
def _md5sum(f):
m = hashlib.new('md5')
@@ -86,4 +68,4 @@ def _changed(filename):
with open(filename_cache, 'wb') as cf:
cf.write(md5_new.encode('utf-8'))
return md5_cached != md5_new
return md5_cached != md5_new.encode('utf-8')
+63
View File
@@ -0,0 +1,63 @@
__all__ = ['all_warnings']
from contextlib import contextmanager
import sys
import warnings
import inspect
@contextmanager
def all_warnings():
"""
Context for use in testing to ensure that all warnings are raised.
Examples
--------
>>> import warnings
>>> def foo():
... warnings.warn(RuntimeWarning("bar"))
We raise the warning once, while the warning filter is set to "once".
Hereafter, the warning is invisible, even with custom filters:
>>> with warnings.catch_warnings():
... warnings.simplefilter('once')
... foo()
We can now run ``foo()`` without a warning being raised:
>>> from numpy.testing import assert_warns
>>> foo()
To catch the warning, we call in the help of ``all_warnings``:
>>> with all_warnings():
... assert_warns(RuntimeWarning, foo)
"""
# Whenever a warning is triggered, Python adds a __warningregistry__
# member to the *calling* module. The exercize here is to find
# and eradicate all those breadcrumbs that were left lying around.
#
# We proceed by first searching all parent calling frames and explicitly
# clearing their warning registries (necessary for the doctests above to
# pass). Then, we search for all submodules of skimage and clear theirs
# as well (necessary for the skimage test suite to pass).
frame = inspect.currentframe()
if frame:
for f in inspect.getouterframes(frame):
f[0].f_locals['__warningregistry__'] = {}
del frame
for mod_name, mod in list(sys.modules.items()):
if 'six.moves' in mod_name:
continue
try:
mod.__warningregistry__.clear()
except AttributeError:
pass
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
yield w
+326 -20
View File
@@ -1,27 +1,333 @@
#cython: cdivision=True
#cython: boundscheck=False
#cython: nonecheck=False
#cython: wraparound=False
from libc.math cimport ceil, floor
cdef double nearest_neighbour_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r,
double c, char mode,
double cval)
cdef double bilinear_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols,
double r, double c, char mode,
double cval)
cdef inline Py_ssize_t round(double r):
return <Py_ssize_t>((r + 0.5) if (r > 0.0) else (r - 0.5))
cdef double quadratic_interpolation(double x, double[3] f)
cdef double biquadratic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols,
double r, double c, char mode,
double cval)
cdef double cubic_interpolation(double x, double[4] f)
cdef double bicubic_interpolation(double* image, Py_ssize_t rows, Py_ssize_t cols,
double r, double c, char mode,
double cval)
cdef inline double nearest_neighbour_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r,
double c, char mode,
double cval):
"""Nearest neighbour interpolation at a given position in the image.
cdef double get_pixel2d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t r,
Py_ssize_t c, char mode, double cval)
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
cdef double get_pixel3d(double* image, Py_ssize_t rows, Py_ssize_t cols, Py_ssize_t dims,
Py_ssize_t r, Py_ssize_t c, Py_ssize_t d, char mode, double cval)
Returns
-------
value : double
Interpolated value.
cdef Py_ssize_t coord_map(Py_ssize_t dim, Py_ssize_t coord, char mode)
"""
return get_pixel2d(image, rows, cols, round(r), round(c), mode, cval)
cdef inline double bilinear_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Bilinear interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef double dr, dc
cdef Py_ssize_t minr, minc, maxr, maxc
minr = <Py_ssize_t>floor(r)
minc = <Py_ssize_t>floor(c)
maxr = <Py_ssize_t>ceil(r)
maxc = <Py_ssize_t>ceil(c)
dr = r - minr
dc = c - minc
top = (1 - dc) * get_pixel2d(image, rows, cols, minr, minc, mode, cval) \
+ dc * get_pixel2d(image, rows, cols, minr, maxc, mode, cval)
bottom = (1 - dc) * get_pixel2d(image, rows, cols, maxr, minc, mode, cval) \
+ dc * get_pixel2d(image, rows, cols, maxr, maxc, mode, cval)
return (1 - dr) * top + dr * bottom
cdef inline double quadratic_interpolation(double x, double[3] f):
"""Quadratic interpolation.
Parameters
----------
x : double
Position in the interval [-1, 1].
f : double[4]
Function values at positions [-1, 0, 1].
Returns
-------
value : double
Interpolated value.
"""
return f[1] - 0.25 * (f[0] - f[2]) * x
cdef inline double biquadratic_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Biquadratic interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef Py_ssize_t r0 = round(r)
cdef Py_ssize_t c0 = round(c)
if r < 0:
r0 -= 1
if c < 0:
c0 -= 1
# scale position to range [-1, 1]
cdef double xr = (r - r0) - 1
cdef double xc = (c - c0) - 1
if r == r0:
xr += 1
if c == c0:
xc += 1
cdef double fc[3]
cdef double fr[3]
cdef Py_ssize_t pr, pc
# row-wise cubic interpolation
for pr in range(r0, r0 + 3):
for pc in range(c0, c0 + 3):
fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval)
fr[pr - r0] = quadratic_interpolation(xc, fc)
# cubic interpolation for interpolated values of each row
return quadratic_interpolation(xr, fr)
cdef inline double cubic_interpolation(double x, double[4] f):
"""Cubic interpolation.
Parameters
----------
x : double
Position in the interval [0, 1].
f : double[4]
Function values at positions [0, 1/3, 2/3, 1].
Returns
-------
value : double
Interpolated value.
"""
return \
f[1] + 0.5 * x * \
(f[2] - f[0] + x * \
(2.0 * f[0] - 5.0 * f[1] + 4.0 * f[2] - f[3] + x * \
(3.0 * (f[1] - f[2]) + f[3] - f[0])))
cdef inline double bicubic_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Bicubic interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef Py_ssize_t r0 = <Py_ssize_t>r - 1
cdef Py_ssize_t c0 = <Py_ssize_t>c - 1
if r < 0:
r0 -= 1
if c < 0:
c0 -= 1
# scale position to range [0, 1]
cdef double xr = (r - r0) / 3
cdef double xc = (c - c0) / 3
cdef double fc[4]
cdef double fr[4]
cdef Py_ssize_t pr, pc
# row-wise cubic interpolation
for pr in range(r0, r0 + 4):
for pc in range(c0, c0 + 4):
fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval)
fr[pr - r0] = cubic_interpolation(xc, fc)
# cubic interpolation for interpolated values of each row
return cubic_interpolation(xr, fr)
cdef inline double get_pixel2d(double* image, Py_ssize_t rows, Py_ssize_t cols,
Py_ssize_t r, Py_ssize_t c, char mode, double cval):
"""Get a pixel from the image, taking wrapping mode into consideration.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : int
Position at which to get the pixel.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Pixel value at given position.
"""
if mode == 'C':
if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1):
return cval
else:
return image[r * cols + c]
else:
return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)]
cdef inline double get_pixel3d(double* image, Py_ssize_t rows, Py_ssize_t cols,
Py_ssize_t dims, Py_ssize_t r, Py_ssize_t c, Py_ssize_t d,
char mode, double cval):
"""Get a pixel from the image, taking wrapping mode into consideration.
Parameters
----------
image : double array
Input image.
rows, cols, dims : int
Shape of image.
r, c, d : int
Position at which to get the pixel.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Pixel value at given position.
"""
if mode == 'C':
if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1):
return cval
else:
return image[r * cols * dims + c * dims + d]
else:
return image[coord_map(rows, r, mode) * cols * dims
+ coord_map(cols, c, mode) * dims
+ d]
cdef inline Py_ssize_t coord_map(Py_ssize_t dim, Py_ssize_t coord, char mode):
"""
Wrap a coordinate, according to a given mode.
Parameters
----------
dim : int
Maximum coordinate.
coord : int
Coord provided by user. May be < 0 or > dim.
mode : {'W', 'R', 'N'}
Whether to wrap or reflect the coordinate if it
falls outside [0, dim).
"""
dim = dim - 1
if mode == 'R': # reflect
if coord < 0:
# How many times times does the coordinate wrap?
if <Py_ssize_t>(-coord / dim) % 2 != 0:
return dim - <Py_ssize_t>(-coord % dim)
else:
return <Py_ssize_t>(-coord % dim)
elif coord > dim:
if <Py_ssize_t>(coord / dim) % 2 != 0:
return <Py_ssize_t>(dim - (coord % dim))
else:
return <Py_ssize_t>(coord % dim)
elif mode == 'W': # wrap
if coord < 0:
return <Py_ssize_t>(dim - (-coord % dim))
elif coord > dim:
return <Py_ssize_t>(coord % dim)
elif mode == 'N': # nearest
if coord < 0:
return 0
elif coord > dim:
return dim
return coord
-331
View File
@@ -1,331 +0,0 @@
#cython: cdivision=True
#cython: boundscheck=False
#cython: nonecheck=False
#cython: wraparound=False
from libc.math cimport ceil, floor
cdef inline Py_ssize_t round(double r):
return <Py_ssize_t>((r + 0.5) if (r > 0.0) else (r - 0.5))
cdef inline double nearest_neighbour_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r,
double c, char mode,
double cval):
"""Nearest neighbour interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
return get_pixel2d(image, rows, cols, round(r), round(c), mode, cval)
cdef inline double bilinear_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Bilinear interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef double dr, dc
cdef Py_ssize_t minr, minc, maxr, maxc
minr = <Py_ssize_t>floor(r)
minc = <Py_ssize_t>floor(c)
maxr = <Py_ssize_t>ceil(r)
maxc = <Py_ssize_t>ceil(c)
dr = r - minr
dc = c - minc
top = (1 - dc) * get_pixel2d(image, rows, cols, minr, minc, mode, cval) \
+ dc * get_pixel2d(image, rows, cols, minr, maxc, mode, cval)
bottom = (1 - dc) * get_pixel2d(image, rows, cols, maxr, minc, mode, cval) \
+ dc * get_pixel2d(image, rows, cols, maxr, maxc, mode, cval)
return (1 - dr) * top + dr * bottom
cdef inline double quadratic_interpolation(double x, double[3] f):
"""Quadratic interpolation.
Parameters
----------
x : double
Position in the interval [-1, 1].
f : double[4]
Function values at positions [-1, 0, 1].
Returns
-------
value : double
Interpolated value.
"""
return f[1] - 0.25 * (f[0] - f[2]) * x
cdef inline double biquadratic_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Biquadratic interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef Py_ssize_t r0 = round(r)
cdef Py_ssize_t c0 = round(c)
if r < 0:
r0 -= 1
if c < 0:
c0 -= 1
# scale position to range [-1, 1]
cdef double xr = (r - r0) - 1
cdef double xc = (c - c0) - 1
if r == r0:
xr += 1
if c == c0:
xc += 1
cdef double fc[3], fr[3]
cdef Py_ssize_t pr, pc
# row-wise cubic interpolation
for pr in range(r0, r0 + 3):
for pc in range(c0, c0 + 3):
fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval)
fr[pr - r0] = quadratic_interpolation(xc, fc)
# cubic interpolation for interpolated values of each row
return quadratic_interpolation(xr, fr)
cdef inline double cubic_interpolation(double x, double[4] f):
"""Cubic interpolation.
Parameters
----------
x : double
Position in the interval [0, 1].
f : double[4]
Function values at positions [0, 1/3, 2/3, 1].
Returns
-------
value : double
Interpolated value.
"""
return \
f[1] + 0.5 * x * \
(f[2] - f[0] + x * \
(2.0 * f[0] - 5.0 * f[1] + 4.0 * f[2] - f[3] + x * \
(3.0 * (f[1] - f[2]) + f[3] - f[0])))
cdef inline double bicubic_interpolation(double* image, Py_ssize_t rows,
Py_ssize_t cols, double r, double c,
char mode, double cval):
"""Bicubic interpolation at a given position in the image.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : double
Position at which to interpolate.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Interpolated value.
"""
cdef Py_ssize_t r0 = <Py_ssize_t>r - 1
cdef Py_ssize_t c0 = <Py_ssize_t>c - 1
if r < 0:
r0 -= 1
if c < 0:
c0 -= 1
# scale position to range [0, 1]
cdef double xr = (r - r0) / 3
cdef double xc = (c - c0) / 3
cdef double fc[4], fr[4]
cdef Py_ssize_t pr, pc
# row-wise cubic interpolation
for pr in range(r0, r0 + 4):
for pc in range(c0, c0 + 4):
fc[pc - c0] = get_pixel2d(image, rows, cols, pr, pc, mode, cval)
fr[pr - r0] = cubic_interpolation(xc, fc)
# cubic interpolation for interpolated values of each row
return cubic_interpolation(xr, fr)
cdef inline double get_pixel2d(double* image, Py_ssize_t rows, Py_ssize_t cols,
Py_ssize_t r, Py_ssize_t c, char mode, double cval):
"""Get a pixel from the image, taking wrapping mode into consideration.
Parameters
----------
image : double array
Input image.
rows, cols : int
Shape of image.
r, c : int
Position at which to get the pixel.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Pixel value at given position.
"""
if mode == 'C':
if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1):
return cval
else:
return image[r * cols + c]
else:
return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)]
cdef inline double get_pixel3d(double* image, Py_ssize_t rows, Py_ssize_t cols,
Py_ssize_t dims, Py_ssize_t r, Py_ssize_t c, Py_ssize_t d,
char mode, double cval):
"""Get a pixel from the image, taking wrapping mode into consideration.
Parameters
----------
image : double array
Input image.
rows, cols, dims : int
Shape of image.
r, c, d : int
Position at which to get the pixel.
mode : {'C', 'W', 'R', 'N'}
Wrapping mode. Constant, Wrap, Reflect or Nearest.
cval : double
Constant value to use for constant mode.
Returns
-------
value : double
Pixel value at given position.
"""
if mode == 'C':
if (r < 0) or (r > rows - 1) or (c < 0) or (c > cols - 1):
return cval
else:
return image[r * cols * dims + c * dims + d]
else:
return image[coord_map(rows, r, mode) * cols * dims
+ coord_map(cols, c, mode) * dims
+ d]
cdef inline Py_ssize_t coord_map(Py_ssize_t dim, Py_ssize_t coord, char mode):
"""
Wrap a coordinate, according to a given mode.
Parameters
----------
dim : int
Maximum coordinate.
coord : int
Coord provided by user. May be < 0 or > dim.
mode : {'W', 'R', 'N'}
Whether to wrap or reflect the coordinate if it
falls outside [0, dim).
"""
dim = dim - 1
if mode == 'R': # reflect
if coord < 0:
# How many times times does the coordinate wrap?
if <Py_ssize_t>(-coord / dim) % 2 != 0:
return dim - <Py_ssize_t>(-coord % dim)
else:
return <Py_ssize_t>(-coord % dim)
elif coord > dim:
if <Py_ssize_t>(coord / dim) % 2 != 0:
return <Py_ssize_t>(dim - (coord % dim))
else:
return <Py_ssize_t>(coord % dim)
elif mode == 'W': # wrap
if coord < 0:
return <Py_ssize_t>(dim - (-coord % dim))
elif coord > dim:
return <Py_ssize_t>(coord % dim)
elif mode == 'N': # nearest
if coord < 0:
return 0
elif coord > dim:
return dim
return coord
-3
View File
@@ -14,12 +14,9 @@ def configuration(parent_package='', top_path=None):
config.add_data_dir('tests')
cython(['geometry.pyx'], working_path=base_path)
cython(['interpolation.pyx'], working_path=base_path)
cython(['transform.pyx'], working_path=base_path)
config.add_extension('geometry', sources=['geometry.c'])
config.add_extension('interpolation', sources=['interpolation.c'],
include_dirs=[get_numpy_include_dirs()])
config.add_extension('transform', sources=['transform.c'],
include_dirs=[get_numpy_include_dirs()])
-423
View File
@@ -1,423 +0,0 @@
"""Utilities for writing code that runs on Python 2 and 3"""
# Copyright (c) 2010-2013 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import operator
import sys
import types
__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.3.0"
# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes
MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
if sys.platform.startswith("java"):
# Jython always uses 32 bits.
MAXSIZE = int((1 << 31) - 1)
else:
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
class X(object):
def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X
def _add_doc(func, doc):
"""Add documentation to a function."""
func.__doc__ = doc
def _import_module(name):
"""Import module, returning the module after the last dot."""
__import__(name)
return sys.modules[name]
class _LazyDescr(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, tp):
result = self._resolve()
setattr(obj, self.name, result)
# This is a bit ugly, but it avoids running this again.
delattr(tp, self.name)
return result
class MovedModule(_LazyDescr):
def __init__(self, name, old, new=None):
super(MovedModule, self).__init__(name)
if PY3:
if new is None:
new = name
self.mod = new
else:
self.mod = old
def _resolve(self):
return _import_module(self.mod)
class MovedAttribute(_LazyDescr):
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
super(MovedAttribute, self).__init__(name)
if PY3:
if new_mod is None:
new_mod = name
self.mod = new_mod
if new_attr is None:
if old_attr is None:
new_attr = name
else:
new_attr = old_attr
self.attr = new_attr
else:
self.mod = old_mod
if old_attr is None:
old_attr = name
self.attr = old_attr
def _resolve(self):
module = _import_module(self.mod)
return getattr(module, self.attr)
class _MovedItems(types.ModuleType):
"""Lazy loading of moved objects"""
_moved_attributes = [
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
MovedAttribute("reduce", "__builtin__", "functools"),
MovedAttribute("StringIO", "StringIO", "io"),
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
MovedModule("builtins", "__builtin__"),
MovedModule("configparser", "ConfigParser"),
MovedModule("copyreg", "copy_reg"),
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
MovedModule("http_cookies", "Cookie", "http.cookies"),
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
MovedModule("html_parser", "HTMLParser", "html.parser"),
MovedModule("http_client", "httplib", "http.client"),
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
MovedModule("cPickle", "cPickle", "pickle"),
MovedModule("queue", "Queue"),
MovedModule("reprlib", "repr"),
MovedModule("socketserver", "SocketServer"),
MovedModule("tkinter", "Tkinter"),
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
MovedModule("tkinter_colorchooser", "tkColorChooser",
"tkinter.colorchooser"),
MovedModule("tkinter_commondialog", "tkCommonDialog",
"tkinter.commondialog"),
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
"tkinter.simpledialog"),
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
MovedModule("winreg", "_winreg"),
]
for attr in _moved_attributes:
setattr(_MovedItems, attr.name, attr)
del attr
moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves")
def add_move(move):
"""Add an item to six.moves."""
setattr(_MovedItems, move.name, move)
def remove_move(name):
"""Remove item from six.moves."""
try:
delattr(_MovedItems, name)
except AttributeError:
try:
del moves.__dict__[name]
except KeyError:
raise AttributeError("no such move, %r" % (name,))
if PY3:
_meth_func = "__func__"
_meth_self = "__self__"
_func_closure = "__closure__"
_func_code = "__code__"
_func_defaults = "__defaults__"
_func_globals = "__globals__"
_iterkeys = "keys"
_itervalues = "values"
_iteritems = "items"
_iterlists = "lists"
else:
_meth_func = "im_func"
_meth_self = "im_self"
_func_closure = "func_closure"
_func_code = "func_code"
_func_defaults = "func_defaults"
_func_globals = "func_globals"
_iterkeys = "iterkeys"
_itervalues = "itervalues"
_iteritems = "iteritems"
_iterlists = "iterlists"
try:
advance_iterator = next
except NameError:
def advance_iterator(it):
return it.next()
next = advance_iterator
try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
if PY3:
def get_unbound_function(unbound):
return unbound
create_bound_method = types.MethodType
Iterator = object
else:
def get_unbound_function(unbound):
return unbound.im_func
def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)
class Iterator(object):
def next(self):
return type(self).__next__(self)
callable = callable
_add_doc(get_unbound_function,
"""Get the function out of a possibly unbound function""")
get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)
def iterkeys(d, **kw):
"""Return an iterator over the keys of a dictionary."""
return iter(getattr(d, _iterkeys)(**kw))
def itervalues(d, **kw):
"""Return an iterator over the values of a dictionary."""
return iter(getattr(d, _itervalues)(**kw))
def iteritems(d, **kw):
"""Return an iterator over the (key, value) pairs of a dictionary."""
return iter(getattr(d, _iteritems)(**kw))
def iterlists(d, **kw):
"""Return an iterator over the (key, [values]) pairs of a dictionary."""
return iter(getattr(d, _iterlists)(**kw))
if PY3:
def b(s):
return s.encode("latin-1")
def u(s):
return s
unichr = chr
if sys.version_info[1] <= 1:
def int2byte(i):
return bytes((i,))
else:
# This is about 2x faster than the implementation above on 3.2+
int2byte = operator.methodcaller("to_bytes", 1, "big")
byte2int = operator.itemgetter(0)
indexbytes = operator.getitem
iterbytes = iter
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
else:
def b(s):
return s
def u(s):
return unicode(s, "unicode_escape")
unichr = unichr
int2byte = chr
def byte2int(bs):
return ord(bs[0])
def indexbytes(buf, i):
return ord(buf[i])
def iterbytes(buf):
return (ord(byte) for byte in buf)
import StringIO
StringIO = BytesIO = StringIO.StringIO
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")
if PY3:
import builtins
exec_ = getattr(builtins, "exec")
def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
print_ = getattr(builtins, "print")
del builtins
else:
def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")
exec_("""def reraise(tp, value, tb=None):
raise tp, value, tb
""")
def print_(*args, **kwargs):
"""The new-style print function."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return
def write(data):
if not isinstance(data, basestring):
data = str(data)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
_add_doc(reraise, """Reraise an exception.""")
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
return meta("NewBase", bases, {})
+51
View File
@@ -1,6 +1,12 @@
"""Testing utilities."""
import re
SKIP_RE = re.compile("(\s*>>>.*?)(\s*)#\s*skip\s+if\s+(.*)$")
def _assert_less(a, b, msg=None):
message = "%r is not lower than %r" % (a, b)
if msg is not None:
@@ -24,3 +30,48 @@ try:
from nose.tools import assert_greater
except ImportError:
assert_greater = _assert_greater
def doctest_skip_parser(func):
""" Decorator replaces custom skip test markup in doctests
Say a function has a docstring::
>>> something # skip if not HAVE_AMODULE
>>> something + else
>>> something # skip if HAVE_BMODULE
This decorator will evaluate the expresssion after ``skip if``. If this
evaluates to True, then the comment is replaced by ``# doctest: +SKIP``. If
False, then the comment is just removed. The expression is evaluated in the
``globals`` scope of `func`.
For example, if the module global ``HAVE_AMODULE`` is False, and module
global ``HAVE_BMODULE`` is False, the returned function will have docstring::
>>> something # doctest: +SKIP
>>> something + else
>>> something
"""
lines = func.__doc__.split('\n')
new_lines = []
for line in lines:
match = SKIP_RE.match(line)
if match is None:
new_lines.append(line)
continue
code, space, expr = match.groups()
try:
# Works as a function decorator
if eval(expr, func.__globals__):
code = code + space + "# doctest: +SKIP"
except AttributeError:
# Works as a class decorator
if eval(expr, func.__init__.__globals__):
code = code + space + "# doctest: +SKIP"
new_lines.append(code)
func.__doc__ = "\n".join(new_lines)
return func
+36
View File
@@ -0,0 +1,36 @@
import numpy as np
from skimage._shared.utils import safe_as_int
def test_int_cast_not_possible():
np.testing.assert_raises(ValueError, safe_as_int, 7.1)
np.testing.assert_raises(ValueError, safe_as_int, [7.1, 0.9])
np.testing.assert_raises(ValueError, safe_as_int, np.r_[7.1, 0.9])
np.testing.assert_raises(ValueError, safe_as_int, (7.1, 0.9))
np.testing.assert_raises(ValueError, safe_as_int, ((3, 4, 1),
(2, 7.6, 289)))
np.testing.assert_raises(ValueError, safe_as_int, 7.1, 0.09)
np.testing.assert_raises(ValueError, safe_as_int, [7.1, 0.9], 0.09)
np.testing.assert_raises(ValueError, safe_as_int, np.r_[7.1, 0.9], 0.09)
np.testing.assert_raises(ValueError, safe_as_int, (7.1, 0.9), 0.09)
np.testing.assert_raises(ValueError, safe_as_int, ((3, 4, 1),
(2, 7.6, 289)), 0.25)
def test_int_cast_possible():
np.testing.assert_equal(safe_as_int(7.1, atol=0.11), 7)
np.testing.assert_equal(safe_as_int(-7.1, atol=0.11), -7)
np.testing.assert_equal(safe_as_int(41.9, atol=0.11), 42)
np.testing.assert_array_equal(safe_as_int([2, 42, 5789234.0, 87, 4]),
np.r_[2, 42, 5789234, 87, 4])
np.testing.assert_array_equal(safe_as_int(np.r_[[[3, 4, 1.000000001],
[7, 2, -8.999999999],
[6, 9, -4234918347.]]]),
np.r_[[[3, 4, 1],
[7, 2, -9],
[6, 9, -4234918347]]])
if __name__ == '__main__':
np.testing.run_module_suite()
+87
View File
@@ -0,0 +1,87 @@
""" Testing decorators module
"""
import numpy as np
from nose.tools import (assert_true, assert_raises, assert_equal)
from skimage._shared.testing import doctest_skip_parser
def test_skipper():
def f():
pass
class c():
def __init__(self):
self.me = "I think, therefore..."
docstring = \
""" Header
>>> something # skip if not HAVE_AMODULE
>>> something + else
>>> a = 1 # skip if not HAVE_BMODULE
>>> something2 # skip if HAVE_AMODULE
"""
f.__doc__ = docstring
c.__doc__ = docstring
global HAVE_AMODULE, HAVE_BMODULE
HAVE_AMODULE = False
HAVE_BMODULE = True
f2 = doctest_skip_parser(f)
c2 = doctest_skip_parser(c)
assert_true(f is f2)
assert_true(c is c2)
assert_equal(f2.__doc__,
""" Header
>>> something # doctest: +SKIP
>>> something + else
>>> a = 1
>>> something2
""")
assert_equal(c2.__doc__,
""" Header
>>> something # doctest: +SKIP
>>> something + else
>>> a = 1
>>> something2
""")
HAVE_AMODULE = True
HAVE_BMODULE = False
f.__doc__ = docstring
c.__doc__ = docstring
f2 = doctest_skip_parser(f)
c2 = doctest_skip_parser(c)
assert_true(f is f2)
assert_equal(f2.__doc__,
""" Header
>>> something
>>> something + else
>>> a = 1 # doctest: +SKIP
>>> something2 # doctest: +SKIP
""")
assert_equal(c2.__doc__,
""" Header
>>> something
>>> something + else
>>> a = 1 # doctest: +SKIP
>>> something2 # doctest: +SKIP
""")
del HAVE_AMODULE
f.__doc__ = docstring
c.__doc__ = docstring
assert_raises(NameError, doctest_skip_parser, f)
assert_raises(NameError, doctest_skip_parser, c)
if __name__ == '__main__':
np.testing.run_module_suite()
+1
View File
@@ -41,4 +41,5 @@ cdef float integrate(float[:, ::1] sat, Py_ssize_t r0, Py_ssize_t c0,
if (c0 - 1 >= 0):
S -= sat[r1, c0 - 1]
return S
+72 -2
View File
@@ -1,11 +1,14 @@
import warnings
import functools
import sys
import numpy as np
from . import six
import six
from ._warnings import all_warnings
__all__ = ['deprecated', 'get_bound_method_class']
__all__ = ['deprecated', 'get_bound_method_class', 'all_warnings',
'safe_as_int']
class skimage_deprecation(Warning):
@@ -71,3 +74,70 @@ def get_bound_method_class(m):
"""
return m.im_class if sys.version < '3' else m.__self__.__class__
def safe_as_int(val, atol=1e-3):
"""
Attempt to safely cast values to integer format.
Parameters
----------
val : scalar or iterable of scalars
Number or container of numbers which are intended to be interpreted as
integers, e.g., for indexing purposes, but which may not carry integer
type.
atol : float
Absolute tolerance away from nearest integer to consider values in
``val`` functionally integers.
Returns
-------
val_int : NumPy scalar or ndarray of dtype `np.int64`
Returns the input value(s) coerced to dtype `np.int64` assuming all
were within ``atol`` of the nearest integer.
Notes
-----
This operation calculates ``val`` modulo 1, which returns the mantissa of
all values. Then all mantissas greater than 0.5 are subtracted from one.
Finally, the absolute tolerance from zero is calculated. If it is less
than ``atol`` for all value(s) in ``val``, they are rounded and returned
in an integer array. Or, if ``val`` was a scalar, a NumPy scalar type is
returned.
If any value(s) are outside the specified tolerance, an informative error
is raised.
Examples
--------
>>> _safe_as_int(7.0)
7
>>> _safe_as_int([9, 4, 2.9999999999])
array([9, 4, 3], dtype=int32)
>>> _safe_as_int(53.01)
Traceback (most recent call last):
...
ValueError: Integer argument required but received 53.1, check inputs.
>>> _safe_as_int(53.01, atol=0.01)
53
"""
mod = np.asarray(val) % 1 # Extract mantissa
# Check for and subtract any mod values > 0.5 from 1
if mod.ndim == 0: # Scalar input, cannot be indexed
if mod > 0.5:
mod = 1 - mod
else: # Iterable input, now ndarray
mod[mod > 0.5] = 1 - mod[mod > 0.5] # Test on each side of nearest int
try:
np.testing.assert_allclose(mod, 0, atol=atol)
except AssertionError:
raise ValueError("Integer argument required but received "
"{0}, check inputs.".format(val))
return np.round(val).astype(np.int64)
+5 -5
View File
@@ -13,6 +13,10 @@ from .colorconv import (convert_colorspace,
lab2xyz,
lab2rgb,
rgb2lab,
xyz2luv,
luv2xyz,
luv2rgb,
rgb2luv,
rgb2hed,
hed2rgb,
lab2lch,
@@ -40,9 +44,7 @@ from .colorconv import (convert_colorspace,
rgb_from_ahx,
ahx_from_rgb,
rgb_from_hpx,
hpx_from_rgb,
is_rgb,
is_gray)
hpx_from_rgb)
from .colorlabel import color_dict, label2rgb
@@ -96,8 +98,6 @@ __all__ = ['convert_colorspace',
'ahx_from_rgb',
'rgb_from_hpx',
'hpx_from_rgb',
'is_rgb',
'is_gray',
'color_dict',
'label2rgb',
'deltaE_cie76',
+247 -90
View File
@@ -29,9 +29,12 @@ Supported color spaces
* LAB CIE : Lightness, a, b
Colorspace derived from XYZ CIE that is intended to be more
perceptually uniform
* LUV CIE : Lightness, u, v
Colorspace derived from XYZ CIE that is intended to be more
perceptually uniform
* LCH CIE : Lightness, Chroma, Hue
Defined in terms of LAB CIE. C and H are the polar representation of
a and b. The polar angle C is defined to be on (0, 2*pi)
a and b. The polar angle C is defined to be on ``(0, 2*pi)``
:author: Nicolas Pinto (rgb2hsv)
:author: Ralf Gommers (hsv2rgb)
@@ -68,7 +71,7 @@ def guess_spatial_dimensions(image):
-------
spatial_dims : int or None
The number of spatial dimensions of `image`. If ambiguous, the value
is `None`.
is ``None``.
Raises
------
@@ -87,32 +90,6 @@ def guess_spatial_dimensions(image):
raise ValueError("Expected 2D, 3D, or 4D array, got %iD." % image.ndim)
@deprecated()
def is_rgb(image):
"""Test whether the image is RGB or RGBA.
Parameters
----------
image : ndarray
Input image.
"""
return (image.ndim == 3 and image.shape[2] in (3, 4))
@deprecated()
def is_gray(image):
"""Test whether the image is gray (i.e. has only one color band).
Parameters
----------
image : ndarray
Input image.
"""
return image.ndim in (2, 3) and not is_rgb(image)
def convert_colorspace(arr, fromspace, tospace):
"""Convert an image array to a new color space.
@@ -122,12 +99,12 @@ def convert_colorspace(arr, fromspace, tospace):
The image to convert.
fromspace : str
The color space to convert from. Valid color space strings are
['RGB', 'HSV', 'RGB CIE', 'XYZ']. Value may also be specified as lower
case.
``['RGB', 'HSV', 'RGB CIE', 'XYZ']``. Value may also be specified as
lower case.
tospace : str
The color space to convert to. Valid color space strings are
['RGB', 'HSV', 'RGB CIE', 'XYZ']. Value may also be specified as lower
case.
``['RGB', 'HSV', 'RGB CIE', 'XYZ']``. Value may also be specified as
lower case.
Returns
-------
@@ -137,7 +114,7 @@ def convert_colorspace(arr, fromspace, tospace):
Notes
-----
Conversion occurs through the "central" RGB color space, i.e. conversion
from XYZ to HSV is implemented as XYZ -> RGB -> HSV instead of directly.
from XYZ to HSV is implemented as ``XYZ -> RGB -> HSV`` instead of directly.
Examples
--------
@@ -181,17 +158,17 @@ def rgb2hsv(rgb):
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in HSV format, in a 3-D array of shape (.., .., 3).
The image in HSV format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `rgb` is not a 3-D array of shape (.., .., 3).
If `rgb` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
@@ -259,21 +236,21 @@ def hsv2rgb(hsv):
Parameters
----------
hsv : array_like
The image in HSV format, in a 3-D array of shape (.., .., 3).
The image in HSV format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `hsv` is not a 3-D array of shape (.., .., 3).
If `hsv` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
The conversion assumes an input data range of [0, 1] for all
The conversion assumes an input data range of ``[0, 1]`` for all
color components.
Conversion between RGB and HSV color spaces results in some loss of
@@ -468,17 +445,17 @@ def xyz2rgb(xyz):
Parameters
----------
xyz : array_like
The image in XYZ format, in a 3-D array of shape (.., .., 3).
The image in XYZ format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `xyz` is not a 3-D array of shape (.., .., 3).
If `xyz` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
@@ -513,18 +490,18 @@ def rgb2xyz(rgb):
----------
rgb : array_like
The image in RGB format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Returns
-------
out : ndarray
The image in XYZ format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Raises
------
ValueError
If `rgb` is not a 3- or 4-D array of shape (.., ..,[ ..,] 3).
If `rgb` is not a 3- or 4-D array of shape ``(.., ..,[ ..,] 3)``.
Notes
-----
@@ -556,17 +533,17 @@ def rgb2rgbcie(rgb):
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB CIE format, in a 3-D array of shape (.., .., 3).
The image in RGB CIE format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `rgb` is not a 3-D array of shape (.., .., 3).
If `rgb` is not a 3-D array of shape ``(.., .., 3)``.
References
----------
@@ -588,17 +565,17 @@ def rgbcie2rgb(rgbcie):
Parameters
----------
rgbcie : array_like
The image in RGB CIE format, in a 3-D array of shape (.., .., 3).
The image in RGB CIE format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `rgbcie` is not a 3-D array of shape (.., .., 3).
If `rgbcie` is not a 3-D array of shape ``(.., .., 3)``.
References
----------
@@ -621,8 +598,8 @@ def rgb2gray(rgb):
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3),
or in RGBA format with shape (.., .., 4).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``,
or in RGBA format with shape ``(.., .., 4)``.
Returns
-------
@@ -632,8 +609,8 @@ def rgb2gray(rgb):
Raises
------
ValueError
If `rgb2gray` is not a 3-D array of shape (.., .., 3) or
(.., .., 4).
If `rgb2gray` is not a 3-D array of shape ``(.., .., 3)`` or
``(.., .., 4)``.
References
----------
@@ -698,18 +675,18 @@ def xyz2lab(xyz):
----------
xyz : array_like
The image in XYZ format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Returns
-------
out : ndarray
The image in CIE-LAB format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Raises
------
ValueError
If `xyz` is not a 3-D array of shape (.., ..,[ ..,] 3).
If `xyz` is not a 3-D array of shape ``(.., ..,[ ..,] 3)``.
Notes
-----
@@ -755,21 +732,21 @@ def lab2xyz(lab):
Parameters
----------
lab : array_like
The image in lab format, in a 3-D array of shape (.., .., 3).
The image in lab format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in XYZ format, in a 3-D array of shape (.., .., 3).
The image in XYZ format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `lab` is not a 3-D array of shape (.., .., 3).
If `lab` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
Observer= 2A, Illuminant= D65
Observer = 2A, Illuminant = D65
CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883
References
@@ -804,18 +781,18 @@ def rgb2lab(rgb):
----------
rgb : array_like
The image in RGB format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Returns
-------
out : ndarray
The image in Lab format, in a 3- or 4-D array of shape
(.., ..,[ ..,] 3).
``(.., ..,[ ..,] 3)``.
Raises
------
ValueError
If `rgb` is not a 3- or 4-D array of shape (.., ..,[ ..,] 3).
If `rgb` is not a 3- or 4-D array of shape ``(.., ..,[ ..,] 3)``.
Notes
-----
@@ -829,18 +806,18 @@ def lab2rgb(lab):
Parameters
----------
rgb : array_like
The image in Lab format, in a 3-D array of shape (.., .., 3).
lab : array_like
The image in Lab format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `lab` is not a 3-D array of shape (.., .., 3).
If `lab` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
@@ -849,23 +826,203 @@ def lab2rgb(lab):
return xyz2rgb(lab2xyz(lab))
def xyz2luv(xyz):
"""XYZ to CIE-Luv color space conversion.
Parameters
----------
xyz : (M, N, [P,] 3) array_like
The 3 or 4 dimensional image in XYZ format. Final dimension denotes
channels.
Returns
-------
out : (M, N, [P,] 3) ndarray
The image in CIE-Luv format. Same dimensions as input.
Raises
------
ValueError
If `xyz` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``.
Notes
-----
XYZ conversion weights use Observer = 2A. Reference whitepoint for D65
Illuminant, with XYZ tristimulus values of ``(95.047, 100., 108.883)``.
References
----------
.. [1] http://www.easyrgb.com/index.php?X=MATH&H=16#text16
.. [2] http://en.wikipedia.org/wiki/CIELUV
Examples
--------
>>> from skimage import data
>>> from skimage.color import rgb2xyz, xyz2luv
>>> lena = data.lena()
>>> lena_xyz = rgb2xyz(lena)
>>> lena_luv = xyz2luv(lena_xyz)
"""
arr = _prepare_colorarray(xyz)
# extract channels
x, y, z = arr[..., 0], arr[..., 1], arr[..., 2]
eps = np.finfo(np.float).eps
# compute y_r and L
L = y / lab_ref_white[1]
mask = L > 0.008856
L[mask] = 116. * np.power(L[mask], 1. / 3.) - 16.
L[~mask] = 903.3 * L[~mask]
u0 = 4*lab_ref_white[0] / np.dot([1, 15, 3], lab_ref_white)
v0 = 9*lab_ref_white[1] / np.dot([1, 15, 3], lab_ref_white)
# u' and v' helper functions
def fu(X, Y, Z):
return (4.*X) / (X + 15.*Y + 3.*Z + eps)
def fv(X, Y, Z):
return (9.*Y) / (X + 15.*Y + 3.*Z + eps)
# compute u and v using helper functions
u = 13.*L * (fu(x, y, z) - u0)
v = 13.*L * (fv(x, y, z) - v0)
return np.concatenate([q[..., np.newaxis] for q in [L, u, v]], axis=-1)
def luv2xyz(luv):
"""CIE-Luv to XYZ color space conversion.
Parameters
----------
luv : (M, N, [P,] 3) array_like
The 3 or 4 dimensional image in CIE-Luv format. Final dimension denotes
channels.
Returns
-------
out : (M, N, [P,] 3) ndarray
The image in XYZ format. Same dimensions as input.
Raises
------
ValueError
If `luv` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``.
Notes
-----
XYZ conversion weights use Observer = 2A. Reference whitepoint for D65
Illuminant, with XYZ tristimulus values of ``(95.047, 100., 108.883)``.
References
----------
.. [1] http://www.easyrgb.com/index.php?X=MATH&H=16#text16
.. [2] http://en.wikipedia.org/wiki/CIELUV
"""
arr = _prepare_colorarray(luv).copy()
L, u, v = arr[:, :, 0], arr[:, :, 1], arr[:, :, 2]
eps = np.finfo(np.float).eps
# compute y
y = L.copy()
mask = y > 7.999625
y[mask] = np.power((y[mask]+16.) / 116., 3.)
y[~mask] = y[~mask] / 903.3
y *= lab_ref_white[1]
# reference white x,z
uv_weights = [1, 15, 3]
u0 = 4*lab_ref_white[0] / np.dot(uv_weights, lab_ref_white)
v0 = 9*lab_ref_white[1] / np.dot(uv_weights, lab_ref_white)
# compute intermediate values
a = u0 + u / (13.*L + eps)
b = v0 + v / (13.*L + eps)
c = 3*y * (5*b-3)
# compute x and z
z = ((a-4)*c - 15*a*b*y) / (12*b)
x = -(c/b + 3.*z)
return np.concatenate([q[..., np.newaxis] for q in [x, y, z]], axis=-1)
def rgb2luv(rgb):
"""RGB to CIE-Luv color space conversion.
Parameters
----------
rgb : (M, N, [P,] 3) array_like
The 3 or 4 dimensional image in RGB format. Final dimension denotes
channels.
Returns
-------
out : (M, N, [P,] 3) ndarray
The image in CIE Luv format. Same dimensions as input.
Raises
------
ValueError
If `rgb` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``.
Notes
-----
This function uses rgb2xyz and xyz2luv.
"""
return xyz2luv(rgb2xyz(rgb))
def luv2rgb(luv):
"""Luv to RGB color space conversion.
Parameters
----------
luv : (M, N, [P,] 3) array_like
The 3 or 4 dimensional image in CIE Luv format. Final dimension denotes
channels.
Returns
-------
out : (M, N, [P,] 3) ndarray
The image in RGB format. Same dimensions as input.
Raises
------
ValueError
If `luv` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``.
Notes
-----
This function uses luv2xyz and xyz2rgb.
"""
return xyz2rgb(luv2xyz(luv))
def rgb2hed(rgb):
"""RGB to Haematoxylin-Eosin-DAB (HED) color space conversion.
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in HED format, in a 3-D array of shape (.., .., 3).
The image in HED format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `rgb` is not a 3-D array of shape (.., .., 3).
If `rgb` is not a 3-D array of shape ``(.., .., 3)``.
References
@@ -891,17 +1048,17 @@ def hed2rgb(hed):
Parameters
----------
hed : array_like
The image in the HED color space, in a 3-D array of shape (.., .., 3).
The image in the HED color space, in a 3-D array of shape ``(.., .., 3)``.
Returns
-------
out : ndarray
The image in RGB, in a 3-D array of shape (.., .., 3).
The image in RGB, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `hed` is not a 3-D array of shape (.., .., 3).
If `hed` is not a 3-D array of shape ``(.., .., 3)``.
References
----------
@@ -927,19 +1084,19 @@ def separate_stains(rgb, conv_matrix):
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
conv_matrix: ndarray
The stain separation matrix as described by G. Landini [1]_.
Returns
-------
out : ndarray
The image in stain color space, in a 3-D array of shape (.., .., 3).
The image in stain color space, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `rgb` is not a 3-D array of shape (.., .., 3).
If `rgb` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
@@ -981,19 +1138,19 @@ def combine_stains(stains, conv_matrix):
Parameters
----------
stains : array_like
The image in stain color space, in a 3-D array of shape (.., .., 3).
The image in stain color space, in a 3-D array of shape ``(.., .., 3)``.
conv_matrix: ndarray
The stain separation matrix as described by G. Landini [1]_.
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
The image in RGB format, in a 3-D array of shape ``(.., .., 3)``.
Raises
------
ValueError
If `stains` is not a 3-D array of shape (.., .., 3).
If `stains` is not a 3-D array of shape ``(.., .., 3)``.
Notes
-----
@@ -1043,9 +1200,9 @@ def lab2lch(lab):
Parameters
----------
lab : array_like
The N-D image in CIE-LAB format. The last (`N+1`th) dimension must have
at least 3 elements, corresponding to the ``L``, ``a``, and ``b`` color
channels. Subsequent elements are copied.
The N-D image in CIE-LAB format. The last (``N+1``-th) dimension must
have at least 3 elements, corresponding to the ``L``, ``a``, and ``b``
color channels. Subsequent elements are copied.
Returns
-------
@@ -1059,7 +1216,7 @@ def lab2lch(lab):
Notes
-----
The Hue is expressed as an angle between (0, 2*pi)
The Hue is expressed as an angle between ``(0, 2*pi)``
Examples
--------
@@ -1079,7 +1236,7 @@ def lab2lch(lab):
def _cart2polar_2pi(x, y):
"""convert cartesian coordiantes to polar (uses non-standard theta range!)
NON-STANDARD RANGE! Maps to (0, 2*pi) rather than usual (-pi, +pi)
NON-STANDARD RANGE! Maps to ``(0, 2*pi)`` rather than usual ``(-pi, +pi)``
"""
r, t = np.hypot(x, y), np.arctan2(y, x)
t += np.where(t < 0., 2 * np.pi, 0)
@@ -1094,9 +1251,9 @@ def lch2lab(lch):
Parameters
----------
lch : array_like
The N-D image in CIE-LCH format. The last (`N+1`th) dimension must have
at least 3 elements, corresponding to the ``L``, ``a``, and ``b`` color
channels. Subsequent elements are copied.
The N-D image in CIE-LCH format. The last (``N+1``-th) dimension must
have at least 3 elements, corresponding to the ``L``, ``a``, and ``b``
color channels. Subsequent elements are copied.
Returns
-------
+6 -4
View File
@@ -4,11 +4,12 @@ import itertools
import numpy as np
from skimage import img_as_float
from skimage._shared import six
from skimage._shared.six.moves import zip
from .colorconv import rgb2gray, gray2rgb
from . import rgb_colors
import six
from six.moves import zip
__all__ = ['color_dict', 'label2rgb', 'DEFAULT_COLORS']
@@ -17,7 +18,8 @@ DEFAULT_COLORS = ('red', 'blue', 'yellow', 'magenta', 'green',
'indigo', 'darkorange', 'cyan', 'pink', 'yellowgreen')
color_dict = rgb_colors.__dict__
color_dict = dict((k, v) for k, v in six.iteritems(rgb_colors.__dict__)
if isinstance(v, tuple))
def _rgb_vector(color):
@@ -110,7 +112,7 @@ def label2rgb(label, image=None, colors=None, alpha=0.3,
label = label - offset # Make sure you don't modify the input array.
bg_label -= offset
new_type = np.min_scalar_type(label.max())
new_type = np.min_scalar_type(int(label.max()))
if new_type == np.bool:
new_type = np.uint8
label = label.astype(new_type)
+54 -22
View File
@@ -33,7 +33,8 @@ from skimage.color import (rgb2hsv, hsv2rgb,
rgb2grey, gray2rgb,
xyz2lab, lab2xyz,
lab2rgb, rgb2lab,
is_rgb, is_gray,
xyz2luv, luv2xyz,
luv2rgb, rgb2luv,
lab2lch, lch2lab,
guess_spatial_dimensions
)
@@ -69,17 +70,24 @@ class TestColorconv(TestCase):
colbars_point75_array = np.swapaxes(colbars_point75.reshape(3, 4, 2), 0, 2)
xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], # red
[[0, 0, 0]], # black
[[.9505, 1., 1.089]], # white
[[.1805, .0722, .9505]], # blue
[[.07719, .15438, .02573]], # green
])
[[0, 0, 0]], # black
[[.9505, 1., 1.089]], # white
[[.1805, .0722, .9505]], # blue
[[.07719, .15438, .02573]], # green
])
lab_array = np.array([[[53.233, 80.109, 67.220]], # red
[[0., 0., 0.]], # black
[[100.0, 0.005, -0.010]], # white
[[32.303, 79.197, -107.864]], # blue
[[46.229, -51.7, 49.898]], # green
])
[[0., 0., 0.]], # black
[[100.0, 0.005, -0.010]], # white
[[32.303, 79.197, -107.864]], # blue
[[46.229, -51.7, 49.898]], # green
])
luv_array = np.array([[[53.233, 175.053, 37.751]], # red
[[0., 0., 0.]], # black
[[100., 0.001, -0.017]], # white
[[32.303, -9.400, -130.358]], # blue
[[46.228, -43.774, 56.589]], # green
])
# RGB to HSV
def test_rgb2hsv_conversion(self):
@@ -250,6 +258,41 @@ class TestColorconv(TestCase):
img_rgb = img_as_float(self.img_rgb)
assert_array_almost_equal(lab2rgb(rgb2lab(img_rgb)), img_rgb)
# test matrices for xyz2luv and luv2xyz generated using
# http://www.easyrgb.com/index.php?X=CALC
# Note: easyrgb website displays xyz*100
def test_xyz2luv(self):
assert_array_almost_equal(xyz2luv(self.xyz_array),
self.luv_array, decimal=3)
def test_luv2xyz(self):
assert_array_almost_equal(luv2xyz(self.luv_array),
self.xyz_array, decimal=3)
def test_rgb2luv_brucelindbloom(self):
"""
Test the RGB->Lab conversion by comparing to the calculator on the
authoritative Bruce Lindbloom
[website](http://brucelindbloom.com/index.html?ColorCalculator.html).
"""
# Obtained with D65 white point, sRGB model and gamma
gt_for_colbars = np.array([
[100, 0, 0],
[97.1393, 7.7056, 106.7866],
[91.1132, -70.4773, -15.2042],
[87.7347, -83.0776, 107.3985],
[60.3242, 84.0714, -108.6834],
[53.2408, 175.0151, 37.7564],
[32.2970, -9.4054, -130.3423],
[0, 0, 0]]).T
gt_array = np.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
assert_array_almost_equal(rgb2luv(self.colbars_array),
gt_array, decimal=2)
def test_luv_rgb_roundtrip(self):
img_rgb = img_as_float(self.img_rgb)
assert_array_almost_equal(luv2rgb(rgb2luv(img_rgb)), img_rgb)
def test_lab_lch_roundtrip(self):
rgb = img_as_float(self.img_rgb)
lab = rgb2lab(rgb)
@@ -311,17 +354,6 @@ def test_gray2rgb_rgb():
assert_equal(x, y)
def test_is_rgb():
color = data.lena()
gray = data.camera()
assert is_rgb(color)
assert not is_gray(color)
assert is_gray(gray)
assert not is_gray(color)
if __name__ == "__main__":
from numpy.testing import run_module_suite
run_module_suite()
+22 -1
View File
@@ -24,7 +24,8 @@ __all__ = ['load',
'clock',
'immunohistochemistry',
'chelsea',
'coffee']
'coffee',
'hubble_deep_field']
def load(f):
@@ -200,3 +201,23 @@ def coffee():
"""
return load("coffee.png")
def hubble_deep_field():
"""Hubble eXtreme Deep Field.
This photograph contains the Hubble Telescope's farthest ever view of
the universe. It can be useful as an example for multi-scale
detection.
Notes
-----
This image was downloaded from
`HubbleSite
<http://hubblesite.org/newscenter/archive/releases/2012/37/image/a/>`__.
The image was captured by NASA and `may be freely used in the
public domain <http://www.nasa.gov/audience/formedia/features/MP_Photo_Guidelines.html>`_.
"""
return load("hubble_deep_field.jpg")
Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

+256
View File
@@ -0,0 +1,256 @@
8.000000000000000000e+00 -3.000000000000000000e+00 9.000000000000000000e+00 5.000000000000000000e+00
4.000000000000000000e+00 2.000000000000000000e+00 7.000000000000000000e+00 -1.200000000000000000e+01
-1.100000000000000000e+01 9.000000000000000000e+00 -8.000000000000000000e+00 2.000000000000000000e+00
7.000000000000000000e+00 -1.200000000000000000e+01 1.200000000000000000e+01 -1.300000000000000000e+01
2.000000000000000000e+00 -1.300000000000000000e+01 2.000000000000000000e+00 1.200000000000000000e+01
1.000000000000000000e+00 -7.000000000000000000e+00 1.000000000000000000e+00 6.000000000000000000e+00
-2.000000000000000000e+00 -1.000000000000000000e+01 -2.000000000000000000e+00 -4.000000000000000000e+00
-1.300000000000000000e+01 -1.300000000000000000e+01 -1.100000000000000000e+01 -8.000000000000000000e+00
-1.300000000000000000e+01 -3.000000000000000000e+00 -1.200000000000000000e+01 -9.000000000000000000e+00
1.000000000000000000e+01 4.000000000000000000e+00 1.100000000000000000e+01 9.000000000000000000e+00
-1.300000000000000000e+01 -8.000000000000000000e+00 -8.000000000000000000e+00 -9.000000000000000000e+00
-1.100000000000000000e+01 7.000000000000000000e+00 -9.000000000000000000e+00 1.200000000000000000e+01
7.000000000000000000e+00 7.000000000000000000e+00 1.200000000000000000e+01 6.000000000000000000e+00
-4.000000000000000000e+00 -5.000000000000000000e+00 -3.000000000000000000e+00 0.000000000000000000e+00
-1.300000000000000000e+01 2.000000000000000000e+00 -1.200000000000000000e+01 -3.000000000000000000e+00
-9.000000000000000000e+00 0.000000000000000000e+00 -7.000000000000000000e+00 5.000000000000000000e+00
1.200000000000000000e+01 -6.000000000000000000e+00 1.200000000000000000e+01 -1.000000000000000000e+00
-3.000000000000000000e+00 6.000000000000000000e+00 -2.000000000000000000e+00 1.200000000000000000e+01
-6.000000000000000000e+00 -1.300000000000000000e+01 -4.000000000000000000e+00 -8.000000000000000000e+00
1.100000000000000000e+01 -1.300000000000000000e+01 1.200000000000000000e+01 -8.000000000000000000e+00
4.000000000000000000e+00 7.000000000000000000e+00 5.000000000000000000e+00 1.000000000000000000e+00
5.000000000000000000e+00 -3.000000000000000000e+00 1.000000000000000000e+01 -3.000000000000000000e+00
3.000000000000000000e+00 -7.000000000000000000e+00 6.000000000000000000e+00 1.200000000000000000e+01
-8.000000000000000000e+00 -7.000000000000000000e+00 -6.000000000000000000e+00 -2.000000000000000000e+00
-2.000000000000000000e+00 1.100000000000000000e+01 -1.000000000000000000e+00 -1.000000000000000000e+01
-1.300000000000000000e+01 1.200000000000000000e+01 -8.000000000000000000e+00 1.000000000000000000e+01
-7.000000000000000000e+00 3.000000000000000000e+00 -5.000000000000000000e+00 -3.000000000000000000e+00
-4.000000000000000000e+00 2.000000000000000000e+00 -3.000000000000000000e+00 7.000000000000000000e+00
-1.000000000000000000e+01 -1.200000000000000000e+01 -6.000000000000000000e+00 1.100000000000000000e+01
5.000000000000000000e+00 -1.200000000000000000e+01 6.000000000000000000e+00 -7.000000000000000000e+00
5.000000000000000000e+00 -6.000000000000000000e+00 7.000000000000000000e+00 -1.000000000000000000e+00
1.000000000000000000e+00 0.000000000000000000e+00 4.000000000000000000e+00 -5.000000000000000000e+00
9.000000000000000000e+00 1.100000000000000000e+01 1.100000000000000000e+01 -1.300000000000000000e+01
4.000000000000000000e+00 7.000000000000000000e+00 4.000000000000000000e+00 1.200000000000000000e+01
2.000000000000000000e+00 -1.000000000000000000e+00 4.000000000000000000e+00 4.000000000000000000e+00
-4.000000000000000000e+00 -1.200000000000000000e+01 -2.000000000000000000e+00 7.000000000000000000e+00
-8.000000000000000000e+00 -5.000000000000000000e+00 -7.000000000000000000e+00 -1.000000000000000000e+01
4.000000000000000000e+00 1.100000000000000000e+01 9.000000000000000000e+00 1.200000000000000000e+01
0.000000000000000000e+00 -8.000000000000000000e+00 1.000000000000000000e+00 -1.300000000000000000e+01
-1.300000000000000000e+01 -2.000000000000000000e+00 -8.000000000000000000e+00 2.000000000000000000e+00
-3.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 3.000000000000000000e+00
-6.000000000000000000e+00 9.000000000000000000e+00 -4.000000000000000000e+00 -9.000000000000000000e+00
8.000000000000000000e+00 1.200000000000000000e+01 1.000000000000000000e+01 7.000000000000000000e+00
0.000000000000000000e+00 9.000000000000000000e+00 1.000000000000000000e+00 3.000000000000000000e+00
7.000000000000000000e+00 -5.000000000000000000e+00 1.100000000000000000e+01 -1.000000000000000000e+01
-1.300000000000000000e+01 -6.000000000000000000e+00 -1.100000000000000000e+01 0.000000000000000000e+00
1.000000000000000000e+01 7.000000000000000000e+00 1.200000000000000000e+01 1.000000000000000000e+00
-6.000000000000000000e+00 -3.000000000000000000e+00 -6.000000000000000000e+00 1.200000000000000000e+01
1.000000000000000000e+01 -9.000000000000000000e+00 1.200000000000000000e+01 -4.000000000000000000e+00
-1.300000000000000000e+01 8.000000000000000000e+00 -8.000000000000000000e+00 -1.200000000000000000e+01
-1.300000000000000000e+01 0.000000000000000000e+00 -8.000000000000000000e+00 -4.000000000000000000e+00
3.000000000000000000e+00 3.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00
5.000000000000000000e+00 7.000000000000000000e+00 1.000000000000000000e+01 -7.000000000000000000e+00
-1.000000000000000000e+00 7.000000000000000000e+00 1.000000000000000000e+00 -1.200000000000000000e+01
3.000000000000000000e+00 -1.000000000000000000e+01 5.000000000000000000e+00 6.000000000000000000e+00
2.000000000000000000e+00 -4.000000000000000000e+00 3.000000000000000000e+00 -1.000000000000000000e+01
-1.300000000000000000e+01 0.000000000000000000e+00 -1.300000000000000000e+01 5.000000000000000000e+00
-1.300000000000000000e+01 -7.000000000000000000e+00 -1.200000000000000000e+01 1.200000000000000000e+01
-1.300000000000000000e+01 3.000000000000000000e+00 -1.100000000000000000e+01 8.000000000000000000e+00
-7.000000000000000000e+00 1.200000000000000000e+01 -4.000000000000000000e+00 7.000000000000000000e+00
6.000000000000000000e+00 -1.000000000000000000e+01 1.200000000000000000e+01 8.000000000000000000e+00
-9.000000000000000000e+00 -1.000000000000000000e+00 -7.000000000000000000e+00 -6.000000000000000000e+00
-2.000000000000000000e+00 -5.000000000000000000e+00 0.000000000000000000e+00 1.200000000000000000e+01
-1.200000000000000000e+01 5.000000000000000000e+00 -7.000000000000000000e+00 5.000000000000000000e+00
3.000000000000000000e+00 -1.000000000000000000e+01 8.000000000000000000e+00 -1.300000000000000000e+01
-7.000000000000000000e+00 -7.000000000000000000e+00 -4.000000000000000000e+00 5.000000000000000000e+00
-3.000000000000000000e+00 -2.000000000000000000e+00 -1.000000000000000000e+00 -7.000000000000000000e+00
2.000000000000000000e+00 9.000000000000000000e+00 5.000000000000000000e+00 -1.100000000000000000e+01
-1.100000000000000000e+01 -1.300000000000000000e+01 -5.000000000000000000e+00 -1.300000000000000000e+01
-1.000000000000000000e+00 6.000000000000000000e+00 0.000000000000000000e+00 -1.000000000000000000e+00
5.000000000000000000e+00 -3.000000000000000000e+00 5.000000000000000000e+00 2.000000000000000000e+00
-4.000000000000000000e+00 -1.300000000000000000e+01 -4.000000000000000000e+00 1.200000000000000000e+01
-9.000000000000000000e+00 -6.000000000000000000e+00 -9.000000000000000000e+00 6.000000000000000000e+00
-1.200000000000000000e+01 -1.000000000000000000e+01 -8.000000000000000000e+00 -4.000000000000000000e+00
1.000000000000000000e+01 2.000000000000000000e+00 1.200000000000000000e+01 -3.000000000000000000e+00
7.000000000000000000e+00 1.200000000000000000e+01 1.200000000000000000e+01 1.200000000000000000e+01
-7.000000000000000000e+00 -1.300000000000000000e+01 -6.000000000000000000e+00 5.000000000000000000e+00
-4.000000000000000000e+00 9.000000000000000000e+00 -3.000000000000000000e+00 4.000000000000000000e+00
7.000000000000000000e+00 -1.000000000000000000e+00 1.200000000000000000e+01 2.000000000000000000e+00
-7.000000000000000000e+00 6.000000000000000000e+00 -5.000000000000000000e+00 1.000000000000000000e+00
-1.300000000000000000e+01 1.100000000000000000e+01 -1.200000000000000000e+01 5.000000000000000000e+00
-3.000000000000000000e+00 7.000000000000000000e+00 -2.000000000000000000e+00 -6.000000000000000000e+00
7.000000000000000000e+00 -8.000000000000000000e+00 1.200000000000000000e+01 -7.000000000000000000e+00
-1.300000000000000000e+01 -7.000000000000000000e+00 -1.100000000000000000e+01 -1.200000000000000000e+01
1.000000000000000000e+00 -3.000000000000000000e+00 1.200000000000000000e+01 1.200000000000000000e+01
2.000000000000000000e+00 -6.000000000000000000e+00 3.000000000000000000e+00 0.000000000000000000e+00
-4.000000000000000000e+00 3.000000000000000000e+00 -2.000000000000000000e+00 -1.300000000000000000e+01
-1.000000000000000000e+00 -1.300000000000000000e+01 1.000000000000000000e+00 9.000000000000000000e+00
7.000000000000000000e+00 1.000000000000000000e+00 8.000000000000000000e+00 -6.000000000000000000e+00
1.000000000000000000e+00 -1.000000000000000000e+00 3.000000000000000000e+00 1.200000000000000000e+01
9.000000000000000000e+00 1.000000000000000000e+00 1.200000000000000000e+01 6.000000000000000000e+00
-1.000000000000000000e+00 -9.000000000000000000e+00 -1.000000000000000000e+00 3.000000000000000000e+00
-1.300000000000000000e+01 -1.300000000000000000e+01 -1.000000000000000000e+01 5.000000000000000000e+00
7.000000000000000000e+00 7.000000000000000000e+00 1.000000000000000000e+01 1.200000000000000000e+01
1.200000000000000000e+01 -5.000000000000000000e+00 1.200000000000000000e+01 9.000000000000000000e+00
6.000000000000000000e+00 3.000000000000000000e+00 7.000000000000000000e+00 1.100000000000000000e+01
5.000000000000000000e+00 -1.300000000000000000e+01 6.000000000000000000e+00 1.000000000000000000e+01
2.000000000000000000e+00 -1.200000000000000000e+01 2.000000000000000000e+00 3.000000000000000000e+00
3.000000000000000000e+00 8.000000000000000000e+00 4.000000000000000000e+00 -6.000000000000000000e+00
2.000000000000000000e+00 6.000000000000000000e+00 1.200000000000000000e+01 -1.300000000000000000e+01
9.000000000000000000e+00 -1.200000000000000000e+01 1.000000000000000000e+01 3.000000000000000000e+00
-8.000000000000000000e+00 4.000000000000000000e+00 -7.000000000000000000e+00 9.000000000000000000e+00
-1.100000000000000000e+01 1.200000000000000000e+01 -4.000000000000000000e+00 -6.000000000000000000e+00
1.000000000000000000e+00 1.200000000000000000e+01 2.000000000000000000e+00 -8.000000000000000000e+00
6.000000000000000000e+00 -9.000000000000000000e+00 7.000000000000000000e+00 -4.000000000000000000e+00
2.000000000000000000e+00 3.000000000000000000e+00 3.000000000000000000e+00 -2.000000000000000000e+00
6.000000000000000000e+00 3.000000000000000000e+00 1.100000000000000000e+01 0.000000000000000000e+00
3.000000000000000000e+00 -3.000000000000000000e+00 8.000000000000000000e+00 -8.000000000000000000e+00
7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00 3.000000000000000000e+00
-1.100000000000000000e+01 -5.000000000000000000e+00 -6.000000000000000000e+00 -4.000000000000000000e+00
-1.000000000000000000e+01 1.100000000000000000e+01 -5.000000000000000000e+00 1.000000000000000000e+01
-5.000000000000000000e+00 -8.000000000000000000e+00 -3.000000000000000000e+00 1.200000000000000000e+01
-1.000000000000000000e+01 5.000000000000000000e+00 -9.000000000000000000e+00 0.000000000000000000e+00
8.000000000000000000e+00 -1.000000000000000000e+00 1.200000000000000000e+01 -6.000000000000000000e+00
4.000000000000000000e+00 -6.000000000000000000e+00 6.000000000000000000e+00 -1.100000000000000000e+01
-1.000000000000000000e+01 1.200000000000000000e+01 -8.000000000000000000e+00 7.000000000000000000e+00
4.000000000000000000e+00 -2.000000000000000000e+00 6.000000000000000000e+00 7.000000000000000000e+00
-2.000000000000000000e+00 0.000000000000000000e+00 -2.000000000000000000e+00 1.200000000000000000e+01
-5.000000000000000000e+00 -8.000000000000000000e+00 -5.000000000000000000e+00 2.000000000000000000e+00
7.000000000000000000e+00 -6.000000000000000000e+00 1.000000000000000000e+01 1.200000000000000000e+01
-9.000000000000000000e+00 -1.300000000000000000e+01 -8.000000000000000000e+00 -8.000000000000000000e+00
-5.000000000000000000e+00 -1.300000000000000000e+01 -5.000000000000000000e+00 -2.000000000000000000e+00
8.000000000000000000e+00 -8.000000000000000000e+00 9.000000000000000000e+00 -1.300000000000000000e+01
-9.000000000000000000e+00 -1.100000000000000000e+01 -9.000000000000000000e+00 0.000000000000000000e+00
1.000000000000000000e+00 -8.000000000000000000e+00 1.000000000000000000e+00 -2.000000000000000000e+00
7.000000000000000000e+00 -4.000000000000000000e+00 9.000000000000000000e+00 1.000000000000000000e+00
-2.000000000000000000e+00 1.000000000000000000e+00 -1.000000000000000000e+00 -4.000000000000000000e+00
1.100000000000000000e+01 -6.000000000000000000e+00 1.200000000000000000e+01 -1.100000000000000000e+01
-1.200000000000000000e+01 -9.000000000000000000e+00 -6.000000000000000000e+00 4.000000000000000000e+00
3.000000000000000000e+00 7.000000000000000000e+00 7.000000000000000000e+00 1.200000000000000000e+01
5.000000000000000000e+00 5.000000000000000000e+00 1.000000000000000000e+01 8.000000000000000000e+00
0.000000000000000000e+00 -4.000000000000000000e+00 2.000000000000000000e+00 8.000000000000000000e+00
-9.000000000000000000e+00 1.200000000000000000e+01 -5.000000000000000000e+00 -1.300000000000000000e+01
0.000000000000000000e+00 7.000000000000000000e+00 2.000000000000000000e+00 1.200000000000000000e+01
-1.000000000000000000e+00 2.000000000000000000e+00 1.000000000000000000e+00 7.000000000000000000e+00
5.000000000000000000e+00 1.100000000000000000e+01 7.000000000000000000e+00 -9.000000000000000000e+00
3.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00 -8.000000000000000000e+00
-1.300000000000000000e+01 -4.000000000000000000e+00 -8.000000000000000000e+00 9.000000000000000000e+00
-5.000000000000000000e+00 9.000000000000000000e+00 -3.000000000000000000e+00 -3.000000000000000000e+00
-4.000000000000000000e+00 -7.000000000000000000e+00 -3.000000000000000000e+00 -1.200000000000000000e+01
6.000000000000000000e+00 5.000000000000000000e+00 8.000000000000000000e+00 0.000000000000000000e+00
-7.000000000000000000e+00 6.000000000000000000e+00 -6.000000000000000000e+00 1.200000000000000000e+01
-1.300000000000000000e+01 6.000000000000000000e+00 -5.000000000000000000e+00 -2.000000000000000000e+00
1.000000000000000000e+00 -1.000000000000000000e+01 3.000000000000000000e+00 1.000000000000000000e+01
4.000000000000000000e+00 1.000000000000000000e+00 8.000000000000000000e+00 -4.000000000000000000e+00
-2.000000000000000000e+00 -2.000000000000000000e+00 2.000000000000000000e+00 -1.300000000000000000e+01
2.000000000000000000e+00 -1.200000000000000000e+01 1.200000000000000000e+01 1.200000000000000000e+01
-2.000000000000000000e+00 -1.300000000000000000e+01 0.000000000000000000e+00 -6.000000000000000000e+00
4.000000000000000000e+00 1.000000000000000000e+00 9.000000000000000000e+00 3.000000000000000000e+00
-6.000000000000000000e+00 -1.000000000000000000e+01 -3.000000000000000000e+00 -5.000000000000000000e+00
-3.000000000000000000e+00 -1.300000000000000000e+01 -1.000000000000000000e+00 1.000000000000000000e+00
7.000000000000000000e+00 5.000000000000000000e+00 1.200000000000000000e+01 -1.100000000000000000e+01
4.000000000000000000e+00 -2.000000000000000000e+00 5.000000000000000000e+00 -7.000000000000000000e+00
-1.300000000000000000e+01 9.000000000000000000e+00 -9.000000000000000000e+00 -5.000000000000000000e+00
7.000000000000000000e+00 1.000000000000000000e+00 8.000000000000000000e+00 6.000000000000000000e+00
7.000000000000000000e+00 -8.000000000000000000e+00 7.000000000000000000e+00 6.000000000000000000e+00
-7.000000000000000000e+00 -4.000000000000000000e+00 -7.000000000000000000e+00 1.000000000000000000e+00
-8.000000000000000000e+00 1.100000000000000000e+01 -7.000000000000000000e+00 -8.000000000000000000e+00
-1.300000000000000000e+01 6.000000000000000000e+00 -1.200000000000000000e+01 -8.000000000000000000e+00
2.000000000000000000e+00 4.000000000000000000e+00 3.000000000000000000e+00 9.000000000000000000e+00
1.000000000000000000e+01 -5.000000000000000000e+00 1.200000000000000000e+01 3.000000000000000000e+00
-6.000000000000000000e+00 -5.000000000000000000e+00 -6.000000000000000000e+00 7.000000000000000000e+00
8.000000000000000000e+00 -3.000000000000000000e+00 9.000000000000000000e+00 -8.000000000000000000e+00
2.000000000000000000e+00 -1.200000000000000000e+01 2.000000000000000000e+00 8.000000000000000000e+00
-1.100000000000000000e+01 -2.000000000000000000e+00 -1.000000000000000000e+01 3.000000000000000000e+00
-1.200000000000000000e+01 -1.300000000000000000e+01 -7.000000000000000000e+00 -9.000000000000000000e+00
-1.100000000000000000e+01 0.000000000000000000e+00 -1.000000000000000000e+01 -5.000000000000000000e+00
5.000000000000000000e+00 -3.000000000000000000e+00 1.100000000000000000e+01 8.000000000000000000e+00
-2.000000000000000000e+00 -1.300000000000000000e+01 -1.000000000000000000e+00 1.200000000000000000e+01
-1.000000000000000000e+00 -8.000000000000000000e+00 0.000000000000000000e+00 9.000000000000000000e+00
-1.300000000000000000e+01 -1.100000000000000000e+01 -1.200000000000000000e+01 -5.000000000000000000e+00
-1.000000000000000000e+01 -2.000000000000000000e+00 -1.000000000000000000e+01 1.100000000000000000e+01
-3.000000000000000000e+00 9.000000000000000000e+00 -2.000000000000000000e+00 -1.300000000000000000e+01
2.000000000000000000e+00 -3.000000000000000000e+00 3.000000000000000000e+00 2.000000000000000000e+00
-9.000000000000000000e+00 -1.300000000000000000e+01 -4.000000000000000000e+00 0.000000000000000000e+00
-4.000000000000000000e+00 6.000000000000000000e+00 -3.000000000000000000e+00 -1.000000000000000000e+01
-4.000000000000000000e+00 1.200000000000000000e+01 -2.000000000000000000e+00 -7.000000000000000000e+00
-6.000000000000000000e+00 -1.100000000000000000e+01 -4.000000000000000000e+00 9.000000000000000000e+00
6.000000000000000000e+00 -3.000000000000000000e+00 6.000000000000000000e+00 1.100000000000000000e+01
-1.300000000000000000e+01 1.100000000000000000e+01 -5.000000000000000000e+00 5.000000000000000000e+00
1.100000000000000000e+01 1.100000000000000000e+01 1.200000000000000000e+01 6.000000000000000000e+00
7.000000000000000000e+00 -5.000000000000000000e+00 1.200000000000000000e+01 -2.000000000000000000e+00
-1.000000000000000000e+00 1.200000000000000000e+01 0.000000000000000000e+00 7.000000000000000000e+00
-4.000000000000000000e+00 -8.000000000000000000e+00 -3.000000000000000000e+00 -2.000000000000000000e+00
-7.000000000000000000e+00 1.000000000000000000e+00 -6.000000000000000000e+00 7.000000000000000000e+00
-1.300000000000000000e+01 -1.200000000000000000e+01 -8.000000000000000000e+00 -1.300000000000000000e+01
-7.000000000000000000e+00 -2.000000000000000000e+00 -6.000000000000000000e+00 -8.000000000000000000e+00
-8.000000000000000000e+00 5.000000000000000000e+00 -6.000000000000000000e+00 -9.000000000000000000e+00
-5.000000000000000000e+00 -1.000000000000000000e+00 -4.000000000000000000e+00 5.000000000000000000e+00
-1.300000000000000000e+01 7.000000000000000000e+00 -8.000000000000000000e+00 1.000000000000000000e+01
1.000000000000000000e+00 5.000000000000000000e+00 5.000000000000000000e+00 -1.300000000000000000e+01
1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+01 -1.300000000000000000e+01
9.000000000000000000e+00 1.200000000000000000e+01 1.000000000000000000e+01 -1.000000000000000000e+00
5.000000000000000000e+00 -8.000000000000000000e+00 1.000000000000000000e+01 -9.000000000000000000e+00
-1.000000000000000000e+00 1.100000000000000000e+01 1.000000000000000000e+00 -1.300000000000000000e+01
-9.000000000000000000e+00 -3.000000000000000000e+00 -6.000000000000000000e+00 2.000000000000000000e+00
-1.000000000000000000e+00 -1.000000000000000000e+01 1.000000000000000000e+00 1.200000000000000000e+01
-1.300000000000000000e+01 1.000000000000000000e+00 -8.000000000000000000e+00 -1.000000000000000000e+01
8.000000000000000000e+00 -1.100000000000000000e+01 1.000000000000000000e+01 -6.000000000000000000e+00
2.000000000000000000e+00 -1.300000000000000000e+01 3.000000000000000000e+00 -6.000000000000000000e+00
7.000000000000000000e+00 -1.300000000000000000e+01 1.200000000000000000e+01 -9.000000000000000000e+00
-1.000000000000000000e+01 -1.000000000000000000e+01 -5.000000000000000000e+00 -7.000000000000000000e+00
-1.000000000000000000e+01 -8.000000000000000000e+00 -8.000000000000000000e+00 -1.300000000000000000e+01
4.000000000000000000e+00 -6.000000000000000000e+00 8.000000000000000000e+00 5.000000000000000000e+00
3.000000000000000000e+00 1.200000000000000000e+01 8.000000000000000000e+00 -1.300000000000000000e+01
-4.000000000000000000e+00 2.000000000000000000e+00 -3.000000000000000000e+00 -3.000000000000000000e+00
5.000000000000000000e+00 -1.300000000000000000e+01 1.000000000000000000e+01 -1.200000000000000000e+01
4.000000000000000000e+00 -1.300000000000000000e+01 5.000000000000000000e+00 -1.000000000000000000e+00
-9.000000000000000000e+00 9.000000000000000000e+00 -4.000000000000000000e+00 3.000000000000000000e+00
0.000000000000000000e+00 3.000000000000000000e+00 3.000000000000000000e+00 -9.000000000000000000e+00
-1.200000000000000000e+01 1.000000000000000000e+00 -6.000000000000000000e+00 1.000000000000000000e+00
3.000000000000000000e+00 2.000000000000000000e+00 4.000000000000000000e+00 -8.000000000000000000e+00
-1.000000000000000000e+01 -1.000000000000000000e+01 -1.000000000000000000e+01 9.000000000000000000e+00
8.000000000000000000e+00 -1.300000000000000000e+01 1.200000000000000000e+01 1.200000000000000000e+01
-8.000000000000000000e+00 -1.200000000000000000e+01 -6.000000000000000000e+00 -5.000000000000000000e+00
2.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 7.000000000000000000e+00
1.000000000000000000e+01 6.000000000000000000e+00 1.100000000000000000e+01 -8.000000000000000000e+00
6.000000000000000000e+00 8.000000000000000000e+00 8.000000000000000000e+00 -1.200000000000000000e+01
-7.000000000000000000e+00 1.000000000000000000e+01 -6.000000000000000000e+00 5.000000000000000000e+00
-3.000000000000000000e+00 -9.000000000000000000e+00 -3.000000000000000000e+00 9.000000000000000000e+00
-1.000000000000000000e+00 -1.300000000000000000e+01 -1.000000000000000000e+00 5.000000000000000000e+00
-3.000000000000000000e+00 -7.000000000000000000e+00 -3.000000000000000000e+00 4.000000000000000000e+00
-8.000000000000000000e+00 -2.000000000000000000e+00 -8.000000000000000000e+00 3.000000000000000000e+00
4.000000000000000000e+00 2.000000000000000000e+00 1.200000000000000000e+01 1.200000000000000000e+01
2.000000000000000000e+00 -5.000000000000000000e+00 3.000000000000000000e+00 1.100000000000000000e+01
6.000000000000000000e+00 -9.000000000000000000e+00 1.100000000000000000e+01 -1.300000000000000000e+01
3.000000000000000000e+00 -1.000000000000000000e+00 7.000000000000000000e+00 1.200000000000000000e+01
1.100000000000000000e+01 -1.000000000000000000e+00 1.200000000000000000e+01 4.000000000000000000e+00
-3.000000000000000000e+00 0.000000000000000000e+00 -3.000000000000000000e+00 6.000000000000000000e+00
4.000000000000000000e+00 -1.100000000000000000e+01 4.000000000000000000e+00 1.200000000000000000e+01
2.000000000000000000e+00 -4.000000000000000000e+00 2.000000000000000000e+00 1.000000000000000000e+00
-1.000000000000000000e+01 -6.000000000000000000e+00 -8.000000000000000000e+00 1.000000000000000000e+00
-1.300000000000000000e+01 7.000000000000000000e+00 -1.100000000000000000e+01 1.000000000000000000e+00
-1.300000000000000000e+01 1.200000000000000000e+01 -1.100000000000000000e+01 -1.300000000000000000e+01
6.000000000000000000e+00 0.000000000000000000e+00 1.100000000000000000e+01 -1.300000000000000000e+01
0.000000000000000000e+00 -1.000000000000000000e+00 1.000000000000000000e+00 4.000000000000000000e+00
-1.300000000000000000e+01 3.000000000000000000e+00 -9.000000000000000000e+00 -2.000000000000000000e+00
-9.000000000000000000e+00 8.000000000000000000e+00 -6.000000000000000000e+00 -3.000000000000000000e+00
-1.300000000000000000e+01 -6.000000000000000000e+00 -8.000000000000000000e+00 -2.000000000000000000e+00
5.000000000000000000e+00 -9.000000000000000000e+00 8.000000000000000000e+00 1.000000000000000000e+01
2.000000000000000000e+00 7.000000000000000000e+00 3.000000000000000000e+00 -9.000000000000000000e+00
-1.000000000000000000e+00 -6.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00
9.000000000000000000e+00 5.000000000000000000e+00 1.100000000000000000e+01 -2.000000000000000000e+00
1.100000000000000000e+01 -3.000000000000000000e+00 1.200000000000000000e+01 -8.000000000000000000e+00
3.000000000000000000e+00 0.000000000000000000e+00 3.000000000000000000e+00 5.000000000000000000e+00
-1.000000000000000000e+00 4.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+01
3.000000000000000000e+00 -6.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00
-1.300000000000000000e+01 0.000000000000000000e+00 -1.000000000000000000e+01 5.000000000000000000e+00
5.000000000000000000e+00 8.000000000000000000e+00 1.200000000000000000e+01 1.100000000000000000e+01
8.000000000000000000e+00 9.000000000000000000e+00 9.000000000000000000e+00 -6.000000000000000000e+00
7.000000000000000000e+00 -4.000000000000000000e+00 8.000000000000000000e+00 -1.200000000000000000e+01
-1.000000000000000000e+01 4.000000000000000000e+00 -1.000000000000000000e+01 9.000000000000000000e+00
7.000000000000000000e+00 3.000000000000000000e+00 1.200000000000000000e+01 4.000000000000000000e+00
9.000000000000000000e+00 -7.000000000000000000e+00 1.000000000000000000e+01 -2.000000000000000000e+00
7.000000000000000000e+00 0.000000000000000000e+00 1.200000000000000000e+01 -2.000000000000000000e+00
-1.000000000000000000e+00 -6.000000000000000000e+00 0.000000000000000000e+00 -1.100000000000000000e+01
+1 -1
View File
@@ -60,7 +60,7 @@ def ellipse(cy, cx, yradius, xradius, shape=None):
cc += cx - xradius
if shape is not None:
_coords_inside_image(rr, cc, shape)
return _coords_inside_image(rr, cc, shape)
return rr, cc
+27
View File
@@ -325,6 +325,33 @@ def test_ellipse():
assert_array_equal(img, img_)
def test_ellipse_with_shape():
img = np.zeros((15, 15), 'uint8')
rr, cc = ellipse(7, 7, 3, 10, shape=img.shape)
img[rr, cc] = 1
img_ = np.array(
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
)
assert_array_equal(img, img_)
def test_ellipse_perimeter_dot_zeroangle():
# dot, angle == 0
img = np.zeros((30, 15), 'uint8')
+22 -6
View File
@@ -1,9 +1,25 @@
import numpy as np
from numpy.testing import assert_array_equal, assert_allclose
from nose.tools import raises
from skimage.draw import ellipsoid, ellipsoid_stats
@raises(ValueError)
def test_ellipsoid_sign_parameters1():
ellipsoid(-1, 2, 2)
@raises(ValueError)
def test_ellipsoid_sign_parameters2():
ellipsoid(0, 2, 2)
@raises(ValueError)
def test_ellipsoid_sign_parameters3():
ellipsoid(-3, -2, 2)
def test_ellipsoid_bool():
test = ellipsoid(2, 2, 2)[1:-1, 1:-1, 1:-1]
test_anisotropic = ellipsoid(2, 2, 4, spacing=(1., 1., 2.))
@@ -86,18 +102,18 @@ def test_ellipsoid_levelset():
def test_ellipsoid_stats():
# Test comparison values generated by Wolfram Alpha
vol, surf = ellipsoid_stats(6, 10, 16)
assert(round(1280 * np.pi, 4) == round(vol, 4))
assert(1383.28 == round(surf, 2))
assert_allclose(1280 * np.pi, vol, atol=1e-4)
assert_allclose(1383.28, surf, atol=1e-2)
# Test when a <= b <= c does not hold
vol, surf = ellipsoid_stats(16, 6, 10)
assert(round(1280 * np.pi, 4) == round(vol, 4))
assert(1383.28 == round(surf, 2))
assert_allclose(1280 * np.pi, vol, atol=1e-4)
assert_allclose(1383.28, surf, atol=1e-2)
# Larger test to ensure reliability over broad range
vol, surf = ellipsoid_stats(17, 27, 169)
assert(round(103428 * np.pi, 4) == round(vol, 4))
assert(37426.3 == round(surf, 1))
assert_allclose(103428 * np.pi, vol, atol=1e-4)
assert_allclose(37426.3, surf, atol=1e-1)
if __name__ == "__main__":
+2 -2
View File
@@ -1,11 +1,11 @@
from .exposure import histogram, equalize, equalize_hist, \
from .exposure import histogram, equalize_hist, \
rescale_intensity, cumulative_distribution, \
adjust_gamma, adjust_sigmoid, adjust_log
from ._adapthist import equalize_adapthist
__all__ = ['histogram',
'equalize',
'equalize_hist',
'equalize_adapthist',
'rescale_intensity',
+5 -4
View File
@@ -126,8 +126,8 @@ def _clahe(image, ntiles_x, ntiles_y, clip_limit, nbins=128):
x_res = image.shape[1] - image.shape[1] % ntiles_x
image = image[: y_res, : x_res]
x_size = image.shape[1] / ntiles_x # Actual size of contextual regions
y_size = image.shape[0] / ntiles_y
x_size = image.shape[1] // ntiles_x # Actual size of contextual regions
y_size = image.shape[0] // ntiles_y
n_pixels = x_size * y_size
if clip_limit > 0.0: # Calculate actual cliplimit
@@ -139,7 +139,7 @@ def _clahe(image, ntiles_x, ntiles_y, clip_limit, nbins=128):
bin_size = 1 + NR_OF_GREY / nbins
aLUT = np.arange(NR_OF_GREY)
aLUT /= bin_size
aLUT //= bin_size
img_blocks = view_as_blocks(image, (y_size, x_size))
# Calculate greylevel mappings for each contextual region
@@ -315,7 +315,8 @@ def interpolate(image, xslice, yslice,
np.arange(yslice.size))
x_inv_coef, y_inv_coef = x_coef[:, ::-1] + 1, y_coef[::-1] + 1
view = image[yslice[0]: yslice[-1] + 1, xslice[0]: xslice[-1] + 1]
view = image[int(yslice[0]):int(yslice[-1] + 1),
int(xslice[0]):int(xslice[-1] + 1)]
im_slice = aLUT[view]
new = ((y_inv_coef * (x_inv_coef * mapLU[im_slice]
+ x_coef * mapRU[im_slice])
+29 -21
View File
@@ -7,14 +7,21 @@ from skimage._shared.utils import deprecated
__all__ = ['histogram', 'cumulative_distribution', 'equalize',
'rescale_intensity', 'adjust_gamma',
'adjust_log', 'adjust_sigmoid']
'rescale_intensity', 'adjust_gamma', 'adjust_log', 'adjust_sigmoid']
DTYPE_RANGE = dtype_range.copy()
DTYPE_RANGE.update((d.__name__, limits) for d, limits in dtype_range.items())
DTYPE_RANGE.update({'uint10': (0, 2**10 - 1),
'uint12': (0, 2**12 - 1),
'uint14': (0, 2**14 - 1),
'bool': dtype_range[np.bool_],
'float': dtype_range[np.float64]})
def histogram(image, nbins=256):
"""Return histogram of image.
Unlike `numpy.histogram`, this function returns the centers of bins and
does not rebin integer arrays. For integer arrays, each integer value has
its own bin, which improves speed and intensity-resolution.
@@ -40,11 +47,12 @@ def histogram(image, nbins=256):
Examples
--------
>>> from skimage import data
>>> hist = histogram(data.camera())
>>> import matplotlib.pyplot as plt
>>> plt.plot(hist[1], hist[0]) # doctest: +ELLIPSIS
[...]
>>> from skimage import data, exposure, util
>>> image = util.img_as_float(data.camera())
>>> np.histogram(image, bins=2)
(array([107432, 154712]), array([ 0. , 0.5, 1. ]))
>>> exposure.histogram(image, nbins=2)
(array([107432, 154712]), array([ 0.25, 0.75]))
"""
sh = image.shape
if len(sh) == 3 and sh[-1] < 4:
@@ -97,11 +105,6 @@ def cumulative_distribution(image, nbins=256):
return img_cdf, bin_centers
@deprecated('equalize_hist')
def equalize(image, nbins=256):
return equalize_hist(image, nbins)
def equalize_hist(image, nbins=256):
"""Return image after histogram equalization.
@@ -143,14 +146,15 @@ def rescale_intensity(image, in_range=None, out_range=None):
----------
image : array
Image array.
in_range : 2-tuple (float, float)
in_range : 2-tuple (float, float) or str
Min and max *allowed* intensity values of input image. If None, the
*allowed* min/max values are set to the *actual* min/max values in the
input image.
out_range : 2-tuple (float, float)
input image. Intensity values outside this range are clipped.
If string, use data limits of dtype specified by the string.
out_range : 2-tuple (float, float) or str
Min and max intensity values of output image. If None, use the min/max
intensities of the image data type. See `skimage.util.dtype` for
details.
details. If string, use data limits of dtype specified by the string.
Returns
-------
@@ -201,11 +205,14 @@ def rescale_intensity(image, in_range=None, out_range=None):
if in_range is None:
imin = np.min(image)
imax = np.max(image)
elif in_range in DTYPE_RANGE:
imin, imax = DTYPE_RANGE[in_range]
else:
imin, imax = in_range
if out_range is None:
omin, omax = dtype_range[dtype]
if out_range is None or out_range in DTYPE_RANGE:
out_range = dtype if out_range is None else out_range
omin, omax = DTYPE_RANGE[out_range]
if imin >= 0:
omin = 0
else:
@@ -263,7 +270,7 @@ def adjust_gamma(image, gamma=1, gain=1):
dtype = image.dtype.type
if gamma < 0:
return "Gamma should be a non-negative real number"
raise ValueError("Gamma should be a non-negative real number.")
scale = float(dtype_limits(image, True)[1] - dtype_limits(image, True)[0])
@@ -339,7 +346,8 @@ def adjust_sigmoid(image, cutoff=0.5, gain=10, inv=False):
References
----------
.. [1] Gustav J. Braun, "Image Lightness Rescaling Using Sigmoidal Contrast
Enhancement Functions" http://www.cis.rit.edu/fairchild/PDFs/PAP07.pdf
Enhancement Functions",
http://www.cis.rit.edu/fairchild/PDFs/PAP07.pdf
"""
_assert_non_negative(image)
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python
import os
from skimage._build import cython
base_path = os.path.abspath(os.path.dirname(__file__))
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
config = Configuration('exposure', parent_package, top_path)
config.add_data_dir('tests')
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
setup(maintainer='scikit-image Developers',
author='scikit-image Developers',
maintainer_email='scikit-image@googlegroups.com',
description='Exposure corrections',
url='https://github.com/scikit-image/scikit-image',
license='SciPy License (BSD Style)',
**(configuration(top_path='').todict())
)

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