def increase_itemsize_of_dtype(dtype, factor): dtype = normalize_dtype(dtype) assert ia.is_single_integer(factor), ( "Expected 'factor' to be an integer, got type %s instead." % (type(factor), )) # int8 -> int64 = factor 8 # uint8 -> uint64 = factor 8 # float16 -> float128 = factor 8 assert factor in [ 1, 2, 4, 8 ], ("The itemsize may only be increased any of the following factors: " "1, 2, 4 or 8. Got factor %d." % (factor, )) assert dtype.kind != "b", "Cannot increase the itemsize of boolean." dt_high_name = "%s%d" % (dtype.kind, dtype.itemsize * factor) try: dt_high = np.dtype(dt_high_name) return dt_high except TypeError: raise TypeError( "Unable to create a numpy dtype matching the name '%s'. " "This error was caused when trying to find a dtype " "that increases the itemsize of dtype '%s' by a factor of %d." "This error can be avoided by choosing arrays with lower " "resolution dtypes as inputs, e.g. by reducing " "float32 to float16." % (dt_high_name, dtype.name, factor))
def clip_to_dtype_value_range_(array, dtype, validate=True, validate_values=None): dtype = normalize_dtype(dtype) min_value, _, max_value = get_value_range_of_dtype(dtype) if validate: array_val = array if ia.is_single_integer(validate): assert validate >= 1, ( "If 'validate' is an integer, it must have a value >=1, " "got %d instead." % (validate, )) assert validate_values is None, ( "If 'validate' is an integer, 'validate_values' must be " "None. Got type %s instead." % (type(validate_values), )) array_val = array.flat[0:validate] if validate_values is not None: min_value_found, max_value_found = validate_values else: min_value_found = np.min(array_val) max_value_found = np.max(array_val) assert min_value <= min_value_found <= max_value, ( "Minimum value of array is outside of allowed value range (%.4f " "vs %.4f to %.4f)." % (min_value_found, min_value, max_value)) assert min_value <= max_value_found <= max_value, ( "Maximum value of array is outside of allowed value range (%.4f " "vs %.4f to %.4f)." % (max_value_found, min_value, max_value)) return clip_(array, min_value, max_value)
def __init__(self, a, b): StochasticParameter.__init__(self) # for two ints the samples will be from range a <= x <= b assert isinstance(a, (int, StochasticParameter)), "Expected a to be int or StochasticParameter, got %s" % (type(a),) assert isinstance(b, (int, StochasticParameter)), "Expected b to be int or StochasticParameter, got %s" % (type(b),) if ia.is_single_integer(a): self.a = Deterministic(a) else: self.a = a if ia.is_single_integer(b): self.b = Deterministic(b) else: self.b = b
def clip_to_dtype_value_range_(array, dtype, validate=True, validate_values=None): dtype = normalize_dtype(dtype) min_value, _, max_value = get_value_range_of_dtype(dtype) if validate: array_val = array if ia.is_single_integer(validate): assert validate >= 1 assert validate_values is None array_val = array.flat[0:validate] if validate_values is not None: min_value_found, max_value_found = validate_values else: min_value_found = np.min(array_val) max_value_found = np.max(array_val) assert min_value <= min_value_found <= max_value, ( "Minimum value of array is outside of allowed value range (%.4f " "vs %.4f to %.4f)." % (min_value_found, min_value, max_value)) assert min_value <= max_value_found <= max_value, ( "Maximum value of array is outside of allowed value range (%.4f " "vs %.4f to %.4f)." % (max_value_found, min_value, max_value)) return clip_(array, min_value, max_value)
def __init__(self, a, b): StochasticParameter.__init__(self) # for two ints the samples will be from range a <= x <= b assert isinstance( a, (int, StochasticParameter) ), "Expected a to be int or StochasticParameter, got %s" % (type(a), ) assert isinstance( b, (int, StochasticParameter) ), "Expected b to be int or StochasticParameter, got %s" % (type(b), ) if ia.is_single_integer(a): self.a = Deterministic(a) else: self.a = a if ia.is_single_integer(b): self.b = Deterministic(b) else: self.b = b
def increase_array_resolutions_(arrays, factor): assert ia.is_single_integer(factor) assert factor in [1, 2, 4, 8] if factor == 1: return arrays for i, array in enumerate(arrays): dtype = array.dtype dtype_target = np.dtype("%s%d" % (dtype.kind, dtype.itemsize * factor)) arrays[i] = array.astype(dtype_target, copy=False) return arrays
def __init__(self, k=1, name=None, deterministic=False, random_state=None): super(MedianBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) # TODO replace this by iap.handle_discrete_kernel_size() self.k = iap.handle_discrete_param(k, "k", value_range=(1, None), tuple_to_uniform=True, list_to_choice=True, allow_floats=False) if ia.is_single_integer(k): ia.do_assert(k % 2 != 0, "Expected k to be odd, got %d. Add or subtract 1." % (int(k),)) elif ia.is_iterable(k): ia.do_assert(all([ki % 2 != 0 for ki in k]), "Expected all values in iterable k to be odd, but at least one was not. " + "Add or subtract 1 to/from that value.")
def handle(val): if ia.is_single_integer(val): do_assert(val > 0) return (val, val) elif ia.is_single_float(val): do_assert(val > 0) return (val, val) elif isinstance(val, tuple): do_assert(len(val) == 2) do_assert(val[0] > 0 and val[1] > 0) return val else: raise Exception( "Expected size to be int, float or tuple, got %s." % type(size))
def __init__(self, k=1, seed=None, name=None, **old_kwargs): super(MedianBlur, self).__init__( seed=seed, name=name, **old_kwargs) # TODO replace this by iap.handle_discrete_kernel_size() self.k = iap.handle_discrete_param( k, "k", value_range=(1, None), tuple_to_uniform=True, list_to_choice=True, allow_floats=False) if ia.is_single_integer(k): assert k % 2 != 0, ( "Expected k to be odd, got %d. Add or subtract 1." % ( int(k),)) elif ia.is_iterable(k): assert all([ki % 2 != 0 for ki in k]), ( "Expected all values in iterable k to be odd, but at least " "one was not. Add or subtract 1 to/from that value.")
def __init__(self, size, name=None, deterministic=False, random_state=None): super(FiveCrop, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if ia.is_single_integer(size): self.size = (size, size) elif isinstance(size, (list, tuple)) and len(size) == 2 and isinstance( size[0], (int, long)) and isinstance(size[1], (int, long)): self.size = size else: raise ValueError('Invalid size parameter: %s' % str(size)) self.choice = ia.parameters.DiscreteUniform(0, 4)
def clip_to_dtype_value_range_(array, dtype, validate=True, validate_values=None): # for some reason, using 'out' did not work for uint64 (would clip max value to 0) # but removing out then results in float64 array instead of uint64 assert array.dtype.name not in ["uint64", "uint128"] dtype = np.dtype(dtype) min_value, _, max_value = get_value_range_of_dtype(dtype) if validate: array_val = array if ia.is_single_integer(validate): assert validate_values is None array_val = array.flat[0:validate] if validate_values is not None: min_value_found, max_value_found = validate_values else: min_value_found = np.min(array_val) max_value_found = np.max(array_val) assert min_value <= min_value_found <= max_value assert min_value <= max_value_found <= max_value return clip_(array, min_value, max_value)
def clip_to_dtype_value_range_(array, dtype, validate=True, validate_values=None): # for some reason, using 'out' did not work for uint64 (would clip max value to 0) # but removing out then results in float64 array instead of uint64 assert array.dtype.name not in ["uint64", "uint128"] dtype = np.dtype(dtype) min_value, _, max_value = get_value_range_of_dtype(dtype) if validate: array_val = array if ia.is_single_integer(validate): assert validate_values is None array_val = array.flat[0:validate] if validate_values is not None: min_value_found, max_value_found = validate_values else: min_value_found = np.min(array_val) max_value_found = np.max(array_val) assert min_value <= min_value_found <= max_value assert min_value <= max_value_found <= max_value array = np.clip(array, min_value, max_value, out=array) return array
def blur_gaussian_(image, sigma, ksize=None, backend="auto", eps=1e-3): """Blur an image using gaussian blurring in-place. This operation *may* change the input image in-place. dtype support:: if (backend="auto"):: * ``uint8``: yes; fully tested (1) * ``uint16``: yes; tested (1) * ``uint32``: yes; tested (2) * ``uint64``: yes; tested (2) * ``int8``: yes; tested (1) * ``int16``: yes; tested (1) * ``int32``: yes; tested (1) * ``int64``: yes; tested (2) * ``float16``: yes; tested (1) * ``float32``: yes; tested (1) * ``float64``: yes; tested (1) * ``float128``: no * ``bool``: yes; tested (1) - (1) Handled by ``cv2``. See ``backend="cv2"``. - (2) Handled by ``scipy``. See ``backend="scipy"``. if (backend="cv2"):: * ``uint8``: yes; fully tested * ``uint16``: yes; tested * ``uint32``: no (2) * ``uint64``: no (3) * ``int8``: yes; tested (4) * ``int16``: yes; tested * ``int32``: yes; tested (5) * ``int64``: no (6) * ``float16``: yes; tested (7) * ``float32``: yes; tested * ``float64``: yes; tested * ``float128``: no (8) * ``bool``: yes; tested (1) - (1) Mapped internally to ``float32``. Otherwise causes ``TypeError: src data type = 0 is not supported``. - (2) Causes ``TypeError: src data type = 6 is not supported``. - (3) Causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (4) Mapped internally to ``int16``. Otherwise causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=1), and buffer format (=5) in function 'getLinearRowFilter'``. - (5) Mapped internally to ``float64``. Otherwise causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (6) Causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (7) Mapped internally to ``float32``. Otherwise causes ``TypeError: src data type = 23 is not supported``. - (8) Causes ``TypeError: src data type = 13 is not supported``. if (backend="scipy"):: * ``uint8``: yes; fully tested * ``uint16``: yes; tested * ``uint32``: yes; tested * ``uint64``: yes; tested * ``int8``: yes; tested * ``int16``: yes; tested * ``int32``: yes; tested * ``int64``: yes; tested * ``float16``: yes; tested (1) * ``float32``: yes; tested * ``float64``: yes; tested * ``float128``: no (2) * ``bool``: yes; tested (3) - (1) Mapped internally to ``float32``. Otherwise causes ``RuntimeError: array type dtype('float16') not supported``. - (2) Causes ``RuntimeError: array type dtype('float128') not supported``. - (3) Mapped internally to ``float32``. Otherwise too inaccurate. Parameters ---------- image : numpy.ndarray The image to blur. Expected to be of shape ``(H, W)`` or ``(H, W, C)``. sigma : number Standard deviation of the gaussian blur. Larger numbers result in more large-scale blurring, which is overall slower than small-scale blurring. ksize : None or int, optional Size in height/width of the gaussian kernel. This argument is only understood by the ``cv2`` backend. If it is set to ``None``, an appropriate value for `ksize` will automatically be derived from `sigma`. The value is chosen tighter for larger sigmas to avoid as much as possible very large kernel sizes and therey improve performance. backend : {'auto', 'cv2', 'scipy'}, optional Backend library to use. If ``auto``, then the likely best library will be automatically picked per image. That is usually equivalent to ``cv2`` (OpenCV) and it will fall back to ``scipy`` for datatypes not supported by OpenCV. eps : number, optional A threshold used to decide whether `sigma` can be considered zero. Returns ------- numpy.ndarray The blurred image. Same shape and dtype as the input. (Input image *might* have been altered in-place.) """ has_zero_sized_axes = (image.size == 0) if sigma > 0 + eps and not has_zero_sized_axes: dtype = image.dtype iadt.gate_dtypes(image, allowed=[ "bool", "uint8", "uint16", "uint32", "int8", "int16", "int32", "int64", "uint64", "float16", "float32", "float64" ], disallowed=[ "uint128", "uint256", "int128", "int256", "float96", "float128", "float256" ], augmenter=None) dts_not_supported_by_cv2 = ["uint32", "uint64", "int64", "float128"] backend_to_use = backend if backend == "auto": backend_to_use = ("cv2" if image.dtype.name not in dts_not_supported_by_cv2 else "scipy") elif backend == "cv2": assert image.dtype.name not in dts_not_supported_by_cv2, ( "Requested 'cv2' backend, but provided %s input image, which " "cannot be handled by that backend. Choose a different " "backend or set backend to 'auto' or use a different " "datatype." % (image.dtype.name, )) elif backend == "scipy": # can handle all dtypes that were allowed in gate_dtypes() pass if backend_to_use == "scipy": if dtype.name == "bool": # We convert bool to float32 here, because gaussian_filter() # seems to only return True when the underlying value is # approximately 1.0, not when it is above 0.5. So we do that # here manually. cv2 does not support bool for gaussian blur. image = image.astype(np.float32, copy=False) elif dtype.name == "float16": image = image.astype(np.float32, copy=False) # gaussian_filter() has no ksize argument # TODO it does have a truncate argument that truncates at x # standard deviations -- maybe can be used similarly to ksize if ksize is not None: ia.warn( "Requested 'scipy' backend or picked it automatically by " "backend='auto' n blur_gaussian_(), but also provided " "'ksize' argument, which is not understood by that " "backend and will be ignored.") # Note that while gaussian_filter can be applied to all channels # at the same time, that should not be done here, because then # the blurring would also happen across channels (e.g. red values # might be mixed with blue values in RGB) if image.ndim == 2: image[:, :] = ndimage.gaussian_filter(image[:, :], sigma, mode="mirror") else: nb_channels = image.shape[2] for channel in sm.xrange(nb_channels): image[:, :, channel] = ndimage.gaussian_filter(image[:, :, channel], sigma, mode="mirror") else: if dtype.name == "bool": image = image.astype(np.float32, copy=False) elif dtype.name == "float16": image = image.astype(np.float32, copy=False) elif dtype.name == "int8": image = image.astype(np.int16, copy=False) elif dtype.name == "int32": image = image.astype(np.float64, copy=False) # ksize here is derived from the equation to compute sigma based # on ksize, see # https://docs.opencv.org/3.1.0/d4/d86/group__imgproc__filter.html # -> cv::getGaussianKernel() # example values: # sig = 0.1 -> ksize = -1.666 # sig = 0.5 -> ksize = 0.9999 # sig = 1.0 -> ksize = 1.0 # sig = 2.0 -> ksize = 11.0 # sig = 3.0 -> ksize = 17.666 # ksize = ((sig - 0.8)/0.3 + 1)/0.5 + 1 if ksize is None: ksize = _compute_gaussian_blur_ksize(sigma) else: assert ia.is_single_integer(ksize), ( "Expected 'ksize' argument to be a number, " "got %s." % (type(ksize), )) ksize = ksize + 1 if ksize % 2 == 0 else ksize if ksize > 0: image_warped = cv2.GaussianBlur( _normalize_cv2_input_arr_(image), (ksize, ksize), sigmaX=sigma, sigmaY=sigma, borderType=cv2.BORDER_REFLECT_101) # re-add channel axis removed by cv2 if input was (H, W, 1) image = (image_warped[..., np.newaxis] if image.ndim == 3 and image_warped.ndim == 2 else image_warped) if dtype.name == "bool": image = image > 0.5 elif dtype.name != image.dtype.name: image = iadt.restore_dtypes_(image, dtype) return image
def blur_gaussian_(image, sigma, ksize=None, backend="auto", eps=1e-3): """ Blur an image using gaussian blurring. This operation might change the input image in-place. dtype support:: if (backend="auto"):: * ``uint8``: yes; fully tested (1) * ``uint16``: yes; tested (1) * ``uint32``: yes; tested (2) * ``uint64``: yes; tested (2) * ``int8``: yes; tested (1) * ``int16``: yes; tested (1) * ``int32``: yes; tested (1) * ``int64``: yes; tested (2) * ``float16``: yes; tested (1) * ``float32``: yes; tested (1) * ``float64``: yes; tested (1) * ``float128``: no * ``bool``: yes; tested (1) - (1) Handled by ``cv2``. See ``backend="cv2"``. - (2) Handled by ``scipy``. See ``backend="scipy"``. if (backend="cv2"):: * ``uint8``: yes; fully tested * ``uint16``: yes; tested * ``uint32``: no (2) * ``uint64``: no (3) * ``int8``: yes; tested (4) * ``int16``: yes; tested * ``int32``: yes; tested (5) * ``int64``: no (6) * ``float16``: yes; tested (7) * ``float32``: yes; tested * ``float64``: yes; tested * ``float128``: no (8) * ``bool``: yes; tested (1) - (1) Mapped internally to ``float32``. Otherwise causes ``TypeError: src data type = 0 is not supported``. - (2) Causes ``TypeError: src data type = 6 is not supported``. - (3) Causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (4) Mapped internally to ``int16``. Otherwise causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=1), and buffer format (=5) in function 'getLinearRowFilter'``. - (5) Mapped internally to ``float64``. Otherwise causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (6) Causes ``cv2.error: OpenCV(3.4.5) (...)/filter.cpp:2957: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=4), and buffer format (=5) in function 'getLinearRowFilter'``. - (7) Mapped internally to ``float32``. Otherwise causes ``TypeError: src data type = 23 is not supported``. - (8) Causes ``TypeError: src data type = 13 is not supported``. if (backend="scipy"):: * ``uint8``: yes; fully tested * ``uint16``: yes; tested * ``uint32``: yes; tested * ``uint64``: yes; tested * ``int8``: yes; tested * ``int16``: yes; tested * ``int32``: yes; tested * ``int64``: yes; tested * ``float16``: yes; tested (1) * ``float32``: yes; tested * ``float64``: yes; tested * ``float128``: no (2) * ``bool``: yes; tested (3) - (1) Mapped internally to ``float32``. Otherwise causes ``RuntimeError: array type dtype('float16') not supported``. - (2) Causes ``RuntimeError: array type dtype('float128') not supported``. - (3) Mapped internally to ``float32``. Otherwise too inaccurate. Parameters ---------- image : numpy.ndarray The image to blur. Expected to be of shape ``(H, W)`` or ``(H, W, C)``. sigma : number Standard deviation of the gaussian blur. Larger numbers result in more large-scale blurring, which is overall slower than small-scale blurring. ksize : None or int, optional Size in height/width of the gaussian kernel. This argument is only understood by the ``cv2`` backend. If it is set to None, an appropriate value for `ksize` will automatically be derived from `sigma`. The value is chosen tighter for larger sigmas to avoid as much as possible very large kernel sizes and therey improve performance. backend : {'auto', 'cv2', 'scipy'}, optional Backend library to use. If ``auto``, then the likely best library will be automatically picked per image. That is usually equivalent to ``cv2`` (OpenCV) and it will fall back to ``scipy`` for datatypes not supported by OpenCV. eps : number, optional A threshold used to decide whether `sigma` can be considered zero. Returns ------- image : numpy.ndarray The blurred image. Same shape and dtype as the input. """ if sigma > 0 + eps: dtype = image.dtype iadt.gate_dtypes(image, allowed=["bool", "uint8", "uint16", "uint32", "int8", "int16", "int32", "int64", "uint64", "float16", "float32", "float64"], disallowed=["uint128", "uint256", "int128", "int256", "float96", "float128", "float256"], augmenter=None) dts_not_supported_by_cv2 = ["uint32", "uint64", "int64", "float128"] backend_to_use = backend if backend == "auto": backend_to_use = "cv2" if image.dtype.name not in dts_not_supported_by_cv2 else "scipy" elif backend == "cv2": assert image.dtype.name not in dts_not_supported_by_cv2,\ ("Requested 'cv2' backend, but provided %s input image, which " + "cannot be handled by that backend. Choose a different backend or " + "set backend to 'auto' or use a different datatype.") % (image.dtype.name,) elif backend == "scipy": # can handle all dtypes that were allowed in gate_dtypes() pass if backend_to_use == "scipy": if dtype.name == "bool": # We convert bool to float32 here, because gaussian_filter() seems to only return True when # the underlying value is approximately 1.0, not when it is above 0.5. So we do that here manually. # cv2 does not support bool for gaussian blur image = image.astype(np.float32, copy=False) elif dtype.name == "float16": image = image.astype(np.float32, copy=False) # gaussian_filter() has no ksize argument # TODO it does have a truncate argument that truncates at x standard deviations -- maybe can be used # similarly to ksize if ksize is not None: warnings.warn("Requested 'scipy' backend or picked it automatically by backend='auto' " "in blur_gaussian_(), but also provided 'ksize' argument, which is not understood by " "that backend and will be ignored.") # Note that while gaussian_filter can be applied to all channels at the same time, that should not # be done here, because then the blurring would also happen across channels (e.g. red values might # be mixed with blue values in RGB) if image.ndim == 2: image[:, :] = ndimage.gaussian_filter(image[:, :], sigma, mode="mirror") else: nb_channels = image.shape[2] for channel in sm.xrange(nb_channels): image[:, :, channel] = ndimage.gaussian_filter(image[:, :, channel], sigma, mode="mirror") else: if dtype.name == "bool": image = image.astype(np.float32, copy=False) elif dtype.name == "float16": image = image.astype(np.float32, copy=False) elif dtype.name == "int8": image = image.astype(np.int16, copy=False) elif dtype.name == "int32": image = image.astype(np.float64, copy=False) # ksize here is derived from the equation to compute sigma based on ksize, # see https://docs.opencv.org/3.1.0/d4/d86/group__imgproc__filter.html -> cv::getGaussianKernel() # example values: # sig = 0.1 -> ksize = -1.666 # sig = 0.5 -> ksize = 0.9999 # sig = 1.0 -> ksize = 1.0 # sig = 2.0 -> ksize = 11.0 # sig = 3.0 -> ksize = 17.666 # ksize = ((sig - 0.8)/0.3 + 1)/0.5 + 1 if ksize is None: if sigma < 3.0: ksize = 3.3 * sigma # 99% of weight elif sigma < 5.0: ksize = 2.9 * sigma # 97% of weight else: ksize = 2.6 * sigma # 95% of weight # we use 5x5 here as the minimum size as that simplifies comparisons with gaussian_filter() in the tests # TODO reduce this to 3x3 ksize = int(max(ksize, 5)) else: assert ia.is_single_integer(ksize), "Expected 'ksize' argument to be a number, got %s." % (type(ksize),) ksize = ksize + 1 if ksize % 2 == 0 else ksize if ksize > 0: image_warped = cv2.GaussianBlur(image, (ksize, ksize), sigmaX=sigma, sigmaY=sigma, borderType=cv2.BORDER_REFLECT_101) # re-add channel axis removed by cv2 if input was (H, W, 1) image = image_warped[..., np.newaxis] if image.ndim == 3 and image_warped.ndim == 2 else image_warped if dtype.name == "bool": image = image > 0.5 elif dtype.name != image.dtype.name: image = iadt.restore_dtypes_(image, dtype) return image