def reseed(self, random_state=None, deterministic_too=False): """Reseed this augmentor and all of its children(if it has any). This function is useful, when augmentatons are run in the background. Parameters: random_state: None or it or np.random.RandState, optional A RandomState that is used to sample seeds per augmentor. If int, the parameter will be used as a seed for a new RandomState. If None, a new RandomState will automatically be creatd. deterministic_too: bool, optional Whether to also change the seed of an augmentor 'A', if 'A' is deterministic. This is the case both when this augmentor object is 'A' or one of its children is 'A'. """ eu.do_assert(isinstance(deterministic_too, bool)) if random_state is None: random_state = eu.current_random_state() elif isinstance(random_state, np.random.RandomState): pass else: random_state = eu.new_random_state(random_state) if not self.deterministic or deterministic_too: seed = random_state.randint(0, 10**6, 1)[0] self.random_state = eu.new_random_state(seed) for lst in self.get_children_lists(): for aug in lst: aug.reseed(random_state=random_state, deterministic_too=deterministic_too)
def __init__(self, batch_loader, augseq, queue_size=50, nb_workers="auto"): eu.do_assert(queue_size > 0) self.augseq = augseq self.source_finished_signals = batch_loader.finished_signals self.queue_source = batch_loader.queue self.queue_result = multiprocessing.Queue(queue_size) if nb_workers == "auto": try: nb_workers = multiprocessing.cpu_count() except (ImportError, NotImplemented): nb_workers = 1 nb_workers = max(1, nb_workers - 1) else: eu.do_assert(nb_workers >= 1) print("Starting {} background processes ...".format(nb_workers)) self.nb_workers = nb_workers self.workers = [] self.nb_workers_finished = 0 self.augment_images = True self.augment_keypoints = True seeds = eu.current_random_state().randint(0, 10**6, size=(nb_workers, )) for i in range(nb_workers): worker = multiprocessing.Process( target=self._augment_images_worker, args=(augseq, self.queue_source, self.queue_result, self.source_finished_signals, seeds[i])) worker.daemon = True worker.start() self.workers.append(worker)
def __init__(self, sigma=0, name=None, deterministic=False, random_state=None): super(GaussianBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if eu.is_single_number(sigma): self.sigma = Deterministic(sigma) elif eu.is_iterable(sigma): eu.do_assert( len(sigma) == 2, "Expected tuple/list with 2 entries, got %d entries." % (len(sigma), )) self.sigma = Uniform(sigma[0], sigma[1]) elif isinstance(sigma, StochasticParameter): self.sigma = sigma else: raise Exception( "Expected float, int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(sigma), )) self.eps = 0.001 # epsilon value to estimate whether sigma is above 0
def _draw_samples(self, size, random_state): p = self.p.draw_sample(random_state=random_state) eu.do_assert( 0 <= p <= 1.0, "Expected probability p to be in range [0.0, 1.0], got %s." % (p, )) return random_state.binomial(1, p, size)
def __init__(self, load_batch_func, queue_size=50, nb_workers=1, threaded=True): eu.do_assert(queue_size > 0) eu.do_assert(nb_workers >= 1) self.queue = multiprocessing.Queue(queue_size) self.join_signal = multiprocessing.Event() self.finished_signals = [] self.workers = [] self.threaded = threaded seeds = eu.current_random_state().randint(0, 10**6, size=(nb_workers, )) for i in range(nb_workers): finished_signal = multiprocessing.Event() self.finished_signals.append(finished_signal) if threaded: worker = threading.Thread(target=self._load_batches, args=(load_batch_func, self.queue, finished_signal, self.join_signal, None)) else: worker = multiprocessing.Process( target=self._load_batches, args=(load_batch_func, self.queue, finished_signal, self.join_signal, seeds[i])) worker.daemon = True worker.start() self.workers.append(worker)
def __init__(self, k=1, name=None, deterministic=False, random_state=None): super(MedianBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if eu.is_single_number(k): eu.do_assert( k % 2 != 0, "Expected k to be odd, got %d. Add or subtract 1." % (int(k), )) self.k = Deterministic(int(k)) elif eu.is_iterable(k): eu.do_assert(len(k) == 2) eu.do_assert(all([eu.is_single_number(ki) for ki in k])) eu.do_assert( k[0] % 2 != 0, "Expected k[0] to be odd, got %d. Add or subtract 1." % (int(k[0]), )) eu.do_assert( k[1] % 2 != 0, "Expected k[1] to be odd, got %d. Add or subtract 1." % (int(k[1]), )) self.k = DiscreteUniform(int(k[0]), int(k[1])) elif isinstance(k, 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): input_dtypes = eu.copy_dtypes_for_restore(images) result = images nb_images = len(images) seeds = random_state.randint(0, 10**6, (nb_images, )) for i in range(nb_images): image = images[i].astype(np.int32) rs_image = eu.new_random_state(seeds[i]) per_channel = self.per_channel.draw_sample(random_state=rs_image) if per_channel == 1: nb_channels = image.shape[2] samples = self.value.draw_samples((nb_channels, ), random_state=rs_image) for c, sample in enumerate(samples): # TODO make value range more flexible eu.do_assert(-255 <= sample <= 255) image[..., c] += sample else: sample = self.value.draw_sample(random_state=rs_image) # TODO make value range more flexible eu.do_assert(-255 <= sample <= 255) image += sample result[i] = image # TODO make value range more flexible eu.clip_augmented_images_(result, 0, 255) eu.restore_augmented_images_dtypes_(result, input_dtypes) return result
def __init__(self, bounding_boxes, shape): self.bounding_boxes = bounding_boxes if eu.is_np_array(shape): self.shape = shape.shape else: eu.do_assert(isinstance(shape, (tuple, list))) self.shape = tuple(shape)
def union(self, other): """两个BoundinigBox的并的面积""" eu.do_assert(isinstance(other, BoundingBox), message="union@BoundingBox: other type error") return BoundingBox(x1=min(self.x1, other.x1), y1=min(self.y1, other.y1), x2=max(self.x2, other.x2), y2=max(self.y2, other.y2))
def handle_continuous_param(param, name, value_range=None, tuple_to_uniform=True, list_to_choice=True): def check_value_range(v): if value_range is None: return True elif isinstance(value_range, tuple): eu.do_assert(len(value_range) == 2) if value_range[0] is None and value_range[1] is None: return True elif value_range[0] is None: eu.do_assert( v <= value_range[1], "Parameter '%s' is outside " "of the expected value range (x <= %.4f)" % (name, value_range[1])) return True elif value_range[1] is None: eu.do_assert( value_range[0] <= v, "Parameter '%s' is outside " "of the expected value range (%.4f <= x)" % (name, value_range[0])) return True else: eu.do_assert( value_range[0] <= v <= value_range[1], "Parameter '%s' is outside of the expected value range (%.4f <= x <= %.4f)" % (name, value_range[0], value_range[1])) return True elif eu.is_callable(value_range): value_range(v) return True else: raise Exception("Unexpected input for value_range, got %s." % (str(value_range), )) if eu.is_single_number(param): check_value_range(param) return Deterministic(param) elif tuple_to_uniform and isinstance(param, tuple): eu.do_assert(len(param) == 2) check_value_range(param[0]) check_value_range(param[1]) return Uniform(param[0], param[1]) elif list_to_choice and eu.is_iterable(param): for param_i in param: check_value_range(param_i) return Choice(param) elif isinstance(param, StochasticParameter): return param else: raise Exception( "Expected number, tuple of two number, list of number or StochasticParameter for %s, got %s." % ( name, type(param), ))
def _draw_samples(self, size, random_state): loc = self.loc.draw_sample(random_state=random_state) scale = self.scale.draw_sample(random_state=random_state) eu.do_assert( scale >= 0, "Expected scale to be in range [0, inf), got %s." % (scale, )) if scale == 0: return np.tile(loc, size) else: return random_state.normal(loc, scale, size=size)
def augment_image(self, image, hooks=None): """Augment a single image. Parameters: image: (H,W,C) ndarray or (H,W) ndarray The image to augment. Should have dtype uint8 Returns: image: ndarray The corresponding augmented image. """ eu.do_assert(image.ndim in [2, 3], message="Expected image to have shape(H,W,C).") return self.augment_images([image], hooks=hooks)[0]
def intersection(self, other, default=None): """两个BoundingBox的交的面积""" eu.do_assert(isinstance(other, BoundingBox), message="intersection@BoundingBox: other type error") x1_i = max(self.x1, other.x1) y1_i = max(self.y1, other.y1) x2_i = min(self.x2, other.x2) y2_i = min(self.y2, other.y2) if x1_i >= x2_i or y1_i >= y2_i: return default else: return BoundingBox(x1=x1_i, y1=y1_i, x2=x2_i, y2=y2_i)
def check_value_range(v): if value_range is None: return True elif isinstance(value_range, tuple): eu.do_assert(len(value_range) == 2) if value_range[0] is None and value_range[1] is None: return True elif value_range[0] is None: eu.do_assert( v <= value_range[1], "Parameter '%s' is outside of the expected value range (x <= %.4f)" % (name, value_range[1])) return True elif value_range[1] is None: eu.do_assert( value_range[0] <= v, "Parameter '%s' is outside of the expected value range (%.4f <= x)" % (name, value_range[0])) return True else: eu.do_assert( value_range[0] <= v <= value_range[1], "Parameter '%s' is outside of the expected value range (%.4f <= x <= %.4f)" % (name, value_range[0], value_range[1])) return True elif eu.is_callable(value_range): value_range(v) return True else: raise Exception("Unexpected input for value_range, got %s." % (str(value_range), ))
def _load_batches(self, load_batch_func, queue, finished_signal, join_signal, seedval): if seedval is not None: random.seed(seedval) np.random.seed(seedval) eu.seed(seedval) for batch in load_batch_func(): eu.do_assert(isinstance(batch, Batch), message="Expected batch returned by lambda " "function to be of class Batch, got " + str(type(Batch))) queue.put(pickle.dumps(batch, protocol=-1)) if join_signal.is_set(): break finished_signal.set()
def __init__(self, k=1, name=None, deterministic=False, random_state=None): super(AverageBlur, self).__init__(name=name, deterministic=deterministic, random_state=random_state) self.mode = "single" if eu.is_single_number(k): self.k = Deterministic(int(k)) elif eu.is_iterable(k): eu.do_assert(len(k) == 2) if all([eu.is_single_number(ki) for ki in k]): self.k = DiscreteUniform(int(k[0]), int(k[1])) elif all([isinstance(ki, StochasticParameter) for ki in k]): self.mode = "two" self.k = (k[0], k[1]) else: k_tuple = [None, None] if eu.is_single_number(k[0]): k_tuple[0] = Deterministic(int(k[0])) elif eu.is_iterable(k[0]) and all( [eu.is_single_number(ki) for ki in k[0]]): k_tuple[0] = 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 eu.is_single_number(k[1]): k_tuple[1] = Deterministic(int(k[1])) elif eu.is_iterable(k[1]) and all( [eu.is_single_number(ki) for ki in k[1]]): k_tuple[1] = 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, StochasticParameter): self.k = k else: raise Exception( "Expected int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(k), ))
def to_keypoint_image(self, size=1): """ Draws a new black image of shape (H,W,N) in which all keypoint coordinates are set to 255. (H=shape height, W=shape width, N=number of keypoints) This function can be used as a helper when augmenting keypoints with a method that only supports the augmentation of images. Parameters ------- size : int Size of each (squared) point. Returns ------- image : (H,W,N) ndarray Image in which the keypoints are marked. H is the height, defined in KeypointsOnImage.shape[0] (analogous W). N is the number of keypoints. """ eu.do_assert(len(self.keypoints) > 0) height, width = self.shape[:2] image = np.zeros((height, width, len(self.keypoints)), dtype=np.uint8) sizeh = max(0, (size - 1) // 2) for i, kp in enumerate(self.keypoints): y, x = kp.y_int, kp.x_int x1 = np.clip(x - sizeh, 0, width - 1) x2 = np.clip(x + sizeh + 1, 0, width - 1) y1 = np.clip(y - sizeh, 0, height - 1) y2 = np.clip(y + sizeh + 1, 0, height - 1) if x1 < x2 and y1 < y2: image[y1:y2, x1:x2] = 128 if 0 <= y < height and 0 <= x < width: image[y, x, i] = 255 return image
def __init__(self, channels=None, children=None, name=None, deterministic=False, random_state=None): super(WithChannels, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if channels is None: self.channels = None elif eu.is_single_integer(channels): self.channels = [channels] elif eu.is_iterable(channels): eu.do_assert( all([eu.is_single_integer(channel) for channel in channels]), "Expected integers as channels, got %s." % ([type(channel) for channel in channels], )) self.channels = channels else: raise Exception( "Expected None, int or list of ints as channels, got %s." % (type(channels), )) if children is None: self.children = Sequential([], name="%s-then" % (self.name, )) elif eu.is_iterable(children): self.children = Sequential(children, name="%s-then" % (self.name, )) elif isinstance(children, Augmentor): self.children = Sequential([children], name="%s-then" % (self.name, )) else: raise Exception( "Expected None, Augmenter or list/tuple of Augmenter as children, got %s." % (type(children), ))
def __init__(self, loc, scale): super(Normal, self).__init__() if isinstance(loc, StochasticParameter): self.loc = loc elif eu.is_single_number(loc): self.loc = Deterministic(loc) else: raise Exception( "Expected float, int or StochasticParameter as loc, got %s." % (type(loc), )) if isinstance(scale, StochasticParameter): self.scale = scale elif eu.is_single_number(scale): eu.do_assert( scale >= 0, "Expected scale to be in range [0, inf) got %s (type %s)." % (scale, type(scale))) self.scale = Deterministic(scale) else: raise Exception( "Expected float, int or StochasticParameter as scale, got %s." % (type(scale), ))
def __init__(self, other_param, minval=None, maxval=None): super(Clip, self).__init__() eu.do_assert(isinstance(other_param, StochasticParameter)) eu.do_assert(minval is None or eu.is_single_number(minval)) eu.do_assert(maxval is None or eu.is_single_number(maxval)) self.other_param = other_param self.minval = minval self.maxval = maxval
def __init__(self, value=0, per_channel=False, name=None, deterministic=False, random_state=None): super(Add, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if eu.is_single_integer(value): eu.do_assert( -255 <= value <= 255, "Expected value to have range [-255, 255], got value %d." % (value, )) self.value = Deterministic(value) elif eu.is_iterable(value): eu.do_assert( len(value) == 2, "Expected tuple/list with 2 entries, got %d entries." % (len(value), )) self.value = DiscreteUniform(value[0], value[1]) elif isinstance(value, StochasticParameter): self.value = value else: raise Exception( "Expected float or int, tuple/list with 2 entries or StochasticParameter. Got %s." % (type(value), )) if per_channel in [True, False, 0, 1, 0.0, 1.0]: self.per_channel = Deterministic(int(per_channel)) elif eu.is_single_number(per_channel): eu.do_assert( 0 <= per_channel <= 1.0, "Expected bool, or number in range [0, 1.0] for per_channel, got %s." % (type(per_channel), )) self.per_channel = Binomial(per_channel) else: raise Exception( "Expected per_channel to be boolean or number or StochasticParameter" )
def __init__(self, keypoints, shape): self.keypoints = keypoints eu.do_assert(isinstance(shape, (tuple, list))) self.shape = tuple(shape)
def augment_images(self, images, parents=None, hooks=None): """Augment multiple images. Parameters: images: list of image(H,W,C) parents: None or list of Augmentor, optional(default=None) Parent augmentors that have previously beem called before the call to this function. Usually you can leave this parameter as None. It is set automatically for child augmentors. Returns: images_results:ndarray or list, Corresponding augmentor images. """ if self.deterministic: state_orig = self.random_state.get_state() if parents is None: parents = [] if eu.is_np_array(images): input_type = "array" input_added_axis = False eu.do_assert(images.ndim in [3, 4], message="Expected 3d/4d array of form (N, H, W) or (" "N, H, W, C)") images_copy = np.copy(images) if images_copy.ndim == 3 and images_copy.shape[-1] in [1, 3]: warnings.warn( "You provided a numpy array of shape %s as input to augment_images(), " "which was interpreted as (N, H, W). The last dimension however has " "value 1 or 3, which indicates that you provided a single image " "with shape (H, W, C) instead. If that is the case, you should use " "augment_image(image) or augment_images([image]), otherwise " "you will not get the expected augmentations." % (images_copy.shape, )) if images_copy.ndim == 3: images_copy == images_copy[..., np.newaxis] input_added_axis = True elif eu.is_iterable(images): input_type = "list" input_added_axis = [] if len(images) == 0: images_copy = [] else: eu.do_assert(all(image.ndim in [2, 3] for image in images), message="Expected list of images with each image " "having shape(H, W) or (H, W, C)") images_copy = [] input_added_axis = [] for image in images: image_copy = np.copy(image) if image.ndim == 2: image_copy = image_copy[:, :, np.newaxis] input_added_axis.append(True) else: input_added_axis.append(False) images_copy.append(image_copy) else: raise Exception("Expected Images as one numpy array " "or list/tuple of numpy arrays.") if hooks is None: hooks = HooksImages() images_copy = hooks.preprocess(images_copy, augmentor=self, parents=parents) if hooks.is_activated(images_copy, augmentor=self, parents=parents, default=self.activated): if len(images) > 0: images_result = self._augment_images( images=images_copy, random_state=eu.copy_random_state(self.random_state), parents=parents, hooks=hooks) eu.forward_random_state(self.random_state) else: images_result = images_copy else: images_result = images_copy images_result = hooks.postprocess(images_result, augmentor=self, parents=parents) if input_type == "array": if input_added_axis == True: images_result = np.squeeze(images_result, axis=3) if input_type == "list": for i in range(len(images_result)): if input_added_axis[i] == True: images_result[i] = np.squeeze(images_result[i], axis=2) if self.deterministic: self.random_state.set_state(state_orig) return images_result
def augment_keypoints(self, keypoints_on_images, parents=None, hooks=None): """ Augment image keypoints. This is the corresponding function to `augment_images()`, just for keypoints/landmarks (i.e. coordinates on the image). Usually you will want to call `augment_images()` with a list of images, e.g. `augment_images([A, B, C])` and then `augment_keypoints()` with the corresponding list of keypoints on these images, e.g. `augment_keypoints([Ak, Bk, Ck])`, where `Ak` are the keypoints on image `A`. Make sure to first convert the augmenter(s) to deterministic states before augmenting images and their corresponding keypoints, e.g. by >>> seq = iaa.Fliplr(0.5) >>> seq_det = seq.to_deterministic() >>> imgs_aug = seq_det.augment_images([A, B, C]) >>> kps_aug = seq_det.augment_keypoints([Ak, Bk, Ck]) Otherwise, different random values will be sampled for the image and keypoint augmentations, resulting in different augmentations (e.g. images might be rotated by `30deg` and keypoints by `-10deg`). Also make sure to call `to_deterministic()` again for each new batch, otherwise you would augment all batches in the same way. Parameters ---------- keypoints_on_images : list of ia.KeypointsOnImage The keypoints/landmarks to augment. Expected is a list of ia.KeypointsOnImage objects, each containing the keypoints of a single image. parents : None or list of Augmenter, optional(default=None) Parent augmenters that have previously been called before the call to this function. Usually you can leave this parameter as None. It is set automatically for child augmenters. hooks : None or ia.HooksKeypoints, optional(default=None) HooksKeypoints object to dynamically interfere with the augmentation process. Returns ------- keypoints_on_images_result : list of ia.KeypointsOnImage Augmented keypoints. """ if self.deterministic: state_orig = self.random_state.get_state() if parents is None: parents = [] if hooks is None: hooks = HooksKeyPoints() eu.do_assert(eu.is_iterable(keypoints_on_images)) eu.do_assert( all([ isinstance(kps_on_img, KeyPointsOnImage) for kps_on_img in keypoints_on_images ])) kps_on_imgs_copy = [ kps_on_img.deepcopy() for kps_on_img in keypoints_on_images ] kps_on_imgs_copy = hooks.preprocess(kps_on_imgs_copy, augmentor=self, parents=parents) if hooks.is_activated(kps_on_imgs_copy, augmentor=self, parents=parents, default=self.activated): if len(kps_on_imgs_copy) > 0: kps_on_imgs_result = self._augment_keypoints( kps_on_imgs_copy, random_state=eu.copy_random_state(self.random_state), parents=parents, hooks=hooks) eu.forward_random_state(self.random_state) else: kps_on_imgs_result = kps_on_imgs_copy else: kps_on_imgs_result = kps_on_imgs_copy kps_on_imgs_result = hooks.postprocess(kps_on_imgs_result, augmentor=self, parents=parents) if self.deterministic: self.random_state.set_state(state_orig) return kps_on_imgs_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=eu.copy_random_state(random_state)) to_colorspaces = self.to_colorspace.draw_samples( (nb_images, ), random_state=eu.copy_random_state(random_state)) for i in range(nb_images): alpha = alphas[i] to_colorspace = to_colorspaces[i] image = images[i] eu.do_assert(0.0 <= alpha <= 1.0) eu.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 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 if eu.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)) if alpha >= (1 - self.eps): result[i] = img_to_cs elif alpha <= self.eps: result[i] = image else: result[i] = (alpha * img_to_cs + (1 - alpha) * image).astype(np.uint8) return images
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) if eu.is_single_number(alpha): self.alpha = Deterministic(alpha) elif eu.is_iterable(alpha): eu.do_assert( len(alpha) == 2, "Expected tuple/list with 2 entries, got %d entries." % (len(alpha), )) self.alpha = Uniform(alpha[0], alpha[1]) elif isinstance(alpha, StochasticParameter): self.alpha = alpha else: raise Exception( "Expected alpha to be int or float or tuple/list of ints/floats or StochasticParameter, got %s." % (type(alpha), )) if eu.is_string(to_colorspace): eu.do_assert(to_colorspace in ChangeColorspace.COLORSPACES) self.to_colorspace = Deterministic(to_colorspace) elif eu.is_iterable(to_colorspace): eu.do_assert( all([eu.is_string(colorspace) for colorspace in to_colorspace])) eu.do_assert( all([(colorspace in ChangeColorspace.COLORSPACES) for colorspace in to_colorspace])) self.to_colorspace = Choice(to_colorspace) elif isinstance(to_colorspace, 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 eu.do_assert(self.from_colorspace in ChangeColorspace.COLORSPACES) eu.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 to_deterministic(self, n=None): eu.do_assert(n is None or n >= 1) if n is None: return self.to_deterministic(1)[0] else: return [self._to_deterministic() for _ in range(n)]
def augment_batches(self, batches, hooks=None, background=False): """ Augment multiple batches of images. Parameters ---------- batches : list List of image batches to augment. The expected input is a list, with each entry having one of the following datatypes: * ia.Batch * [] * list of ia.KeypointsOnImage * list of (H,W,C) ndarray * list of (H,W) ndarray * (N,H,W,C) ndarray * (N,H,W) ndarray where N = number of images, H = height, W = width, C = number of channels. Each image is recommended to have dtype uint8 (range 0-255). Yields ------- augmented_batch : ia.Batch or list of ia.KeypointsOnImage or list of (H,W,C) ndarray or list of (H,W) ndarray or (N,H,W,C) ndarray or (N,H,W) ndarray Augmented images/keypoints. Datatype usually matches the input datatypes per list element. """ eu.do_assert(isinstance(batches, list)) eu.do_assert(len(batches) > 0) if background: eu.do_assert(hooks is None, message="Hooks can not be used when background " "augmentation is activated.") batches_normalized = [] batches_original_dts = [] for i, batch in enumerate(batches): if isinstance(batch, Batch): batch.data = (i, batch.data) batches_normalized.append(batch) batches_original_dts.append(BatchStatus.IMG_AUG_BATCH) elif eu.is_np_array(batch): eu.do_assert(batch.ndim in (3, 4), message="Expected numpy array to have shape(N,H," "W) or (N,H,W,C)") batches_normalized.append(Batch(images=batch, data=i)) batches_original_dts.append(BatchStatus.NP_ARRAY) elif isinstance(batch, list): if len(batch) == 0: batches_normalized.append(Batch()) batches_original_dts.append(BatchStatus.EMPTY_LIST) elif eu.is_np_array(batch[0]): batches_normalized.append(Batch(images=batch, data=i)) batches_original_dts.append(BatchStatus.NP_ARRAYS) elif isinstance(batch[0], KeyPointsOnImage): batches_normalized.append(Batch(keypoints=batch, data=i)) batches_original_dts.append(BatchStatus.KPS_ON_IMAGE) else: raise Exception( "Unknown datatype in batch[0]. " "Expected numpy array or imgaug.KeypointsOnImage") else: raise Exception( "Unknown datatype in of batch. Expected imgaug." "Batch or numpy array or list of numpy arrays/imgaug.KeypointsOnImage." ) def unnormalize_batch(batch_aug): i = batch_aug.data if isinstance(i, tuple): i = i[0] dt_orig = batches_original_dts[i] if dt_orig == BatchStatus.IMG_AUG_BATCH: batch_unnormalized = batch_aug batch_unnormalized.data = batch_unnormalized.data[1] elif dt_orig == BatchStatus.NP_ARRAY: batch_unnormalized = batch_aug.images_aug elif dt_orig == BatchStatus.EMPTY_LIST: batch_unnormalized = [] elif dt_orig == BatchStatus.NP_ARRAYS: batch_unnormalized = batch_aug.images_aug elif dt_orig == BatchStatus.KPS_ON_IMAGE: batch_unnormalized = batch_aug.keypoints_aug else: raise Exception("Internal Error. Unexpected value in dt_orig") return batch_unnormalized if not background: for batch_normalized in batches_normalized: batch_augment_images = batch_normalized.images is not None batch_augment_keypoints = batch_normalized.keypoints is not None if batch_augment_images and batch_augment_keypoints: augseq_det = self.to_deterministic( ) if not self.deterministic else self batch_normalized.images_aug = augseq_det.augment_images( batch_normalized.images, hooks=hooks) batch_normalized.keypoints_aug = augseq_det.augment_keypoints( batch_normalized.keypoints, hooks=hooks) elif batch_augment_images: batch_normalized.images_aug = self.augment_images( batch_normalized.images, hooks=hooks) elif batch_augment_keypoints: batch_normalized.keypoints_aug = self.augment_keypoints( batch_normalized.keypoints, hooks=hooks) batch_unnormalized = unnormalize_batch(batch_normalized) yield batch_unnormalized else: def load_batches(): for batch in batches_normalized: yield batch batch_loader = BatchLoader(load_batches) bg_augmentor = BackgroundAugmentor(batch_loader, self) while True: batch_aug = bg_augmentor.get_batch() if batch_aug is None: break else: batch_unnormalized = unnormalize_batch(batch_aug) yield batch_unnormalized batch_loader.terminate() bg_augmentor.terminate()
def __init__(self, other_param): super(Discretize, self).__init__() eu.do_assert(isinstance(other_param, StochasticParameter)) self.other_param = other_param