mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-27 11:27:08 +08:00
Merge branch 'master' of https://github.com/scikit-image/scikit-image
This commit is contained in:
+1
-1
@@ -107,7 +107,7 @@
|
||||
|
||||
- Johannes Schönberger
|
||||
Drawing functions, adaptive thresholding, regionprops, geometric
|
||||
transformations, LBPs, polygon approximations, and more.
|
||||
transformations, LBPs, polygon approximations, web layout, and more.
|
||||
|
||||
- Pavel Campr
|
||||
Fixes and tests for Histograms of Oriented Gradients.
|
||||
|
||||
+4
-4
@@ -4,8 +4,8 @@ Development process
|
||||
:doc:`Read this overview <gitwash/index>` of how to use Git with
|
||||
``skimage``. Here's the long and short of it:
|
||||
|
||||
* Go to `https://github.com/scikits-image/scikits-image
|
||||
<http://github.com/scikits-image/scikits-image>`_ and follow the
|
||||
* Go to `https://github.com/scikit-image/scikit-image
|
||||
<http://github.com/scikit-image/scikit-image>`_ and follow the
|
||||
instructions on making your own fork.
|
||||
* Create a new branch for the feature you want to work on. Since the
|
||||
branch name will appear in the merge message, use a sensible name
|
||||
@@ -42,7 +42,7 @@ Guidelines
|
||||
* Follow the `Python PEPs <http://www.python.org/dev/peps/pep-0008/>`_
|
||||
where possible.
|
||||
* No major changes should be committed without review. Ask on the
|
||||
`mailing list <http://groups.google.com/group/scikits-image>`_ if
|
||||
`mailing list <http://groups.google.com/group/scikit-image>`_ if
|
||||
you get no response to your pull request.
|
||||
* Examples in the gallery should have a maximum figure width of 8 inches.
|
||||
|
||||
@@ -99,4 +99,4 @@ detailing the test coverage::
|
||||
|
||||
Bugs
|
||||
````
|
||||
Please `report bugs on Github <https://github.com/scikits-image/scikits-image/issues>`_.
|
||||
Please `report bugs on Github <https://github.com/scikit-image/scikit-image/issues>`_.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
Unless otherwise specified by LICENSE.txt files in individual
|
||||
directories, all code is
|
||||
|
||||
Copyright (C) 2011, the scikits-image team
|
||||
Copyright (C) 2011, the scikit-image team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
+2
-2
@@ -3,11 +3,11 @@ Image Processing SciKit
|
||||
|
||||
Source
|
||||
------
|
||||
https://github.com/scikits-image/scikits-image
|
||||
https://github.com/scikit-image/scikit-image
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
http://groups.google.com/group/scikits-image
|
||||
http://groups.google.com/group/scikit-image
|
||||
|
||||
Installation from source
|
||||
------------------------
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ How to make a new release of ``skimage``
|
||||
- In ``bento.info``, set to ``0.X.dev0``.
|
||||
|
||||
- Update the web frontpage:
|
||||
The webpage is kept in a separate repo: scikits-image-web
|
||||
The webpage is kept in a separate repo: scikit-image-web
|
||||
|
||||
- Sync your branch with the remote repo: ``git pull``.
|
||||
If you try to ``make gh-pages`` when your branch is out of sync, it
|
||||
|
||||
@@ -16,122 +16,14 @@ How to contribute to ``skimage``
|
||||
|
||||
|
||||
Developing Open Source is great fun! Join us on the `skimage mailing
|
||||
list <http://groups.google.com/group/scikits-image>`_ and tell us which of the
|
||||
list <http://groups.google.com/group/scikit-image>`_ and tell us which of the
|
||||
following challenges you'd like to solve.
|
||||
|
||||
* Mentoring is available for those new to scientific programming in Python.
|
||||
* The technical detail of the `development process`_ is given below.
|
||||
* :doc:`How to use GitHub <gitwash/index>` when developing skimage
|
||||
* If you're looking something to implement, you can find a list of `requested features on github <https://github.com/scikit-image/scikit-image/wiki/Requested-features>`__. In addition, you can browse the `open issues on github <https://github.com/scikit-image/scikit-image/issues?state=open>`__.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Tasks
|
||||
-----
|
||||
|
||||
.. :doc:`gsoc2011`
|
||||
.. :doc:`coverage_table`
|
||||
|
||||
Implement Algorithms
|
||||
````````````````````
|
||||
- Graph cut segmentation
|
||||
- `Image colorization <http://www.cs.huji.ac.il/~yweiss/Colorization/>`__
|
||||
- Fast 2D convex hull (consider using CellProfiler version)
|
||||
`Algorithm overview <http://www.tcs.fudan.edu.cn/rudolf/Courses/Algorithms/Alg_cs_07w/Webprojects/Zhaobo_hull/index.html#section26>`__.
|
||||
`One free implementation
|
||||
<http://cm.bell-labs.com/cm/cs/who/clarkson/2dch.c>`_.
|
||||
[Compare against current implementation]
|
||||
- Convex hulls of objects in a labels matrix (simply adapt current convex hull
|
||||
image code--this one's low hanging fruit). Generalise this solution to also
|
||||
skeletonize objects in a labels matrix.
|
||||
- Add binary features (BRIEF, BRISK, FREAK)
|
||||
- Add `STAR features <http://pr.willowgarage.com/wiki/Star_Detector>`__
|
||||
- `Blurring kernel estimation <http://bit.ly/Nril3u>`__
|
||||
|
||||
Drawing (directly on an ndarray)
|
||||
````````````````````````````````
|
||||
- Wu's algorithm for circles
|
||||
- Text rendering
|
||||
- Add anti-aliasing
|
||||
|
||||
Infrastructure
|
||||
--------------
|
||||
- Add @greyimage decorator to check if input is a greyscale image
|
||||
- :strike:`Implement a new backend system so that we may start including
|
||||
PyOpenCL-based algorithms`
|
||||
|
||||
Adapt existing code for use
|
||||
```````````````````````````
|
||||
These snippets and packages have already been written. Some need to be
|
||||
modified to work as part of the scikit, others may be lacking in documentation
|
||||
or tests.
|
||||
|
||||
* :strike:`Connected components`
|
||||
* Nadav's bilateral filtering (first compare against CellProfiler's
|
||||
code, based on http://groups.csail.mit.edu/graphics/bilagrid/bilagrid_web.pdf)
|
||||
Also see https://github.com/stefanv/scikits-image/tree/bilateral
|
||||
* 2D image warping via thin-plate splines [ask Zach Pincus]
|
||||
|
||||
Merge code provided by `CellProfiler <http://www.cellprofiler.org>`_ team
|
||||
`````````````````````````````````````````````````````````````````````````
|
||||
* Roberts filter - convolution with diagonal and anti-diagonal
|
||||
kernels to detect edges
|
||||
* Minimum enclosing circles of objects in a labels matrix
|
||||
* spur removal, thinning, thickening, and other morphological operations on
|
||||
binary images, framework for creating arbitrary morphological operations
|
||||
using a 3x3 grid.
|
||||
|
||||
Their SVN repository is read-accessible at
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler
|
||||
|
||||
The files for the above algorithms are
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/cpmorphology.py
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/filter.py
|
||||
|
||||
There are test suites for the files at
|
||||
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/tests/test_cpmorphology.py
|
||||
- https://svn.broadinstitute.org/CellProfiler/trunk/CellProfiler/cellprofiler/cpmath/tests/test_filter.py
|
||||
|
||||
Quoting a message from Lee Kamentsky to Stefan van der Walt sent on
|
||||
5 August 2009::
|
||||
|
||||
We're part of the Broad Institute which is non-profit. We would be happy
|
||||
to include our algorithm code in SciPy under the BSD license since that is
|
||||
more appropriate for a library that might be integrated into a
|
||||
commercial product whereas CellProfiler needs the more stringent
|
||||
protection of GPL as an application.
|
||||
|
||||
In 2010, Vebjorn Ljosa officially released parts of the code under a
|
||||
BSD license (:doc:`cell_profiler` | `original message
|
||||
<http://groups.google.com/group/scikits-image/browse_thread/thread/c4f8fc584bfd839d>`_).
|
||||
|
||||
Thanks to Lee Kamentsky, Thouis Jones and Anne Carpenter and their colleagues
|
||||
who contributed.
|
||||
|
||||
Rework linear filters
|
||||
`````````````````````
|
||||
* Fast, SSE2 convolution (high priority) (see prototype in pull requests)
|
||||
* Should take kernel or function for parameter (currently only takes function)
|
||||
* Kernel shape should be specifiable (currently defaults to image shape)
|
||||
|
||||
io
|
||||
``
|
||||
* Update ``qt_plugin.py`` and other plugins to view collections.
|
||||
* Rewrite GTK backend using GObject Introspection for Py3K compatibility.
|
||||
* Add DICOM plugin for `GDCM <http://sourceforge.net/apps/mediawiki/gdcm>`__.
|
||||
* Add ``imread_collection`` to all ``imread`` backends
|
||||
* Better video loading (move to plugin framework, add backends)
|
||||
|
||||
viewer
|
||||
``````
|
||||
* Using the visualization tools, add an FFT-domain image editor
|
||||
|
||||
docs
|
||||
````
|
||||
* Add examples to the gallery
|
||||
* Write topics for the `user guide
|
||||
<http://scikits-image.org/docs/dev/user_guide.html>`_
|
||||
* Integrate BiBTeX plugin into Sphinx build
|
||||
|
||||
+7
-4
@@ -1,15 +1,15 @@
|
||||
Name: scikits-image
|
||||
Name: scikit-image
|
||||
Version: 0.8.dev0
|
||||
Summary: Image processing routines for SciPy
|
||||
Url: http://scikits-image.org
|
||||
DownloadUrl: http://github.com/scikits-image/scikits-image
|
||||
Url: http://scikit-image.org
|
||||
DownloadUrl: http://github.com/scikit-image/scikit-image
|
||||
Description: Image Processing SciKit
|
||||
|
||||
Image processing algorithms for SciPy, including IO, morphology, filtering,
|
||||
warping, color manipulation, object detection, etc.
|
||||
|
||||
Please refer to the online documentation at
|
||||
http://scikits-image.org/
|
||||
http://scikit-image.org/
|
||||
Maintainer: Stefan van der Walt
|
||||
MaintainerEmail: stefan@sun.ac.za
|
||||
License: Modified BSD
|
||||
@@ -64,6 +64,9 @@ Library:
|
||||
Extension: skimage.filter._ctmf
|
||||
Sources:
|
||||
skimage/filter/_ctmf.pyx
|
||||
Extension: skimage.filter._denoise
|
||||
Sources:
|
||||
skimage/filter/_denoise.pyx
|
||||
Extension: skimage.morphology.ccomp
|
||||
Sources:
|
||||
skimage/morphology/ccomp.pyx
|
||||
|
||||
@@ -69,7 +69,8 @@ def print_results(cy_bento, cy_setup):
|
||||
print(text)
|
||||
print('-' * len(text))
|
||||
|
||||
print # blank line; just for aesthetics
|
||||
print "Bento errors:"
|
||||
print "-------------"
|
||||
|
||||
if cy_bento:
|
||||
info("The following extensions in 'bento.info' were not found:")
|
||||
|
||||
+4
-4
@@ -77,17 +77,17 @@ qthelp:
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in build/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator build/qthelp/scikitsimage.qhcp"
|
||||
@echo "# qcollectiongenerator build/qthelp/scikitimage.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile build/qthelp/scikitsimage.qhc"
|
||||
@echo "# assistant -collectionFile build/qthelp/scikitimage.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(DEST)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/scikitsimage"
|
||||
@echo "# ln -s build/devhelp $$HOME/.local/share/devhelp/scikitsimage"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/scikitimage"
|
||||
@echo "# ln -s build/devhelp $$HOME/.local/share/devhelp/scikitimage"
|
||||
@echo "# devhelp"
|
||||
|
||||
latex:
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
=============================
|
||||
Denoising the picture of Lena
|
||||
=============================
|
||||
|
||||
In this example, we denoise a noisy version of the picture of Lena using the
|
||||
total variation and bilateral denoising filter.
|
||||
|
||||
These algorithms typically produce "posterized" images with flat domains
|
||||
separated by sharp edges. It is possible to change the degree of posterization
|
||||
by controlling the tradeoff between denoising and faithfulness to the original
|
||||
image.
|
||||
|
||||
Total variation filter
|
||||
----------------------
|
||||
|
||||
The result of this filter is an image that has a minimal total variation norm,
|
||||
while being as close to the initial image as possible. The total variation is
|
||||
the L1 norm of the gradient of the image.
|
||||
|
||||
Bilateral filter
|
||||
----------------
|
||||
|
||||
A bilateral filter is an edge-preserving and noise reducing filter. It averages
|
||||
pixels based on their spatial closeness and radiometric similarity.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data, color, img_as_float
|
||||
from skimage.filter import denoise_tv, denoise_bilateral
|
||||
|
||||
lena = img_as_float(data.lena())
|
||||
lena = lena[220:300, 220:320]
|
||||
|
||||
noisy = lena + 0.5 * lena.std() * np.random.random(lena.shape)
|
||||
noisy = np.clip(noisy, 0, 1)
|
||||
|
||||
fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 5))
|
||||
|
||||
ax[0, 0].imshow(noisy)
|
||||
ax[0, 0].axis('off')
|
||||
ax[0, 0].set_title('noisy')
|
||||
ax[0, 1].imshow(denoise_tv(noisy, weight=0.1))
|
||||
ax[0, 1].axis('off')
|
||||
ax[0, 1].set_title('TV')
|
||||
ax[0, 2].imshow(denoise_bilateral(noisy, sigma_range=0.03, sigma_spatial=15))
|
||||
ax[0, 2].axis('off')
|
||||
ax[0, 2].set_title('Bilateral')
|
||||
|
||||
ax[1, 0].imshow(denoise_tv(noisy, weight=0.2))
|
||||
ax[1, 0].axis('off')
|
||||
ax[1, 0].set_title('(more) TV')
|
||||
ax[1, 1].imshow(denoise_bilateral(noisy, sigma_range=0.06, sigma_spatial=15))
|
||||
ax[1, 1].axis('off')
|
||||
ax[1, 1].set_title('(more) Bilateral')
|
||||
ax[1, 2].imshow(lena)
|
||||
ax[1, 2].axis('off')
|
||||
ax[1, 2].set_title('original')
|
||||
|
||||
fig.subplots_adjust(wspace=0.02, hspace=0.2,
|
||||
top=0.9, bottom=0.05, left=0, right=1)
|
||||
|
||||
plt.show()
|
||||
@@ -1,51 +0,0 @@
|
||||
"""
|
||||
====================================================
|
||||
Denoising the picture of Lena using total variation
|
||||
====================================================
|
||||
|
||||
In this example, we denoise a noisy version of the picture of Lena
|
||||
using the total variation denoising filter. The result of this filter
|
||||
is an image that has a minimal total variation norm, while being as
|
||||
close to the initial image as possible. The total variation is the L1
|
||||
norm of the gradient of the image, and minimizing the total variation
|
||||
typically produces "posterized" images with flat domains separated by
|
||||
sharp edges.
|
||||
|
||||
It is possible to change the degree of posterization by controlling
|
||||
the tradeoff between denoising and faithfulness to the original image.
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data, color, img_as_ubyte
|
||||
from skimage.filter import tv_denoise
|
||||
|
||||
l = img_as_ubyte(color.rgb2gray(data.lena()))
|
||||
l = l[230:290, 220:320]
|
||||
|
||||
noisy = l + 0.4 * l.std() * np.random.random(l.shape)
|
||||
|
||||
tv_denoised = tv_denoise(noisy, weight=10)
|
||||
|
||||
plt.figure(figsize=(8, 2))
|
||||
|
||||
plt.subplot(131)
|
||||
plt.imshow(noisy, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('noisy', fontsize=20)
|
||||
plt.subplot(132)
|
||||
plt.imshow(tv_denoised, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('TV denoising', fontsize=20)
|
||||
|
||||
tv_denoised = tv_denoise(noisy, weight=50)
|
||||
plt.subplot(133)
|
||||
plt.imshow(tv_denoised, cmap=plt.cm.gray, vmin=40, vmax=220)
|
||||
plt.axis('off')
|
||||
plt.title('(more) TV denoising', fontsize=20)
|
||||
|
||||
plt.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9, bottom=0, left=0,
|
||||
right=1)
|
||||
plt.show()
|
||||
@@ -63,8 +63,8 @@ import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from skimage.data import lena
|
||||
from skimage.segmentation import felzenszwalb, \
|
||||
visualize_boundaries, slic, quickshift
|
||||
from skimage.segmentation import felzenszwalb, slic, quickshift
|
||||
from skimage.segmentation import mark_boundaries
|
||||
from skimage.util import img_as_float
|
||||
|
||||
img = img_as_float(lena()[::2, ::2])
|
||||
@@ -80,11 +80,11 @@ fig, ax = plt.subplots(1, 3)
|
||||
fig.set_size_inches(8, 3, forward=True)
|
||||
plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
|
||||
|
||||
ax[0].imshow(visualize_boundaries(img, segments_fz))
|
||||
ax[0].imshow(mark_boundaries(img, segments_fz))
|
||||
ax[0].set_title("Felzenszwalbs's method")
|
||||
ax[1].imshow(visualize_boundaries(img, segments_slic))
|
||||
ax[1].imshow(mark_boundaries(img, segments_slic))
|
||||
ax[1].set_title("SLIC")
|
||||
ax[2].imshow(visualize_boundaries(img, segments_quick))
|
||||
ax[2].imshow(mark_boundaries(img, segments_quick))
|
||||
ax[2].set_title("Quickshift")
|
||||
for a in ax:
|
||||
a.set_xticks(())
|
||||
|
||||
+33
-6
@@ -27,9 +27,10 @@ plot2rst_rcparams : dict
|
||||
plot2rst_default_thumb : str
|
||||
Path (relative to doc root) of default thumbnail image.
|
||||
|
||||
plot2rst_thumb_scale : float
|
||||
Scale factor for thumbnail (e.g., 0.2 to scale plot to 1/5th the
|
||||
original size).
|
||||
plot2rst_thumb_shape : float
|
||||
Shape of thumbnail in pixels. The image is resized to fit within this shape
|
||||
and the excess is filled with white pixels. This fixed size ensures that
|
||||
that gallery images are displayed in a grid.
|
||||
|
||||
plot2rst_plot_tag : str
|
||||
When this tag is found in the example file, the current plot is saved and
|
||||
@@ -73,7 +74,10 @@ import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import image
|
||||
|
||||
from skimage import io
|
||||
from skimage import transform
|
||||
from skimage.util.dtype import dtype_range
|
||||
|
||||
|
||||
LITERALINCLUDE = """
|
||||
@@ -160,7 +164,7 @@ def setup(app):
|
||||
('../examples', 'auto_examples'), True)
|
||||
app.add_config_value('plot2rst_rcparams', {}, True)
|
||||
app.add_config_value('plot2rst_default_thumb', None, True)
|
||||
app.add_config_value('plot2rst_thumb_scale', 0.25, True)
|
||||
app.add_config_value('plot2rst_thumb_shape', (250, 300), True)
|
||||
app.add_config_value('plot2rst_plot_tag', 'PLOT2RST.current_figure', True)
|
||||
app.add_config_value('plot2rst_index_name', 'index', True)
|
||||
|
||||
@@ -335,7 +339,8 @@ def write_example(src_name, src_dir, rst_dir, cfg):
|
||||
thumb_path = thumb_dir.pjoin(src_name[:-3] + '.png')
|
||||
first_image_file = image_dir.pjoin(figure_list[0].lstrip('/'))
|
||||
if first_image_file.exists:
|
||||
image.thumbnail(first_image_file, thumb_path, cfg.plot2rst_thumb_scale)
|
||||
first_image = io.imread(first_image_file)
|
||||
save_thumbnail(first_image, thumb_path, cfg.plot2rst_thumb_shape)
|
||||
|
||||
if not thumb_path.exists:
|
||||
if cfg.plot2rst_default_thumb is None:
|
||||
@@ -345,6 +350,28 @@ def write_example(src_name, src_dir, rst_dir, cfg):
|
||||
shutil.copy(cfg.plot2rst_default_thumb, thumb_path)
|
||||
|
||||
|
||||
def save_thumbnail(image, thumb_path, shape):
|
||||
"""Save image as a thumbnail with the specified shape.
|
||||
|
||||
The image is first resized to fit within the specified shape and then
|
||||
centered in an array of the specified shape before saving.
|
||||
"""
|
||||
rescale = min(float(w_1) / w_2 for w_1, w_2 in zip(shape, image.shape))
|
||||
small_shape = (rescale * np.asarray(image.shape[:2])).astype(int)
|
||||
small_image = transform.resize(image, small_shape)
|
||||
|
||||
if len(image.shape) == 3:
|
||||
shape = shape + (image.shape[2],)
|
||||
background_value = dtype_range[small_image.dtype.type][1]
|
||||
thumb = background_value * np.ones(shape, dtype=small_image.dtype)
|
||||
|
||||
i = (shape[0] - small_shape[0]) // 2
|
||||
j = (shape[1] - small_shape[1]) // 2
|
||||
thumb[i:i+small_shape[0], j:j+small_shape[1]] = small_image
|
||||
|
||||
io.imsave(thumb_path, thumb)
|
||||
|
||||
|
||||
def _plots_are_current(src_path, image_path):
|
||||
first_image_file = Path(image_path.format(1))
|
||||
needs_replot = (not first_image_file.exists or
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
.PHONY: logo
|
||||
|
||||
logo: green_orange_snake.png snake_logo.svg
|
||||
inkscape --export-png=scikits_image_logo.png --export-dpi=100 \
|
||||
inkscape --export-png=scikit_image_logo.png --export-dpi=100 \
|
||||
--export-area-drawing --export-background-opacity=1 \
|
||||
snake_logo.svg
|
||||
python shrink_logo.py
|
||||
|
||||
green_orange_snake.png:
|
||||
python scikits_image_logo.py --no-plot
|
||||
python scikit_image_logo.py --no-plot
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from skimage import io, transform
|
||||
|
||||
s = 0.7
|
||||
|
||||
img = io.imread('scikits_image_logo.png')
|
||||
img = io.imread('scikit_image_logo.png')
|
||||
h, w, c = img.shape
|
||||
|
||||
print "\nScaling down logo by %.1fx..." % s
|
||||
@@ -13,4 +13,4 @@ img = transform.homography(img, [[s, 0, 0],
|
||||
output_shape=(int(h*s), int(w*s), 4),
|
||||
order=3)
|
||||
|
||||
io.imsave('scikits_image_logo_small.png', img)
|
||||
io.imsave('scikit_image_logo_small.png', img)
|
||||
|
||||
+2
-2
@@ -74,9 +74,9 @@ if "%1" == "qthelp" (
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in build/qthelp, like this:
|
||||
echo.^> qcollectiongenerator build\qthelp\scikitsimage.qhcp
|
||||
echo.^> qcollectiongenerator build\qthelp\scikitimage.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile build\qthelp\scikitsimage.ghc
|
||||
echo.^> assistant -collectionFile build\qthelp\scikitimage.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ Python (>=2.6 or 3.x), NumPy and SciPy can be installed.
|
||||
|
||||
For more information, visit our website
|
||||
|
||||
http://scikit-image.org
|
||||
http://scikits-image.org
|
||||
|
||||
or the examples gallery at
|
||||
|
||||
http://scikit-image.org/docs/0.3/auto_examples/
|
||||
http://scikits-image.org/docs/0.3/auto_examples/
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
Announcement: scikit-image 0.4
|
||||
Announcement: scikits-image 0.4
|
||||
===============================
|
||||
|
||||
We're happy to announce the 0.4 release of scikit-image, an image processing
|
||||
We're happy to announce the 0.4 release of scikits-image, an image processing
|
||||
toolbox for SciPy.
|
||||
|
||||
Please visit our examples gallery to see what we've been up to:
|
||||
|
||||
http://scikit-image.org/docs/0.4/auto_examples/
|
||||
http://scikits-image.org/docs/0.4/auto_examples/
|
||||
|
||||
Note that, in this release, we renamed the module from ``scikits.image`` to
|
||||
``skimage``, to work around name space conflicts with other scikits (similarly,
|
||||
the machine learning scikit is now imported as ``sklearn``).
|
||||
|
||||
A big shout-out also to everyone currently at SciPy India; have fun, and
|
||||
remember to join the scikit-image sprint!
|
||||
remember to join the scikits-image sprint!
|
||||
|
||||
This release runs under all major operating systems where Python (>=2.6 or
|
||||
3.x), NumPy and SciPy can be installed.
|
||||
|
||||
For more information, visit our website
|
||||
|
||||
http://scikit-image.org
|
||||
http://scikits-image.org
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Announcement: scikit-image 0.5
|
||||
Announcement: scikits-image 0.5
|
||||
===============================
|
||||
|
||||
We're happy to announce the 0.5 release of scikit-image, our image processing
|
||||
We're happy to announce the 0.5 release of scikits-image, our image processing
|
||||
toolbox for SciPy.
|
||||
|
||||
For more information, please visit our website
|
||||
|
||||
http://scikit-image.org
|
||||
http://scikits-image.org
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Announcement: scikit-image 0.6
|
||||
Announcement: scikits-image 0.6
|
||||
===============================
|
||||
|
||||
We're happy to announce the 6th version of scikit-image!
|
||||
We're happy to announce the 6th version of scikits-image!
|
||||
|
||||
scikit-image is an image processing toolbox for SciPy that includes algorithms
|
||||
Scikits-image is an image processing toolbox for SciPy that includes algorithms
|
||||
for segmentation, geometric transformations, color space manipulation,
|
||||
analysis, filtering, morphology, feature detection, and more.
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Announcement: scikit-image 0.7.0
|
||||
Announcement: scikits-image 0.7.0
|
||||
=================================
|
||||
|
||||
We're happy to announce the 7th version of scikit-image!
|
||||
We're happy to announce the 7th version of scikits-image!
|
||||
|
||||
scikit-image is an image processing toolbox for SciPy that includes algorithms
|
||||
Scikits-image is an image processing toolbox for SciPy that includes algorithms
|
||||
for segmentation, geometric transformations, color space manipulation,
|
||||
analysis, filtering, morphology, feature detection, and more.
|
||||
|
||||
@@ -15,7 +15,7 @@ For more information, examples, and documentation, please visit our website
|
||||
New Features
|
||||
------------
|
||||
|
||||
It's been only 3 months since scikit-image 0.6 was released, but in that short
|
||||
It's been only 3 months since scikits-image 0.6 was released, but in that short
|
||||
time, we've managed to add plenty of new features and enhancements, including
|
||||
|
||||
- Geometric image transforms
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
function insert_version_links() {
|
||||
var labels = ['dev', '0.7', '0.6', '0.5', '0.4', '0.3'];
|
||||
var labels = ['dev', '0.7.0', '0.6', '0.5', '0.4', '0.3'];
|
||||
|
||||
for (i = 0; i < labels.length; i++){
|
||||
open_list = '<li>'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<li><a href="{{ pathto(master_doc) }}">Home</a></li>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/download.html">Download</a></li>
|
||||
<li><a href="/docs/dev/auto_examples">Gallery</a></li>
|
||||
<li><a href="/docs">Documentation</a></li>
|
||||
<li><a href="/docs/dev">Documentation</a></li>
|
||||
<li><a href="https://github.com/scikit-image/scikit-image">Source</a></li>
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ html_sidebars = {
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'scikitsimagedoc'
|
||||
htmlhelp_basename = 'scikitimagedoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
@@ -190,7 +190,7 @@ htmlhelp_basename = 'scikitsimagedoc'
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('contents', 'scikitsimage.tex', u'The Image Scikit Documentation',
|
||||
('contents', 'scikitimage.tex', u'The Image Scikit Documentation',
|
||||
u'SciPy Developers', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Pre-built installation
|
||||
----------------------
|
||||
|
||||
.. !! Also update scikit-image-web !!
|
||||
|
||||
`Windows binaries
|
||||
<http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image>`__
|
||||
are kindly provided by Christoph Gohlke.
|
||||
@@ -23,7 +21,7 @@ or
|
||||
|
||||
::
|
||||
|
||||
pip -U scikit-image
|
||||
pip install -U scikit-image
|
||||
|
||||
Installation from source
|
||||
------------------------
|
||||
|
||||
@@ -14,10 +14,9 @@ pre {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
clear: left;
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
line-height: 36px;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
@@ -71,11 +71,6 @@ issued::
|
||||
float64 to uint8
|
||||
array([ 0, 128, 255], dtype=uint8)
|
||||
|
||||
Wherever possible, functions should try to handle input without explicit
|
||||
conversion. For example, there is no need to force values to a specific type
|
||||
for doing a convolution; a plotting function, on the other hand, needs to know
|
||||
the range of the input.
|
||||
|
||||
|
||||
Output types
|
||||
============
|
||||
|
||||
@@ -6,17 +6,17 @@ Image processing algorithms for SciPy, including IO, morphology, filtering,
|
||||
warping, color manipulation, object detection, etc.
|
||||
|
||||
Please refer to the online documentation at
|
||||
http://scikits-image.org/
|
||||
http://scikit-image.org/
|
||||
"""
|
||||
|
||||
DISTNAME = 'scikits-image'
|
||||
DISTNAME = 'scikit-image'
|
||||
DESCRIPTION = 'Image processing routines for SciPy'
|
||||
LONG_DESCRIPTION = descr
|
||||
MAINTAINER = 'Stefan van der Walt'
|
||||
MAINTAINER_EMAIL = 'stefan@sun.ac.za'
|
||||
URL = 'http://scikits-image.org'
|
||||
URL = 'http://scikit-image.org'
|
||||
LICENSE = 'Modified BSD'
|
||||
DOWNLOAD_URL = 'http://github.com/scikits-image/scikits-image'
|
||||
DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image'
|
||||
VERSION = '0.8dev'
|
||||
PYTHON_VERSION = (2, 5)
|
||||
DEPENDENCIES = {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
"""Image Processing SciKit (Toolbox for SciPy)
|
||||
|
||||
``scikits-image`` (a.k.a. ``skimage``) is a collection of algorithms for image
|
||||
``scikit-image`` (a.k.a. ``skimage``) is a collection of algorithms for image
|
||||
processing and computer vision.
|
||||
|
||||
The main package of ``skimage`` only provides a few utilities for converting
|
||||
@@ -65,7 +65,7 @@ except ImportError:
|
||||
def _setup_test(verbose=False):
|
||||
import functools
|
||||
|
||||
args = ['', '--exe', '-w', pkg_dir]
|
||||
args = ['', pkg_dir, '--exe']
|
||||
if verbose:
|
||||
args.extend(['-v', '-s'])
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@ cdef double bicubic_interpolation(double* image, int rows, int cols,
|
||||
double r, double c, char mode,
|
||||
double cval)
|
||||
|
||||
cdef double get_pixel(double* image, int rows, int cols, int r, int c,
|
||||
char mode, double cval)
|
||||
cdef double get_pixel2d(double* image, int rows, int cols, int r, int c,
|
||||
char mode, double cval)
|
||||
|
||||
cdef double get_pixel3d(double* image, int rows, int cols, int dims, int r,
|
||||
int c, int d, char mode, double cval)
|
||||
|
||||
cdef int coord_map(int dim, int coord, char mode)
|
||||
|
||||
@@ -35,8 +35,8 @@ cdef inline double nearest_neighbour_interpolation(double* image, int rows,
|
||||
|
||||
"""
|
||||
|
||||
return get_pixel(image, rows, cols, <int>round(r), <int>round(c),
|
||||
mode, cval)
|
||||
return get_pixel2d(image, rows, cols, <int>round(r), <int>round(c),
|
||||
mode, cval)
|
||||
|
||||
|
||||
cdef inline double bilinear_interpolation(double* image, int rows, int cols,
|
||||
@@ -72,10 +72,10 @@ cdef inline double bilinear_interpolation(double* image, int rows, int cols,
|
||||
maxc = <int>ceil(c)
|
||||
dr = r - minr
|
||||
dc = c - minc
|
||||
top = (1 - dc) * get_pixel(image, rows, cols, minr, minc, mode, cval) \
|
||||
+ dc * get_pixel(image, rows, cols, minr, maxc, mode, cval)
|
||||
bottom = (1 - dc) * get_pixel(image, rows, cols, maxr, minc, mode, cval) \
|
||||
+ dc * get_pixel(image, rows, cols, maxr, maxc, mode, cval)
|
||||
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
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ cdef inline double biquadratic_interpolation(double* image, int rows, int cols,
|
||||
# row-wise cubic interpolation
|
||||
for pr in range(r0, r0 + 3):
|
||||
for pc in range(c0, c0 + 3):
|
||||
fc[pc - c0] = get_pixel(image, rows, cols, pr, pc, mode, cval)
|
||||
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
|
||||
@@ -216,15 +216,15 @@ cdef inline double bicubic_interpolation(double* image, int rows, int cols,
|
||||
# row-wise cubic interpolation
|
||||
for pr in range(r0, r0 + 4):
|
||||
for pc in range(c0, c0 + 4):
|
||||
fc[pc - c0] = get_pixel(image, rows, cols, pr, pc, mode, cval)
|
||||
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_pixel(double* image, int rows, int cols, int r, int c,
|
||||
char mode, double cval):
|
||||
cdef inline double get_pixel2d(double* image, int rows, int cols, int r, int c,
|
||||
char mode, double cval):
|
||||
"""Get a pixel from the image, taking wrapping mode into consideration.
|
||||
|
||||
Parameters
|
||||
@@ -255,6 +255,40 @@ cdef inline double get_pixel(double* image, int rows, int cols, int r, int c,
|
||||
return image[coord_map(rows, r, mode) * cols + coord_map(cols, c, mode)]
|
||||
|
||||
|
||||
cdef inline double get_pixel3d(double* image, int rows, int cols, int dims, int r,
|
||||
int c, int 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 int coord_map(int dim, int coord, char mode):
|
||||
"""
|
||||
Wrap a coordinate, according to a given mode.
|
||||
|
||||
@@ -28,11 +28,11 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='Scikits-image Developers',
|
||||
author='Scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Transforms',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import warnings
|
||||
import functools
|
||||
|
||||
|
||||
__all__ = ['deprecated']
|
||||
|
||||
|
||||
class deprecated(object):
|
||||
"""Decorator to mark deprecated functions with warning.
|
||||
|
||||
Adapted from <http://wiki.python.org/moin/PythonDecoratorLibrary>.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
alt_func : str
|
||||
If given, tell user what function to use instead.
|
||||
behavior : {'warn', 'raise'}
|
||||
Behavior during call to deprecated function: 'warn' = warn user that
|
||||
function is deprecated; 'raise' = raise error.
|
||||
"""
|
||||
|
||||
def __init__(self, alt_func=None, behavior='warn'):
|
||||
self.alt_func = alt_func
|
||||
self.behavior = behavior
|
||||
|
||||
def __call__(self, func):
|
||||
|
||||
msg = "Call to deprecated function `%s`." % func.__name__
|
||||
if self.alt_func is not None:
|
||||
msg = msg + " Use `%s` instead." % self.alt_func
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapped(*args, **kwargs):
|
||||
if self.behavior == 'warn':
|
||||
warnings.warn_explicit(msg,
|
||||
category=DeprecationWarning,
|
||||
filename=func.func_code.co_filename,
|
||||
lineno=func.func_code.co_firstlineno + 1)
|
||||
elif self.behavior == 'raise':
|
||||
raise DeprecationWarning(msg)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapped
|
||||
+40
-14
@@ -45,7 +45,7 @@ from __future__ import division
|
||||
|
||||
__all__ = ['convert_colorspace', 'rgb2hsv', 'hsv2rgb', 'rgb2xyz', 'xyz2rgb',
|
||||
'rgb2rgbcie', 'rgbcie2rgb', 'rgb2grey', 'rgb2gray', 'gray2rgb',
|
||||
'xyz2lab', 'lab2xyz', 'lab2rgb', 'rgb2lab'
|
||||
'xyz2lab', 'lab2xyz', 'lab2rgb', 'rgb2lab', 'is_rgb', 'is_gray'
|
||||
]
|
||||
|
||||
__docformat__ = "restructuredtext en"
|
||||
@@ -55,6 +55,31 @@ from scipy import linalg
|
||||
from ..util import dtype
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
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 == 2
|
||||
|
||||
|
||||
|
||||
def convert_colorspace(arr, fromspace, tospace):
|
||||
"""Convert an image array to a new color space.
|
||||
|
||||
@@ -281,7 +306,7 @@ rgbcie_from_rgb = np.dot(rgbcie_from_xyz, xyz_from_rgb)
|
||||
rgb_from_rgbcie = np.dot(rgb_from_xyz, xyz_from_rgbcie)
|
||||
|
||||
|
||||
grey_from_rgb = np.array([[0.2125, 0.7154, 0.0721],
|
||||
gray_from_rgb = np.array([[0.2125, 0.7154, 0.0721],
|
||||
[0, 0, 0],
|
||||
[0, 0, 0]])
|
||||
|
||||
@@ -458,7 +483,7 @@ def rgbcie2rgb(rgbcie):
|
||||
return _convert(rgb_from_rgbcie, rgbcie)
|
||||
|
||||
|
||||
def rgb2grey(rgb):
|
||||
def rgb2gray(rgb):
|
||||
"""Compute luminance of an RGB image.
|
||||
|
||||
Parameters
|
||||
@@ -475,7 +500,7 @@ def rgb2grey(rgb):
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If `rgb2grey` is not a 3-D array of shape (.., .., 3) or
|
||||
If `rgb2gray` is not a 3-D array of shape (.., .., 3) or
|
||||
(.., .., 4).
|
||||
|
||||
References
|
||||
@@ -493,21 +518,21 @@ def rgb2grey(rgb):
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from skimage.color import rgb2grey
|
||||
>>> from skimage.color import rgb2gray
|
||||
>>> from skimage import data
|
||||
>>> lena = data.lena()
|
||||
>>> lena_grey = rgb2grey(lena)
|
||||
>>> lena_gray = rgb2gray(lena)
|
||||
"""
|
||||
if rgb.ndim == 2:
|
||||
return rgb
|
||||
|
||||
return _convert(grey_from_rgb, rgb[:, :, :3])[..., 0]
|
||||
return _convert(gray_from_rgb, rgb[:, :, :3])[..., 0]
|
||||
|
||||
rgb2gray = rgb2grey
|
||||
rgb2grey = rgb2gray
|
||||
|
||||
|
||||
def gray2rgb(image):
|
||||
"""Create an RGB representation of a grey-level image.
|
||||
"""Create an RGB representation of a gray-level image.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -525,11 +550,12 @@ def gray2rgb(image):
|
||||
If the input is not 2-dimensional.
|
||||
|
||||
"""
|
||||
if image.ndim != 2:
|
||||
raise ValueError('Gray-level image should be two-dimensional.')
|
||||
|
||||
M, N = image.shape
|
||||
return np.dstack((image, image, image))
|
||||
if is_rgb(image):
|
||||
return image
|
||||
elif is_gray(image):
|
||||
return np.dstack((image, image, image))
|
||||
else:
|
||||
raise ValueError("Input image expected to be RGB, RGBA or gray.")
|
||||
|
||||
|
||||
def xyz2lab(xyz):
|
||||
|
||||
@@ -25,10 +25,11 @@ from skimage.color import (
|
||||
convert_colorspace,
|
||||
rgb2grey, gray2rgb,
|
||||
xyz2lab, lab2xyz,
|
||||
lab2rgb, rgb2lab
|
||||
lab2rgb, rgb2lab,
|
||||
is_rgb, is_gray
|
||||
)
|
||||
|
||||
from skimage import data_dir
|
||||
from skimage import data_dir, data
|
||||
|
||||
import colorsys
|
||||
|
||||
@@ -196,5 +197,23 @@ def test_gray2rgb():
|
||||
assert_equal(z[..., 0], x)
|
||||
assert_equal(z[0, 1, :], [128, 128, 128])
|
||||
|
||||
|
||||
def test_gray2rgb_rgb():
|
||||
x = np.random.random((5, 5, 4))
|
||||
y = gray2rgb(x)
|
||||
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__":
|
||||
run_module_suite()
|
||||
|
||||
@@ -114,3 +114,16 @@ def page():
|
||||
|
||||
"""
|
||||
return load("page.png")
|
||||
|
||||
|
||||
def clock():
|
||||
"""Motion blurred clock.
|
||||
|
||||
This photograph of a wall clock was taken while moving the camera in an
|
||||
aproximately horizontal direction. It may be used to illustrate
|
||||
inverse filters and deconvolution.
|
||||
|
||||
Released into the public domain by the photographer (Stefan van der Walt).
|
||||
|
||||
"""
|
||||
return load("clock_motion.png")
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
@@ -15,9 +15,30 @@ def test_camera():
|
||||
|
||||
|
||||
def test_checkerboard():
|
||||
""" Test that checkerboard image can be loaded. """
|
||||
""" Test that "checkerboard" image can be loaded. """
|
||||
data.checkerboard()
|
||||
|
||||
|
||||
def test_text():
|
||||
""" Test that "text" image can be loaded. """
|
||||
data.text()
|
||||
|
||||
|
||||
def test_moon():
|
||||
""" Test that "moon" image can be loaded. """
|
||||
data.moon()
|
||||
|
||||
|
||||
def test_page():
|
||||
""" Test that "page" image can be loaded. """
|
||||
data.page()
|
||||
|
||||
|
||||
def test_page():
|
||||
""" Test that "clock" image can be loaded. """
|
||||
data.clock()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from numpy.testing import run_module_suite
|
||||
run_module_suite()
|
||||
|
||||
@@ -21,11 +21,11 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image developers',
|
||||
author='scikits-image developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image developers',
|
||||
author='scikit-image developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Drawing',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -24,11 +24,11 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
author='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Features',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from .lpi_filter import *
|
||||
from .ctmf import median_filter
|
||||
from ._canny import canny
|
||||
from .edges import sobel, hsobel, vsobel, hprewitt, vprewitt, prewitt
|
||||
from ._tv_denoise import tv_denoise
|
||||
from .edges import (sobel, hsobel, vsobel, scharr, hscharr, vscharr, prewitt,
|
||||
hprewitt, vprewitt)
|
||||
from .denoise import tv_denoise, denoise_tv
|
||||
from ._denoise import denoise_bilateral
|
||||
from ._rank_order import rank_order
|
||||
from .thresholding import threshold_otsu, threshold_adaptive
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
#cython: cdivision=True
|
||||
#cython: boundscheck=False
|
||||
#cython: nonecheck=False
|
||||
#cython: wraparound=False
|
||||
|
||||
cimport numpy as cnp
|
||||
import numpy as np
|
||||
from libc.math cimport exp, fabs, sqrt
|
||||
from libc.stdlib cimport malloc, free
|
||||
from skimage._shared.interpolation cimport get_pixel3d
|
||||
from skimage.util import img_as_float
|
||||
|
||||
|
||||
cdef inline double _gaussian_weight(double sigma, double value):
|
||||
return exp(-0.5 * (value / sigma)**2)
|
||||
|
||||
|
||||
cdef double* _compute_color_lut(int bins, double sigma, double max_value):
|
||||
|
||||
cdef:
|
||||
double* color_lut = <double*>malloc(bins * sizeof(double))
|
||||
Py_ssize_t b
|
||||
|
||||
for b in range(bins):
|
||||
color_lut[b] = _gaussian_weight(sigma, b * max_value / bins)
|
||||
|
||||
return color_lut
|
||||
|
||||
|
||||
cdef double* _compute_range_lut(int win_size, double sigma):
|
||||
|
||||
cdef:
|
||||
double* range_lut = <double*>malloc(win_size**2 * sizeof(double))
|
||||
Py_ssize_t kr, kc
|
||||
Py_ssize_t window_ext = (win_size - 1) / 2
|
||||
double dist
|
||||
|
||||
for kr in range(win_size):
|
||||
for kc in range(win_size):
|
||||
dist = sqrt((kr - window_ext)**2 + (kc - window_ext)**2)
|
||||
range_lut[kr * win_size + kc] = _gaussian_weight(sigma, dist)
|
||||
|
||||
return range_lut
|
||||
|
||||
|
||||
def denoise_bilateral(image, int win_size=5, sigma_range=None,
|
||||
double sigma_spatial=1, int bins=10000, mode='constant',
|
||||
double cval=0):
|
||||
"""Denoise image using bilateral filter.
|
||||
|
||||
This is an edge-preserving and noise reducing denoising filter. It averages
|
||||
pixels based on their spatial closeness and radiometric similarity.
|
||||
|
||||
Spatial closeness is measured by the gaussian function of the euclidian
|
||||
distance between two pixels and a certain standard deviation
|
||||
(`sigma_spatial`).
|
||||
|
||||
Radiometric similarity is measured by the gaussian function of the euclidian
|
||||
distance between two color values and a certain standard deviation
|
||||
(`sigma_range`).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input image.
|
||||
win_size : int
|
||||
Window size for filtering.
|
||||
sigma_range : float
|
||||
Standard deviation for grayvalue/color distance (radiometric
|
||||
similarity). A larger value results in averaging of pixels with larger
|
||||
radiometric differences. Note, that the image will be converted using
|
||||
the `img_as_float` function and thus the standard deviation is in
|
||||
respect to the range `[0, 1]`.
|
||||
sigma_spatial : float
|
||||
Standard deviation for range distance. A larger value results in
|
||||
averaging of pixels with larger spatial differences.
|
||||
bins : int
|
||||
Number of discrete values for gaussian weights of color filtering.
|
||||
A larger value results in improved accuracy.
|
||||
mode : string
|
||||
How to handle values outside the image borders. See
|
||||
`scipy.ndimage.map_coordinates` for detail.
|
||||
cval : string
|
||||
Used in conjunction with mode 'constant', the value outside
|
||||
the image boundaries.
|
||||
|
||||
Returns
|
||||
-------
|
||||
denoised : ndarray
|
||||
Denoised image.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
|
||||
|
||||
"""
|
||||
|
||||
image = np.atleast_3d(img_as_float(image))
|
||||
|
||||
cdef:
|
||||
Py_ssize_t rows = image.shape[0]
|
||||
Py_ssize_t cols = image.shape[1]
|
||||
Py_ssize_t dims = image.shape[2]
|
||||
Py_ssize_t window_ext = (win_size - 1) / 2
|
||||
|
||||
double max_value = image.max()
|
||||
|
||||
cnp.ndarray[dtype=cnp.double_t, ndim=3, mode='c'] cimage = \
|
||||
np.ascontiguousarray(image)
|
||||
cnp.ndarray[dtype=cnp.double_t, ndim=3, mode='c'] out = \
|
||||
np.zeros((rows, cols, dims), dtype=np.double)
|
||||
|
||||
double* image_data = <double*>cimage.data
|
||||
double* out_data = <double*>out.data
|
||||
|
||||
double* color_lut = _compute_color_lut(bins, sigma_range, max_value)
|
||||
double* range_lut = _compute_range_lut(win_size, sigma_spatial)
|
||||
|
||||
Py_ssize_t r, c, d, wr, wc, kr, kc, rr, cc, pixel_addr
|
||||
double value, weight, dist, total_weight, csigma_range, color_weight, \
|
||||
range_weight
|
||||
double dist_scale = bins / dims / max_value
|
||||
double* values = <double*>malloc(dims * sizeof(double))
|
||||
double* centres = <double*>malloc(dims * sizeof(double))
|
||||
double* total_values = <double*>malloc(dims * sizeof(double))
|
||||
|
||||
if sigma_range is None:
|
||||
csigma_range = image.std()
|
||||
else:
|
||||
csigma_range = sigma_range
|
||||
|
||||
if mode not in ('constant', 'wrap', 'reflect', 'nearest'):
|
||||
raise ValueError("Invalid mode specified. Please use "
|
||||
"`constant`, `nearest`, `wrap` or `reflect`.")
|
||||
cdef char cmode = ord(mode[0].upper())
|
||||
|
||||
for r in range(rows):
|
||||
for c in range(cols):
|
||||
pixel_addr = r * cols * dims + c * dims
|
||||
total_weight = 0
|
||||
for d in range(dims):
|
||||
total_values[d] = 0
|
||||
centres[d] = image_data[pixel_addr + d]
|
||||
for wr in range(-window_ext, window_ext + 1):
|
||||
rr = wr + r
|
||||
kr = wr + window_ext
|
||||
for wc in range(-window_ext, window_ext + 1):
|
||||
cc = wc + c
|
||||
kc = wc + window_ext
|
||||
|
||||
# save pixel values for all dims and compute euclidian
|
||||
# distance between centre stack and current position
|
||||
dist = 0
|
||||
for d in range(dims):
|
||||
value = get_pixel3d(image_data, rows, cols, dims,
|
||||
rr, cc, d, cmode, cval)
|
||||
values[d] = value
|
||||
dist += (centres[d] - value)**2
|
||||
dist = sqrt(dist)
|
||||
|
||||
range_weight = range_lut[kr * win_size + kc]
|
||||
color_weight = color_lut[<int>(dist * dist_scale)]
|
||||
|
||||
weight = range_weight * color_weight
|
||||
for d in range(dims):
|
||||
total_values[d] += values[d] * weight
|
||||
total_weight += weight
|
||||
for d in range(dims):
|
||||
out_data[pixel_addr + d] = total_values[d] / total_weight
|
||||
|
||||
free(color_lut)
|
||||
free(range_lut)
|
||||
free(values)
|
||||
free(centres)
|
||||
free(total_values)
|
||||
|
||||
return out
|
||||
@@ -1,37 +1,35 @@
|
||||
import numpy as np
|
||||
from skimage import img_as_float
|
||||
from skimage._shared.utils import deprecated
|
||||
|
||||
|
||||
def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200):
|
||||
"""
|
||||
Perform total-variation denoising on 3-D arrays
|
||||
def _denoise_tv_3d(im, weight=100, eps=2.e-4, n_iter_max=200):
|
||||
"""Perform total-variation denoising on 3-D arrays.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
im: ndarray
|
||||
3-D input data to be denoised
|
||||
|
||||
3-D input data to be denoised.
|
||||
weight: float, optional
|
||||
denoising weight. The greater ``weight``, the more denoising (at
|
||||
the expense of fidelity to ``input``)
|
||||
|
||||
Denoising weight. The greater ``weight``, the more denoising (at
|
||||
the expense of fidelity to ``input``).
|
||||
eps: float, optional
|
||||
relative difference of the value of the cost function that determines
|
||||
Relative difference of the value of the cost function that determines
|
||||
the stop criterion. The algorithm stops when:
|
||||
|
||||
(E_(n-1) - E_n) < eps * E_0
|
||||
|
||||
n_iter_max: int, optional
|
||||
maximal number of iterations used for the optimization.
|
||||
Maximal number of iterations used for the optimization.
|
||||
|
||||
Returns
|
||||
-------
|
||||
out: ndarray
|
||||
denoised array of floats
|
||||
Denoised array of floats.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Rudin, Osher and Fatemi algorithm
|
||||
Rudin, Osher and Fatemi algorithm.
|
||||
|
||||
Examples
|
||||
---------
|
||||
@@ -40,7 +38,7 @@ def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200):
|
||||
>>> mask = (x -22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
|
||||
>>> mask = mask.astype(np.float)
|
||||
>>> mask += 0.2*np.random.randn(*mask.shape)
|
||||
>>> res = tv_denoise_3d(mask, weight=100)
|
||||
>>> res = denoise_tv_3d(mask, weight=100)
|
||||
"""
|
||||
px = np.zeros_like(im)
|
||||
py = np.zeros_like(im)
|
||||
@@ -85,44 +83,40 @@ def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200):
|
||||
return out
|
||||
|
||||
|
||||
def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
"""
|
||||
Perform total-variation denoising
|
||||
def _denoise_tv_2d(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
"""Perform total-variation denoising.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
im: ndarray
|
||||
input data to be denoised
|
||||
|
||||
Input data to be denoised.
|
||||
weight: float, optional
|
||||
denoising weight. The greater ``weight``, the more denoising (at
|
||||
Denoising weight. The greater ``weight``, the more denoising (at
|
||||
the expense of fidelity to ``input``)
|
||||
|
||||
eps: float, optional
|
||||
relative difference of the value of the cost function that determines
|
||||
Relative difference of the value of the cost function that determines
|
||||
the stop criterion. The algorithm stops when:
|
||||
|
||||
(E_(n-1) - E_n) < eps * E_0
|
||||
|
||||
n_iter_max: int, optional
|
||||
maximal number of iterations used for the optimization.
|
||||
Maximal number of iterations used for the optimization.
|
||||
|
||||
Returns
|
||||
-------
|
||||
out: ndarray
|
||||
denoised array of floats
|
||||
Denoised array of floats.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The principle of total variation denoising is explained in
|
||||
http://en.wikipedia.org/wiki/Total_variation_denoising
|
||||
http://en.wikipedia.org/wiki/Total_variation_denoising.
|
||||
|
||||
This code is an implementation of the algorithm of Rudin, Fatemi and Osher
|
||||
that was proposed by Chambolle in [1]_.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] A. Chambolle, An algorithm for total variation minimization and
|
||||
applications, Journal of Mathematical Imaging and Vision,
|
||||
Springer, 2004, 20, 89-97.
|
||||
@@ -134,7 +128,7 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
>>> import scipy
|
||||
>>> lena = scipy.lena().astype(np.float)
|
||||
>>> lena += 0.5 * lena.std()*np.random.randn(*lena.shape)
|
||||
>>> denoised_lena = tv_denoise(lena, weight=60.0)
|
||||
>>> denoised_lena = denoise_tv(lena, weight=60.0)
|
||||
"""
|
||||
px = np.zeros_like(im)
|
||||
py = np.zeros_like(im)
|
||||
@@ -172,34 +166,31 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
return out
|
||||
|
||||
|
||||
def tv_denoise(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
"""
|
||||
Perform total-variation denoising on 2-d and 3-d images
|
||||
def denoise_tv(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
"""Perform total-variation denoising on 2-d and 3-d images.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
im: ndarray (2d or 3d) of ints, uints or floats
|
||||
input data to be denoised. `im` can be of any numeric type,
|
||||
Input data to be denoised. `im` can be of any numeric type,
|
||||
but it is cast into an ndarray of floats for the computation
|
||||
of the denoised image.
|
||||
|
||||
weight: float, optional
|
||||
denoising weight. The greater ``weight``, the more denoising (at
|
||||
the expense of fidelity to ``input``)
|
||||
|
||||
Denoising weight. The greater ``weight``, the more denoising (at
|
||||
the expense of fidelity to ``input``).
|
||||
eps: float, optional
|
||||
relative difference of the value of the cost function that
|
||||
Relative difference of the value of the cost function that
|
||||
determines the stop criterion. The algorithm stops when:
|
||||
|
||||
(E_(n-1) - E_n) < eps * E_0
|
||||
|
||||
n_iter_max: int, optional
|
||||
maximal number of iterations used for the optimization.
|
||||
Maximal number of iterations used for the optimization.
|
||||
|
||||
Returns
|
||||
-------
|
||||
out: ndarray
|
||||
denoised array of floats
|
||||
Denoised array of floats.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -217,7 +208,6 @@ def tv_denoise(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] A. Chambolle, An algorithm for total variation minimization and
|
||||
applications, Journal of Mathematical Imaging and Vision,
|
||||
Springer, 2004, 20, 89-97.
|
||||
@@ -230,23 +220,26 @@ def tv_denoise(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||||
>>> import scipy
|
||||
>>> lena = scipy.lena().astype(np.float)
|
||||
>>> lena += 0.5 * lena.std()*np.random.randn(*lena.shape)
|
||||
>>> denoised_lena = tv_denoise(lena, weight=60)
|
||||
>>> denoised_lena = denoise_tv(lena, weight=60)
|
||||
>>> # 3D example on synthetic data
|
||||
>>> x, y, z = np.ogrid[0:40, 0:40, 0:40]
|
||||
>>> mask = (x -22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
|
||||
>>> mask = mask.astype(np.float)
|
||||
>>> mask += 0.2*np.random.randn(*mask.shape)
|
||||
>>> res = tv_denoise_3d(mask, weight=100)
|
||||
>>> res = denoise_tv_3d(mask, weight=100)
|
||||
"""
|
||||
im_type = im.dtype
|
||||
if not im_type.kind == 'f':
|
||||
im = img_as_float(im)
|
||||
|
||||
if im.ndim == 2:
|
||||
out = _tv_denoise_2d(im, weight, eps, n_iter_max)
|
||||
out = _denoise_tv_2d(im, weight, eps, n_iter_max)
|
||||
elif im.ndim == 3:
|
||||
out = _tv_denoise_3d(im, weight, eps, n_iter_max)
|
||||
out = _denoise_tv_3d(im, weight, eps, n_iter_max)
|
||||
else:
|
||||
raise ValueError('only 2-d and 3-d images may be denoised with this '
|
||||
'function')
|
||||
return out
|
||||
|
||||
|
||||
tv_denoise = deprecated('skimage.filter.denoise_tv')(denoise_tv)
|
||||
+136
-23
@@ -1,6 +1,7 @@
|
||||
"""edges.py - Sobel edge filter
|
||||
"""edges.py - Edge filters
|
||||
|
||||
Originally part of CellProfiler, code licensed under both GPL and BSD licenses.
|
||||
Sobel and Prewitt filters originally part of CellProfiler, code licensed under
|
||||
both GPL and BSD licenses.
|
||||
Website: http://www.cellprofiler.org
|
||||
Copyright (c) 2003-2009 Massachusetts Institute of Technology
|
||||
Copyright (c) 2009-2011 Broad Institute
|
||||
@@ -34,13 +35,13 @@ def _mask_filter_result(result, mask):
|
||||
|
||||
|
||||
def sobel(image, mask=None):
|
||||
"""Calculate the absolute magnitude Sobel to find edges.
|
||||
"""Find the edge magnitude using the Sobel transform.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -48,7 +49,7 @@ def sobel(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Sobel edge map.
|
||||
The Sobel edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -67,9 +68,9 @@ def hsobel(image, mask=None):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -77,7 +78,7 @@ def hsobel(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Sobel edge map.
|
||||
The Sobel edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -102,9 +103,9 @@ def vsobel(image, mask=None):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -112,7 +113,7 @@ def vsobel(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Sobel edge map.
|
||||
The Sobel edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -132,14 +133,14 @@ def vsobel(image, mask=None):
|
||||
return _mask_filter_result(result, mask)
|
||||
|
||||
|
||||
def prewitt(image, mask=None):
|
||||
"""Find the edge magnitude using the Prewitt transform.
|
||||
def scharr(image, mask=None):
|
||||
"""Find the edge magnitude using the Scharr transform.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -147,7 +148,119 @@ def prewitt(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Prewitt edge map.
|
||||
The Scharr edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Take the square root of the sum of the squares of the horizontal and
|
||||
vertical Scharrs to get a magnitude that's somewhat insensitive to
|
||||
direction.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
return np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2)
|
||||
|
||||
|
||||
def hscharr(image, mask=None):
|
||||
"""Find the horizontal edges of an image using the Scharr transform.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Scharr edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
We use the following kernel and return the absolute value of the
|
||||
result at each point::
|
||||
|
||||
3 10 3
|
||||
0 0 0
|
||||
-3 -10 -3
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
image = img_as_float(image)
|
||||
result = np.abs(convolve(image,
|
||||
np.array([[ 3, 10, 3],
|
||||
[ 0, 0, 0],
|
||||
[-3, -10, -3]]).astype(float) / 16.0))
|
||||
return _mask_filter_result(result, mask)
|
||||
|
||||
|
||||
def vscharr(image, mask=None):
|
||||
"""Find the vertical edges of an image using the Scharr transform.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2-D array
|
||||
Image to process
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Scharr edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
We use the following kernel and return the absolute value of the
|
||||
result at each point::
|
||||
|
||||
3 0 -3
|
||||
10 0 -10
|
||||
3 0 -3
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
image = img_as_float(image)
|
||||
result = np.abs(convolve(image,
|
||||
np.array([[ 3, 0, -3],
|
||||
[10, 0, -10],
|
||||
[ 3, 0, -3]]).astype(float) / 16.0))
|
||||
return _mask_filter_result(result, mask)
|
||||
|
||||
|
||||
def prewitt(image, mask=None):
|
||||
"""Find the edge magnitude using the Prewitt transform.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Prewitt edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -162,9 +275,9 @@ def hprewitt(image, mask=None):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -172,7 +285,7 @@ def hprewitt(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Prewitt edge map.
|
||||
The Prewitt edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -197,9 +310,9 @@ def vprewitt(image, mask=None):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array_like, dtype=float
|
||||
image : 2-D array
|
||||
Image to process.
|
||||
mask : array_like, dtype=bool, optional
|
||||
mask : 2-D array, optional
|
||||
An optional mask to limit the application to a certain area.
|
||||
Note that pixels surrounding masked regions are also masked to
|
||||
prevent masked regions from affecting the result.
|
||||
@@ -207,7 +320,7 @@ def vprewitt(image, mask=None):
|
||||
Returns
|
||||
-------
|
||||
output : ndarray
|
||||
The Prewitt edge map.
|
||||
The Prewitt edge map.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
@@ -75,7 +75,7 @@ class LPIFilter2D(object):
|
||||
>>> filter = LPIFilter2D(filt_func)
|
||||
|
||||
"""
|
||||
if impulse_response is None:
|
||||
if not callable(impulse_response):
|
||||
raise ValueError("Impulse response must be a callable.")
|
||||
|
||||
self.impulse_response = impulse_response
|
||||
|
||||
@@ -13,19 +13,22 @@ def configuration(parent_package='', top_path=None):
|
||||
config.add_data_dir('tests')
|
||||
|
||||
cython(['_ctmf.pyx'], working_path=base_path)
|
||||
cython(['_denoise.pyx'], working_path=base_path)
|
||||
|
||||
config.add_extension('_ctmf', sources=['_ctmf.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('_denoise', sources=['_denoise.c'],
|
||||
include_dirs=[get_numpy_include_dirs(), '../_shared'])
|
||||
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
author='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Filters',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -61,3 +61,8 @@ class TestCanny(unittest.TestCase):
|
||||
|
||||
def test_image_shape(self):
|
||||
self.assertRaises(TypeError, F.canny, np.zeros((20, 20, 20)), 4, 0, 0)
|
||||
|
||||
def test_mask_none(self):
|
||||
result1 = F.canny(np.zeros((20, 20)), 4, 0, 0, np.ones((20, 20), bool))
|
||||
result2 = F.canny(np.zeros((20, 20)), 4, 0, 0)
|
||||
self.assertTrue(np.all(result1 == result2))
|
||||
|
||||
@@ -117,5 +117,11 @@ def test_insufficient_size():
|
||||
median_filter(img, radius=1)
|
||||
|
||||
|
||||
@raises(TypeError)
|
||||
def test_wrong_shape():
|
||||
img = np.empty((10, 10, 3))
|
||||
median_filter(img)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
np.testing.run_module_suite()
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import numpy as np
|
||||
from numpy.testing import run_module_suite, assert_raises
|
||||
|
||||
from skimage import filter, data, color, img_as_float
|
||||
|
||||
|
||||
lena = img_as_float(data.lena()[:256, :256])
|
||||
lena_gray = color.rgb2gray(lena)
|
||||
|
||||
|
||||
def test_denoise_tv_2d():
|
||||
# lena image
|
||||
img = lena_gray
|
||||
# add noise to lena
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
# clip noise so that it does not exceed allowed range for float images.
|
||||
img = np.clip(img, 0, 1)
|
||||
# denoise
|
||||
denoised_lena = filter.denoise_tv(img, weight=60.0)
|
||||
# which dtype?
|
||||
assert denoised_lena.dtype in [np.float, np.float32, np.float64]
|
||||
from scipy import ndimage
|
||||
grad = ndimage.morphological_gradient(img, size=((3, 3)))
|
||||
grad_denoised = ndimage.morphological_gradient(
|
||||
denoised_lena, size=((3, 3)))
|
||||
# test if the total variation has decreased
|
||||
assert grad_denoised.dtype == np.float
|
||||
assert (np.sqrt((grad_denoised**2).sum())
|
||||
< np.sqrt((grad**2).sum()) / 2)
|
||||
|
||||
|
||||
def test_denoise_tv_float_result_range():
|
||||
# lena image
|
||||
img = lena_gray
|
||||
int_lena = np.multiply(img, 255).astype(np.uint8)
|
||||
assert np.max(int_lena) > 1
|
||||
denoised_int_lena = filter.denoise_tv(int_lena, weight=60.0)
|
||||
# test if the value range of output float data is within [0.0:1.0]
|
||||
assert denoised_int_lena.dtype == np.float
|
||||
assert np.max(denoised_int_lena) <= 1.0
|
||||
assert np.min(denoised_int_lena) >= 0.0
|
||||
|
||||
|
||||
def test_denoise_tv_3d():
|
||||
"""Apply the TV denoising algorithm on a 3D image representing a sphere."""
|
||||
x, y, z = np.ogrid[0:40, 0:40, 0:40]
|
||||
mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
|
||||
mask = 100 * mask.astype(np.float)
|
||||
mask += 60
|
||||
mask += 20 * np.random.random(mask.shape)
|
||||
mask[mask < 0] = 0
|
||||
mask[mask > 255] = 255
|
||||
res = filter.denoise_tv(mask.astype(np.uint8), weight=100)
|
||||
assert res.dtype == np.float
|
||||
assert res.std() * 255 < mask.std()
|
||||
|
||||
# test wrong number of dimensions
|
||||
assert_raises(ValueError, filter.denoise_tv, np.random.random((8, 8, 8, 8)))
|
||||
|
||||
|
||||
def test_denoise_bilateral_2d():
|
||||
img = lena_gray
|
||||
# add some random noise
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20)
|
||||
out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
assert out1.std() > out2.std()
|
||||
|
||||
|
||||
def test_denoise_bilateral_3d():
|
||||
img = lena
|
||||
# add some random noise
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20)
|
||||
out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
assert out1.std() > out2.std()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
@@ -9,6 +9,7 @@ def test_sobel_zeros():
|
||||
result = F.sobel(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_sobel_mask():
|
||||
"""Sobel on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -16,6 +17,7 @@ def test_sobel_mask():
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_sobel_horizontal():
|
||||
"""Sobel on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -26,6 +28,7 @@ def test_sobel_horizontal():
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
def test_sobel_vertical():
|
||||
"""Sobel on a vertical edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -41,6 +44,7 @@ def test_hsobel_zeros():
|
||||
result = F.hsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_hsobel_mask():
|
||||
"""Horizontal Sobel on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -48,6 +52,7 @@ def test_hsobel_mask():
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_hsobel_horizontal():
|
||||
"""Horizontal Sobel on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -58,6 +63,7 @@ def test_hsobel_horizontal():
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
def test_hsobel_vertical():
|
||||
"""Horizontal Sobel on a vertical edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -71,6 +77,7 @@ def test_vsobel_zeros():
|
||||
result = F.vsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vsobel_mask():
|
||||
"""Vertical Sobel on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -78,6 +85,7 @@ def test_vsobel_mask():
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vsobel_vertical():
|
||||
"""Vertical Sobel on an edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -88,6 +96,7 @@ def test_vsobel_vertical():
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert (np.all(result[np.abs(j) > 1] == 0))
|
||||
|
||||
|
||||
def test_vsobel_horizontal():
|
||||
"""vertical Sobel on a horizontal edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -97,11 +106,114 @@ def test_vsobel_horizontal():
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
|
||||
|
||||
def test_scharr_zeros():
|
||||
"""Scharr on an array of all zeros"""
|
||||
result = F.scharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_scharr_mask():
|
||||
"""Scharr on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
result = F.scharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_scharr_horizontal():
|
||||
"""Scharr on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.scharr(image)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
def test_scharr_vertical():
|
||||
"""Scharr on a vertical edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.scharr(image)
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert (np.all(result[np.abs(j) > 1] == 0))
|
||||
|
||||
|
||||
def test_hscharr_zeros():
|
||||
"""Horizontal Scharr on an array of all zeros"""
|
||||
result = F.hscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_hscharr_mask():
|
||||
"""Horizontal Scharr on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
result = F.hscharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_hscharr_horizontal():
|
||||
"""Horizontal Scharr on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.hscharr(image)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
def test_hscharr_vertical():
|
||||
"""Horizontal Scharr on a vertical edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.hscharr(image)
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vscharr_zeros():
|
||||
"""Vertical Scharr on an array of all zeros"""
|
||||
result = F.vscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vscharr_mask():
|
||||
"""Vertical Scharr on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
result = F.vscharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vscharr_vertical():
|
||||
"""Vertical Scharr on an edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.vscharr(image)
|
||||
# Fudge the eroded points
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert (np.all(result[np.abs(j) > 1] == 0))
|
||||
|
||||
|
||||
def test_vscharr_horizontal():
|
||||
"""vertical Scharr on a horizontal edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.vscharr(image)
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
|
||||
|
||||
def test_prewitt_zeros():
|
||||
"""Prewitt on an array of all zeros"""
|
||||
result = F.prewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_prewitt_mask():
|
||||
"""Prewitt on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -110,6 +222,7 @@ def test_prewitt_mask():
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
|
||||
|
||||
def test_prewitt_horizontal():
|
||||
"""Prewitt on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -121,6 +234,7 @@ def test_prewitt_horizontal():
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
|
||||
|
||||
|
||||
def test_prewitt_vertical():
|
||||
"""Prewitt on a vertical edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -137,6 +251,7 @@ def test_hprewitt_zeros():
|
||||
result = F.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_hprewitt_mask():
|
||||
"""Horizontal prewitt on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -145,6 +260,7 @@ def test_hprewitt_mask():
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
|
||||
|
||||
def test_hprewitt_horizontal():
|
||||
"""Horizontal prewitt on an edge should be a horizontal line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -156,6 +272,7 @@ def test_hprewitt_horizontal():
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
|
||||
|
||||
|
||||
def test_hprewitt_vertical():
|
||||
"""Horizontal prewitt on a vertical edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -170,6 +287,7 @@ def test_vprewitt_zeros():
|
||||
result = F.vprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vprewitt_mask():
|
||||
"""Vertical prewitt on a masked array should be zero"""
|
||||
np.random.seed(0)
|
||||
@@ -177,6 +295,7 @@ def test_vprewitt_mask():
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
|
||||
|
||||
def test_vprewitt_vertical():
|
||||
"""Vertical prewitt on an edge should be a vertical line"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -188,6 +307,7 @@ def test_vprewitt_vertical():
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result[np.abs(j) > 1]) < eps))
|
||||
|
||||
|
||||
def test_vprewitt_horizontal():
|
||||
"""Vertical prewitt on a horizontal edge should be zero"""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
@@ -209,7 +329,7 @@ def test_horizontal_mask_line():
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[4:7, 1:-1] = 0 # but line and neighbors masked
|
||||
|
||||
for grad_func in (F.hprewitt, F.hsobel):
|
||||
for grad_func in (F.hprewitt, F.hsobel, F.hscharr):
|
||||
result = grad_func(vgrad, mask)
|
||||
yield assert_close, result, expected
|
||||
|
||||
@@ -226,7 +346,7 @@ def test_vertical_mask_line():
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[1:-1, 4:7] = 0 # but line and neighbors masked
|
||||
|
||||
for grad_func in (F.vprewitt, F.vsobel):
|
||||
for grad_func in (F.vprewitt, F.vsobel, F.vscharr):
|
||||
result = grad_func(hgrad, mask)
|
||||
yield assert_close, result, expected
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ from skimage.io import *
|
||||
from skimage.filter import *
|
||||
|
||||
|
||||
class TestLPIFilter2D():
|
||||
class TestLPIFilter2D(object):
|
||||
|
||||
img = imread(os.path.join(data_dir, 'camera.png'),
|
||||
flatten=True)[:50, :50]
|
||||
|
||||
@@ -55,5 +56,9 @@ class TestLPIFilter2D():
|
||||
g1 = wiener(F[::-1, ::-1], self.filt_func)
|
||||
assert ((g - g1[::-1, ::-1]).sum() < 1)
|
||||
|
||||
def test_non_callable(self):
|
||||
assert_raises(ValueError, LPIFilter2D, None)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import numpy as np
|
||||
from numpy.testing import run_module_suite
|
||||
|
||||
from skimage import filter, data, color
|
||||
|
||||
|
||||
class TestTvDenoise():
|
||||
|
||||
def test_tv_denoise_2d(self):
|
||||
"""
|
||||
Apply the TV denoising algorithm on the lena image provided
|
||||
by scipy
|
||||
"""
|
||||
# lena image
|
||||
lena = color.rgb2gray(data.lena())[:256, :256]
|
||||
# add noise to lena
|
||||
lena += 0.5 * lena.std() * np.random.randn(*lena.shape)
|
||||
# clip noise so that it does not exceed allowed range for float images.
|
||||
lena = np.clip(lena, 0, 1)
|
||||
# denoise
|
||||
denoised_lena = filter.tv_denoise(lena, weight=60.0)
|
||||
# which dtype?
|
||||
assert denoised_lena.dtype in [np.float, np.float32, np.float64]
|
||||
from scipy import ndimage
|
||||
grad = ndimage.morphological_gradient(lena, size=((3, 3)))
|
||||
grad_denoised = ndimage.morphological_gradient(
|
||||
denoised_lena, size=((3, 3)))
|
||||
# test if the total variation has decreased
|
||||
assert grad_denoised.dtype == np.float
|
||||
assert (np.sqrt((grad_denoised**2).sum())
|
||||
< np.sqrt((grad**2).sum()) / 2)
|
||||
|
||||
def test_tv_denoise_float_result_range(self):
|
||||
# lena image
|
||||
lena = color.rgb2gray(data.lena())[:256, :256]
|
||||
int_lena = np.multiply(lena, 255).astype(np.uint8)
|
||||
assert np.max(int_lena) > 1
|
||||
denoised_int_lena = filter.tv_denoise(int_lena, weight=60.0)
|
||||
# test if the value range of output float data is within [0.0:1.0]
|
||||
assert denoised_int_lena.dtype == np.float
|
||||
assert np.max(denoised_int_lena) <= 1.0
|
||||
assert np.min(denoised_int_lena) >= 0.0
|
||||
|
||||
def test_tv_denoise_3d(self):
|
||||
"""
|
||||
Apply the TV denoising algorithm on a 3D image representing
|
||||
a sphere.
|
||||
"""
|
||||
x, y, z = np.ogrid[0:40, 0:40, 0:40]
|
||||
mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
|
||||
mask = 100 * mask.astype(np.float)
|
||||
mask += 60
|
||||
mask += 20 * np.random.randn(*mask.shape)
|
||||
mask[mask < 0] = 0
|
||||
mask[mask > 255] = 255
|
||||
res = filter.tv_denoise(mask.astype(np.uint8), weight=100)
|
||||
assert res.dtype == np.float
|
||||
assert res.std() * 255 < mask.std()
|
||||
|
||||
# test wrong number of dimensions
|
||||
a = np.random.random((8, 8, 8, 8))
|
||||
try:
|
||||
res = filter.tv_denoise(a)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
@@ -29,10 +29,10 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Graph-based Image-processing Algorithms',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='Modified BSD',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -3,9 +3,9 @@ Skivi is written/maintained/developed by:
|
||||
|
||||
S. Chris Colbert - sccolbert@gmail.com
|
||||
|
||||
Skivi is free software and is part of the scikits-image project.
|
||||
Skivi is free software and is part of the scikit-image project.
|
||||
|
||||
Skivi is governed by the licenses of the scikits-image project.
|
||||
Skivi is governed by the licenses of the scikit-image project.
|
||||
|
||||
Please report any bugs to the author.
|
||||
|
||||
|
||||
+3
-3
@@ -31,10 +31,10 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Image I/O Routines',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='Modified BSD',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ def approximate_polygon(coords, tolerance):
|
||||
----------
|
||||
.. [1] http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
|
||||
"""
|
||||
if tolerance == 0:
|
||||
if tolerance <= 0:
|
||||
return coords
|
||||
|
||||
chain = np.zeros(coords.shape[0], 'bool')
|
||||
|
||||
@@ -98,7 +98,7 @@ def find_contours(array, level,
|
||||
"""
|
||||
array = np.asarray(array, dtype=np.double)
|
||||
if array.ndim != 2:
|
||||
raise RuntimeError('Only 2D arrays are supported.')
|
||||
raise ValueError('Only 2D arrays are supported.')
|
||||
level = float(level)
|
||||
if (fully_connected not in _param_options or
|
||||
positive_orientation not in _param_options):
|
||||
|
||||
@@ -24,10 +24,10 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Graph-based Image-processing Algorithms',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='Modified BSD',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -21,34 +21,37 @@ r = np.sqrt(x**2 + y**2)
|
||||
|
||||
|
||||
def test_binary():
|
||||
contours = find_contours(a, 0.5)
|
||||
ref = [[6. , 1.5],
|
||||
[5. , 1.5],
|
||||
[4. , 1.5],
|
||||
[3. , 1.5],
|
||||
[2. , 1.5],
|
||||
[1.5, 2. ],
|
||||
[1.5, 3. ],
|
||||
[1.5, 4. ],
|
||||
[1.5, 5. ],
|
||||
[1.5, 6. ],
|
||||
[1. , 6.5],
|
||||
[0.5, 6. ],
|
||||
[0.5, 5. ],
|
||||
[0.5, 4. ],
|
||||
[0.5, 3. ],
|
||||
[0.5, 2. ],
|
||||
[0.5, 1. ],
|
||||
[1. , 0.5],
|
||||
[2. , 0.5],
|
||||
[3. , 0.5],
|
||||
[4. , 0.5],
|
||||
[5. , 0.5],
|
||||
[6. , 0.5],
|
||||
[6.5, 1. ],
|
||||
[6. , 1.5]]
|
||||
|
||||
contours = find_contours(a, 0.5, positive_orientation='high')
|
||||
assert len(contours) == 1
|
||||
assert_array_equal(contours[0],
|
||||
[[6. , 1.5],
|
||||
[5. , 1.5],
|
||||
[4. , 1.5],
|
||||
[3. , 1.5],
|
||||
[2. , 1.5],
|
||||
[1.5, 2. ],
|
||||
[1.5, 3. ],
|
||||
[1.5, 4. ],
|
||||
[1.5, 5. ],
|
||||
[1.5, 6. ],
|
||||
[1. , 6.5],
|
||||
[0.5, 6. ],
|
||||
[0.5, 5. ],
|
||||
[0.5, 4. ],
|
||||
[0.5, 3. ],
|
||||
[0.5, 2. ],
|
||||
[0.5, 1. ],
|
||||
[1. , 0.5],
|
||||
[2. , 0.5],
|
||||
[3. , 0.5],
|
||||
[4. , 0.5],
|
||||
[5. , 0.5],
|
||||
[6. , 0.5],
|
||||
[6.5, 1. ],
|
||||
[6. , 1.5]])
|
||||
assert_array_equal(contours[0][::-1], ref)
|
||||
|
||||
|
||||
|
||||
|
||||
def test_float():
|
||||
@@ -70,6 +73,11 @@ def test_memory_order():
|
||||
assert len(contours) == 1
|
||||
|
||||
|
||||
def test_invalid_input():
|
||||
assert_raises(ValueError, find_contours, r, 0.5, 'foo', 'bar')
|
||||
assert_raises(ValueError, find_contours, r[..., None], 0.5)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.testing import run_module_suite
|
||||
run_module_suite()
|
||||
|
||||
@@ -22,6 +22,8 @@ def test_approximate_polygon():
|
||||
|
||||
out = approximate_polygon(square, -1)
|
||||
np.testing.assert_array_equal(out, square)
|
||||
out = approximate_polygon(square, 0)
|
||||
np.testing.assert_array_equal(out, square)
|
||||
|
||||
|
||||
def test_subdivide_polygon():
|
||||
@@ -51,6 +53,10 @@ def test_subdivide_polygon():
|
||||
np.testing.assert_equal(new_square3.shape[0],
|
||||
2 * (square3.shape[0] - mask_len + 2))
|
||||
|
||||
# not supported B-Spline degree
|
||||
np.testing.assert_raises(ValueError, subdivide_polygon, square, 0)
|
||||
np.testing.assert_raises(ValueError, subdivide_polygon, square, 8)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
np.testing.run_module_suite()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from numpy.testing import assert_array_equal, assert_almost_equal, \
|
||||
assert_array_almost_equal
|
||||
assert_array_almost_equal, assert_raises
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
from skimage.measure import regionprops
|
||||
from skimage.measure._regionprops import regionprops, PROPS, perimeter
|
||||
|
||||
|
||||
SAMPLE = np.array(
|
||||
@@ -22,6 +22,16 @@ INTENSITY_SAMPLE = SAMPLE.copy()
|
||||
INTENSITY_SAMPLE[1, 9:11] = 2
|
||||
|
||||
|
||||
def test_unsupported_dtype():
|
||||
assert_raises(TypeError, regionprops, np.zeros((10, 10), dtype=np.double))
|
||||
|
||||
|
||||
def test_all_props():
|
||||
props = regionprops(SAMPLE, 'all', INTENSITY_SAMPLE)[0]
|
||||
for prop in PROPS:
|
||||
assert prop in props
|
||||
|
||||
|
||||
def test_area():
|
||||
area = regionprops(SAMPLE, ['Area'])[0]['Area']
|
||||
assert area == np.sum(SAMPLE)
|
||||
@@ -36,6 +46,7 @@ def test_bbox():
|
||||
bbox = regionprops(SAMPLE_mod, ['BoundingBox'])[0]['BoundingBox']
|
||||
assert_array_almost_equal(bbox, (0, 0, SAMPLE.shape[0], SAMPLE.shape[1]-1))
|
||||
|
||||
|
||||
def test_central_moments():
|
||||
mu = regionprops(SAMPLE, ['CentralMoments'])[0]['CentralMoments']
|
||||
#: determined with OpenCV
|
||||
@@ -48,6 +59,7 @@ def test_central_moments():
|
||||
assert_almost_equal(mu[2,1], 2000.296296296291)
|
||||
assert_almost_equal(mu[3,0], -760.0246913580195)
|
||||
|
||||
|
||||
def test_centroid():
|
||||
centroid = regionprops(SAMPLE, ['Centroid'])[0]['Centroid']
|
||||
# determined with MATLAB
|
||||
@@ -90,6 +102,11 @@ def test_eccentricity():
|
||||
eps = regionprops(SAMPLE, ['Eccentricity'])[0]['Eccentricity']
|
||||
assert_almost_equal(eps, 0.814629313427)
|
||||
|
||||
img = np.zeros((5, 5), dtype=np.int)
|
||||
img[2, 2] = 1
|
||||
eps = regionprops(img, ['Eccentricity'])[0]['Eccentricity']
|
||||
assert_almost_equal(eps, 0)
|
||||
|
||||
|
||||
def test_equiv_diameter():
|
||||
diameter = regionprops(SAMPLE, ['EquivDiameter'])[0]['EquivDiameter']
|
||||
@@ -142,6 +159,11 @@ def test_filled_area():
|
||||
assert area == np.sum(SAMPLE)
|
||||
|
||||
|
||||
def test_filled_image():
|
||||
img = regionprops(SAMPLE, ['FilledImage'])[0]['FilledImage']
|
||||
assert_array_equal(img, SAMPLE)
|
||||
|
||||
|
||||
def test_major_axis_length():
|
||||
length = regionprops(SAMPLE, ['MajorAxisLength'])[0]['MajorAxisLength']
|
||||
# MATLAB has different interpretation of ellipse than found in literature,
|
||||
@@ -188,6 +210,7 @@ def test_moments():
|
||||
assert_almost_equal(m[2,1], 43882.0)
|
||||
assert_almost_equal(m[3,0], 95588.0)
|
||||
|
||||
|
||||
def test_normalized_moments():
|
||||
nu = regionprops(SAMPLE, ['NormalizedMoments'])[0]['NormalizedMoments']
|
||||
#: determined with OpenCV
|
||||
@@ -198,6 +221,7 @@ def test_normalized_moments():
|
||||
assert_almost_equal(nu[2,1], 0.045473992910668816)
|
||||
assert_almost_equal(nu[3,0], -0.017278118992041805)
|
||||
|
||||
|
||||
def test_orientation():
|
||||
orientation = regionprops(SAMPLE, ['Orientation'])[0]['Orientation']
|
||||
# determined with MATLAB
|
||||
@@ -219,15 +243,21 @@ def test_orientation():
|
||||
)[0]['Orientation']
|
||||
assert_almost_equal(orientation_diag, -math.pi / 4)
|
||||
|
||||
|
||||
def test_perimeter():
|
||||
perimeter = regionprops(SAMPLE, ['Perimeter'])[0]['Perimeter']
|
||||
assert_almost_equal(perimeter, 59.2132034355964)
|
||||
per = regionprops(SAMPLE, ['Perimeter'])[0]['Perimeter']
|
||||
assert_almost_equal(per, 59.2132034355964)
|
||||
|
||||
per = perimeter(SAMPLE.astype('double'), neighbourhood=8)
|
||||
assert_almost_equal(per, 43.1213203436)
|
||||
|
||||
|
||||
def test_solidity():
|
||||
solidity = regionprops(SAMPLE, ['Solidity'])[0]['Solidity']
|
||||
# determined with MATLAB
|
||||
assert_almost_equal(solidity, 0.580645161290323)
|
||||
|
||||
|
||||
def test_weighted_central_moments():
|
||||
wmu = regionprops(SAMPLE, ['WeightedCentralMoments'], INTENSITY_SAMPLE
|
||||
)[0]['WeightedCentralMoments']
|
||||
@@ -281,6 +311,7 @@ def test_weighted_moments():
|
||||
)
|
||||
assert_array_almost_equal(wm, ref)
|
||||
|
||||
|
||||
def test_weighted_normalized_moments():
|
||||
wnu = regionprops(SAMPLE, ['WeightedNormalizedMoments'], INTENSITY_SAMPLE
|
||||
)[0]['WeightedNormalizedMoments']
|
||||
@@ -292,6 +323,7 @@ def test_weighted_normalized_moments():
|
||||
)
|
||||
assert_array_almost_equal(wnu, ref)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from numpy.testing import run_module_suite
|
||||
run_module_suite()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_equal
|
||||
from numpy.testing import assert_equal, assert_raises
|
||||
|
||||
from skimage.measure import structural_similarity as ssim
|
||||
|
||||
@@ -24,20 +24,19 @@ def test_ssim_image():
|
||||
S1 = ssim(X, Y, win_size=3)
|
||||
assert(S1 < 0.3)
|
||||
|
||||
## Come up with a better way of testing the gradient
|
||||
##
|
||||
## def test_ssim_grad():
|
||||
## N = 30
|
||||
## X = np.random.random((N, N)) * 255
|
||||
## Y = np.random.random((N, N)) * 255
|
||||
|
||||
## def func(Y):
|
||||
## return ssim(X, Y, dynamic_range=255)
|
||||
# NOTE: This test is known to randomly fail on some systems (Mac OS X 10.6)
|
||||
def test_ssim_grad():
|
||||
N = 30
|
||||
X = np.random.random((N, N)) * 255
|
||||
Y = np.random.random((N, N)) * 255
|
||||
|
||||
## def grad(Y):
|
||||
## return ssim(X, Y, dynamic_range=255, gradient=True)[1]
|
||||
f = ssim(X, Y, dynamic_range=255)
|
||||
g = ssim(X, Y, dynamic_range=255, gradient=True)
|
||||
|
||||
## assert(np.all(opt.check_grad(func, grad, Y) < 0.05))
|
||||
assert f < 0.05
|
||||
assert g[0] < 0.05
|
||||
assert np.all(g[1] < 0.05)
|
||||
|
||||
|
||||
def test_ssim_dtype():
|
||||
@@ -56,5 +55,15 @@ def test_ssim_dtype():
|
||||
assert S2 < 0.1
|
||||
|
||||
|
||||
def test_invalid_input():
|
||||
X = np.zeros((3, 3), dtype=np.double)
|
||||
Y = np.zeros((3, 3), dtype=np.int)
|
||||
assert_raises(ValueError, ssim, X, Y)
|
||||
|
||||
Y = np.zeros((4, 4), dtype=np.double)
|
||||
assert_raises(ValueError, ssim, X, Y)
|
||||
|
||||
assert_raises(ValueError, ssim, X, X, win_size=8)
|
||||
|
||||
if __name__ == "__main__":
|
||||
np.testing.run_module_suite()
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
"""
|
||||
:author: Damian Eads, 2009
|
||||
:license: modified BSD
|
||||
"""
|
||||
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import warnings
|
||||
from skimage import img_as_ubyte
|
||||
|
||||
@@ -45,6 +38,7 @@ def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
Examples
|
||||
--------
|
||||
>>> # Erosion shrinks bright regions
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> bright_square = np.array([[0, 0, 0, 0, 0],
|
||||
... [0, 1, 1, 1, 0],
|
||||
@@ -97,6 +91,7 @@ def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
Examples
|
||||
--------
|
||||
>>> # Dilation enlarges bright regions
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> bright_pixel = np.array([[0, 0, 0, 0, 0],
|
||||
... [0, 0, 0, 0, 0],
|
||||
@@ -146,6 +141,7 @@ def opening(image, selem, out=None):
|
||||
Examples
|
||||
--------
|
||||
>>> # Open up gap between two bright regions (but also shrink regions)
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> bad_connection = np.array([[1, 0, 0, 0, 1],
|
||||
... [1, 1, 0, 1, 1],
|
||||
@@ -196,6 +192,7 @@ def closing(image, selem, out=None):
|
||||
Examples
|
||||
--------
|
||||
>>> # Close a gap between two bright lines
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> broken_line = np.array([[0, 0, 0, 0, 0],
|
||||
... [0, 0, 0, 0, 0],
|
||||
@@ -245,6 +242,7 @@ def white_tophat(image, selem, out=None):
|
||||
Examples
|
||||
--------
|
||||
>>> # Subtract grey background from bright peak
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> bright_on_grey = np.array([[2, 3, 3, 3, 2],
|
||||
... [3, 4, 5, 4, 3],
|
||||
@@ -261,7 +259,6 @@ def white_tophat(image, selem, out=None):
|
||||
"""
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
image = img_as_ubyte(image)
|
||||
|
||||
out = opening(image, selem, out=out)
|
||||
out = image - out
|
||||
@@ -294,6 +291,7 @@ def black_tophat(image, selem, out=None):
|
||||
Examples
|
||||
--------
|
||||
>>> # Change dark peak to bright peak and subtract background
|
||||
>>> import numpy as np
|
||||
>>> from skimage.morphology import square
|
||||
>>> dark_on_grey = np.array([[7, 6, 6, 6, 7],
|
||||
... [6, 5, 4, 5, 6],
|
||||
@@ -311,7 +309,6 @@ def black_tophat(image, selem, out=None):
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
image = img_as_ubyte(image)
|
||||
|
||||
out = closing(image, selem, out=out)
|
||||
out = out - image
|
||||
|
||||
@@ -39,11 +39,11 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='Damian Eads',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Morphology Wrapper',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -2,5 +2,5 @@ from .random_walker_segmentation import random_walker
|
||||
from ._felzenszwalb import felzenszwalb
|
||||
from ._slic import slic
|
||||
from ._quickshift import quickshift
|
||||
from .boundaries import find_boundaries, visualize_boundaries
|
||||
from .boundaries import find_boundaries, visualize_boundaries, mark_boundaries
|
||||
from ._clear_border import clear_border
|
||||
|
||||
@@ -1,19 +1,45 @@
|
||||
import numpy as np
|
||||
from ..morphology import dilation, square
|
||||
from ..util import img_as_float
|
||||
from ..color import gray2rgb
|
||||
from .._shared.utils import deprecated
|
||||
|
||||
|
||||
def find_boundaries(label_img):
|
||||
"""Return bool array where boundaries between labeled regions are True."""
|
||||
boundaries = np.zeros(label_img.shape, dtype=np.bool)
|
||||
boundaries[1:, :] += label_img[1:, :] != label_img[:-1, :]
|
||||
boundaries[:, 1:] += label_img[:, 1:] != label_img[:, :-1]
|
||||
return boundaries
|
||||
|
||||
|
||||
def visualize_boundaries(img, label_img):
|
||||
img = img_as_float(img, force_copy=True)
|
||||
def mark_boundaries(image, label_img, color=(1, 1, 0), outline_color=None):
|
||||
"""Return image with boundaries between labeled regions highlighted.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : (M, N[, 3]) array
|
||||
Grayscale or RGB image.
|
||||
label_img : (M, N) array
|
||||
Label array where regions are marked by different integer values.
|
||||
color : length-3 sequence
|
||||
RGB color of boundaries in the output image.
|
||||
outline_color : length-3 sequence
|
||||
RGB color surrounding boundaries in the output image. If None, no
|
||||
outline is drawn.
|
||||
"""
|
||||
if image.ndim == 2:
|
||||
image = gray2rgb(image)
|
||||
image = img_as_float(image, force_copy=True)
|
||||
|
||||
boundaries = find_boundaries(label_img)
|
||||
outer_boundaries = dilation(boundaries.astype(np.uint8), square(2))
|
||||
img[outer_boundaries != 0, :] = np.array([0, 0, 0]) # black
|
||||
img[boundaries, :] = np.array([1, 1, 0]) # yellow
|
||||
return img
|
||||
if outline_color is not None:
|
||||
outer_boundaries = dilation(boundaries.astype(np.uint8), square(2))
|
||||
image[outer_boundaries != 0, :] = np.array(outline_color)
|
||||
image[boundaries, :] = np.array(color)
|
||||
return image
|
||||
|
||||
|
||||
@deprecated('mark_boundaries')
|
||||
def visualize_boundaries(*args, **kwargs):
|
||||
return mark_boundaries(*args, **kwargs)
|
||||
|
||||
@@ -25,10 +25,10 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Segmentation Algorithms',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -6,6 +6,6 @@ from ._geometric import (warp, warp_coords, estimate_transform,
|
||||
SimilarityTransform, AffineTransform,
|
||||
ProjectiveTransform, PolynomialTransform,
|
||||
PiecewiseAffineTransform)
|
||||
from ._warps import swirl, homography, resize, rotate
|
||||
from ._warps import swirl, homography, resize, rotate, rescale
|
||||
from .pyramids import (pyramid_reduce, pyramid_expand,
|
||||
pyramid_gaussian, pyramid_laplacian)
|
||||
|
||||
@@ -1015,7 +1015,8 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
|
||||
if mode == 'constant' and not (0 <= cval <= 1):
|
||||
clipped[out == cval] = cval
|
||||
|
||||
if clipped.shape[0] == 1 or clipped.shape[1] == 1:
|
||||
if clipped.ndim == 3 and orig_ndim == 2:
|
||||
# remove singleton dim introduced by atleast_3d
|
||||
return clipped[..., 0]
|
||||
else:
|
||||
return clipped
|
||||
else: # remove singleton dim introduced by atleast_3d
|
||||
return clipped.squeeze()
|
||||
|
||||
+86
-15
@@ -1,17 +1,21 @@
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
from ._geometric import (warp, SimilarityTransform, AffineTransform,
|
||||
ProjectiveTransform)
|
||||
|
||||
|
||||
def resize(image, output_shape, order=1, mode='constant', cval=0.):
|
||||
"""Resize image.
|
||||
"""Resize image to match a certain size.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input image.
|
||||
output_shape : tuple or ndarray
|
||||
Size of the generated output image `(rows, cols)`.
|
||||
Size of the generated output image `(rows, cols[, dim])`. If `dim` is
|
||||
not provided, the number of channels are preserved. In case the number
|
||||
of input channels does not equal the number of output channels a
|
||||
3-dimensional interpolation is applied.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -32,24 +36,88 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.):
|
||||
|
||||
"""
|
||||
|
||||
rows, cols = output_shape
|
||||
rows, cols = output_shape[0], output_shape[1]
|
||||
orig_rows, orig_cols = image.shape[0], image.shape[1]
|
||||
|
||||
rscale = float(orig_rows) / rows
|
||||
cscale = float(orig_cols) / cols
|
||||
row_scale = float(orig_rows) / rows
|
||||
col_scale = float(orig_cols) / cols
|
||||
|
||||
# 3 control points necessary to estimate exact AffineTransform
|
||||
src_corners = np.array([[1, 1], [1, rows], [cols, rows]]) - 1
|
||||
dst_corners = np.zeros(src_corners.shape, dtype=np.double)
|
||||
# take into account that 0th pixel is at position (0.5, 0.5)
|
||||
dst_corners[:, 0] = cscale * (src_corners[:, 0] + 0.5) - 0.5
|
||||
dst_corners[:, 1] = rscale * (src_corners[:, 1] + 0.5) - 0.5
|
||||
# 3-dimensional interpolation
|
||||
if len(output_shape) == 3 and (image.ndim == 2
|
||||
or output_shape[2] != image.shape[2]):
|
||||
dim = output_shape[2]
|
||||
orig_dim = 1 if image.ndim == 2 else image.shape[2]
|
||||
dim_scale = float(orig_dim) / dim
|
||||
|
||||
tform = AffineTransform()
|
||||
tform.estimate(src_corners, dst_corners)
|
||||
map_rows, map_cols, map_dims = np.mgrid[:rows, :cols, :dim]
|
||||
map_rows = row_scale * (map_rows + 0.5) - 0.5
|
||||
map_cols = col_scale * (map_cols + 0.5) - 0.5
|
||||
map_dims = dim_scale * (map_dims + 0.5) - 0.5
|
||||
|
||||
return warp(image, tform, output_shape=output_shape, order=order,
|
||||
mode=mode, cval=cval)
|
||||
coord_map = np.array([map_rows, map_cols, map_dims])
|
||||
|
||||
out = ndimage.map_coordinates(image, coord_map, order=order, mode=mode,
|
||||
cval=cval)
|
||||
|
||||
else: # 2-dimensional interpolation
|
||||
|
||||
# 3 control points necessary to estimate exact AffineTransform
|
||||
src_corners = np.array([[1, 1], [1, rows], [cols, rows]]) - 1
|
||||
dst_corners = np.zeros(src_corners.shape, dtype=np.double)
|
||||
# take into account that 0th pixel is at position (0.5, 0.5)
|
||||
dst_corners[:, 0] = col_scale * (src_corners[:, 0] + 0.5) - 0.5
|
||||
dst_corners[:, 1] = row_scale * (src_corners[:, 1] + 0.5) - 0.5
|
||||
|
||||
tform = AffineTransform()
|
||||
tform.estimate(src_corners, dst_corners)
|
||||
|
||||
out = warp(image, tform, output_shape=output_shape, order=order,
|
||||
mode=mode, cval=cval)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def rescale(image, scale, order=1, mode='constant', cval=0.):
|
||||
"""Scale image by a certain factor.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input image.
|
||||
scale : {float, tuple of floats}
|
||||
Scale factors. Separate scale factors can be defined as
|
||||
`(row_scale, col_scale)`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
scaled : ndarray
|
||||
Scaled version of the input.
|
||||
|
||||
Other parameters
|
||||
----------------
|
||||
order : int
|
||||
Order of splines used in interpolation. See
|
||||
`scipy.ndimage.map_coordinates` for detail.
|
||||
mode : string
|
||||
How to handle values outside the image borders. See
|
||||
`scipy.ndimage.map_coordinates` for detail.
|
||||
cval : string
|
||||
Used in conjunction with mode 'constant', the value outside
|
||||
the image boundaries.
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
row_scale, col_scale = scale
|
||||
except TypeError:
|
||||
row_scale = col_scale = scale
|
||||
|
||||
orig_rows, orig_cols = image.shape[0], image.shape[1]
|
||||
rows = np.round(row_scale * orig_rows)
|
||||
cols = np.round(col_scale * orig_cols)
|
||||
output_shape = (rows, cols)
|
||||
|
||||
return resize(image, output_shape, order=order, mode=mode, cval=cval)
|
||||
|
||||
|
||||
def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.):
|
||||
@@ -280,3 +348,6 @@ def homography(image, H, output_shape=None, order=1,
|
||||
tform = ProjectiveTransform(H)
|
||||
return warp(image, inverse_map=tform.inverse, output_shape=output_shape,
|
||||
order=order, mode=mode, cval=cval)
|
||||
|
||||
return warp(image, inverse_map=tform.inverse, output_shape=output_shape,
|
||||
order=order, mode=mode, cval=cval)
|
||||
|
||||
@@ -57,7 +57,7 @@ def pyramid_reduce(image, downscale=2, sigma=None, order=1,
|
||||
|
||||
References
|
||||
----------
|
||||
..[1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
.. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
|
||||
"""
|
||||
|
||||
@@ -111,7 +111,7 @@ def pyramid_expand(image, upscale=2, sigma=None, order=1,
|
||||
|
||||
References
|
||||
----------
|
||||
..[1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
.. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
|
||||
"""
|
||||
|
||||
@@ -176,7 +176,7 @@ def pyramid_gaussian(image, max_layer=-1, downscale=2, sigma=None, order=1,
|
||||
|
||||
References
|
||||
----------
|
||||
..[1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
.. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
|
||||
"""
|
||||
|
||||
@@ -257,8 +257,8 @@ def pyramid_laplacian(image, max_layer=-1, downscale=2, sigma=None, order=1,
|
||||
|
||||
References
|
||||
----------
|
||||
..[1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
..[2] http://sepwww.stanford.edu/~morgan/texturematch/paper_html/node3.html
|
||||
.. [1] http://web.mit.edu/persci/people/adelson/pub_pdfs/pyramid83.pdf
|
||||
.. [2] http://sepwww.stanford.edu/~morgan/texturematch/paper_html/node3.html
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -20,19 +20,17 @@ def configuration(parent_package='', top_path=None):
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
|
||||
config.add_extension('_warps_cy', sources=['_warps_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs(), '../_shared'],
|
||||
extra_compile_args=['-fopenmp'],
|
||||
extra_link_args=['-fopenmp'])
|
||||
include_dirs=[get_numpy_include_dirs(), '../_shared'])
|
||||
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='Scikits-image Developers',
|
||||
author='Scikits-image Developers',
|
||||
maintainer_email='scikits-image@googlegroups.com',
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Transforms',
|
||||
url='https://github.com/scikits-image/scikits-image',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
|
||||
@@ -1,41 +1,72 @@
|
||||
from numpy.testing import assert_array_equal, run_module_suite
|
||||
from numpy.testing import assert_array_equal, assert_raises, run_module_suite
|
||||
from skimage import data
|
||||
from skimage.transform import (pyramid_reduce, pyramid_expand,
|
||||
pyramid_gaussian, pyramid_laplacian)
|
||||
from skimage.transform import pyramids
|
||||
|
||||
|
||||
image = data.lena()
|
||||
image_gray = image[..., 0]
|
||||
|
||||
|
||||
def test_pyramid_reduce():
|
||||
def test_pyramid_reduce_rgb():
|
||||
rows, cols, dim = image.shape
|
||||
out = pyramid_reduce(image, downscale=2)
|
||||
out = pyramids.pyramid_reduce(image, downscale=2)
|
||||
assert_array_equal(out.shape, (rows / 2, cols / 2, dim))
|
||||
|
||||
|
||||
def test_pyramid_expand():
|
||||
def test_pyramid_reduce_gray():
|
||||
rows, cols = image_gray.shape
|
||||
out = pyramids.pyramid_reduce(image_gray, downscale=2)
|
||||
assert_array_equal(out.shape, (rows / 2, cols / 2))
|
||||
|
||||
|
||||
def test_pyramid_expand_rgb():
|
||||
rows, cols, dim = image.shape
|
||||
out = pyramid_expand(image, upscale=2)
|
||||
out = pyramids.pyramid_expand(image, upscale=2)
|
||||
assert_array_equal(out.shape, (rows * 2, cols * 2, dim))
|
||||
|
||||
|
||||
def test_build_gaussian_pyramid():
|
||||
rows, cols, dim = image.shape
|
||||
pyramid = pyramid_gaussian(image, downscale=2)
|
||||
def test_pyramid_expand_gray():
|
||||
rows, cols = image_gray.shape
|
||||
out = pyramids.pyramid_expand(image_gray, upscale=2)
|
||||
assert_array_equal(out.shape, (rows * 2, cols * 2))
|
||||
|
||||
|
||||
def test_build_gaussian_pyramid_rgb():
|
||||
rows, cols, dim = image.shape
|
||||
pyramid = pyramids.pyramid_gaussian(image, downscale=2)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2 ** layer, cols / 2 ** layer, dim)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_laplacian_pyramid():
|
||||
rows, cols, dim = image.shape
|
||||
pyramid = pyramid_laplacian(image, downscale=2)
|
||||
def test_build_gaussian_pyramid_gray():
|
||||
rows, cols = image_gray.shape
|
||||
pyramid = pyramids.pyramid_gaussian(image_gray, downscale=2)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2 ** layer, cols / 2 ** layer)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_laplacian_pyramid_rgb():
|
||||
rows, cols, dim = image.shape
|
||||
pyramid = pyramids.pyramid_laplacian(image, downscale=2)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2 ** layer, cols / 2 ** layer, dim)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_laplacian_pyramid_gray():
|
||||
rows, cols = image_gray.shape
|
||||
pyramid = pyramids.pyramid_laplacian(image_gray, downscale=2)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2 ** layer, cols / 2 ** layer)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_check_factor():
|
||||
assert_raises(ValueError, pyramids._check_factor, 0.99)
|
||||
assert_raises(ValueError, pyramids._check_factor, - 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
|
||||
@@ -2,7 +2,7 @@ from numpy.testing import assert_array_almost_equal, run_module_suite
|
||||
import numpy as np
|
||||
from scipy.ndimage import map_coordinates
|
||||
|
||||
from skimage.transform import (warp, warp_coords, rotate, resize,
|
||||
from skimage.transform import (warp, warp_coords, rotate, resize, rescale,
|
||||
AffineTransform,
|
||||
ProjectiveTransform,
|
||||
SimilarityTransform, homography)
|
||||
@@ -85,7 +85,25 @@ def test_rotate():
|
||||
assert_array_almost_equal(x90, np.rot90(x))
|
||||
|
||||
|
||||
def test_resize():
|
||||
def test_rescale():
|
||||
# same scale factor
|
||||
x = np.zeros((5, 5), dtype=np.double)
|
||||
x[1, 1] = 1
|
||||
scaled = rescale(x, 2, order=0)
|
||||
ref = np.zeros((10, 10))
|
||||
ref[2:4, 2:4] = 1
|
||||
assert_array_almost_equal(scaled, ref)
|
||||
|
||||
# different scale factors
|
||||
x = np.zeros((5, 5), dtype=np.double)
|
||||
x[1, 1] = 1
|
||||
scaled = rescale(x, (2, 1), order=0)
|
||||
ref = np.zeros((10, 5))
|
||||
ref[2:4, 1] = 1
|
||||
assert_array_almost_equal(scaled, ref)
|
||||
|
||||
|
||||
def test_resize2d():
|
||||
x = np.zeros((5, 5), dtype=np.double)
|
||||
x[1, 1] = 1
|
||||
resized = resize(x, (10, 10), order=0)
|
||||
@@ -94,6 +112,42 @@ def test_resize():
|
||||
assert_array_almost_equal(resized, ref)
|
||||
|
||||
|
||||
def test_resize3d_keep():
|
||||
# keep 3rd dimension
|
||||
x = np.zeros((5, 5, 3), dtype=np.double)
|
||||
x[1, 1, :] = 1
|
||||
resized = resize(x, (10, 10), order=0)
|
||||
ref = np.zeros((10, 10, 3))
|
||||
ref[2:4, 2:4, :] = 1
|
||||
assert_array_almost_equal(resized, ref)
|
||||
resized = resize(x, (10, 10, 3), order=0)
|
||||
assert_array_almost_equal(resized, ref)
|
||||
|
||||
|
||||
def test_resize3d_resize():
|
||||
# resize 3rd dimension
|
||||
x = np.zeros((5, 5, 3), dtype=np.double)
|
||||
x[1, 1, :] = 1
|
||||
resized = resize(x, (10, 10, 1), order=0)
|
||||
ref = np.zeros((10, 10, 1))
|
||||
ref[2:4, 2:4] = 1
|
||||
assert_array_almost_equal(resized, ref)
|
||||
|
||||
|
||||
def test_resize3d_bilinear():
|
||||
# bilinear 3rd dimension
|
||||
x = np.zeros((5, 5, 2), dtype=np.double)
|
||||
x[1, 1, 0] = 0
|
||||
x[1, 1, 1] = 1
|
||||
resized = resize(x, (10, 10, 1), order=1)
|
||||
ref = np.zeros((10, 10, 1))
|
||||
ref[1:5, 1:5, :] = 0.03125
|
||||
ref[1:5, 2:4, :] = 0.09375
|
||||
ref[2:4, 1:5, :] = 0.09375
|
||||
ref[2:4, 2:4, :] = 0.28125
|
||||
assert_array_almost_equal(resized, ref)
|
||||
|
||||
|
||||
def test_swirl():
|
||||
image = img_as_float(data.checkerboard())
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ def montage2d(arr_in, fill='mean', rescale_intensity=False):
|
||||
assert arr_in.ndim == 3
|
||||
|
||||
n_images, height, width = arr_in.shape
|
||||
|
||||
arr_in = arr_in.copy()
|
||||
|
||||
# -- rescale intensity if necessary
|
||||
if rescale_intensity:
|
||||
|
||||
Reference in New Issue
Block a user