mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-12 03:52:02 +08:00
Merge branch 'master' of git://github.com/scikit-image/scikit-image into int_idx_patch
This commit is contained in:
@@ -32,7 +32,18 @@ let's see an example of how a pre-defined plugin is added to the viewer:
|
||||
|
||||
viewer = ImageViewer(image)
|
||||
viewer += LineProfile(viewer)
|
||||
viewer.show()
|
||||
overlay, data = viewer.show()[0]
|
||||
|
||||
The viewer's ``show()`` method returns a list of tuples, one for each attached
|
||||
plugin. Each tuple contains two elements: an overlay of the same shape as the
|
||||
input image, and a data field (which may be ``None``). A plugin class documents
|
||||
its return value in its ``output`` method.
|
||||
|
||||
In this example, only one plugin is attached, so the list returned by ``show``
|
||||
will have length 1. We extract the single tuple and bind its ``overlay`` and
|
||||
``data`` elements to individual variables. Here, ``overlay`` contains an image
|
||||
of the line drawn on the viewer, and ``data`` contains the 1-dimensional
|
||||
intensity profile along that line.
|
||||
|
||||
At the moment, there are not many plugins pre-defined, but there is a really
|
||||
simple interface for creating your own plugin. First, let us create a plugin to
|
||||
@@ -74,8 +85,10 @@ All that's left is to create an image viewer and add the plugin to that viewer.
|
||||
|
||||
viewer = ImageViewer(image)
|
||||
viewer += denoise_plugin
|
||||
viewer.show()
|
||||
denoised = viewer.show()[0][0]
|
||||
|
||||
Here, we access only the overlay returned by the plugin, which contains the
|
||||
filtered image for the last used setting of ``weight``.
|
||||
|
||||
.. image:: data/denoise_viewer_window.png
|
||||
.. image:: data/denoise_plugin_window.png
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import numpy as np
|
||||
from skimage._shared.utils import safe_as_int
|
||||
|
||||
|
||||
def test_int_cast_not_possible():
|
||||
np.testing.assert_raises(ValueError, safe_as_int, 7.1)
|
||||
np.testing.assert_raises(ValueError, safe_as_int, [7.1, 0.9])
|
||||
np.testing.assert_raises(ValueError, safe_as_int, np.r_[7.1, 0.9])
|
||||
np.testing.assert_raises(ValueError, safe_as_int, (7.1, 0.9))
|
||||
np.testing.assert_raises(ValueError, safe_as_int, ((3, 4, 1),
|
||||
(2, 7.6, 289)))
|
||||
|
||||
np.testing.assert_raises(ValueError, safe_as_int, 7.1, 0.09)
|
||||
np.testing.assert_raises(ValueError, safe_as_int, [7.1, 0.9], 0.09)
|
||||
np.testing.assert_raises(ValueError, safe_as_int, np.r_[7.1, 0.9], 0.09)
|
||||
np.testing.assert_raises(ValueError, safe_as_int, (7.1, 0.9), 0.09)
|
||||
np.testing.assert_raises(ValueError, safe_as_int, ((3, 4, 1),
|
||||
(2, 7.6, 289)), 0.25)
|
||||
|
||||
|
||||
def test_int_cast_possible():
|
||||
np.testing.assert_equal(safe_as_int(7.1, atol=0.11), 7)
|
||||
np.testing.assert_equal(safe_as_int(-7.1, atol=0.11), -7)
|
||||
np.testing.assert_equal(safe_as_int(41.9, atol=0.11), 42)
|
||||
np.testing.assert_array_equal(safe_as_int([2, 42, 5789234.0, 87, 4]),
|
||||
np.r_[2, 42, 5789234, 87, 4])
|
||||
np.testing.assert_array_equal(safe_as_int(np.r_[[[3, 4, 1.000000001],
|
||||
[7, 2, -8.999999999],
|
||||
[6, 9, -4234918347.]]]),
|
||||
np.r_[[[3, 4, 1],
|
||||
[7, 2, -9],
|
||||
[6, 9, -4234918347]]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
np.testing.run_module_suite()
|
||||
@@ -1,12 +1,14 @@
|
||||
import warnings
|
||||
import functools
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
import six
|
||||
|
||||
from ._warnings import all_warnings
|
||||
|
||||
__all__ = ['deprecated', 'get_bound_method_class', 'all_warnings']
|
||||
__all__ = ['deprecated', 'get_bound_method_class', 'all_warnings',
|
||||
'safe_as_int']
|
||||
|
||||
|
||||
class skimage_deprecation(Warning):
|
||||
@@ -72,3 +74,70 @@ def get_bound_method_class(m):
|
||||
|
||||
"""
|
||||
return m.im_class if sys.version < '3' else m.__self__.__class__
|
||||
|
||||
|
||||
def safe_as_int(val, atol=1e-3):
|
||||
"""
|
||||
Attempt to safely cast values to integer format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
val : scalar or iterable of scalars
|
||||
Number or container of numbers which are intended to be interpreted as
|
||||
integers, e.g., for indexing purposes, but which may not carry integer
|
||||
type.
|
||||
atol : float
|
||||
Absolute tolerance away from nearest integer to consider values in
|
||||
``val`` functionally integers.
|
||||
|
||||
Returns
|
||||
-------
|
||||
val_int : NumPy scalar or ndarray of dtype `np.int64`
|
||||
Returns the input value(s) coerced to dtype `np.int64` assuming all
|
||||
were within ``atol`` of the nearest integer.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This operation calculates ``val`` modulo 1, which returns the mantissa of
|
||||
all values. Then all mantissas greater than 0.5 are subtracted from one.
|
||||
Finally, the absolute tolerance from zero is calculated. If it is less
|
||||
than ``atol`` for all value(s) in ``val``, they are rounded and returned
|
||||
in an integer array. Or, if ``val`` was a scalar, a NumPy scalar type is
|
||||
returned.
|
||||
|
||||
If any value(s) are outside the specified tolerance, an informative error
|
||||
is raised.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> _safe_as_int(7.0)
|
||||
7
|
||||
|
||||
>>> _safe_as_int([9, 4, 2.9999999999])
|
||||
array([9, 4, 3], dtype=int32)
|
||||
|
||||
>>> _safe_as_int(53.01)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Integer argument required but received 53.1, check inputs.
|
||||
|
||||
>>> _safe_as_int(53.01, atol=0.01)
|
||||
53
|
||||
|
||||
"""
|
||||
mod = np.asarray(val) % 1 # Extract mantissa
|
||||
|
||||
# Check for and subtract any mod values > 0.5 from 1
|
||||
if mod.ndim == 0: # Scalar input, cannot be indexed
|
||||
if mod > 0.5:
|
||||
mod = 1 - mod
|
||||
else: # Iterable input, now ndarray
|
||||
mod[mod > 0.5] = 1 - mod[mod > 0.5] # Test on each side of nearest int
|
||||
|
||||
try:
|
||||
np.testing.assert_allclose(mod, 0, atol=atol)
|
||||
except AssertionError:
|
||||
raise ValueError("Integer argument required but received "
|
||||
"{0}, check inputs.".format(val))
|
||||
|
||||
return np.round(val).astype(np.int64)
|
||||
|
||||
@@ -344,9 +344,9 @@ def regionprops(label_image, intensity_image=None, cache=True):
|
||||
|
||||
Returns
|
||||
-------
|
||||
properties : list
|
||||
List containing a properties for each region. The properties of each
|
||||
region can be accessed as attributes and keys.
|
||||
properties : list of RegionProperties
|
||||
Each item describes one labeled region, and can be accessed using the
|
||||
attributes listed below.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
@@ -154,7 +154,7 @@ class TestWatershed(unittest.TestCase):
|
||||
[-1, -1, 1, 1, 1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1]], out)
|
||||
self.failUnless(error < eps)
|
||||
self.assertTrue(error < eps)
|
||||
|
||||
def test_watershed03(self):
|
||||
"watershed 3"
|
||||
@@ -189,7 +189,7 @@ class TestWatershed(unittest.TestCase):
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1]], out)
|
||||
self.failUnless(error < eps)
|
||||
self.assertTrue(error < eps)
|
||||
|
||||
def test_watershed04(self):
|
||||
"watershed 4"
|
||||
@@ -224,7 +224,7 @@ class TestWatershed(unittest.TestCase):
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1]], out)
|
||||
self.failUnless(error < eps)
|
||||
self.assertTrue(error < eps)
|
||||
|
||||
def test_watershed05(self):
|
||||
"watershed 5"
|
||||
@@ -259,7 +259,7 @@ class TestWatershed(unittest.TestCase):
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1]], out)
|
||||
self.failUnless(error < eps)
|
||||
self.assertTrue(error < eps)
|
||||
|
||||
def test_watershed06(self):
|
||||
"watershed 6"
|
||||
@@ -291,7 +291,7 @@ class TestWatershed(unittest.TestCase):
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1],
|
||||
[-1, -1, -1, -1, -1, -1, -1]], out)
|
||||
self.failUnless(error < eps)
|
||||
self.assertTrue(error < eps)
|
||||
|
||||
def test_watershed07(self):
|
||||
"A regression test of a competitive case that failed"
|
||||
|
||||
@@ -389,7 +389,7 @@ def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True,
|
||||
dims = data[..., 0].shape # To reshape final labeled result
|
||||
data = img_as_float(data)
|
||||
if data.ndim == 3: # 2D multispectral, needs singleton in 3rd axis
|
||||
data = data[:, :, np.newaxis, :].transpose((0, 1, 3, 2))
|
||||
data = data[:, :, np.newaxis, :]
|
||||
|
||||
# Spacing kwarg checks
|
||||
if spacing is None:
|
||||
|
||||
@@ -4,7 +4,7 @@ import warnings
|
||||
import numpy as np
|
||||
from scipy import ndimage, spatial
|
||||
|
||||
from skimage._shared.utils import get_bound_method_class
|
||||
from skimage._shared.utils import get_bound_method_class, safe_as_int
|
||||
from skimage.util import img_as_float
|
||||
from ._warps_cy import _warp_fast
|
||||
from .._shared.utils import safe_as_int
|
||||
@@ -1006,7 +1006,8 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
|
||||
Keyword arguments passed to `inverse_map`.
|
||||
output_shape : tuple (rows, cols), optional
|
||||
Shape of the output image generated. By default the shape of the input
|
||||
image is preserved.
|
||||
image is preserved. Note that, even for multi-band images, only rows
|
||||
and columns need to be specified.
|
||||
order : int, optional
|
||||
The order of interpolation. The order has to be in the range 0-5:
|
||||
* 0: Nearest-neighbor
|
||||
@@ -1077,6 +1078,12 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
|
||||
ishape = np.array(image.shape)
|
||||
bands = ishape[2]
|
||||
|
||||
if output_shape is None:
|
||||
output_shape = ishape
|
||||
else:
|
||||
output_shape = safe_as_int(output_shape)
|
||||
|
||||
|
||||
out = None
|
||||
|
||||
# use fast Cython version for specific interpolation orders and input
|
||||
@@ -1105,17 +1112,13 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
|
||||
dims = []
|
||||
for dim in range(image.shape[2]):
|
||||
dims.append(_warp_fast(image[..., dim], matrix,
|
||||
output_shape=output_shape,
|
||||
order=order, mode=mode, cval=cval))
|
||||
output_shape=output_shape,
|
||||
order=order, mode=mode, cval=cval))
|
||||
out = np.dstack(dims)
|
||||
if orig_ndim == 2:
|
||||
out = out[..., 0]
|
||||
|
||||
if out is None: # use ndimage.map_coordinates
|
||||
|
||||
if output_shape is None:
|
||||
output_shape = ishape
|
||||
|
||||
rows, cols = output_shape[:2]
|
||||
|
||||
# inverse_map is a transformation matrix as numpy array
|
||||
|
||||
@@ -248,5 +248,14 @@ def test_inverse():
|
||||
assert_array_equal(warp(image, inverse_tform), warp(image, tform.inverse))
|
||||
|
||||
|
||||
def test_slow_warp_nonint_oshape():
|
||||
image = np.random.random((5, 5))
|
||||
|
||||
assert_raises(ValueError, warp, image, lambda xy: xy,
|
||||
output_shape=(13.1, 19.5))
|
||||
|
||||
warp(image, lambda xy: xy, output_shape=(13.0001, 19.9999))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
|
||||
@@ -63,9 +63,9 @@ class Plugin(QtGui.QDialog):
|
||||
>>> plugin += Slider('threshold', 0, 255) # doctest: +SKIP
|
||||
>>>
|
||||
>>> image = data.coins()
|
||||
>>> viewer = ImageViewer(image) # doctest: +SKIP
|
||||
>>> viewer += plugin # doctest: +SKIP
|
||||
>>> viewer.show() # doctest: +SKIP
|
||||
>>> viewer = ImageViewer(image) # doctest: +SKIP
|
||||
>>> viewer += plugin # doctest: +SKIP
|
||||
>>> thresholded = viewer.show()[0][0] # doctest: +SKIP
|
||||
|
||||
The plugin will automatically delegate parameters to `image_filter` based
|
||||
on its parameter type, i.e., `ptype` (widgets for required arguments must
|
||||
|
||||
@@ -6,4 +6,4 @@ from skimage.viewer.plugins.canny import CannyPlugin
|
||||
image = data.camera()
|
||||
viewer = ImageViewer(image)
|
||||
viewer += CannyPlugin()
|
||||
viewer.show()
|
||||
canny_edges = viewer.show()[0][0]
|
||||
|
||||
@@ -21,4 +21,4 @@ plugin += SaveButtons(name='Save overlay to:')
|
||||
# Finally, attach the plugin to an image viewer.
|
||||
viewer = ImageViewer(image)
|
||||
viewer += plugin
|
||||
viewer.show()
|
||||
canny_edges = viewer.show()[0][0]
|
||||
|
||||
@@ -6,4 +6,4 @@ from skimage.viewer.plugins.lineprofile import LineProfile
|
||||
image = data.camera()
|
||||
viewer = ImageViewer(image)
|
||||
viewer += LineProfile()
|
||||
viewer.show()
|
||||
line, profile = viewer.show()[0]
|
||||
|
||||
@@ -6,4 +6,4 @@ from skimage.viewer.plugins.lineprofile import LineProfile
|
||||
image = data.chelsea()
|
||||
viewer = ImageViewer(image)
|
||||
viewer += LineProfile()
|
||||
viewer.show()
|
||||
line, rgb_profiles = viewer.show()[0]
|
||||
|
||||
Reference in New Issue
Block a user