Merge pull request #121 from tonysyu/dtype-convert-updates

BUG: Clean up dtype conversion

- Fix casting error in numpy dev.
- Assert that float images are in [0, 1], and fix tests to comply.
- Add tests for full coverage.
- Rename _convert to convert since it is used by other modules,
  such as match_template, to convert to "non-standard" types such as
  float32.
This commit is contained in:
Stefan van der Walt
2012-02-05 09:42:22 -08:00
3 changed files with 51 additions and 7 deletions
+2
View File
@@ -15,6 +15,8 @@ class TestTvDenoise():
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?
+8 -6
View File
@@ -20,7 +20,7 @@ _supported_types = (np.uint8, np.uint16, np.uint32,
np.float16, np.float32, np.float64)
def _convert(image, dtype):
def convert(image, dtype):
"""
Convert an image to the requested data-type.
@@ -63,6 +63,8 @@ def _convert(image, dtype):
"%s to %s" % (dtypeobj_in, dtypeobj))
if kind_in == 'f':
if np.min(image) < 0 or np.max(image) > 1:
raise ValueError("Images of type float must be between 0 and 1")
if kind == 'f':
# floating point -> floating point
if itemsize_in > itemsize:
@@ -120,7 +122,7 @@ def _convert(image, dtype):
# int8 -> uint32
image = dtype(image)
image *= 2**16 + 2**8 + 1
result += image
result += dtype(image)
return result
if kind == 'i':
# signed integer -> signed integer
@@ -165,7 +167,7 @@ def img_as_float(image):
Negative input values will be shifted to the positive domain.
"""
return _convert(image, np.float64)
return convert(image, np.float64)
def img_as_uint(image):
@@ -186,7 +188,7 @@ def img_as_uint(image):
Negative input values will be shifted to the positive domain.
"""
return _convert(image, np.uint16)
return convert(image, np.uint16)
def img_as_int(image):
@@ -208,7 +210,7 @@ def img_as_int(image):
the output image will still only have positive values.
"""
return _convert(image, np.int16)
return convert(image, np.int16)
def img_as_ubyte(image):
@@ -230,4 +232,4 @@ def img_as_ubyte(image):
the output image will still only have positive values.
"""
return _convert(image, np.uint8)
return convert(image, np.uint8)
+41 -1
View File
@@ -1,7 +1,9 @@
import numpy as np
from numpy.testing import assert_equal
from numpy.testing import assert_equal, assert_raises
from skimage import img_as_int, img_as_float, \
img_as_uint, img_as_ubyte
from skimage.util.dtype import convert
dtype_range = {np.uint8: (0, 255),
np.uint16: (0, 65535),
@@ -34,6 +36,44 @@ def test_range():
"From %s to %s" % (np.dtype(dtype), np.dtype(dt)), \
y, omin, omax
def test_range_extra_dtypes():
"""Test code paths that are not skipped by `test_range`"""
# Add non-standard data types that are allowed by the `convert` function.
dtype_range_extra = dtype_range.copy()
dtype_range_extra.update({np.int32: (-2147483648, 2147483647),
np.uint32: (0, 4294967295)})
dtype_pairs = [(np.uint8, np.uint32),
(np.int8, np.uint32),
(np.int8, np.int32),
(np.int32, np.int8),
(np.float64, np.float32),
(np.int32, np.float32)]
for dtype_in, dt in dtype_pairs:
imin, imax = dtype_range_extra[dtype_in]
x = np.linspace(imin, imax, 10).astype(dtype_in)
y = convert(x, dt)
omin, omax = dtype_range_extra[dt]
yield _verify_range, \
"From %s to %s" % (np.dtype(dtype_in), np.dtype(dt)), \
y, omin, omax
def test_unsupported_dtype():
x = np.arange(10).astype(np.uint64)
assert_raises(ValueError, img_as_int, x)
def test_float_out_of_range():
too_high = np.array([2], dtype=np.float32)
assert_raises(ValueError, img_as_int, too_high)
too_low = np.array([-1], dtype=np.float32)
assert_raises(ValueError, img_as_int, too_low)
if __name__ == '__main__':
np.testing.run_module_suite()