def undo(self): self.successful_actions -= 1 self.img.delete() self.img = Image(self.prev_img.img, self.prev_img.array) self.reward = self.prev_reward self.distance = self.prev_distance self.undo_before_step = True
def __init__(self, input_path, output_path, output_size, bg): src_img, img = initialize(src_path=input_path, input_path=None, size=output_size) self.src_img = Image(src_img) self.img = Image(img) self.viewer = None self.output_path = output_path color_to_fill = self.src_img.get_average_color( ) if bg == 'None' else hex_to_rgb(bg) self.img.fill_with(color_to_fill)
def __init__(self, src_path, action_type, limit, output_size, diffs): self.src_path = src_path src_image, image = initialize_with_scaled_src( self.src_path + "/src.jpg", output_size) self.src_image = Image(src_image) self.image = Image(image) self.diffs = diffs if self.diffs: self.action_type_limited = True if action_type >= 0 else False if self.action_type_limited: self.action_type = action_type self.action_number_limited = True if limit >= 0 else False if self.action_number_limited: self.limit = limit self.out_path = None self.img_src_out_path = None self.abs_out_path = None
def generate_set(image_n, image_size, name): def initialize(): X = np.zeros((image_n, image_size, image_size, 3)) Y = np.zeros((image_n, 9)) return X, Y def rand(): return np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.) X, Y = initialize() image = Image(initializer.new_image(image_size, image_size)) white_image_np = np.ones((image_size, image_size, 3)) action = Environment.Action.LINE for i in tqdm.tqdm(range(image_n), "Generating %s set" % name): r, g, b, a, x1, y1, x2, y2, size = rand() image.perform_action(action, (r, g, b, a, x1, y1, x2, y2, size)) array = image.array X[i] = (array / 255.) - white_image_np Y[i] = [r, g, b, a, x1, y1, x2, y2, size] image.clear() path = "./{}_{}.npy" np.save(path.format(name, "X"), X) np.save(path.format(name, "Y"), Y)
def generate_set(image_n, image_size, name, shape, without_rotation): def initialize(): X = np.zeros((image_n, image_size, image_size, 3)) Y = np.zeros((image_n, 9)) return X, Y def rand(): return np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0. + (1. / image_size), 1.), \ np.random.uniform(0. + (1. / image_size), 1.), np.random.uniform(0., 1.) X, Y = initialize() image = Image(initializer.new_image(image_size, image_size)) white_image_np = np.ones((image_size, image_size, 3)) action = Environment.Action.ELLIPSE if shape == 'ellipse' else Environment.Action.RECTANGLE for i in tqdm.tqdm(range(image_n), "Generating %s set" % name): r, g, b, a, x, y, w, h, rotation = rand() w = min(w, 1 - x) h = min(h, 1 - y) rotation = 0.5 if without_rotation else rotation image.perform_action(action, (r, g, b, a, x, y, w, h, rotation)) array = image.array X[i] = (array / 255.) - white_image_np Y[i] = [r, g, b, a, x, y, w, h, rotation] image.clear() path = "./{}_{}.npy" np.save(path.format(name, "X"), X) np.save(path.format(name, "Y"), Y)
def __init__(self, src_path, acceptable_distance, input_path, actions, size): self.src_path = src_path src_img, img = initializer.initialize(src_path, input_path, size) self.src_img = Image(src_img) self.img = Image(img) self.prev_img = None self.acceptable_dist = acceptable_distance self.state = None self.reward = 0 self.prev_reward = 0 self.distance = sum(abs(self.src_img.array - self.img.array)) self.prev_distance = 0 self.done = False self.action_space = ToolSpace() self.viewer = None self.version_info = self.construct_version_info() self.out_path = None self.undo_before_step = False self.action = None self.args = None self.successful_actions = 0 self.actions_before_success = 0 self.actions = actions
class Environment(object): def __init__(self, input_path, output_path, output_size, bg): src_img, img = initialize(src_path=input_path, input_path=None, size=output_size) self.src_img = Image(src_img) self.img = Image(img) self.viewer = None self.output_path = output_path color_to_fill = self.src_img.get_average_color( ) if bg == 'None' else hex_to_rgb(bg) self.img.fill_with(color_to_fill) # todo: not working def render(self): if self.viewer is None: self.viewer = rendering.SimpleImageViewer() image = np.concatenate( (self.src_img.renderable(), self.img.renderable()), axis=1) self.viewer.img_show(image) def save(self): self.img.update_array() imsave(self.output_path, self.img.renderable())
def generate_set(image_n, image_size, name): def scale(x): return x / float(image_size) def initialize(): X = np.zeros((image_n, image_size, image_size)) Y = np.zeros((image_n, 9)) return X, Y X, Y = initialize() image = Image(initializer.new_image(image_size, image_size)) white_image_np = np.ones((image_size, image_size)) for i in tqdm.tqdm(range(image_n), "Generating %s set" % name): square_size = np.random.randint(3, image_size) x_coor = np.random.randint(0, image_size - square_size) y_coor = np.random.randint(0, image_size - square_size) image.perform_action( RECTANGLE, (RED, GREEN, BLUE, ALPHA, scale(x_coor), scale(y_coor), scale(square_size), scale(square_size), ROTATION)) array = np.sum(image.array, axis=2) / 3 X[i] = (array / 255.) - white_image_np # draw white rectangle to "reset" image image.perform_action_without_array_update( RECTANGLE, (1., 1., 1., ALPHA, scale(x_coor), scale(y_coor), scale(square_size), scale(square_size), ROTATION)) Y[i][0] = RED Y[i][1] = GREEN Y[i][2] = BLUE Y[i][3] = ALPHA Y[i][4] = scale(x_coor) Y[i][5] = scale(y_coor) Y[i][6] = scale(square_size) Y[i][7] = scale(square_size) Y[i][8] = ROTATION path = "./{}_{}.npy" np.save(path.format(name, "X"), X) np.save(path.format(name, "Y"), Y)
def plugin_main(name, size, r, g, b, a, x1, y1, x2, y2, x3, y3): image = Image(initializer.new_image(size, size)) action = Environment.Action.TRIANGLE image.perform_action(action, (r, g, b, a, x1, y1, x2, y2, x3, y3)) image.save("%s/%s" % (PATH, name))
class ImageGenerator(object): def __init__(self, src_path, action_type, limit, output_size, diffs): self.src_path = src_path src_image, image = initialize_with_scaled_src( self.src_path + "/src.jpg", output_size) self.src_image = Image(src_image) self.image = Image(image) self.diffs = diffs if self.diffs: self.action_type_limited = True if action_type >= 0 else False if self.action_type_limited: self.action_type = action_type self.action_number_limited = True if limit >= 0 else False if self.action_number_limited: self.limit = limit self.out_path = None self.img_src_out_path = None self.abs_out_path = None def setup_diffs_output(self): if self.diffs: image_number = self.src_path.split("/")[-2] image_dir = os.path.expandvars("$GIMP_PROJECT/out/diffs/%s" % image_number) if not os.path.exists(image_dir): os.mkdir(image_dir) self.out_path = image_dir def run(self): start = time.time() self.setup_diffs_output() actions = self.parse_actions() self.perform_actions_with_saving_data(actions) self.save_generated_image() end = time.time() print "Script executed in {} seconds".format(end - start) def save_generated_image(self): if not self.diffs: self.image.save(self.src_path + "/generated_image.jpg") def perform_actions_with_saving_data(self, actions): for index, (action_type, action_args) in enumerate(actions): if self.should_save(action_type): self.save(index, action_type, action_args) self.image.perform_action_without_array_update( action_type, action_args) def should_save(self, action_type): return self.diffs and (not self.action_type_limited or action_type == self.action_type) def save(self, index, action_type, action_args): def get_path(x): return "{}/{}_{}.npy".format(self.out_path, x, index + 1) X = (self.src_image.array - self.image.get_updated_array()) / 255. np.save(get_path("X"), X) # Y without action_type for now Y = np.array(list(action_args)) np.save(get_path("Y"), Y) def parse_actions(self): import glob path_to_actions = self.src_path + "/*.json" action_files = glob.glob(path_to_actions) if self.diffs and self.action_number_limited: action_files = [ f for f in action_files if int(extract_number(f)) <= self.limit ] action_files.sort(key=natural_keys) actions = [] for action_file in action_files: with open(action_file) as json_file: data = json.load(json_file)["action"] actions.append((data["actionNumber"], tuple(data["args"]))) return actions
class Environment(object): def __init__(self, src_path, acceptable_distance, input_path, actions, size): self.src_path = src_path src_img, img = initializer.initialize(src_path, input_path, size) self.src_img = Image(src_img) self.img = Image(img) self.prev_img = None self.acceptable_dist = acceptable_distance self.state = None self.reward = 0 self.prev_reward = 0 self.distance = sum(abs(self.src_img.array - self.img.array)) self.prev_distance = 0 self.done = False self.action_space = ToolSpace() self.viewer = None self.version_info = self.construct_version_info() self.out_path = None self.undo_before_step = False self.action = None self.args = None self.successful_actions = 0 self.actions_before_success = 0 self.actions = actions @timed def construct_version_info(self): additional_info = "" return "{}_{}_{}_{}_space_{}_{}".format( imprvs["eps"], imprvs["improvements_by_one_attempt"], imprvs["attempts"], reducer_rate, self.action_space.n, additional_info) @timed def reset(self): # self.__setup_output() return (self.src_img.array - self.img.array) / 255. @timed def setup_output(self): filename = str(os.path.basename(self.src_path).split(".")[0]) image_dir = os.path.expandvars("$GIMP_PROJECT/out/drawing/%s" % filename) date = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") execution_dirname = date + "_" + self.version_info if not os.path.exists(image_dir): os.mkdir(image_dir) self.out_path = "%s/%s" % (image_dir, execution_dirname) os.mkdir(self.out_path) self.src_img.save(self.out_path + "/src.jpg") @timed def render(self): if self.viewer is None: self.viewer = rendering.SimpleImageViewer() image = self.get_concatenated_src_with_image(self.img) self.viewer.img_show(image) @timed def get_concatenated_src_with_image(self, image_to_concatenate): images_to_display = (self.src_img.renderable(), image_to_concatenate.renderable()) image = concatenate(images_to_display, axis=1) return image @timed def save(self, seconds_from_start, seconds_for_action): data = self.construct_json_data(seconds_from_start, seconds_for_action) action_string = "action_{}".format(self.successful_actions) with open(self.out_path + "/{}.json".format(action_string), "w") as outfile: json.dump(data, outfile, sort_keys=True, indent=4, separators=(',', ': ')) if self.successful_actions % 100 == 0: np.save(self.out_path + "/{}.npy".format(action_string), self.img.array) self.actions_before_success = 0 @timed def save_jpg(self, path): misc.imsave(path, self.get_concatenated_src_with_image(self.img)) @timed def construct_json_data(self, seconds_from_start, seconds_for_action): return { "distanceBefore": self.prev_distance, "distanceAfter": self.distance, "reward": self.reward, "time": int(seconds_from_start * 1000), "timeString": formatter.format_time(seconds_from_start), "actionTime": int(seconds_for_action * 1000), "actionTimeString": formatter.format_time(seconds_for_action), "action": { "actionNumber": self.action, "actionString": self.action_space.subspace_name(self.action), "args": self.args, }, "configuration": { "epsilon": imprvs["eps"], "improvementsByOneAttempt": imprvs["improvements_by_one_attempt"], "attempts": imprvs["attempts"] }, "numberOfActionsBeforeSuccess": self.actions_before_success - 1 } @timed def step(self, action, args): self.successful_actions += 1 self.actions_before_success += 1 if self.prev_img is not None and not self.undo_before_step: self.prev_img.delete() self.prev_img = self.img self.img = self.img.duplicate() self.prev_reward = self.reward self.prev_distance = self.distance self.img.perform_action(action, args) self.update_reward_and_distance() self.check_if_done() self.undo_before_step = False self.action = action self.args = args diff = (self.src_img.array - self.img.array) / 255. return self.reward, self.done, diff @timed def update_reward_and_distance(self): new_distance = np.sum(np.abs(self.src_img.array - self.img.array)) self.reward = int(self.distance) - int(new_distance) self.distance = int(new_distance) @timed def check_if_done(self): self.done = self.distance <= self.acceptable_dist or self.successful_actions >= self.actions @timed def undo(self): self.successful_actions -= 1 self.img.delete() self.img = Image(self.prev_img.img, self.prev_img.array) self.reward = self.prev_reward self.distance = self.prev_distance self.undo_before_step = True @timed def generate_image(self): pdb.python_fu_image_generator(self.out_path) results_dir = os.path.expandvars("$GIMP_PROJECT/results") if not os.path.exists(results_dir): os.mkdir(results_dir) filename = str(os.path.basename(self.src_path).split(".")[0]) image_result_dir = results_dir + "/" + filename if not os.path.exists(image_result_dir): os.mkdir(image_result_dir) os.system("cp {} {}".format(self.out_path + "/generated_image.jpg", image_result_dir)) os.system("cp {} {}".format(self.out_path + "/src.jpg", image_result_dir)) class Action(object): ELLIPSE = 0 RECTANGLE = 1 LINE = 2 TRIANGLE = 3
def plugin_main(name, size, r, g, b, a, x, y, w, h, rotation, shape): image = Image(initializer.new_image(size, size)) action = Environment.Action.ELLIPSE if shape == 'ellipse' else Environment.Action.RECTANGLE image.perform_action(action, (r, g, b, a, x, y, w, h, rotation)) image.save("%s/%s" % (PATH, name))
def generate_set(num_images, image_size, name, max_examples_per_part, without_rotation): def initialize(num_examples): X = np.zeros((num_examples, image_size, image_size, 3)) Y = np.zeros((num_examples, 4)) return X, Y def save(X, Y, p): path = "./{}_{}_{}.npy" np.save(path.format(name, "X", p), X) np.save(path.format(name, "Y", p), Y) def generate_args(a): if a == 0 or a == 1: return generate_args_for_selection_shape() elif a == 2: return generate_args_for_line() else: return generate_args_for_triangle() def generate_args_for_selection_shape(): def rand(): return np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0. + (1. / image_size), 1.), \ np.random.uniform(0. + (1. / image_size), 1.), np.random.uniform(0., 1.) r, g, b, a, x, y, w, h, rotation = rand() w = min(w, 1 - x) h = min(h, 1 - y) rotation = 0.5 if without_rotation else rotation return r, g, b, a, x, y, w, h, rotation def generate_args_for_line(): def rand(): return np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.) return rand() def generate_args_for_triangle(): def rand(): return np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.), np.random.uniform(0., 1.), np.random.uniform(0., 1.), \ np.random.uniform(0., 1.) return rand() remaining_examples = num_images part = 1 image = Image(initializer.new_image(image_size, image_size)) white_image_np = np.ones((image_size, image_size, 3)) while remaining_examples > 0: examples_in_current_part = min(remaining_examples, max_examples_per_part) X, Y = initialize(examples_in_current_part) for i in tqdm.tqdm(range(examples_in_current_part), "Generating {} set, part {}".format(name, part)): action = np.random.randint(0, 4) args = generate_args(action) image.perform_action(action, args) array = image.array X[i] = (array / 255.) - white_image_np Y[i][action] = 1 image.clear() save(X, Y, part) remaining_examples -= examples_in_current_part part += 1