_invert.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import numpy as np
  2. from .dtype import dtype_limits
  3. def invert(image, signed_float=False):
  4. """Invert an image.
  5. Invert the intensity range of the input image, so that the dtype maximum
  6. is now the dtype minimum, and vice-versa. This operation is
  7. slightly different depending on the input dtype:
  8. - unsigned integers: subtract the image from the dtype maximum
  9. - signed integers: subtract the image from -1 (see Notes)
  10. - floats: subtract the image from 1 (if signed_float is False, so we
  11. assume the image is unsigned), or from 0 (if signed_float is True).
  12. See the examples for clarification.
  13. Parameters
  14. ----------
  15. image : ndarray
  16. Input image.
  17. signed_float : bool, optional
  18. If True and the image is of type float, the range is assumed to
  19. be [-1, 1]. If False and the image is of type float, the range is
  20. assumed to be [0, 1].
  21. Returns
  22. -------
  23. inverted : ndarray
  24. Inverted image.
  25. Notes
  26. -----
  27. Ideally, for signed integers we would simply multiply by -1. However,
  28. signed integer ranges are asymmetric. For example, for np.int8, the range
  29. of possible values is [-128, 127], so that -128 * -1 equals -128! By
  30. subtracting from -1, we correctly map the maximum dtype value to the
  31. minimum.
  32. Examples
  33. --------
  34. >>> img = np.array([[100, 0, 200],
  35. ... [ 0, 50, 0],
  36. ... [ 30, 0, 255]], np.uint8)
  37. >>> invert(img)
  38. array([[155, 255, 55],
  39. [255, 205, 255],
  40. [225, 255, 0]], dtype=uint8)
  41. >>> img2 = np.array([[ -2, 0, -128],
  42. ... [127, 0, 5]], np.int8)
  43. >>> invert(img2)
  44. array([[ 1, -1, 127],
  45. [-128, -1, -6]], dtype=int8)
  46. >>> img3 = np.array([[ 0., 1., 0.5, 0.75]])
  47. >>> invert(img3)
  48. array([[1. , 0. , 0.5 , 0.25]])
  49. >>> img4 = np.array([[ 0., 1., -1., -0.25]])
  50. >>> invert(img4, signed_float=True)
  51. array([[-0. , -1. , 1. , 0.25]])
  52. """
  53. if image.dtype == 'bool':
  54. inverted = ~image
  55. elif np.issubdtype(image.dtype, np.unsignedinteger):
  56. max_val = dtype_limits(image, clip_negative=False)[1]
  57. inverted = np.subtract(max_val, image, dtype=image.dtype)
  58. elif np.issubdtype(image.dtype, np.signedinteger):
  59. inverted = np.subtract(-1, image, dtype=image.dtype)
  60. else: # float dtype
  61. if signed_float:
  62. inverted = -image
  63. else:
  64. inverted = np.subtract(1, image, dtype=image.dtype)
  65. return inverted