diff --git a/src/machinevisiontoolbox/ImageCore.py b/src/machinevisiontoolbox/ImageCore.py index 7d920df4..da9764f8 100644 --- a/src/machinevisiontoolbox/ImageCore.py +++ b/src/machinevisiontoolbox/ImageCore.py @@ -1966,6 +1966,9 @@ def to(self, dtype: Dtype) -> "Image": :param dtype: Numpy data type :type dtype: str or NumPy dtype + + |dtype_aliases| + :return: image :rtype: :class:`Image` @@ -1988,8 +1991,9 @@ def to(self, dtype: Dtype) -> "Image": :seealso: :meth:`astype` :meth:`to_int` :meth:`to_float` """ # convert image to different type, does rescaling - # as just changes type - dtype = np.dtype(dtype) # convert to dtype if it's a string + # as just changes type. array_as() and the constructor both + # resolve dtype (including the short-name aliases) themselves, + # so just pass it through unchanged rather than resolving twice. return self.__class__(self.array_as(dtype), dtype=dtype) def astype(self, dtype: Dtype) -> "Image": @@ -1998,6 +2002,9 @@ def astype(self, dtype: Dtype) -> "Image": :param dtype: Numpy data type :type dtype: str or NumPy dtype + + |dtype_aliases| + :return: image :rtype: :class:`Image` @@ -2018,6 +2025,8 @@ def astype(self, dtype: Dtype) -> "Image": :seealso: :meth:`to` """ + if isinstance(dtype, str): + dtype = DTYPE_ALIASES.get(dtype, dtype) return self.__class__(self._A.astype(dtype), dtype=dtype) # ---- NumPy array access ---- # @@ -2293,7 +2302,9 @@ def array_as(self, dtype: Dtype | None = None) -> np.ndarray: Convert Image to NumPy array of specified type :param dtype: data type of the output array - :type dtype: str or np.dtype + :type dtype: str or np.dtype, optional + + |dtype_aliases| :return: NumPy array with specified type :rtype: ndarray(H,W) or ndarray(H,W,P) @@ -2335,6 +2346,8 @@ def array_as(self, dtype: Dtype | None = None) -> np.ndarray: if dtype is None: return self._A else: + if isinstance(dtype, str): + dtype = DTYPE_ALIASES.get(dtype, dtype) dtype = np.dtype(dtype) # convert to dtype if it's a string if np.issubdtype(dtype, np.integer) or np.issubdtype(dtype, np.bool_): return int_image(self._A, dtype) diff --git a/tests/test_dtype_resolution.py b/tests/test_dtype_resolution.py index 27728076..41497ad2 100644 --- a/tests/test_dtype_resolution.py +++ b/tests/test_dtype_resolution.py @@ -2,8 +2,8 @@ Consolidated dtype-resolution consistency tests. Multiple entry points resolve a user-supplied dtype string into an actual -NumPy dtype: the Image constructor (via _infer_dtype), convert(), and (once -fixed on their own branches) Image.to()/.array_as()/.astype() and the +NumPy dtype: the Image constructor (via _infer_dtype), convert(), Image.to(), +Image.array_as(), Image.astype(), and (once fixed on its own branch) the ImageConstantsMixin factory methods (Zeros, Constant, Random, ...). All of them are supposed to honour the same short-name aliases (DTYPE_ALIASES: 'int'->uint8, 'float'->float32, 'double'->float64, 'half'->float16) plus @@ -56,6 +56,18 @@ def test_convert(self, dtype_in, expected): arr = convert(np.ones((2, 3), dtype=np.uint8), dtype=dtype_in) assert arr.dtype == expected + def test_image_to(self, dtype_in, expected): + im = Image(np.ones((2, 3), dtype=np.uint8)) + assert im.to(dtype_in).dtype == expected + + def test_image_astype(self, dtype_in, expected): + im = Image(np.ones((2, 3), dtype=np.uint8)) + assert im.astype(dtype_in).dtype == expected + + def test_image_array_as(self, dtype_in, expected): + im = Image(np.ones((2, 3), dtype=np.uint8)) + assert im.array_as(dtype_in).dtype == expected + # ImageConstantsMixin factory methods: a *different* bug from the above -- # they build their raw pixel array with the (now alias-resolved)