def create_matrices(_image, nb_channels, random_state_func): alpha_sample = alpha_param.draw_sample(random_state=random_state_func) ia.do_assert(0 <= alpha_sample <= 1.0) direction_sample = direction_param.draw_sample( random_state=random_state_func) deg = int(direction_sample * 360) % 360 rad = np.deg2rad(deg) x = np.cos(rad - 0.5 * np.pi) y = np.sin(rad - 0.5 * np.pi) direction_vector = np.array([x, y]) matrix_effect = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]], dtype=np.float32) for x in [-1, 0, 1]: for y in [-1, 0, 1]: if (x, y) != (0, 0): cell_vector = np.array([x, y]) distance_deg = np.rad2deg( ia.angle_between_vectors(cell_vector, direction_vector)) distance = distance_deg / 180 similarity = (1 - distance)**4 matrix_effect[y + 1, x + 1] = similarity matrix_effect = matrix_effect / np.sum(matrix_effect) matrix_effect = matrix_effect * (-1) matrix_effect[1, 1] = 1 matrix_nochange = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.float32) matrix = ( 1 - alpha_sample) * matrix_nochange + alpha_sample * matrix_effect return [matrix] * nb_channels
def __init__(self, to_colorspace, from_colorspace="RGB", alpha=1.0, name=None, deterministic=False, random_state=None): super(ChangeColorspace, self).__init__(name=name, deterministic=deterministic, random_state=random_state) # TODO somehow merge this with Alpha augmenter? self.alpha = iap.handle_continuous_param(alpha, "alpha", value_range=(0, 1.0), tuple_to_uniform=True, list_to_choice=True) if ia.is_string(to_colorspace): ia.do_assert(to_colorspace in ChangeColorspace.COLORSPACES) self.to_colorspace = iap.Deterministic(to_colorspace) elif ia.is_iterable(to_colorspace): ia.do_assert(all([ia.is_string(colorspace) for colorspace in to_colorspace])) ia.do_assert(all([(colorspace in ChangeColorspace.COLORSPACES) for colorspace in to_colorspace])) self.to_colorspace = iap.Choice(to_colorspace) elif isinstance(to_colorspace, iap.StochasticParameter): self.to_colorspace = to_colorspace else: raise Exception("Expected to_colorspace to be string, list of strings or StochasticParameter, got %s." % ( type(to_colorspace),)) self.from_colorspace = from_colorspace ia.do_assert(self.from_colorspace in ChangeColorspace.COLORSPACES) ia.do_assert(from_colorspace != ChangeColorspace.GRAY) self.eps = 0.001 # epsilon value to check if alpha is close to 1.0 or 0.0
def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): nb_images = len(keypoints_on_images) ia.do_assert(len(self.bboxs) == nb_images) scale_samples, translate_samples, rotate_samples = self._draw_samples( nb_images, random_state) augmented = [] for i, keypoints_on_image in enumerate(keypoints_on_images): bb_width, bb_height = self.bboxs[i] c_x, c_y = self.centers[i] scale = scale_samples[i] rotate = rotate_samples[i] translate = translate_samples[i] if len(translate) == 1: trans_x = trans_y = translate[0] elif len(translate) == 2: trans_x, trans_y = translate else: raise ValueError trans = transform_from_bbox(c_x, c_y, bb_width, bb_height, scale, rotate, trans_x, trans_y) augmented_keypoints = trans_point2d( keypoints_on_image.get_coords_array(), trans) augmented_keypoints = ia.KeypointsOnImage.from_coords_array( augmented_keypoints, shape=(bb_height, bb_width)) augmented.append(augmented_keypoints) return augmented
def _augment_images(self, images, random_state, parents, hooks): nb_images = len(images) ia.do_assert(len(self.bboxs) == nb_images) ia.do_assert(len(self.centers) == nb_images) scale_samples, translate_samples, rotate_samples = self._draw_samples( nb_images, random_state) augmented = [] # Translation is currently not used for i, image in enumerate(images): bbox = self.bboxs[i] bb_width, bb_height = bbox c_x, c_y = self.centers[i] scale = scale_samples[i] rotate = rotate_samples[i] translate = translate_samples[i] if len(translate) == 1: trans_x = trans_y = translate[0] elif len(translate) == 2: trans_x, trans_y = translate else: raise ValueError trans = transform_from_bbox(c_x, c_y, bb_width, bb_height, scale, rotate, trans_x, trans_y) image = transform_and_crop_image(image, trans, bbox) augmented.append(image) return augmented
def __init__(self, matrix=None, name=None, deterministic=False, random_state=None): super(Convolve, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if matrix is None: self.matrix = None self.matrix_type = "None" elif ia.is_np_array(matrix): ia.do_assert( len(matrix.shape) == 2, "Expected convolution matrix to have 2 axis, got %d (shape %s)." % (len(matrix.shape), matrix.shape)) self.matrix = matrix self.matrix_type = "constant" elif isinstance(matrix, types.FunctionType): self.matrix = matrix self.matrix_type = "function" else: raise Exception( "Expected float, int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(matrix), ))
def create_matrices(_image, nb_channels, random_state_func): alpha_sample = alpha_param.draw_sample(random_state=random_state_func) ia.do_assert(0 <= alpha_sample <= 1.0) matrix_nochange = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.float32) matrix_effect = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]], dtype=np.float32) matrix = ( 1 - alpha_sample) * matrix_nochange + alpha_sample * matrix_effect return [matrix] * nb_channels
def array_equal_lists(list1, list2): ia.do_assert(isinstance(list1, list)) ia.do_assert(isinstance(list2, list)) if len(list1) != len(list2): return False for a, b in zip(list1, list2): if not np.array_equal(a, b): return False return True
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 array_equal_lists(list1, list2): ia.do_assert(isinstance(list1, list)) ia.do_assert(isinstance(list2, list)) if len(list1) != len(list2): return False for a, b in zip(list1, list2): if not np.array_equal(a, b): return False return True
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 interpolate_points_by_max_distance(points, max_distance, closed=True): ia.do_assert(max_distance > 0, "max_distance must have value greater than 0, got %.8f" % (max_distance,)) if len(points) <= 1: return points if closed: points = list(points) + [points[0]] points_interp = [] for point_a, point_b in zip(points[:-1], points[1:]): dist = np.sqrt((point_a[0] - point_b[0]) ** 2 + (point_a[1] - point_b[1]) ** 2) nb_steps = int((dist / max_distance) - 1) points_interp.extend([point_a] + interpolate_point_pair(point_a, point_b, nb_steps)) if not closed: points_interp.append(points[-1]) return points_interp
def __init__(self, x1, y1, x2, y2, label=None, confidence=1.0): if x1 > x2: x2, x1 = x1, x2 ia.do_assert(x2 >= x1) if y1 > y2: y2, y1 = y1, y2 ia.do_assert(y2 >= y1) self.x1 = x1 self.y1 = y1 self.x2 = x2 self.y2 = y2 self.label = label self.confidence = confidence
def _augment_images(self, images, random_state, parents, hooks): nb_images = len(images) ia.do_assert(len(self.bboxs) == nb_images) ia.do_assert(len(self.centers) == nb_images) augmented = [] # Translation is currently not used for i, image in enumerate(images): bbox = self.bboxs[i] bb_width, bb_height = bbox c_x, c_y = self.centers[i] trans = transform_from_bbox(c_x, c_y, bb_width, bb_height, 1.0, 0, 0, 0) image = transform_and_crop_image(image, trans, bbox) augmented.append(image) return augmented
def __init__(self, k=1, name=None, deterministic=False, random_state=None): super(AverageBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) # TODO replace this by iap.handle_discrete_kernel_size() self.mode = "single" if ia.is_single_number(k): self.k = iap.Deterministic(int(k)) elif ia.is_iterable(k): ia.do_assert(len(k) == 2) if all([ia.is_single_number(ki) for ki in k]): self.k = iap.DiscreteUniform(int(k[0]), int(k[1])) elif all([isinstance(ki, iap.StochasticParameter) for ki in k]): self.mode = "two" self.k = (k[0], k[1]) else: k_tuple = [None, None] if ia.is_single_number(k[0]): k_tuple[0] = iap.Deterministic(int(k[0])) elif ia.is_iterable(k[0]) and all( [ia.is_single_number(ki) for ki in k[0]]): k_tuple[0] = iap.DiscreteUniform(int(k[0][0]), int(k[0][1])) else: raise Exception( "k[0] expected to be int or tuple of two ints, got %s" % (type(k[0]), )) if ia.is_single_number(k[1]): k_tuple[1] = iap.Deterministic(int(k[1])) elif ia.is_iterable(k[1]) and all( [ia.is_single_number(ki) for ki in k[1]]): k_tuple[1] = iap.DiscreteUniform(int(k[1][0]), int(k[1][1])) else: raise Exception( "k[1] expected to be int or tuple of two ints, got %s" % (type(k[1]), )) self.mode = "two" self.k = k_tuple elif isinstance(k, iap.StochasticParameter): self.k = k else: raise Exception( "Expected int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(k), ))
def _augment_images(self, images, random_state, parents, hooks): # Make sure that all images have 3 channels ia.do_assert(all([image.shape[2] == 3 for image in images]), ("BilateralBlur can currently only be applied to images with 3 channels." + "Got channels: %s") % ([image.shape[2] for image in images],)) nb_images = len(images) rss = ia.derive_random_states(random_state, 3) samples_d = self.d.draw_samples((nb_images,), random_state=rss[0]) samples_sigma_color = self.sigma_color.draw_samples((nb_images,), random_state=rss[1]) samples_sigma_space = self.sigma_space.draw_samples((nb_images,), random_state=rss[2]) gen = enumerate(zip(images, samples_d, samples_sigma_color, samples_sigma_space)) for i, (image, di, sigma_color_i, sigma_space_i) in gen: if di != 1: images[i] = cv2.bilateralFilter(image, di, sigma_color_i, sigma_space_i) return images
def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): nb_images = len(keypoints_on_images) ia.do_assert(len(self.bboxs) == nb_images) augmented = [] for i, keypoints_on_image in enumerate(keypoints_on_images): bb_width, bb_height = self.bboxs[i] c_x, c_y = self.centers[i] trans = transform_from_bbox(c_x, c_y, bb_width, bb_height, 1.0, 0, 0, 0) augmented_keypoints = trans_point2d( keypoints_on_image.get_coords_array(), trans) augmented_keypoints = ia.KeypointsOnImage.from_coords_array( augmented_keypoints, shape=(bb_height, bb_width)) augmented.append(augmented_keypoints) return augmented
def _augment_images(self, images, random_state, parents, hooks): # Make sure that all images have 3 channels ia.do_assert(all([image.shape[2] == 3 for image in images]), ("BilateralBlur can currently only be applied to images with 3 channels." + "Got channels: %s") % ([image.shape[2] for image in images],)) nb_images = len(images) rss = ia.derive_random_states(random_state, 3) samples_d = self.d.draw_samples((nb_images,), random_state=rss[0]) samples_sigma_color = self.sigma_color.draw_samples((nb_images,), random_state=rss[1]) samples_sigma_space = self.sigma_space.draw_samples((nb_images,), random_state=rss[2]) gen = enumerate(zip(images, samples_d, samples_sigma_color, samples_sigma_space)) for i, (image, di, sigma_color_i, sigma_space_i) in gen: if di != 1: images[i] = cv2.bilateralFilter(image, di, sigma_color_i, sigma_space_i) return images
def interpolate_points_by_max_distance(points, max_distance, closed=True): ia.do_assert( max_distance > 0, "max_distance must have value greater than 0, got %.8f" % (max_distance, )) if len(points) <= 1: return points if closed: points = list(points) + [points[0]] points_interp = [] for point_a, point_b in zip(points[:-1], points[1:]): dist = np.sqrt((point_a[0] - point_b[0])**2 + (point_a[1] - point_b[1])**2) nb_steps = int((dist / max_distance) - 1) points_interp.extend( [point_a] + interpolate_point_pair(point_a, point_b, nb_steps)) if not closed: points_interp.append(points[-1]) return points_interp
def create_matrices(image, nb_channels, random_state_func): alpha_sample = alpha_param.draw_sample(random_state=random_state_func) ia.do_assert(0 <= alpha_sample <= 1.0) strength_sample = strength_param.draw_sample( random_state=random_state_func) matrix_nochange = np.array([ [0, 0, 0], [0, 1, 0], [0, 0, 0] ], dtype=np.float32) matrix_effect = np.array([ [-1-strength_sample, 0-strength_sample, 0], [0-strength_sample, 1, 0+strength_sample], [0, 0+strength_sample, 1+strength_sample] ], dtype=np.float32) matrix = ( (1-alpha_sample) * matrix_nochange + alpha_sample * matrix_effect ) return [matrix] * nb_channels
def create_matrices(image, nb_channels, random_state_func): alpha_sample = alpha_param.draw_sample(random_state=random_state_func) ia.do_assert(0 <= alpha_sample <= 1.0) lightness_sample = lightness_param.draw_sample( random_state=random_state_func) matrix_nochange = np.array([ [0, 0, 0], [0, 1, 0], [0, 0, 0] ], dtype=np.float32) matrix_effect = np.array([ [-1, -1, -1], [-1, 8+lightness_sample, -1], [-1, -1, -1] ], dtype=np.float32) matrix = ( (1-alpha_sample) * matrix_nochange + alpha_sample * matrix_effect ) return [matrix] * nb_channels
def __init__(self, to_colorspace, from_colorspace="RGB", alpha=1.0, name=None, deterministic=False, random_state=None): super(ChangeColorspace, self).__init__(name=name, deterministic=deterministic, random_state=random_state) # TODO somehow merge this with Alpha augmenter? self.alpha = iap.handle_continuous_param(alpha, "alpha", value_range=(0, 1.0), tuple_to_uniform=True, list_to_choice=True) if ia.is_string(to_colorspace): ia.do_assert(to_colorspace in ChangeColorspace.COLORSPACES) self.to_colorspace = iap.Deterministic(to_colorspace) elif ia.is_iterable(to_colorspace): ia.do_assert( all([ia.is_string(colorspace) for colorspace in to_colorspace])) ia.do_assert( all([(colorspace in ChangeColorspace.COLORSPACES) for colorspace in to_colorspace])) self.to_colorspace = iap.Choice(to_colorspace) elif isinstance(to_colorspace, iap.StochasticParameter): self.to_colorspace = to_colorspace else: raise Exception( "Expected to_colorspace to be string, list of strings or StochasticParameter, got %s." % (type(to_colorspace), )) self.from_colorspace = from_colorspace ia.do_assert(self.from_colorspace in ChangeColorspace.COLORSPACES) ia.do_assert(from_colorspace != ChangeColorspace.GRAY) self.eps = 0.001 # epsilon value to check if alpha is close to 1.0 or 0.0
def _draw_samples(self, nb_samples, random_state): seed = random_state.randint(0, 10**6, 1)[0] if isinstance(self.scale, tuple): scale_samples = ( self.scale[0].draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 10)), self.scale[1].draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 20)), ) else: scale_samples = self.scale.draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 30)) scale_samples = (scale_samples, scale_samples) if isinstance(self.translate, tuple): translate_samples = ( self.translate[0].draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 40)), self.translate[1].draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 50)), ) else: translate_samples = self.translate.draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 60)) translate_samples = (translate_samples, translate_samples) ia.do_assert(translate_samples[0].dtype in [np.int32, np.int64, np.float32, np.float64]) ia.do_assert(translate_samples[1].dtype in [np.int32, np.int64, np.float32, np.float64]) rotate_samples = self.rotate.draw_samples( (nb_samples, ), random_state=ia.new_random_state(seed + 70)) return scale_samples, translate_samples, rotate_samples
def __init__(self, k=1, name=None, deterministic=False, random_state=None): super(AverageBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) # TODO replace this by iap.handle_discrete_kernel_size() self.mode = "single" if ia.is_single_number(k): self.k = iap.Deterministic(int(k)) elif ia.is_iterable(k): ia.do_assert(len(k) == 2) if all([ia.is_single_number(ki) for ki in k]): self.k = iap.DiscreteUniform(int(k[0]), int(k[1])) elif all([isinstance(ki, iap.StochasticParameter) for ki in k]): self.mode = "two" self.k = (k[0], k[1]) else: k_tuple = [None, None] if ia.is_single_number(k[0]): k_tuple[0] = iap.Deterministic(int(k[0])) elif ia.is_iterable(k[0]) and all([ia.is_single_number(ki) for ki in k[0]]): k_tuple[0] = iap.DiscreteUniform(int(k[0][0]), int(k[0][1])) else: raise Exception("k[0] expected to be int or tuple of two ints, got %s" % (type(k[0]),)) if ia.is_single_number(k[1]): k_tuple[1] = iap.Deterministic(int(k[1])) elif ia.is_iterable(k[1]) and all([ia.is_single_number(ki) for ki in k[1]]): k_tuple[1] = iap.DiscreteUniform(int(k[1][0]), int(k[1][1])) else: raise Exception("k[1] expected to be int or tuple of two ints, got %s" % (type(k[1]),)) self.mode = "two" self.k = k_tuple elif isinstance(k, iap.StochasticParameter): self.k = k else: raise Exception("Expected int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(k),))
def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): result = self.func_keypoints(keypoints_on_images, random_state, parents=parents, hooks=hooks, **self.kwargs) ia.do_assert(isinstance(result, list)) ia.do_assert(all([isinstance(el, ia.KeypointsOnImage) for el in result])) return result
def __init__(self, scale=1.0, translate_percent=None, rotate=0.0, name=None, deterministic=False, random_state=None): """Copied from imgaug/transforms/geometric.py.""" super().__init__(name=name, deterministic=deterministic, random_state=random_state) # scale if isinstance(scale, dict): ia.do_assert("x" in scale or "y" in scale) x = scale.get("x", 1.0) y = scale.get("y", 1.0) self.scale = (iap.handle_continuous_param(x, "scale['x']", value_range=(0 + 1e-4, None), tuple_to_uniform=True, list_to_choice=True), iap.handle_continuous_param(y, "scale['y']", value_range=(0 + 1e-4, None), tuple_to_uniform=True, list_to_choice=True)) else: self.scale = iap.handle_continuous_param(scale, "scale", value_range=(0 + 1e-4, None), tuple_to_uniform=True, list_to_choice=True) # translate by percent if isinstance(translate_percent, dict): ia.do_assert("x" in translate_percent or "y" in translate_percent) x = translate_percent.get("x", 0) y = translate_percent.get("y", 0) self.translate = (iap.handle_continuous_param( x, "translate_percent['x']", value_range=None, tuple_to_uniform=True, list_to_choice=True), iap.handle_continuous_param( y, "translate_percent['y']", value_range=None, tuple_to_uniform=True, list_to_choice=True)) else: self.translate = iap.handle_continuous_param(translate_percent, "translate_percent", value_range=None, tuple_to_uniform=True, list_to_choice=True) self.rotate = iap.handle_continuous_param(rotate, "rotate", value_range=None, tuple_to_uniform=True, list_to_choice=True) self.centers = None self.bboxs = None
def _augment_images(self, images, random_state, parents, hooks): result = images nb_images = len(images) alphas = self.alpha.draw_samples((nb_images,), random_state=ia.copy_random_state(random_state)) to_colorspaces = self.to_colorspace.draw_samples((nb_images,), random_state=ia.copy_random_state(random_state)) for i in sm.xrange(nb_images): alpha = alphas[i] to_colorspace = to_colorspaces[i] image = images[i] ia.do_assert(0.0 <= alpha <= 1.0) ia.do_assert(to_colorspace in ChangeColorspace.COLORSPACES) if alpha == 0 or self.from_colorspace == to_colorspace: pass # no change necessary else: # some colorspaces here should use image/255.0 according to the docs, # but at least for conversion to grayscale that results in errors, # ie uint8 is expected if image.ndim != 3: import warnings warnings.warn( "Received an image with %d dimensions in " "ChangeColorspace._augment_image(), but expected 3 dimensions, i.e. shape " "(height, width, channels)." % (image.ndim,) ) elif image.shape[2] != 3: import warnings warnings.warn( "Received an image with shape (H, W, C) and C=%d in " "ChangeColorspace._augment_image(). Expected C to usually be 3 -- any " "other value will likely result in errors. (Note that this function is " "e.g. called during grayscale conversion and hue/saturation " "changes.)" % (image.shape[2],) ) if self.from_colorspace in [ChangeColorspace.RGB, ChangeColorspace.BGR]: from_to_var_name = "%s2%s" % (self.from_colorspace, to_colorspace) from_to_var = ChangeColorspace.CV_VARS[from_to_var_name] img_to_cs = cv2.cvtColor(image, from_to_var) else: # convert to RGB from_to_var_name = "%s2%s" % (self.from_colorspace, ChangeColorspace.RGB) from_to_var = ChangeColorspace.CV_VARS[from_to_var_name] img_rgb = cv2.cvtColor(image, from_to_var) if to_colorspace == ChangeColorspace.RGB: img_to_cs = img_rgb else: # convert from RGB to desired target colorspace from_to_var_name = "%s2%s" % (ChangeColorspace.RGB, to_colorspace) from_to_var = ChangeColorspace.CV_VARS[from_to_var_name] img_to_cs = cv2.cvtColor(img_rgb, from_to_var) # this will break colorspaces that have values outside 0-255 or 0.0-1.0 # TODO dont convert to uint8 if ia.is_integer_array(img_to_cs): img_to_cs = np.clip(img_to_cs, 0, 255).astype(np.uint8) else: img_to_cs = np.clip(img_to_cs * 255, 0, 255).astype(np.uint8) # for grayscale: covnert from (H, W) to (H, W, 3) if len(img_to_cs.shape) == 2: img_to_cs = img_to_cs[:, :, np.newaxis] img_to_cs = np.tile(img_to_cs, (1, 1, 3)) result[i] = blend.blend_alpha(img_to_cs, image, alpha, self.eps) return images
def _augment_images(self, images, random_state, parents, hooks): input_dtypes = iadt.copy_dtypes_for_restore(images, force_list=True) result = images nb_images = len(images) # surprisingly, placing this here seems to be slightly slower than placing it inside the loop # if isinstance(images_hsv, list): # images_hsv = [img.astype(np.int32) for img in images_hsv] # else: # images_hsv = images_hsv.astype(np.int32) rss = ia.derive_random_states(random_state, 3) images_hsv = self.colorspace_changer._augment_images( images, rss[0], parents + [self], hooks) samples = self.value.draw_samples((nb_images, 2), random_state=rss[1]).astype(np.int32) samples_hue = ((samples.astype(np.float32) / 255.0) * (360 / 2)).astype(np.int32) per_channel = self.per_channel.draw_samples((nb_images, ), random_state=rss[2]) rs_inv = random_state ia.do_assert(-255 <= samples[0, 0] <= 255) # this is needed if no cache for LUT is used: # value_range = np.arange(0, 256, dtype=np.int16) gen = enumerate(zip(images_hsv, samples, samples_hue, per_channel)) for i, (image_hsv, samples_i, samples_hue_i, per_channel_i) in gen: assert image_hsv.dtype.name == "uint8" sample_saturation = samples_i[0] if per_channel_i > 0.5: sample_hue = samples_hue_i[1] else: sample_hue = samples_hue_i[0] if self.backend == "cv2": # this has roughly the same speed as the numpy backend for 64x64 and is about 25% faster for 224x224 # code without using cache: # table_hue = np.mod(value_range + sample_hue, 180) # table_saturation = np.clip(value_range + sample_saturation, 0, 255) # table_hue = table_hue.astype(np.uint8, copy=False) # table_saturation = table_saturation.astype(np.uint8, copy=False) # image_hsv[..., 0] = cv2.LUT(image_hsv[..., 0], table_hue) # image_hsv[..., 1] = cv2.LUT(image_hsv[..., 1], table_saturation) # code with using cache (at best maybe 10% faster for 64x64): image_hsv[..., 0] = cv2.LUT(image_hsv[..., 0], self._LUT_CACHE[0][int(sample_hue)]) image_hsv[..., 1] = cv2.LUT( image_hsv[..., 1], self._LUT_CACHE[1][int(sample_saturation)]) else: image_hsv = image_hsv.astype( np.int16) # int16 seems to be slightly faster than int32 # np.mod() works also as required here for negative values image_hsv[..., 0] = np.mod(image_hsv[..., 0] + sample_hue, 180) image_hsv[..., 1] = np.clip(image_hsv[..., 1] + sample_saturation, 0, 255) image_hsv = image_hsv.astype(input_dtypes[i]) # the inverse colorspace changer has a deterministic output (always <from_colorspace>, so that can # always provide it the same random state as input image_rgb = self.colorspace_changer_inv._augment_images( [image_hsv], rs_inv, parents + [self], hooks)[0] result[i] = image_rgb return result
def map_coordinates(cls, image, dx, dy, order=1, cval=0, mode="constant"): # small debug message to be sure that the right function is executed print("map_coordinates() with cv2") if order == 0 and image.dtype.name in ["uint64", "int64"]: raise Exception(("dtypes uint64 and int64 are only supported in ElasticTransformation for order=0, " + "got order=%d with dtype=%s.") % (order, image.dtype.name)) input_dtype = image.dtype if image.dtype.name == "bool": image = image.astype(np.float32) elif order == 1 and image.dtype.name in ["int8", "int16", "int32"]: image = image.astype(np.float64) elif order >= 2 and image.dtype.name == "int8": image = image.astype(np.int16) elif order >= 2 and image.dtype.name == "int32": image = image.astype(np.float64) shrt_max = 32767 backend = "cv2" if order == 0: bad_dtype_cv2 = (image.dtype.name in ["uint32", "uint64", "int64", "float128", "bool"]) elif order == 1: bad_dtype_cv2 = (image.dtype.name in ["uint32", "uint64", "int8", "int16", "int32", "int64", "float128", "bool"]) else: bad_dtype_cv2 = (image.dtype.name in ["uint32", "uint64", "int8", "int32", "int64", "float128", "bool"]) bad_dx_shape_cv2 = (dx.shape[0] >= shrt_max or dx.shape[1] >= shrt_max) bad_dy_shape_cv2 = (dy.shape[0] >= shrt_max or dy.shape[1] >= shrt_max) if bad_dtype_cv2 or bad_dx_shape_cv2 or bad_dy_shape_cv2: backend = "scipy" ia.do_assert(image.ndim == 3) result = np.copy(image) height, width = image.shape[0:2] # False was added here, only difference to usual code if False or backend == "scipy": h, w = image.shape[0:2] y, x = np.meshgrid(np.arange(h).astype(np.float32), np.arange(w).astype(np.float32), indexing='ij') x_shifted = x + (-1) * dx y_shifted = y + (-1) * dy for c in sm.xrange(image.shape[2]): remapped_flat = ndimage.interpolation.map_coordinates( image[..., c], (x_shifted.flatten(), y_shifted.flatten()), order=order, cval=cval, mode=mode ) remapped = remapped_flat.reshape((height, width)) result[..., c] = remapped else: h, w, nb_channels = image.shape y, x = np.meshgrid(np.arange(h).astype(np.float32), np.arange(w).astype(np.float32), indexing='ij') x_shifted = x + (-1) * dx y_shifted = y + (-1) * dy if image.dtype.kind == "f": cval = float(cval) else: cval = int(cval) border_mode = cls._MAPPING_MODE_SCIPY_CV2[mode] interpolation = cls._MAPPING_ORDER_SCIPY_CV2[order] is_nearest_neighbour = (interpolation == cv2.INTER_NEAREST) map1, map2 = cv2.convertMaps(x_shifted, y_shifted, cv2.CV_16SC2, nninterpolation=is_nearest_neighbour) # remap only supports up to 4 channels if nb_channels <= 4: result = cv2.remap(image, map1, map2, interpolation=interpolation, borderMode=border_mode, borderValue=cval) if image.ndim == 3 and result.ndim == 2: result = result[..., np.newaxis] else: current_chan_idx = 0 result = [] while current_chan_idx < nb_channels: channels = image[..., current_chan_idx:current_chan_idx+4] result_c = cv2.remap(channels, map1, map2, interpolation=interpolation, borderMode=border_mode, borderValue=cval) if result_c.ndim == 2: result_c = result_c[..., np.newaxis] result.append(result_c) current_chan_idx += 4 result = np.concatenate(result, axis=2) if result.dtype.name != input_dtype.name: result = meta.restore_dtypes_(result, input_dtype) return result
def map_coordinates(cls, image, dx, dy, order=1, cval=0, mode="constant"): # small debug message to be sure that the right function is executed print("map_coordinates() with cv2") if order == 0 and image.dtype.name in ["uint64", "int64"]: raise Exception(( "dtypes uint64 and int64 are only supported in ElasticTransformation for order=0, " + "got order=%d with dtype=%s.") % (order, image.dtype.name)) input_dtype = image.dtype if image.dtype.name == "bool": image = image.astype(np.float32) elif order == 1 and image.dtype.name in ["int8", "int16", "int32"]: image = image.astype(np.float64) elif order >= 2 and image.dtype.name == "int8": image = image.astype(np.int16) elif order >= 2 and image.dtype.name == "int32": image = image.astype(np.float64) shrt_max = 32767 backend = "cv2" if order == 0: bad_dtype_cv2 = (image.dtype.name in [ "uint32", "uint64", "int64", "float128", "bool" ]) elif order == 1: bad_dtype_cv2 = (image.dtype.name in [ "uint32", "uint64", "int8", "int16", "int32", "int64", "float128", "bool" ]) else: bad_dtype_cv2 = (image.dtype.name in [ "uint32", "uint64", "int8", "int32", "int64", "float128", "bool" ]) bad_dx_shape_cv2 = (dx.shape[0] >= shrt_max or dx.shape[1] >= shrt_max) bad_dy_shape_cv2 = (dy.shape[0] >= shrt_max or dy.shape[1] >= shrt_max) if bad_dtype_cv2 or bad_dx_shape_cv2 or bad_dy_shape_cv2: backend = "scipy" ia.do_assert(image.ndim == 3) result = np.copy(image) height, width = image.shape[0:2] # False was added here, only difference to usual code if False or backend == "scipy": h, w = image.shape[0:2] y, x = np.meshgrid(np.arange(h).astype(np.float32), np.arange(w).astype(np.float32), indexing='ij') x_shifted = x + (-1) * dx y_shifted = y + (-1) * dy for c in sm.xrange(image.shape[2]): remapped_flat = ndimage.interpolation.map_coordinates( image[..., c], (x_shifted.flatten(), y_shifted.flatten()), order=order, cval=cval, mode=mode) remapped = remapped_flat.reshape((height, width)) result[..., c] = remapped else: h, w, nb_channels = image.shape y, x = np.meshgrid(np.arange(h).astype(np.float32), np.arange(w).astype(np.float32), indexing='ij') x_shifted = x + (-1) * dx y_shifted = y + (-1) * dy if image.dtype.kind == "f": cval = float(cval) else: cval = int(cval) border_mode = cls._MAPPING_MODE_SCIPY_CV2[mode] interpolation = cls._MAPPING_ORDER_SCIPY_CV2[order] is_nearest_neighbour = (interpolation == cv2.INTER_NEAREST) map1, map2 = cv2.convertMaps(x_shifted, y_shifted, cv2.CV_16SC2, nninterpolation=is_nearest_neighbour) # remap only supports up to 4 channels if nb_channels <= 4: result = cv2.remap(image, map1, map2, interpolation=interpolation, borderMode=border_mode, borderValue=cval) if image.ndim == 3 and result.ndim == 2: result = result[..., np.newaxis] else: current_chan_idx = 0 result = [] while current_chan_idx < nb_channels: channels = image[..., current_chan_idx:current_chan_idx + 4] result_c = cv2.remap(channels, map1, map2, interpolation=interpolation, borderMode=border_mode, borderValue=cval) if result_c.ndim == 2: result_c = result_c[..., np.newaxis] result.append(result_c) current_chan_idx += 4 result = np.concatenate(result, axis=2) if result.dtype.name != input_dtype.name: result = meta.restore_dtypes_(result, input_dtype) return result
def _augment_images(self, images, random_state, parents, hooks): result = images nb_images = len(images) alphas = self.alpha.draw_samples( (nb_images, ), random_state=ia.copy_random_state(random_state)) to_colorspaces = self.to_colorspace.draw_samples( (nb_images, ), random_state=ia.copy_random_state(random_state)) for i in sm.xrange(nb_images): alpha = alphas[i] to_colorspace = to_colorspaces[i] image = images[i] ia.do_assert(0.0 <= alpha <= 1.0) ia.do_assert(to_colorspace in ChangeColorspace.COLORSPACES) if alpha == 0 or self.from_colorspace == to_colorspace: pass # no change necessary else: # some colorspaces here should use image/255.0 according to the docs, # but at least for conversion to grayscale that results in errors, # ie uint8 is expected if image.ndim != 3: import warnings warnings.warn( "Received an image with %d dimensions in " "ChangeColorspace._augment_image(), but expected 3 dimensions, i.e. shape " "(height, width, channels)." % (image.ndim, )) elif image.shape[2] != 3: import warnings warnings.warn( "Received an image with shape (H, W, C) and C=%d in " "ChangeColorspace._augment_image(). Expected C to usually be 3 -- any " "other value will likely result in errors. (Note that this function is " "e.g. called during grayscale conversion and hue/saturation " "changes.)" % (image.shape[2], )) if self.from_colorspace in [ ChangeColorspace.RGB, ChangeColorspace.BGR ]: from_to_var_name = "%s2%s" % (self.from_colorspace, to_colorspace) from_to_var = ChangeColorspace.CV_VARS[from_to_var_name] img_to_cs = cv2.cvtColor(image, from_to_var) else: # convert to RGB from_to_var_name = "%s2%s" % (self.from_colorspace, ChangeColorspace.RGB) from_to_var = ChangeColorspace.CV_VARS[from_to_var_name] img_rgb = cv2.cvtColor(image, from_to_var) if to_colorspace == ChangeColorspace.RGB: img_to_cs = img_rgb else: # convert from RGB to desired target colorspace from_to_var_name = "%s2%s" % (ChangeColorspace.RGB, to_colorspace) from_to_var = ChangeColorspace.CV_VARS[ from_to_var_name] img_to_cs = cv2.cvtColor(img_rgb, from_to_var) # this will break colorspaces that have values outside 0-255 or 0.0-1.0 # TODO dont convert to uint8 if ia.is_integer_array(img_to_cs): img_to_cs = np.clip(img_to_cs, 0, 255).astype(np.uint8) else: img_to_cs = np.clip(img_to_cs * 255, 0, 255).astype(np.uint8) # for grayscale: covnert from (H, W) to (H, W, 3) if len(img_to_cs.shape) == 2: img_to_cs = img_to_cs[:, :, np.newaxis] img_to_cs = np.tile(img_to_cs, (1, 1, 3)) result[i] = blend.blend_alpha(img_to_cs, image, alpha, self.eps) return images
def _augment_images(self, images, random_state, parents, hooks): input_dtypes = iadt.copy_dtypes_for_restore(images, force_list=True) result = images nb_images = len(images) # surprisingly, placing this here seems to be slightly slower than placing it inside the loop # if isinstance(images_hsv, list): # images_hsv = [img.astype(np.int32) for img in images_hsv] # else: # images_hsv = images_hsv.astype(np.int32) rss = ia.derive_random_states(random_state, 3) images_hsv = self.colorspace_changer._augment_images(images, rss[0], parents + [self], hooks) samples = self.value.draw_samples((nb_images, 2), random_state=rss[1]).astype(np.int32) samples_hue = ((samples.astype(np.float32) / 255.0) * (360/2)).astype(np.int32) per_channel = self.per_channel.draw_samples((nb_images,), random_state=rss[2]) rs_inv = random_state ia.do_assert(-255 <= samples[0, 0] <= 255) # this is needed if no cache for LUT is used: # value_range = np.arange(0, 256, dtype=np.int16) gen = enumerate(zip(images_hsv, samples, samples_hue, per_channel)) for i, (image_hsv, samples_i, samples_hue_i, per_channel_i) in gen: assert image_hsv.dtype.name == "uint8" sample_saturation = samples_i[0] if per_channel_i > 0.5: sample_hue = samples_hue_i[1] else: sample_hue = samples_hue_i[0] if self.backend == "cv2": # this has roughly the same speed as the numpy backend for 64x64 and is about 25% faster for 224x224 # code without using cache: # table_hue = np.mod(value_range + sample_hue, 180) # table_saturation = np.clip(value_range + sample_saturation, 0, 255) # table_hue = table_hue.astype(np.uint8, copy=False) # table_saturation = table_saturation.astype(np.uint8, copy=False) # image_hsv[..., 0] = cv2.LUT(image_hsv[..., 0], table_hue) # image_hsv[..., 1] = cv2.LUT(image_hsv[..., 1], table_saturation) # code with using cache (at best maybe 10% faster for 64x64): image_hsv[..., 0] = cv2.LUT(image_hsv[..., 0], self._LUT_CACHE[0][int(sample_hue)]) image_hsv[..., 1] = cv2.LUT(image_hsv[..., 1], self._LUT_CACHE[1][int(sample_saturation)]) else: image_hsv = image_hsv.astype(np.int16) # int16 seems to be slightly faster than int32 # np.mod() works also as required here for negative values image_hsv[..., 0] = np.mod(image_hsv[..., 0] + sample_hue, 180) image_hsv[..., 1] = np.clip(image_hsv[..., 1] + sample_saturation, 0, 255) image_hsv = image_hsv.astype(input_dtypes[i]) # the inverse colorspace changer has a deterministic output (always <from_colorspace>, so that can # always provide it the same random state as input image_rgb = self.colorspace_changer_inv._augment_images([image_hsv], rs_inv, parents + [self], hooks)[0] result[i] = image_rgb return result
def _augment_images(self, images, random_state, parents, hooks): iadt.gate_dtypes(images, allowed=["bool", "uint8", "uint16", "int8", "int16", "float16", "float32", "float64"], disallowed=["uint32", "uint64", "uint128", "uint256", "int32", "int64", "int128", "int256", "float96", "float128", "float256"], augmenter=self) rss = ia.derive_random_states(random_state, len(images)) for i, image in enumerate(images): _height, _width, nb_channels = images[i].shape input_dtype = image.dtype if image.dtype.type in [np.bool_, np.float16]: image = image.astype(np.float32, copy=False) elif image.dtype.type == np.int8: image = image.astype(np.int16, copy=False) if self.matrix_type == "None": matrices = [None] * nb_channels elif self.matrix_type == "constant": matrices = [self.matrix] * nb_channels elif self.matrix_type == "function": matrices = self.matrix(images[i], nb_channels, rss[i]) if ia.is_np_array(matrices) and matrices.ndim == 2: matrices = np.tile( matrices[..., np.newaxis], (1, 1, nb_channels)) is_valid_list = (isinstance(matrices, list) and len(matrices) == nb_channels) is_valid_array = (ia.is_np_array(matrices) and matrices.ndim == 3 and matrices.shape[2] == nb_channels) ia.do_assert( is_valid_list or is_valid_array, "Callable provided to Convole must return either a " "list of 2D matrices (one per image channel) " "or a 2D numpy array " "or a 3D numpy array where the last dimension's size " "matches the number of image channels. " "Got type %s." % (type(matrices),) ) if ia.is_np_array(matrices): # Shape of matrices is currently (H, W, C), but in the # loop below we need the first axis to be the channel # index to unify handling of lists of arrays and arrays. # So we move the channel axis here to the start. matrices = matrices.transpose((2, 0, 1)) else: raise Exception("Invalid matrix type") image_aug = image for channel in sm.xrange(nb_channels): if matrices[channel] is not None: # ndimage.convolve caused problems here cv2.filter2D() # always returns same output dtype as input dtype image_aug[..., channel] = cv2.filter2D( image_aug[..., channel], -1, matrices[channel] ) if input_dtype == np.bool_: image_aug = image_aug > 0.5 elif input_dtype in [np.int8, np.float16]: image_aug = iadt.restore_dtypes_(image_aug, input_dtype) images[i] = image_aug return images