Merge branch 'master' of git://github.com/scikit-image/scikit-image

This commit is contained in:
François Boulogne
2016-01-06 09:31:54 -05:00
137 changed files with 1756 additions and 649 deletions
+18
View File
@@ -0,0 +1,18 @@
K.-Michael Aye <michaelaye@users.noreply.github.com> <kmichael.aye@gmail.com>
Nelson Brown <nelson.brown@gmail.com> <nelson.a.brown@nasa.gov>
Luis Pedro Coelho <luis@luispedro.org> <lpc@cmu.edu>
Marianne Corvellec <marianne.corvellec@ens-lyon.org> <mcorvellec@april.org>
Riaan van den Dool <riaanvddool@gmail.com> <rvddool@csir.co.za>
Emmanuelle Gouillart <emmanuelle.gouillart@normalesup.org> <emma@aleph.(none)> <gouillar@epsilon.(none)> <emmanuelle.gouillart@nsup.org> <gouillar@aleph.(none)>
Thouis (Ray) Jones <thouis@gmail.com> <thouis@seas.harvard.edu>
Gregory R. Lee <gregory.lee@cchmc.org> <grlee77@gmail.com>
Andreas Mueller <amueller@ais.uni-bonn.de> <andreas@wuerl.net>
Juan Nunez-Iglesias <juan.n@unimelb.edu.au> <jni.soma@gmail.com> <jni@janelia.hhmi.org>
Nicolas Pinto <pinto@alum.mit.edu> <nicolas.pinto@gmail.com>
Johannes Schönberger <jsch@demuc.de> <ahojnnes@users.noreply.github.com> <hannesschoenberger@gmail.com> <jschoenberger@demuc.de>
Tim Sheerman-Chase <tim2009@sheerman-chase.org.uk> <t.sheerman-chase@surrey.ac.uk>
Matthew Trentacoste <trentaco@adobe.com> <web@matttrent.com>
James Turner <jturner@gemini.edu> <jehturner@yahoo.co.uk>
Stefan van der Walt <stefanv@berkeley.edu> <stefan@sun.ac.za> <github@mentat.za.net> <sjvdwalt@gmail.com>
John Wiggins <jwiggins@enthought.com> <john.wiggins@xfel.eu>
Tony S Yu <tyu@tony-yus-macbook.local> <tsyu80@gmail.com>
+67
View File
@@ -225,6 +225,73 @@ Every time Travis is triggered, it also calls on `Coveralls
<http://coveralls.io>`_ to inspect the current test overage.
Building docs
-------------
To build docs, run ``make`` from the ``docs`` directory. ``make help`` lists
all targets.
Requirements
~~~~~~~~~~~~
Sphinx (>= 1.3) and Latex is needed to build doc.
**Sphinx:**
.. code:: sh
pip install sphinx
**Latex Ubuntu:**
.. code:: sh
sudo apt-get install -qq texlive texlive-latex-extra dvipng
**Latex Mac:**
Install the full `MacTex <http://www.tug.org/mactex/>`__ installation or
install the smaller
`BasicTex <http://www.tug.org/mactex/morepackages.html>`__ and add *ucs*
and *dvipng* packages:
.. code:: sh
sudo tlmgr install ucs dvipng
Fixing Warnings
~~~~~~~~~~~~~~~
- "citation not found: R###" There is probably an underscore after a
reference in the first line of a docstring (e.g. [1]\_). Use this
method to find the source file: $ cd doc/build; grep -rin R####
- "Duplicate citation R###, other instance in..."" There is probably a
[2] without a [1] in one of the docstrings
- Make sure to use pre-sphinxification paths to images (not the
\_images directory)
Auto-generating dev docs
~~~~~~~~~~~~~~~~~~~~~~~~
This set of instructions was used to create
scikit-image/tools/deploy-docs.sh
- Go to Github account settings -> personal access tokens
- Create a new token with access rights ``public_repo`` and
``user:email only``
- Install the travis command line tool: ``gem install travis``. On OSX,
you can get gem via ``brew install ruby``.
- Take then token generated by Github and run
``travis encrypt GH_TOKEN=<token>`` from inside a scikit-image repo
- Paste the output into the secure: field of ``.travis.yml``.
- The decrypted GH\_TOKEN env var will be available for travis scripts
https://help.github.com/articles/creating-an-access-token-for-command-line-use/
http://docs.travis-ci.com/user/encryption-keys/
Bugs
----
+7
View File
@@ -56,3 +56,10 @@ Testing requirements
A Python Unit Testing Framework
* `Coverage.py <http://nedbatchelder.com/code/coverage/>`__
A tool that generates a unit test code coverage report
Documentation requirements
--------------------------
`sphinx >= 1.3 <http://sphinx-doc.org/>`_ is required to build the
documentation.
+3 -2
View File
@@ -12,10 +12,13 @@ Version 0.14
add an alias LineModel = LineModelND. While the deprecated LineModel has for
parameters `(dist, theta)`, LineModelND has the more general parameters
`(origin, direction)`.
* Remove deprecated old syntax support for ``skimage.transform.integrate``.
Version 0.13
------------
* Require Python 2.7+, remove warning in `__init__.py` and 2.6 hack in
`doc/release/contribs.py`.
* Remove deprecated `None` defaults for `skimage.exposure.rescale_intensity`
* Remove deprecated `skimage.filters.canny` import in `filters/__init__.py`
file (canny is now in `skimage.feature.canny`).
@@ -36,8 +39,6 @@ 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 deprecated `enforce_connectivity=False` on skimage.segmentation.slic
and set it to True as default
-53
View File
@@ -1,53 +0,0 @@
# Building docs #
To build docs, run `make` in this directory. `make help` lists all targets.
## Requirements ##
Sphinx and Latex is needed to build doc.
**Sphinx:**
```sh
pip install sphinx
```
**Latex Ubuntu:**
```sh
sudo apt-get install -qq texlive texlive-latex-extra dvipng
```
**Latex Mac:**
Install the full [MacTex](http://www.tug.org/mactex/) installation or install the smaller [BasicTex](http://www.tug.org/mactex/morepackages.html) and add *ucs* and *dvipng* packages:
```sh
sudo tlmgr install ucs dvipng
```
## Fixing Warnings ##
- "citation not found: R###"
There is probably an underscore after a reference
in the first line of a docstring (e.g. [1]_).
Use this method to find the source file:
$ cd doc/build; grep -rin R####
- "Duplicate citation R###, other instance in...""
There is probably a [2] without a [1] in one of
the docstrings
- Make sure to use pre-sphinxification paths to images
(not the _images directory)
## Auto-generating dev docs ##
This set of instructions was used to create scikit-image/tools/deploy-docs.sh
- Go to Github account settings -> personal access tokens
- Create a new token with access rights `public_repo` and `user:email only`
- Install the travis command line tool: `gem install travis`. On OSX, you can get gem via `brew install ruby`.
- Take then token generated by Github and run `travis encrypt GH_TOKEN=<token>` from inside a scikit-image repo
- Paste the output into the secure: field of `.travis.yml`.
- The decrypted GH_TOKEN env var will be available for travis scripts
https://help.github.com/articles/creating-an-access-token-for-command-line-use/
http://docs.travis-ci.com/user/encryption-keys/
+2
View File
@@ -0,0 +1,2 @@
Manipulating exposure and color channels
----------------------------------------
@@ -99,5 +99,5 @@ ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))
# prevent overlap of y-axis labels
fig.subplots_adjust(wspace=0.4)
fig.tight_layout()
plt.show()
@@ -26,7 +26,8 @@ from skimage.color import rgb2hed
ihc_rgb = data.immunohistochemistry()
ihc_hed = rgb2hed(ihc_rgb)
fig, axes = plt.subplots(2, 2, figsize=(7, 6), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, axes = plt.subplots(2, 2, figsize=(7, 6), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax0, ax1, ax2, ax3 = axes.ravel()
ax0.imshow(ihc_rgb)
@@ -44,7 +45,7 @@ ax3.set_title("DAB")
for ax in axes.ravel():
ax.axis('off')
fig.subplots_adjust(hspace=0.3)
fig.tight_layout()
"""
@@ -74,12 +74,14 @@ img_eq = rank.equalize(img, selem=selem)
# Display results
fig = plt.figure(figsize=(8, 5))
axes = np.zeros((2, 3), dtype=np.object)
axes[0,0] = plt.subplot(2, 3, 1, adjustable='box-forced')
axes[0,1] = plt.subplot(2, 3, 2, sharex=axes[0,0], sharey=axes[0,0], adjustable='box-forced')
axes[0,2] = plt.subplot(2, 3, 3, sharex=axes[0,0], sharey=axes[0,0], adjustable='box-forced')
axes[1,0] = plt.subplot(2, 3, 4)
axes[1,1] = plt.subplot(2, 3, 5)
axes[1,2] = plt.subplot(2, 3, 6)
axes[0, 0] = plt.subplot(2, 3, 1, adjustable='box-forced')
axes[0, 1] = plt.subplot(2, 3, 2, sharex=axes[0, 0], sharey=axes[0, 0],
adjustable='box-forced')
axes[0, 2] = plt.subplot(2, 3, 3, sharex=axes[0, 0], sharey=axes[0, 0],
adjustable='box-forced')
axes[1, 0] = plt.subplot(2, 3, 4)
axes[1, 1] = plt.subplot(2, 3, 5)
axes[1, 2] = plt.subplot(2, 3, 6)
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
ax_img.set_title('Low contrast image')
@@ -94,5 +96,5 @@ ax_cdf.set_ylabel('Fraction of total intensity')
# prevent overlap of y-axis labels
fig.subplots_adjust(wspace=0.4)
fig.tight_layout()
plt.show()
@@ -55,10 +55,12 @@ logarithmic_corrected = exposure.adjust_log(img, 1)
# Display results
fig = plt.figure(figsize=(8, 5))
axes = np.zeros((2,3), dtype=np.object)
axes = np.zeros((2, 3), dtype=np.object)
axes[0, 0] = plt.subplot(2, 3, 1, adjustable='box-forced')
axes[0, 1] = plt.subplot(2, 3, 2, sharex=axes[0, 0], sharey=axes[0, 0], adjustable='box-forced')
axes[0, 2] = plt.subplot(2, 3, 3, sharex=axes[0, 0], sharey=axes[0, 0], adjustable='box-forced')
axes[0, 1] = plt.subplot(2, 3, 2, sharex=axes[0, 0], sharey=axes[0, 0],
adjustable='box-forced')
axes[0, 2] = plt.subplot(2, 3, 3, sharex=axes[0, 0], sharey=axes[0, 0],
adjustable='box-forced')
axes[1, 0] = plt.subplot(2, 3, 4)
axes[1, 1] = plt.subplot(2, 3, 5)
axes[1, 2] = plt.subplot(2, 3, 6)
@@ -80,5 +82,5 @@ ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))
# prevent overlap of y-axis labels
fig.subplots_adjust(wspace=0.4)
fig.tight_layout()
plt.show()
+2
View File
@@ -0,0 +1,2 @@
Edges and lines
---------------
@@ -0,0 +1,99 @@
"""
====================
Active Contour Model
====================
The active contour model is a method to fit open or closed splines to lines or
edges in an image. It works by minimising an energy that is in part defined by
the image and part by the spline's shape: length and smoothness. The
minimization is done implicitly in the shape energy and explicitly in the
image energy.
In the following two examples the active contour model is used (1) to segment
the face of a person from the rest of an image by fitting a closed curve
to the edges of the face and (2) to find the darkest curve between two fixed
points while obeying smoothness considerations. Typically it is a good idea to
smooth images a bit before analyzing, as done in the following examples.
.. [1] *Snakes: Active contour models*. Kass, M.; Witkin, A.; Terzopoulos, D.
International Journal of Computer Vision 1 (4): 321 (1988).
We initialize a circle around the astronaut's face and use the default boundary
condition ``bc='periodic'`` to fit a closed curve. The default parameters
``w_line=0, w_edge=1`` will make the curve search towards edges, such as the
boundaries of the face.
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage.color import rgb2gray
from skimage import data
from skimage.filters import gaussian_filter
from skimage.segmentation import active_contour
# Test scipy version, since active contour is only possible
# with recent scipy version
import scipy
scipy_version = list(map(int, scipy.__version__.split('.')))
new_scipy = scipy_version[0] > 0 or \
(scipy_version[0] == 0 and scipy_version[1] >= 14)
img = data.astronaut()
img = rgb2gray(img)
s = np.linspace(0, 2*np.pi, 400)
x = 220 + 100*np.cos(s)
y = 100 + 100*np.sin(s)
init = np.array([x, y]).T
if not new_scipy:
print('You are using an old version of scipy. '
'Active contours is implemented for scipy versions '
'0.14.0 and above.')
if new_scipy:
snake = active_contour(gaussian_filter(img, 3),
init, alpha=0.015, beta=10, gamma=0.001)
fig = plt.figure(figsize=(7, 7))
ax = fig.add_subplot(111)
plt.gray()
ax.imshow(img)
ax.plot(init[:, 0], init[:, 1], '--r', lw=3)
ax.plot(snake[:, 0], snake[:, 1], '-b', lw=3)
ax.set_xticks([]), ax.set_yticks([])
ax.axis([0, img.shape[1], img.shape[0], 0])
"""
.. image:: PLOT2RST.current_figure
Here we initialize a straight line between two points, `(5, 136)` and
`(424, 50)`, and require that the spline has its end points there by giving
the boundary condition `bc='fixed'`. We furthermore make the algorithm search
for dark lines by giving a negative `w_line` value.
"""
img = data.text()
x = np.linspace(5, 424, 100)
y = np.linspace(136, 50, 100)
init = np.array([x, y]).T
if new_scipy:
snake = active_contour(gaussian_filter(img, 1), init, bc='fixed',
alpha=0.1, beta=1.0, w_line=-5, w_edge=0, gamma=0.1)
fig = plt.figure(figsize=(9, 5))
ax = fig.add_subplot(111)
plt.gray()
ax.imshow(img)
ax.plot(init[:, 0], init[:, 1], '--r', lw=3)
ax.plot(snake[:, 0], snake[:, 1], '-b', lw=3)
ax.set_xticks([]), ax.set_yticks([])
ax.axis([0, img.shape[1], img.shape[0], 0])
plt.show()
"""
.. image:: PLOT2RST.current_figure
"""
@@ -35,7 +35,8 @@ edges1 = feature.canny(im)
edges2 = feature.canny(im, sigma=3)
# display results
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3), sharex=True, sharey=True)
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3),
sharex=True, sharey=True)
ax1.imshow(im, cmap=plt.cm.jet)
ax1.axis('off')
@@ -49,7 +50,6 @@ ax3.imshow(edges2, cmap=plt.cm.gray)
ax3.axis('off')
ax3.set_title('Canny filter, $\sigma=3$', fontsize=20)
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
bottom=0.02, left=0.02, right=0.98)
fig.tight_layout()
plt.show()
@@ -1,4 +1,4 @@
r"""
"""
=============================
Straight line Hough transform
=============================
@@ -6,7 +6,7 @@ Straight line Hough transform
The Hough transform in its simplest form is a `method to detect straight lines
<http://en.wikipedia.org/wiki/Hough_transform>`__.
In the following example, we construct an image with a line intersection. We
In the following example, we construct an image with a line intersection. We
then use the Hough transform to explore a parameter space for straight lines
that may run through the image.
@@ -53,9 +53,9 @@ References
.. [2] Duda, R. O. and P. E. Hart, "Use of the Hough Transformation to
Detect Lines and Curves in Pictures," Comm. ACM, Vol. 15,
pp. 11-15 (January, 1972)
"""
from matplotlib import cm
from skimage.transform import (hough_line, hough_line_peaks,
probabilistic_hough_line)
from skimage.feature import canny
@@ -64,70 +64,71 @@ from skimage import data
import numpy as np
import matplotlib.pyplot as plt
# Construct test image
# Constructing test image.
image = np.zeros((100, 100))
# Classic straight-line Hough transform
idx = np.arange(25, 75)
image[idx[::-1], idx] = 255
image[idx, idx] = 255
# Classic straight-line Hough transform.
h, theta, d = hough_line(image)
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8,4))
# Generating figure 1.
fig, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(12, 6))
plt.tight_layout()
ax1.imshow(image, cmap=plt.cm.gray)
ax1.set_title('Input image')
ax1.set_axis_off()
ax0.imshow(image, cmap=cm.gray)
ax0.set_title('Input image')
ax0.set_axis_off()
ax2.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)
ax2.set_title('Hough transform')
ax2.set_xlabel('Angles (degrees)')
ax2.set_ylabel('Distance (pixels)')
ax2.axis('image')
ax1.imshow(np.log(1 + h), extent=[np.rad2deg(theta[-1]), np.rad2deg(theta[0]),
d[-1], d[0]], cmap=cm.gray, aspect=1/1.5)
ax1.set_title('Hough transform')
ax1.set_xlabel('Angles (degrees)')
ax1.set_ylabel('Distance (pixels)')
ax1.axis('image')
ax3.imshow(image, cmap=plt.cm.gray)
rows, cols = image.shape
ax2.imshow(image, cmap=cm.gray)
row1, col1 = 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)
ax3.plot((0, cols), (y0, y1), '-r')
ax3.axis((0, cols, rows, 0))
ax3.set_title('Detected lines')
ax3.set_axis_off()
# Line finding, using the Probabilistic Hough Transform
y1 = (dist - col1 * np.cos(angle)) / np.sin(angle)
ax2.plot((0, col1), (y0, y1), '-r')
ax2.axis((0, col1, row1, 0))
ax2.set_title('Detected lines')
ax2.set_axis_off()
# Line finding using the Probabilistic Hough Transform.
image = data.camera()
edges = canny(image, 2, 1, 25)
lines = probabilistic_hough_line(edges, threshold=10, line_length=5,
line_gap=3)
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8,4), sharex=True, sharey=True)
# Generating figure 2.
fig, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(16, 6), sharex=True,
sharey=True)
plt.tight_layout()
ax1.imshow(image, cmap=plt.cm.gray)
ax1.set_title('Input image')
ax0.imshow(image, cmap=cm.gray)
ax0.set_title('Input image')
ax0.set_axis_off()
ax0.set_adjustable('box-forced')
ax1.imshow(edges, cmap=cm.gray)
ax1.set_title('Canny edges')
ax1.set_axis_off()
ax1.set_adjustable('box-forced')
ax2.imshow(edges, cmap=plt.cm.gray)
ax2.set_title('Canny edges')
ax2.imshow(edges * 0)
for line in lines:
p0, p1 = line
ax2.plot((p0[0], p1[0]), (p0[1], p1[1]))
row2, col2 = image.shape
ax2.axis((0, col2, row2, 0))
ax2.set_title('Probabilistic Hough')
ax2.set_axis_off()
ax2.set_adjustable('box-forced')
ax3.imshow(edges * 0)
for line in lines:
p0, p1 = line
ax3.plot((p0[0], p1[0]), (p0[1], p1[1]))
ax3.set_title('Probabilistic Hough')
ax3.set_axis_off()
ax3.set_adjustable('box-forced')
plt.show()
@@ -54,12 +54,13 @@ skel, distance = medial_axis(data, return_distance=True)
# Distance to the background for pixels of the skeleton
dist_on_skel = distance * skel
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
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')
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
fig.tight_layout()
plt.show()
@@ -5,16 +5,16 @@ 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
- line
- circle
"""
import math
@@ -47,7 +47,9 @@ image[circle2] = 0
skeleton = skeletonize(image)
# display results
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4.5),
sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax1.imshow(image, cmap=plt.cm.gray)
ax1.axis('off')
@@ -57,7 +59,6 @@ ax2.imshow(skeleton, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('skeleton', fontsize=20)
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.98,
bottom=0.02, left=0.02, right=0.98)
fig.tight_layout()
plt.show()
@@ -0,0 +1,2 @@
Detection of features and objects
---------------------------------
@@ -34,19 +34,20 @@ 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
import matplotlib.pyplot as plt
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)
@@ -61,14 +62,17 @@ titles = ['Laplacian of Gaussian', 'Difference of Gaussian',
'Determinant of Hessian']
sequence = zip(blobs_list, colors, titles)
fig, axes = plt.subplots(1, 3, figsize=(14, 4), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
plt.tight_layout()
fig,axes = plt.subplots(1, 3, sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
axes = axes.ravel()
for blobs, color, title in sequence:
ax = axes[0]
axes = axes[1:]
ax.set_title(title)
ax.imshow(image, interpolation='nearest')
ax.set_axis_off()
for blob in blobs:
y, x, r = blob
c = plt.Circle((x, y), r, color=color, linewidth=2, fill=False)
@@ -87,5 +87,5 @@ ax3.set_title("K-means filterbank (codebook)\non LGN-like DoG image")
for ax in axes.ravel():
ax.axis('off')
fig.subplots_adjust(hspace=0.3)
fig.tight_layout()
plt.show()
@@ -15,11 +15,11 @@ Algorithm overview
Compute a Histogram of Oriented Gradients (HOG) by
1. (optional) global image normalisation
2. computing the gradient image in x and y
3. computing gradient histograms
4. normalising across blocks
5. flattening into a feature vector
1. (optional) global image normalisation
2. computing the gradient image in x and y
3. computing gradient histograms
4. normalising across blocks
5. flattening into a feature vector
The first stage applies an optional global image normalisation
equalisation that is designed to reduce the influence of illumination
+2
View File
@@ -0,0 +1,2 @@
Filtering and restoration
-------------------------
@@ -38,7 +38,8 @@ astro = astro[220:300, 220:320]
noisy = astro + 0.6 * astro.std() * np.random.random(astro.shape)
noisy = np.clip(noisy, 0, 1)
fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5), sharex=True,
sharey=True, subplot_kw={'adjustable': 'box-forced'})
plt.gray()
@@ -62,7 +63,6 @@ ax[1, 2].imshow(astro)
ax[1, 2].axis('off')
ax[1, 2].set_title('original')
fig.subplots_adjust(wspace=0.02, hspace=0.2,
top=0.9, bottom=0.05, left=0, right=1)
fig.tight_layout()
plt.show()
@@ -26,7 +26,8 @@ noisy = np.clip(noisy, 0, 1)
denoise = denoise_nl_means(noisy, 7, 9, 0.08)
fig, ax = plt.subplots(ncols=2, figsize=(8, 4), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(ncols=2, figsize=(8, 4), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax[0].imshow(noisy)
ax[0].axis('off')
@@ -35,7 +36,6 @@ ax[1].imshow(denoise)
ax[1].axis('off')
ax[1].set_title('non-local means')
fig.subplots_adjust(wspace=0.02, hspace=0.2,
top=0.9, bottom=0.05, left=0, right=1)
fig.tight_layout()
plt.show()
@@ -5,12 +5,12 @@ Mean filters
This example compares the following mean filters of the rank filter package:
* **local mean**: all pixels belonging to the structuring element to compute
average gray level.
* **percentile mean**: only use values between percentiles p0 and p1
(here 10% and 90%).
* **bilateral mean**: only use pixels of the structuring element having a gray
level situated inside g-s0 and g+s1 (here g-500 and g+500)
* **local mean**: all pixels belonging to the structuring element to compute
average gray level.
* **percentile mean**: only use values between percentiles p0 and p1
(here 10% and 90%).
* **bilateral mean**: only use pixels of the structuring element having a gray
level situated inside g-s0 and g+s1 (here g-500 and g+500)
Percentile and usual mean give here similar results, these filters smooth the
complete image (background and details). Bilateral mean exhibits a high
@@ -34,7 +34,8 @@ bilateral_result = rank.mean_bilateral(image, selem=selem, s0=500, s1=500)
normal_result = rank.mean(image, selem=selem)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 10), sharex=True, sharey=True)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 10),
sharex=True, sharey=True)
ax = axes.ravel()
titles = ['Original', 'Percentile mean', 'Bilateral mean', 'Local mean']
@@ -42,7 +42,9 @@ astro += 0.1 * astro.std() * np.random.standard_normal(astro.shape)
deconvolved, _ = restoration.unsupervised_wiener(astro, psf)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 5),
sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
plt.gray()
@@ -54,7 +56,6 @@ 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)
fig.tight_layout()
plt.show()
+2
View File
@@ -0,0 +1,2 @@
Operations on NumPy arrays
--------------------------
@@ -49,8 +49,9 @@ ax0, ax1, ax2, ax3 = axes.ravel()
ax0.set_title("Original rescaled with\n spline interpolation (order=3)")
l_resized = ndi.zoom(l, 2, order=3)
#ax0.imshow(l_resized, cmap=cm.Greys_r)
ax0.imshow(l_resized, extent=(0, 128, 128, 0), interpolation='nearest', cmap=cm.Greys_r)
ax0.imshow(l_resized, extent=(0, 128, 128, 0), interpolation='nearest',
cmap=cm.Greys_r)
ax0.set_axis_off()
ax1.set_title("Block view with\n local mean pooling")
@@ -65,5 +66,5 @@ ax3.set_title("Block view with\n local median pooling")
ax3.imshow(median_view, interpolation='nearest', cmap=cm.Greys_r)
ax3.set_axis_off()
fig.subplots_adjust(hspace=0.4, wspace=0.4)
fig.tight_layout()
plt.show()
+2
View File
@@ -0,0 +1,2 @@
Segmentation of objects
-----------------------
@@ -40,7 +40,8 @@ seg2 = slic(coins, n_segments=117, max_iter=160, sigma=1, compactness=0.75,
segj = join_segmentations(seg1, seg2)
# show the segmentations
fig, axes = plt.subplots(ncols=4, figsize=(9, 2.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, axes = plt.subplots(ncols=4, figsize=(9, 2.5), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
axes[0].imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
axes[0].set_title('Image')
@@ -58,5 +59,5 @@ axes[3].set_title('Join')
for ax in axes:
ax.axis('off')
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
fig.tight_layout()
plt.show()
@@ -10,23 +10,21 @@ structuring element.
The example compares the local threshold with the global threshold.
.. note: local is much slower than global thresholding
.. Note: local is much slower than global thresholding
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
"""
import matplotlib
import matplotlib.pyplot as plt
from skimage import data
from skimage.morphology import disk
from skimage.filters import threshold_otsu, rank
from skimage.util import img_as_ubyte
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rcParams['font.size'] = 9
img = img_as_ubyte(data.page())
radius = 15
@@ -36,26 +34,26 @@ local_otsu = rank.otsu(img, selem)
threshold_global_otsu = threshold_otsu(img)
global_otsu = img >= threshold_global_otsu
fig, ax = plt.subplots(2, 2, figsize=(8, 5), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax0, ax1, ax2, ax3 = ax.ravel()
fig, ax = plt.subplots(2, 2, figsize=(8, 5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
ax1, ax2, ax3, ax4 = ax.ravel()
fig.colorbar(ax0.imshow(img, cmap=plt.cm.gray),
ax=ax0, orientation='horizontal')
ax0.set_title('Original')
ax0.axis('off')
fig.colorbar(ax1.imshow(img, cmap=plt.cm.gray),
fig.colorbar(ax1.imshow(local_otsu, cmap=plt.cm.gray),
ax=ax1, orientation='horizontal')
ax1.set_title('Original')
ax1.set_title('Local Otsu (radius=%d)' % radius)
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.imshow(img >= local_otsu, cmap=plt.cm.gray)
ax2.set_title('Original >= Local Otsu' % threshold_global_otsu)
ax2.axis('off')
ax3.imshow(img >= local_otsu, cmap=plt.cm.gray)
ax3.set_title('Original >= Local Otsu' % threshold_global_otsu)
ax3.imshow(global_otsu, cmap=plt.cm.gray)
ax3.set_title('Global Otsu (threshold = %d)' % 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()
@@ -25,7 +25,8 @@ image_max = ndi.maximum_filter(im, size=20, mode='constant')
coordinates = peak_local_max(im, min_distance=20)
# display results
fig, ax = plt.subplots(1, 3, figsize=(8, 3), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(1, 3, figsize=(8, 3), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax1, ax2, ax3 = ax.ravel()
ax1.imshow(im, cmap=plt.cm.gray)
ax1.axis('off')
@@ -41,7 +42,6 @@ ax3.plot(coordinates[:, 1], coordinates[:, 0], 'r.')
ax3.axis('off')
ax3.set_title('Peak local max')
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
bottom=0.02, left=0.02, right=0.98)
fig.tight_layout()
plt.show()
@@ -38,7 +38,8 @@ markers[data > 1.3] = 2
labels = random_walker(data, markers, beta=10, mode='bf')
# Plot results
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 3.2), sharex=True, sharey=True)
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 3.2),
sharex=True, sharey=True)
ax1.imshow(data, cmap='gray', interpolation='nearest')
ax1.axis('off')
ax1.set_adjustable('box-forced')
@@ -52,6 +53,5 @@ ax3.axis('off')
ax3.set_adjustable('box-forced')
ax3.set_title('Segmentation')
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
right=1)
fig.tight_layout()
plt.show()
@@ -79,9 +79,10 @@ print("Felzenszwalb's number of segments: %d" % len(np.unique(segments_fz)))
print("Slic number of segments: %d" % len(np.unique(segments_slic)))
print("Quickshift number of segments: %d" % len(np.unique(segments_quick)))
fig, ax = plt.subplots(1, 3, sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(1, 3, sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
fig.set_size_inches(8, 3, forward=True)
fig.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
fig.tight_layout()
ax[0].imshow(mark_boundaries(img, segments_fz))
ax[0].set_title("Felzenszwalbs's method")
@@ -48,7 +48,8 @@ local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)),
markers = ndi.label(local_maxi)[0]
labels = watershed(-distance, markers, mask=image)
fig, axes = plt.subplots(ncols=3, figsize=(8, 2.7), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, axes = plt.subplots(ncols=3, figsize=(8, 2.7), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax0, ax1, ax2 = axes
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
@@ -61,6 +62,5 @@ ax2.set_title('Separated objects')
for ax in axes:
ax.axis('off')
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=0.9, bottom=0, left=0,
right=1)
fig.tight_layout()
plt.show()
+2
View File
@@ -0,0 +1,2 @@
Geometrical transformations and registration
--------------------------------------------
@@ -7,10 +7,10 @@ This example illustrates the different edge modes available during
interpolation in routines such as `skimage.transform.rescale` and
`skimage.transform.resize`.
"""
from skimage._shared.interpolation import extend_image
import skimage.data
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from skimage._shared.interpolation import extend_image
img = np.zeros((16, 16))
img[:8, :8] += 1
@@ -20,18 +20,19 @@ img[:1, :1] += 2
img[8, 8] = 4
modes = ['constant', 'edge', 'wrap', 'reflect', 'symmetric']
fig, axes = plt.subplots(1, 5, figsize=(15, 5))
fig, axes = plt.subplots(2, 3)
axes = axes.flatten()
for n, mode in enumerate(modes):
img_extended = extend_image(img, pad=img.shape[0], mode=mode)
axes[n].imshow(img_extended, cmap=plt.cm.gray, interpolation='nearest')
axes[n].plot([15.5, 15.5], [15.5, 31.5], 'y--', linewidth=0.5)
axes[n].plot([31.5, 31.5], [15.5, 31.5], 'y--', linewidth=0.5)
axes[n].plot([15.5, 31.5], [15.5, 15.5], 'y--', linewidth=0.5)
axes[n].plot([15.5, 31.5], [31.5, 31.5], 'y--', linewidth=0.5)
axes[n].set_axis_off()
axes[n].set_aspect('equal')
axes[n].plot([15.5, 15.5, 31.5, 31.5, 15.5],
[15.5, 31.5, 31.5, 15.5, 15.5], 'y--', linewidth=0.5)
axes[n].set_title(mode)
for n in range(len(axes)):
axes[n].set_axis_off()
axes[n].set_aspect('equal')
plt.tight_layout()
plt.show()
@@ -31,9 +31,9 @@ Technique (SART).
For further information on tomographic reconstruction, see
- AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging",
http://www.slaney.org/pct/pct-toc.html
- http://en.wikipedia.org/wiki/Radon_transform
- AC Kak, M Slaney, "Principles of Computerized Tomographic Imaging",
http://www.slaney.org/pct/pct-toc.html
- http://en.wikipedia.org/wiki/Radon_transform
The forward transform
=====================
@@ -73,7 +73,7 @@ ax2.set_ylabel("Projection position (pixels)")
ax2.imshow(sinogram, cmap=plt.cm.Greys_r,
extent=(0, 180, 0, sinogram.shape[0]), aspect='auto')
fig.subplots_adjust(hspace=0.4, wspace=0.5)
fig.tight_layout()
plt.show()
"""
@@ -101,7 +101,9 @@ error = reconstruction_fbp - image
print('FBP rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2)))
imkwargs = dict(vmin=-0.2, vmax=0.2)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5),
sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax1.set_title("Reconstruction\nFiltered back projection")
ax1.imshow(reconstruction_fbp, cmap=plt.cm.Greys_r)
ax2.set_title("Reconstruction error\nFiltered back projection")
@@ -152,7 +154,8 @@ error = reconstruction_sart - image
print('SART (1 iteration) rms reconstruction error: %.3g'
% np.sqrt(np.mean(error**2)))
fig, ax = plt.subplots(2, 2, figsize=(8, 8.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, ax = plt.subplots(2, 2, figsize=(8, 8.5), sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
ax1, ax2, ax3, ax4 = ax.ravel()
ax1.set_title("Reconstruction\nSART")
ax1.imshow(reconstruction_sart, cmap=plt.cm.Greys_r)
@@ -19,19 +19,14 @@ but with very different mean structural similarity indices.
assessment: From error visibility to structural similarity," IEEE
Transactions on Image Processing, vol. 13, no. 4, pp. 600-612,
Apr. 2004.
"""
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
@@ -45,7 +40,10 @@ def mse(x, y):
img_noise = img + noise
img_const = img + abs(noise)
fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(8, 4), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(16, 6),
sharex=True, sharey=True,
subplot_kw={'adjustable': 'box-forced'})
plt.tight_layout()
mse_none = mse(img, img)
ssim_none = ssim(img, img, dynamic_range=img.max() - img.min())
@@ -63,13 +61,16 @@ label = 'MSE: %2.f, SSIM: %.2f'
ax0.imshow(img, cmap=plt.cm.gray, vmin=0, vmax=1)
ax0.set_xlabel(label % (mse_none, ssim_none))
ax0.set_title('Original image')
ax0.axes.get_yaxis().set_visible(False)
ax1.imshow(img_noise, cmap=plt.cm.gray, vmin=0, vmax=1)
ax1.set_xlabel(label % (mse_noise, ssim_noise))
ax1.set_title('Image with noise')
ax1.axes.get_yaxis().set_visible(False)
ax2.imshow(img_const, cmap=plt.cm.gray, vmin=0, vmax=1)
ax2.set_xlabel(label % (mse_const, ssim_const))
ax2.set_title('Image plus constant')
ax2.axes.get_yaxis().set_visible(False)
plt.show()
+31 -27
View File
@@ -10,41 +10,45 @@ if len(sys.argv) != 2:
tag = sys.argv[1]
def call(cmd):
return subprocess.check_output(shlex.split(cmd), universal_newlines=True).split('\n')
tag_date = call("git show --format='%%ci' %s" % tag)[0]
print("Release %s was on %s\n" % (tag, tag_date))
if not sys.version_info[:2] == (2, 6):
merges = call("git log --since='%s' --merges --format='>>>%%B' --reverse" % tag_date)
merges = [m for m in merges if m.strip()]
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()]
def call(cmd):
return subprocess.check_output(shlex.split(cmd), universal_newlines=True).split('\n')
num_commits = call("git rev-list %s..HEAD --count" % tag)[0]
print("A total of %s changes have been committed.\n" % num_commits)
tag_date = call("git show --format='%%ci' %s" % tag)[0]
print("Release %s was on %s\n" % (tag, tag_date))
print("It contained the following %d merges:\n" % len(merges))
for (merge, message) in merges:
if merge.startswith('Merge pull request #'):
PR = ' (%s)' % merge.split()[3]
else:
PR = ''
merges = call("git log --since='%s' --merges --format='>>>%%B' --reverse" % tag_date)
merges = [m for m in merges if m.strip()]
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('- ' + message + PR)
num_commits = call("git rev-list %s..HEAD --count" % tag)[0]
print("A total of %s changes have been committed.\n" % num_commits)
print("It contained the following %d merges:\n" % len(merges))
for (merge, message) in merges:
if merge.startswith('Merge pull request #'):
PR = ' (%s)' % merge.split()[3]
else:
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()]
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.ascii_letters]
return author[-1]
def key(author):
author = [v for v in author.split() if v[0] in string.ascii_letters]
if len(author) > 0:
return author[-1]
authors = sorted(set(authors), key=key)
authors = sorted(set(authors), key=key)
for a in authors:
print('- ' + a)
for a in authors:
print('- ' + a)
+2 -2
View File
@@ -81,9 +81,9 @@ disk: ::
... (nrows / 2)**2)
>>> camera[outer_disk_mask] = 0
.. image:: ../auto_examples/images/plot_camera_numpy_1.png
.. image:: ../auto_examples/numpy_operations/images/plot_camera_numpy_1.png
:width: 45%
:target: ../auto_examples/plot_camera_numpy.html
:target: ../auto_examples/numpy_operations/plot_camera_numpy.html
Boolean arithmetic can be used to define more complex masks: ::
@@ -78,8 +78,8 @@ using an array of labels to encode the regions to be represented with the
same color.
.. image: ../auto_examples/images/plot_join_segmentations_1.png
:target: ../auto_examples/plot_join_segmentations.html
.. image: ../auto_examples/segmentation/images/plot_join_segmentations_1.png
:target: ../auto_examples/segmentation/plot_join_segmentations.html
:align: center
:width: 80%
@@ -87,9 +87,9 @@ same color.
.. topic:: Examples:
* :ref:`example_plot_tinting_grayscale_images.py`
* :ref:`example_plot_join_segmentations.py`
* :ref:`example_plot_rag_mean_color.py`
* :ref:`example_color_exposure_plot_tinting_grayscale_images.py`
* :ref:`example_segmentation_plot_join_segmentations.py`
* :ref:`example_segmentation_plot_rag_mean_color.py`
Contrast and exposure
@@ -122,7 +122,7 @@ the image. The histogram of pixel values is computed with
:func:`histogram` returns the number of pixels for each value bin, and
the centers of the bins. The behavior of :func:`histogram` is therefore
slightly different from the one of :func:`np.histogram`, which returns
slightly different from the one of :func:`numpy.histogram`, which returns
the boundaries of the bins.
The simplest contrast enhancement :func:`rescale_intensity` consists in
@@ -157,16 +157,16 @@ details are enhanced in large regions with poor contrast. As a further
refinement, histogram equalization can be performed in subregions of the
image with :func:`equalize_adapthist`, in order to correct for exposure
gradients across the image. See the example
:ref:`example_plot_equalize.py`.
:ref:`example_color_exposure_plot_equalize.py`.
.. image:: ../auto_examples/images/plot_equalize_1.png
:target: ../auto_examples/plot_equalize.html
.. image:: ../auto_examples/color_exposure/images/plot_equalize_1.png
:target: ../auto_examples/color_exposure/plot_equalize.html
:align: center
:width: 90%
.. topic:: Examples:
* :ref:`example_plot_equalize.py`
* :ref:`example_color_exposure_plot_equalize.py`
+18 -18
View File
@@ -11,8 +11,8 @@ the coins cannot be done directly from the histogram of grey values,
because the background shares enough grey levels with the coins that a
thresholding segmentation is not sufficient.
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_1.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_1.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
::
@@ -26,8 +26,8 @@ Simply thresholding the image leads either to missing significant parts
of the coins, or to merging parts of the background with the
coins. This is due to the inhomogeneous lighting of the image.
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_2.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_2.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
A first idea is to take advantage of the local contrast, that is, to
@@ -53,8 +53,8 @@ boundary of the coins, or inside the coins.
>>> from scipy import ndimage as ndi
>>> fill_coins = ndi.binary_fill_holes(edges)
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_3.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_3.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
Now that we have contours that delineate the outer boundary of the coins,
@@ -62,8 +62,8 @@ we fill the inner part of the coins using the
``ndi.binary_fill_holes`` function, which uses mathematical morphology
to fill the holes.
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_4.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_4.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
Most coins are well segmented out of the background. Small objects from
@@ -83,8 +83,8 @@ has not been segmented correctly at all. The reason is that the contour
that we got from the Canny detector was not completely closed, therefore
the filling function did not fill the inner part of the coin.
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_5.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_5.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
Therefore, this segmentation method is not very robust: if we miss a
@@ -128,8 +128,8 @@ separate the coins from the background.
and here is the corresponding 2-D plot:
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_6.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_6.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
The next step is to find markers of the background and the coins based on the
@@ -139,8 +139,8 @@ extreme parts of the histogram of grey values::
>>> markers[coins < 30] = 1
>>> markers[coins > 150] = 2
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_7.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_7.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
Let us now compute the watershed transform::
@@ -148,8 +148,8 @@ Let us now compute the watershed transform::
>>> from skimage.morphology import watershed
>>> segmentation = watershed(elevation_map, markers)
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_8.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_8.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
With this method, the result is satisfying for all coins. Even if the
@@ -165,7 +165,7 @@ We can now label all the coins one by one using ``ndi.label``::
>>> labeled_coins, _ = ndi.label(segmentation)
.. image:: ../auto_examples/applications/images/plot_coins_segmentation_9.png
:target: ../auto_examples/applications/plot_coins_segmentation.html
.. image:: ../auto_examples/xx_applications/images/plot_coins_segmentation_9.png
:target: ../auto_examples/xx_applications/plot_coins_segmentation.html
:align: center
+1 -1
View File
@@ -3,5 +3,5 @@ numpy>=1.6.1
scipy>=0.9.0
six>=1.4
networkx>=1.8
pillow>=1.7.8
pillow>=2.1.0
dask[array]>=0.5.0
+5
View File
@@ -156,4 +156,9 @@ else:
_raise_build_error(e)
from .util.dtype import *
if sys.version.startswith('2.6'):
warnings.warn("Python 2.6 is deprecated and will not be supported in scikit-image 0.13+")
del warnings, functools, osp, imp, sys
Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.
+9 -9
View File
@@ -5,19 +5,19 @@ from ._draw import _coords_inside_image
def _ellipse_in_shape(shape, center, radiuses):
"""Generate coordinates of points within ellipse bounded by shape."""
y, x = np.ogrid[0:float(shape[0]), 0:float(shape[1])]
cy, cx = center
r_lim, c_lim = np.ogrid[0:float(shape[0]), 0:float(shape[1])]
r, c = center
ry, rx = radiuses
distances = ((y - cy) / ry) ** 2 + ((x - cx) / rx) ** 2
distances = ((r_lim - r) / ry) ** 2 + ((c_lim - c) / rx) ** 2
return np.nonzero(distances < 1)
def ellipse(cy, cx, yradius, xradius, shape=None):
def ellipse(r, c, yradius, xradius, shape=None):
"""Generate coordinates of pixels within ellipse.
Parameters
----------
cy, cx : double
r, c : double
Centre coordinate of ellipse.
yradius, xradius : double
Minor and major semi-axes. ``(x/xradius)**2 + (y/yradius)**2 = 1``.
@@ -53,7 +53,7 @@ def ellipse(cy, cx, yradius, xradius, shape=None):
"""
center = np.array([cy, cx])
center = np.array([r, c])
radiuses = np.array([yradius, xradius])
# The upper_left and lower_right corners of the
@@ -77,12 +77,12 @@ def ellipse(cy, cx, yradius, xradius, shape=None):
return rr, cc
def circle(cy, cx, radius, shape=None):
def circle(r, c, radius, shape=None):
"""Generate coordinates of pixels within circle.
Parameters
----------
cy, cx : double
r, c : double
Centre coordinate of circle.
radius: double
Radius of circle.
@@ -122,7 +122,7 @@ def circle(cy, cx, radius, shape=None):
"""
return ellipse(cy, cx, radius, radius, shape)
return ellipse(r, c, radius, radius, shape)
def set_color(img, coords, color):
+11 -6
View File
@@ -5,7 +5,8 @@ from . import _hoghistogram
def hog(image, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(3, 3), visualise=False, normalise=False):
cells_per_block=(3, 3), visualise=False, normalise=False,
feature_vector=True):
"""Extract Histogram of Oriented Gradients (HOG) for a given image.
Compute a Histogram of Oriented Gradients (HOG) by
@@ -31,6 +32,9 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
normalise : bool, optional
Apply power law compression to normalise the image before
processing.
feature_vector : bool, optional
Return the data as a feature vector by calling .ravel() on the result
just before returning.
Returns
-------
@@ -127,13 +131,11 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
orientations_arr = np.arange(orientations)
dx_arr = radius * np.cos(orientations_arr / orientations * np.pi)
dy_arr = radius * np.sin(orientations_arr / orientations * np.pi)
cr2 = cy + cy
cc2 = cx + cx
hog_image = np.zeros((sy, sx), dtype=float)
for x in range(n_cellsx):
for y in range(n_cellsy):
for o, dx, dy in zip(orientations_arr, dx_arr, dy_arr):
centre = tuple([y * cr2 // 2, x * cc2 // 2])
centre = tuple([y * cy + cy // 2, x * cx + cx // 2])
rr, cc = draw.line(int(centre[0] - dx),
int(centre[1] + dy),
int(centre[0] + dx),
@@ -171,8 +173,11 @@ def hog(image, orientations=9, pixels_per_cell=(8, 8),
overlapping grid of blocks covering the detection window into a combined
feature vector for use in the window classifier.
"""
if feature_vector:
normalised_blocks = normalised_blocks.ravel()
if visualise:
return normalised_blocks.ravel(), hog_image
return normalised_blocks, hog_image
else:
return normalised_blocks.ravel()
return normalised_blocks
+23 -13
View File
@@ -10,7 +10,9 @@ cdef float cell_hog(double[:, ::1] magnitude,
float orientation_start, float orientation_end,
int cell_columns, int cell_rows,
int column_index, int row_index,
int size_columns, int size_rows) nogil:
int size_columns, int size_rows,
int range_rows_start, int range_rows_stop,
int range_columns_start, int range_columns_stop) nogil:
"""Calculation of the cell's HOG value
Parameters
@@ -35,22 +37,23 @@ cdef float cell_hog(double[:, ::1] magnitude,
Number of columns.
size_rows : int
Number of rows.
range_rows_start : int
Start row of cell.
range_rows_stop : int
Stop row of cell.
range_columns_start : int
Start column of cell.
range_columns_stop : int
Stop column of cell
Returns
-------
total : float
The total HOG value.
"""
cdef int cell_column, cell_row, cell_row_index, cell_column_index, \
range_columns_start, range_columns_stop, range_rows_start, \
range_rows_stop
range_rows_stop = cell_rows/2
range_rows_start = -range_rows_stop
range_columns_stop = cell_columns/2
range_columns_start = -range_columns_stop
cdef int cell_column, cell_row, cell_row_index, cell_column_index
cdef float total = 0.
for cell_row in range(range_rows_start, range_rows_stop):
cell_row_index = row_index + cell_row
if (cell_row_index < 0 or cell_row_index >= size_rows):
@@ -67,7 +70,7 @@ cdef float cell_hog(double[:, ::1] magnitude,
total += magnitude[cell_row_index, cell_column_index]
return total
return total / (cell_rows * cell_columns)
def hog_histograms(double[:, ::1] gradient_columns,
double[:, ::1] gradient_rows,
@@ -106,7 +109,9 @@ def hog_histograms(double[:, ::1] gradient_columns,
gradient_rows)
cdef double[:, ::1] orientation = \
np.arctan2(gradient_rows, gradient_columns) * (180 / np.pi) % 180
cdef int i, x, y, o, yi, xi, cc, cr, x0, y0
cdef int i, x, y, o, yi, xi, cc, cr, x0, y0, \
range_rows_start, range_rows_stop, \
range_columns_start, range_columns_stop
cdef float orientation_start, orientation_end, \
number_of_orientations_per_180
@@ -115,6 +120,10 @@ def hog_histograms(double[:, ::1] gradient_columns,
cc = cell_rows * number_of_cells_rows
cr = cell_columns * number_of_cells_columns
number_of_orientations_per_180 = 180. / number_of_orientations
range_rows_stop = cell_rows/2
range_rows_start = -range_rows_stop
range_columns_stop = cell_columns/2
range_columns_start = -range_columns_stop
with nogil:
# compute orientations integral images
@@ -134,7 +143,8 @@ def hog_histograms(double[:, ::1] gradient_columns,
while x < cr:
orientation_histogram[yi, xi, i] = cell_hog(magnitude,
orientation, orientation_start, orientation_end,
cell_columns, cell_rows, x, y, size_columns, size_rows)
cell_columns, cell_rows, x, y, size_columns, size_rows,
range_rows_start, range_rows_stop, range_columns_start, range_columns_stop)
xi += 1
x += cell_columns
+2 -2
View File
@@ -271,8 +271,8 @@ def _local_binary_pattern(double[:, ::1] image,
# Values represent offsets of neighbour rectangles relative to central one.
# It has order starting from top left and going clockwise.
cdef:
Py_ssize_t[::1] mlbp_r_offsets = np.asarray([-1, -1, -1, 0, 1, 1, 1, 0])
Py_ssize_t[::1] mlbp_c_offsets = np.asarray([-1, 0, 1, 1, 1, 0, -1, -1])
Py_ssize_t[::1] mlbp_r_offsets = np.asarray([-1, -1, -1, 0, 1, 1, 1, 0], dtype=np.intp)
Py_ssize_t[::1] mlbp_c_offsets = np.asarray([-1, 0, 1, 1, 1, 0, -1, -1], dtype=np.intp)
def _multiblock_lbp(float[:, ::1] int_image,
+14 -1
View File
@@ -1,5 +1,7 @@
import os
import numpy as np
from scipy import ndimage as ndi
import skimage as si
from skimage import data
from skimage import feature
from skimage import img_as_float
@@ -9,7 +11,7 @@ from numpy.testing import (assert_raises,
)
def test_histogram_of_oriented_gradients():
def test_histogram_of_oriented_gradients_output_size():
img = img_as_float(data.astronaut()[:256, :].mean(axis=2))
fd = feature.hog(img, orientations=9, pixels_per_cell=(8, 8),
@@ -18,6 +20,17 @@ def test_histogram_of_oriented_gradients():
assert len(fd) == 9 * (256 // 8) * (512 // 8)
def test_histogram_of_oriented_gradients_output_correctness():
img = np.load(os.path.join(si.data_dir, 'lena_GRAY_U8.npy'))
correct_output = np.load(os.path.join(si.data_dir, 'lena_GRAY_U8_hog.npy'))
output = feature.hog(img, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(3, 3), feature_vector=True,
normalise=False, visualise=False)
assert_almost_equal(output, correct_output)
def test_hog_image_size_cell_size_mismatch():
image = data.camera()[:150, :200]
fd = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),
+67 -77
View File
@@ -1,16 +1,6 @@
try:
import networkx as nx
except ImportError:
msg = "Graph functions require networkx, which is not installed"
class nx:
class Graph:
def __init__(self, *args, **kwargs):
raise ImportError(msg)
import warnings
warnings.warn(msg)
import networkx as nx
import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy import ndimage as ndi
import math
from ... import draw, measure, segmentation, util, color
@@ -51,21 +41,79 @@ def min_weight(graph, src, dst, n):
return min(w1, w2)
def _add_edge_filter(values, graph):
"""Create edge in `graph` between central element of `values` and the rest.
Add an edge between the middle element in `values` and
all other elements of `values` into `graph`. ``values[len(values) // 2]``
is expected to be the central value of the footprint used.
Parameters
----------
values : array
The array to process.
graph : RAG
The graph to add edges in.
Returns
-------
0 : float
Always returns 0. The return value is required so that `generic_filter`
can put it in the output array, but it is ignored by this filter.
"""
values = values.astype(int)
center = values[len(values) // 2]
for value in values:
if value != center and not graph.has_edge(center, value):
graph.add_edge(center, value)
return 0.
class RAG(nx.Graph):
"""
The Region Adjacency Graph (RAG) of an image, subclasses
`networx.Graph <http://networkx.github.io/documentation/latest/reference/classes.graph.html>`_
Parameters
----------
label_image : array of int
An initial segmentation, with each region labeled as a different
integer. Every unique value in ``label_image`` will correspond to
a node in the graph.
connectivity : int in {1, ..., ``label_image.ndim``}, optional
The connectivity between pixels in ``label_image``. For a 2D image,
a connectivity of 1 corresponds to immediate neighbors up, down,
left, and right, while a connectivity of 2 also includes diagonal
neighbors. See `scipy.ndimage.generate_binary_structure`.
data : networkx Graph specification, optional
Initial or additional edges to pass to the NetworkX Graph
constructor. See `networkx.Graph`. Valid edge specifications
include edge list (list of tuples), NumPy arrays, and SciPy
sparse matrices.
**attr : keyword arguments, optional
Additional attributes to add to the graph.
"""
def __init__(self, data=None, **attr):
def __init__(self, label_image=None, connectivity=1, data=None, **attr):
super(RAG, self).__init__(data, **attr)
try:
self.max_id = max(self.nodes_iter())
except ValueError:
# Empty sequence
if self.number_of_nodes() == 0:
self.max_id = 0
else:
self.max_id = max(self.nodes_iter())
if label_image is not None:
fp = ndi.generate_binary_structure(label_image.ndim, connectivity)
ndi.generic_filter(
label_image,
function=_add_edge_filter,
footprint=fp,
mode='nearest',
output=as_strided(np.empty((1,), dtype=np.float_),
shape=label_image.shape,
strides=((0,) * label_image.ndim)),
extra_arguments=(self,))
def merge_nodes(self, src, dst, weight_func=min_weight, in_place=True,
extra_arguments=[], extra_keywords={}):
@@ -172,36 +220,6 @@ class RAG(nx.Graph):
super(RAG, self).add_node(n)
def _add_edge_filter(values, graph):
"""Create edge in `g` between the first element of `values` and the rest.
Add an edge between the first element in `values` and
all other elements of `values` in the graph `g`. `values[0]`
is expected to be the central value of the footprint used.
Parameters
----------
values : array
The array to process.
graph : RAG
The graph to add edges in.
Returns
-------
0 : int
Always returns 0. The return value is required so that `generic_filter`
can put it in the output array.
"""
values = values.astype(int)
current = values[0]
for value in values[1:]:
if value != current:
graph.add_edge(current, value)
return 0
def rag_mean_color(image, labels, connectivity=2, mode='distance',
sigma=255.0):
"""Compute the Region Adjacency Graph using mean colors.
@@ -224,7 +242,7 @@ def rag_mean_color(image, labels, connectivity=2, mode='distance',
Pixels with a squared distance less than `connectivity` from each other
are considered adjacent. It can range from 1 to `labels.ndim`. Its
behavior is the same as `connectivity` parameter in
`scipy.ndimage.filters.generate_binary_structure`.
`scipy.ndimage.generate_binary_structure`.
mode : {'distance', 'similarity'}, optional
The strategy to assign edge weights.
@@ -263,35 +281,7 @@ def rag_mean_color(image, labels, connectivity=2, mode='distance',
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.11.5274
"""
graph = RAG()
# The footprint is constructed in such a way that the first
# element in the array being passed to _add_edge_filter is
# the central value.
fp = ndi.generate_binary_structure(labels.ndim, connectivity)
for d in range(fp.ndim):
fp = fp.swapaxes(0, d)
fp[0, ...] = 0
fp = fp.swapaxes(0, d)
# For example
# if labels.ndim = 2 and connectivity = 1
# fp = [[0,0,0],
# [0,1,1],
# [0,1,0]]
#
# if labels.ndim = 2 and connectivity = 2
# fp = [[0,0,0],
# [0,1,1],
# [0,1,1]]
ndi.generic_filter(
labels,
function=_add_edge_filter,
footprint=fp,
mode='nearest',
output=np.zeros(labels.shape, dtype=np.uint8),
extra_arguments=(graph,))
graph = RAG(labels, connectivity=connectivity)
for n in graph:
graph.node[n].update({'labels': [n],

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