def __init__(self, width, height, xmin, xmax, ymin, ymax, mask_name, image_size, do_check_bounds, init_black=False): self.pixels = np.zeros((channels, height, width)) if init_black: alpha_channel = np.index_exp[3:, :, :] self.pixels[alpha_channel] = 1.0 self.canvas_xmin = 0 self.canvas_xmax = width self.canvas_ymin = 0 self.canvas_ymax = height self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax self.do_check_bounds = do_check_bounds self.canvas_xspread = self.canvas_xmax - self.canvas_xmin self.canvas_yspread = self.canvas_ymax - self.canvas_ymin self.xspread = self.xmax - self.xmin self.yspread = self.ymax - self.ymin self.xspread_ratio = float(self.canvas_xspread) / self.xspread self.yspread_ratio = float(self.canvas_yspread) / self.yspread self.gsize = image_size self.gsize2 = image_size/2 self.gsize4 = image_size/4 if mask_name is not None: _, _, mask_images = anchors_from_image("mask/{}_mask{}.png".format(mask_name, image_size), image_size=(image_size, image_size)) # _, _, mask_images = anchors_from_image("mask/rounded_mask{}.png".format(gsize), image_size=(gsize, gsize)) # _, _, mask_images = anchors_from_image("mask/hexagons/hex1_{}_blur.png".format(gsize), image_size=(gsize, gsize)) self.mask = mask_images[0][0] else: self.mask = None
def __init__(self, width, height, xmin, xmax, ymin, ymax, mask_name, image_size, do_check_bounds, init_black=False): self.pixels = np.zeros((channels, height, width)) if init_black: alpha_channel = np.index_exp[3:, :, :] self.pixels[alpha_channel] = 1.0 self.canvas_xmin = 0 self.canvas_xmax = width self.canvas_ymin = 0 self.canvas_ymax = height self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax self.do_check_bounds = do_check_bounds self.canvas_xspread = self.canvas_xmax - self.canvas_xmin self.canvas_yspread = self.canvas_ymax - self.canvas_ymin self.xspread = self.xmax - self.xmin self.yspread = self.ymax - self.ymin self.xspread_ratio = float(self.canvas_xspread) / self.xspread self.yspread_ratio = float(self.canvas_yspread) / self.yspread self.gsize = image_size self.gsize2 = image_size / 2 self.gsize4 = image_size / 4 if mask_name is not None: _, _, mask_images = anchors_from_image( "mask/{}_mask{}.png".format(mask_name, image_size), image_size=(image_size, image_size)) # _, _, mask_images = anchors_from_image("mask/rounded_mask{}.png".format(gsize), image_size=(gsize, gsize)) # _, _, mask_images = anchors_from_image("mask/hexagons/hex1_{}_blur.png".format(gsize), image_size=(gsize, gsize)) self.mask = mask_images[0][0] else: self.mask = None
def run_with_args(args, dmodel, cur_anchor_image, cur_save_path, cur_z_step): if args.seed is not None: np.random.seed(args.seed) random.seed(args.seed) anchor_images = None if args.anchors: _, get_anchor_images = lazy_init_fuel_dependencies() allowed = None prohibited = None include_targets = False if(args.allowed): include_targets = True allowed = map(int, args.allowed.split(",")) if(args.prohibited): include_targets = True prohibited = map(int, args.prohibited.split(",")) anchor_images = get_anchor_images(args.dataset, args.split, args.offset, args.stepsize, args.numanchors, allowed, prohibited, args.image_size, args.color_convert, include_targets=include_targets) if cur_anchor_image is not None: _, _, anchor_images = anchors_from_image(cur_anchor_image, image_size=(args.image_size, args.image_size)) if args.offset > 0: anchor_images = anchor_images[args.offset:] # untested if args.numanchors is not None: anchor_images = anchor_images[:args.numanchors] if args.passthrough: print('Preparing image grid...') img = grid2img(anchor_images, args.rows, args.cols, not args.tight) img.save(cur_save_path) sys.exit(0) if dmodel is None: model_class_parts = args.model_class.split(".") model_class_name = model_class_parts[-1] model_module_name = ".".join(model_class_parts[:-1]) print("Loading {} interface from {}".format(model_class_name, model_module_name)) ModelClass = getattr(importlib.import_module(model_module_name), model_class_name) print("Loading model from {}".format(args.model)) dmodel = ModelClass(filename=args.model) if anchor_images is not None: x_queue = anchor_images[:] anchors = None # print("========> ENCODING {} at a time".format(args.batch_size)) while(len(x_queue) > 0): cur_x = x_queue[:args.batch_size] x_queue = x_queue[args.batch_size:] encoded = dmodel.encode_images(cur_x) if anchors is None: anchors = encoded else: anchors = np.concatenate((anchors, encoded), axis=0) # anchors = dmodel.encode_images(anchor_images) elif args.anchor_vectors is not None: anchors = get_json_vectors(args.anchor_vectors) else: anchors = None if args.invert_anchors: anchors = -1 * anchors if args.encoder: if anchors is not None: output_vectors(anchors) else: stream_output_vectors(dmodel, args.dataset, args.split, batch_size=args.batch_size) sys.exit(0) global_offset = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor offsets = get_json_vectors(args.anchor_offset) if args.anchor_noise: anchors = anchors_noise_offsets(anchors, offsets, args.rows, args.cols, args.spacing, cur_z_step, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) else: anchors = anchors_from_offsets(anchors[0], offsets, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) if args.global_offset is not None: offsets = get_json_vectors(args.global_offset) if args.global_ramp: offsets = cur_z_step * offsets global_offset = get_global_offset(offsets, args.global_indices, args.global_scale) z_dim = dmodel.get_zdim() # I don't remember what partway/encircle do so they are not handling the chain layout # this handles the case (at least) of mines with random anchors if (args.partway is not None) or args.encircle or (args.mine and anchors is None): srows=((args.rows // args.spacing) + 1) scols=((args.cols // args.spacing) + 1) rand_anchors = generate_latent_grid(z_dim, rows=srows, cols=scols, fan=False, gradient=False, spherical=False, gaussian=False, anchors=None, anchor_images=None, mine=False, chain=False, spacing=args.spacing, analogy=False, rand_uniform=args.uniform) if args.partway is not None: l = len(rand_anchors) clipped_anchors = anchors[:l] anchors = (1.0 - args.partway) * rand_anchors + args.partway * clipped_anchors elif args.encircle: anchors = surround_anchors(srows, scols, anchors, rand_anchors) else: anchors = rand_anchors z = generate_latent_grid(z_dim, args.rows, args.cols, args.fan, args.gradient, not args.linear, args.gaussian, anchors, anchor_images, args.mine, args.chain, args.spacing, args.analogy) if global_offset is not None: z = z + global_offset grid_from_latents(z, dmodel, args.rows, args.cols, anchor_images, args.tight, args.shoulders, cur_save_path, args.batch_size) return dmodel
def main(cliargs): parser = argparse.ArgumentParser(description="Plot model samples") # models are only for seeds-image parser.add_argument("--model", dest='model', type=str, default=None, help="name of model in plat zoo") parser.add_argument("--model-file", dest='model_file', type=str, default=None, help="path to the saved model") parser.add_argument( "--model-type", dest='model_type', type=str, default=None, help="the type of model (usually inferred from filename)") parser.add_argument( "--model-interface", dest='model_interface', type=str, default=None, help="class interface for model (usually inferred from model-type)") parser.add_argument('--build-annoy', dest='build_annoy', default=False, action='store_true') parser.add_argument("--jsons", type=str, default=None, help="Comma separated list of json arrays") parser.add_argument('--dataset', dest='dataset', default=None, help="Source dataset.") parser.add_argument('--dataset-image', dest='dataset_image', default=None, help="use image as source dataset") parser.add_argument("--dataset-offset", dest='dataset_offset', type=int, default=0, help="dataset offset to skip") parser.add_argument("--dataset-max", type=int, default=None, help="Source dataset.") parser.add_argument('--seeds-image', dest='seeds_image', default=None, help="image source of seeds") parser.add_argument('--drop-seeds', dest='drop_seeds', default=False, action='store_true') parser.add_argument('--annoy-index', dest='annoy_index', default=None, help="Annoy index.") parser.add_argument( '--split', dest='split', default="all", help= "Which split to use from the dataset (train/nontrain/valid/test/any).") parser.add_argument("--image-size", dest='image_size', type=int, default=64, help="size of (offset) images") parser.add_argument("--z-dim", dest='z_dim', type=int, default=100, help="z dimension") parser.add_argument('--outdir', dest='outdir', default="neighborgrids", help="Output dir for neighborgrids.") parser.add_argument('--outfile', dest='outfile', default="index_{:03d}.png", help="Output file (template) for neighborgrids.") parser.add_argument("--outgrid-width", dest='outgrid_width', type=int, default=5, help="width of output grid") parser.add_argument("--outgrid-height", dest='outgrid_height', type=int, default=3, help="height of output grid") parser.add_argument('--range', dest='range', default="0", help="Range of indexes to run.") args = parser.parse_args(cliargs) # check for model download first if args.model is not None: zoo.check_model_download(args.model) encoded = json_list_to_array(args.jsons) # print(encoded.shape) if args.build_annoy: aindex = build_annoy_index(encoded, args.annoy_index) sys.exit(0) # open annoy index and spit out some neighborgrids aindex = load_annoy_index(args.annoy_index, args.z_dim) if args.dataset is not None: anchor_images = get_anchor_images(args.dataset, args.split, offset=args.dataset_offset, numanchors=args.dataset_max, unit_scale=False) image_size = anchor_images.shape[2] # dataset_image requires image_size if args.dataset_image is not None: image_size = args.image_size _, _, anchor_images = anchors_from_image(args.dataset_image, image_size=(image_size, image_size), unit_scale=False) if args.dataset_offset > 0: anchor_images = anchor_images[args.dataset_offset:] if args.dataset_max is not None: anchor_images = anchor_images[:args.dataset_max] r = map(int, args.range.split(",")) core_dataset_size = len(anchor_images) if (len(encoded) != core_dataset_size): print("Warning: {} vectors and {} images".format( len(encoded), core_dataset_size)) if args.seeds_image is not None: image_size = args.image_size _, _, extra_images = anchors_from_image(args.seeds_image, image_size=(image_size, image_size), unit_scale=False) net_inputs = (extra_images / 255.0).astype('float32') print('Loading saved model') dmodel = zoo.load_model(args.model, args.model_file, args.model_type, args.model_interface) image_vectors = dmodel.encode_images(net_inputs) num_extras = len(extra_images) encoded = np.concatenate((encoded, image_vectors), axis=0) anchor_images = np.concatenate((anchor_images, extra_images), axis=0) # for now, override given range r = [core_dataset_size, core_dataset_size + num_extras] print anchor_images.shape if not os.path.exists(args.outdir): os.makedirs(args.outdir) if len(r) == 1: r = [r[0], r[0] + 1] num_out_cells = args.outgrid_width * args.outgrid_height for i in range(r[0], r[1]): if i < core_dataset_size: # will find the N nearest neighbors neighbors = aindex.get_nns_by_item(i, num_out_cells, include_distances=True) file_num = i else: if args.drop_seeds: # just the N nearest neighbors neighbors = aindex.get_nns_by_vector( encoded[i], num_out_cells, include_distances=True ) # will find the 20 nearest neighbors else: # original seed + (N-1) nearest neigbors neighbors = aindex.get_nns_by_vector( encoded[i], num_out_cells - 1, include_distances=True ) # will find the 20 nearest neighbors neighbors[0].append(i) neighbors[1].append(0) file_num = i - core_dataset_size g = neighbors_to_rfgrid(neighbors[0], encoded, anchor_images, image_size, args.outgrid_width, args.outgrid_height) out_template = "{}/{}".format(args.outdir, args.outfile) g.save(out_template.format(file_num))
def run_with_args(args, dmodel, cur_anchor_image, cur_save_path, cur_z_step, cur_basename="basename", range_data=None, template_dict={}): anchor_images = None anchor_labels = None if args.anchors: allowed = None prohibited = None include_targets = False if (args.allowed): include_targets = True allowed = map(int, args.allowed.split(",")) if (args.prohibited): include_targets = True prohibited = map(int, args.prohibited.split(",")) anchor_images = get_anchor_images(args.dataset, args.split, args.offset, args.stepsize, args.numanchors, allowed, prohibited, args.image_size, args.color_convert, include_targets=include_targets) if args.with_labels: anchor_labels = get_anchor_labels(args.dataset, args.split, args.offset, args.stepsize, args.numanchors) if args.anchor_glob is not None: files = plat.sampling.real_glob(args.anchor_glob) if args.offset > 0: files = files[args.offset:] if args.stepsize > 1: files = files[::args.stepsize] if args.numanchors is not None: files = files[:args.numanchors] anchor_images = anchors_from_filelist(files) print("Read {} images from {} files".format(len(anchor_images), len(files))) if len(anchor_images) == 0: print("No images, cannot contine") sys.exit(0) if cur_anchor_image is not None: _, _, anchor_images = anchors_from_image(cur_anchor_image, image_size=(args.image_size, args.image_size)) if args.offset > 0: anchor_images = anchor_images[args.offset:] if args.stepsize > 0: anchor_images = anchor_images[::args.stepsize] if args.numanchors is not None: anchor_images = anchor_images[:args.numanchors] # at this point we can make a dummy anchor_labels if we need if anchor_images is not None and anchor_labels is None: anchor_labels = [None] * len(anchor_images) if args.passthrough: # determine final filename string image_size = anchor_images[0].shape[1] save_path = plat.sampling.emit_filename(cur_save_path, {}, args) print("Preparing image file {}".format(save_path)) img = grid2img(anchor_images, args.rows, args.cols, not args.tight) img.save(save_path) sys.exit(0) if dmodel is None: dmodel = zoo.load_model(args.model, args.model_file, args.model_type, args.model_interface) embedded = None if anchor_images is not None: x_queue = anchor_images[:] c_queue = anchor_labels[:] anchors = None # print("========> ENCODING {} at a time".format(args.batch_size)) while (len(x_queue) > 0): cur_x = x_queue[:args.batch_size] cur_c = c_queue[:args.batch_size] x_queue = x_queue[args.batch_size:] c_queue = c_queue[args.batch_size:] encoded = dmodel.encode_images(cur_x, cur_c) try: emb_l = dmodel.embed_labels(cur_c) except AttributeError: emb_l = [None] * args.batch_size if anchors is None: anchors = encoded embedded = emb_l else: anchors = np.concatenate((anchors, encoded), axis=0) embedded = np.concatenate((embedded, emb_l), axis=0) # anchors = dmodel.encode_images(anchor_images) elif args.anchor_vectors is not None: anchors = get_json_vectors(args.anchor_vectors) else: anchors = None if args.invert_anchors: anchors = -1 * anchors if args.encoder: if anchors is not None: plat.sampling.output_vectors(anchors, args.save_path) else: plat.sampling.stream_output_vectors(dmodel, args.dataset, args.split, args.save_path, batch_size=args.batch_size) sys.exit(0) global_offset = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor offsets = get_json_vectors(args.anchor_offset) if args.anchor_wave: anchors = plat.sampling.anchors_wave_offsets( anchors, offsets, args.rows, args.cols, args.spacing, args.radial_wave, args.clip_wave, cur_z_step, args.anchor_offset_x, args.anchor_offset_x_minscale, args.anchor_offset_x_maxscale) elif args.anchor_noise: anchors = plat.sampling.anchors_noise_offsets( anchors, offsets, args.rows, args.cols, args.spacing, cur_z_step, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) elif range_data is not None: anchors = plat.sampling.anchors_json_offsets( anchors, offsets, args.rows, args.cols, args.spacing, cur_z_step, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale, range_data) else: anchors = plat.sampling.anchors_from_offsets( anchors[0], offsets, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) if args.global_offset is not None: offsets = get_json_vectors(args.global_offset) if args.global_ramp: offsets = cur_z_step * offsets global_offset = plat.sampling.get_global_offset( offsets, args.global_indices, args.global_scale) z_dim = dmodel.get_zdim() # I don't remember what partway/encircle do so they are not handling the chain layout # this handles the case (at least) of mines with random anchors if (args.partway is not None) or args.encircle or (anchors is None): srows = ((args.rows // args.spacing) + 1) scols = ((args.cols // args.spacing) + 1) rand_anchors = plat.sampling.generate_latent_grid( z_dim, rows=srows, cols=scols, fan=False, gradient=False, spherical=False, gaussian=False, anchors=None, anchor_images=None, mine=False, chain=False, spacing=args.spacing, analogy=False, rand_uniform=args.uniform) if args.partway is not None: l = len(rand_anchors) clipped_anchors = anchors[:l] anchors = (1.0 - args.partway ) * rand_anchors + args.partway * clipped_anchors elif args.encircle: anchors = surround_anchors(srows, scols, anchors, rand_anchors) else: anchors = rand_anchors z = plat.sampling.generate_latent_grid(z_dim, args.rows, args.cols, args.fan, args.gradient, not args.linear, args.gaussian, anchors, anchor_images, True, args.chain, args.spacing, args.analogy) if global_offset is not None: z = z + global_offset template_dict["BASENAME"] = cur_basename # emb_l = None # emb_l = [None] * len(z) if args.clone_label is not None: emb_l = np.tile(embedded[args.clone_label], [len(z), 1]) else: emb_l = plat.sampling.generate_latent_grid( z_dim, args.rows, args.cols, args.fan, args.gradient, not args.linear, args.gaussian, embedded, anchor_images, True, args.chain, args.spacing, args.analogy) #TODO - maybe not best way to check if labels are valid # if anchor_labels is None or anchor_labels[0] is None: # emb_l = [None] * len(z) plat.sampling.grid_from_latents(z, dmodel, args.rows, args.cols, anchor_images, args.tight, args.shoulders, cur_save_path, args, args.batch_size, template_dict=template_dict, emb_l=emb_l) return dmodel
def do_convert(raw_infile, outfile, dmodel, classifier, do_smile, smile_offsets, image_size, initial_steps=10, recon_steps=10, offset_steps=20, optimal_steps=10, end_bumper_steps=10, check_extent=True, wraparound=True): failure_return_status = False, False, False, False # infile = resized_input_file; # did_resize, movie_compatible, scale_ratio = resize_to_a_good_size(raw_infile, infile) # if not did_resize: # return failure_return_status # first align input face to canonical alignment and save result try: did_align, align_rect = doalign.align_face(raw_infile, aligned_file, image_size, max_extension_amount=0, min_span=72) width = align_rect.right() - align_rect.left() print("did_align, rect, width:{},{},{}".format(did_align, align_rect, width)) if not did_align: return failure_return_status except Exception as e: # get_landmarks strangely fails sometimes (see bad_shriek test image) print("faceswap: doalign failure {}".format(e)) return failure_return_status # save optimally scaled input optimal_shape = resize_to_optimal(raw_infile, 1.0, align_rect, optimal_input) infile = optimal_input movie_compatible = check_movie_compatible(optimal_shape) # go ahead and cache the main (body) image and landmarks, and fail if face is too big try: body_image_array = imread(infile, mode='RGB') print(body_image_array.shape) body_rect, body_landmarks = faceswap.core.get_landmarks( body_image_array) max_extent = faceswap.core.get_max_extent(body_landmarks) except faceswap.core.NoFaces: print("faceswap: no faces in {}".format(infile)) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status if check_extent and max_extent > max_allowable_extent: print("face too large: {}".format(max_extent)) return failure_return_status elif check_extent and max_extent < min_allowable_extent: print("face to small: {}".format(max_extent)) return failure_return_status else: print("face not too large: {}".format(max_extent)) # read in aligned file to image array _, _, anchor_images = anchors_from_image(aligned_file, image_size=(image_size, image_size)) # encode aligned image array as vector, apply offset encoded = dmodel.encode_images(anchor_images)[0] deblur_vector = smile_offsets[0] # randint is inclusive and blur is [0], so subtract 2 anchor_index = random.randint(0, len(smile_offsets) - 2) smile_vector = smile_offsets[anchor_index + 1] smile_score = np.dot(smile_vector, encoded) smile_detected = (smile_score > 0) print("Attribute vector detector for {}: {} {}".format( anchor_index, smile_score, smile_detected)) if do_smile is not None: apply_smile = str2bool(do_smile) else: apply_smile = not smile_detected if apply_smile: print("Adding attribute {}".format(anchor_index)) chosen_anchor = [encoded, encoded + smile_vector + deblur_vector] else: print("Removing attribute {}".format(anchor_index)) chosen_anchor = [encoded, encoded - smile_vector + deblur_vector] z_dim = dmodel.get_zdim() # TODO: fix variable renaming anchors, samples_sequence_dir, movie_file = chosen_anchor, sequence_dir, outfile # these are the output png files samples_sequence_filename = samples_sequence_dir + generic_sequence # prepare output directory make_or_cleanup(samples_sequence_dir) # generate latents from anchors z_latents = create_mine_grid(rows=1, cols=offset_steps, dim=z_dim, space=offset_steps - 1, anchors=anchors, spherical=True, gaussian=False) samples_array = dmodel.sample_at(z_latents) print("Samples array: ", samples_array.shape) # save original file as-is for i in range(initial_steps): filename = samples_sequence_filename.format(1 + i) imsave(filename, body_image_array) print("original file: {}".format(filename)) # build face swapped reconstruction sample = samples_array[0] try: # face_image_array = (255 * np.dstack(sample)).astype(np.uint8) face_image_array = (255 * np.dstack(sample)).astype(np.uint8) imsave(recon_file, face_image_array) # face_landmarks = faceswap.core.get_landmarks(face_image_array) # faceswap.core.do_faceswap_from_face(infile, face_image_array, face_landmarks, swapped_file) faceswap.core.do_faceswap(infile, recon_file, swapped_file) print("swapped file: {}".format(swapped_file)) recon_array = imread(swapped_file, mode='RGB') except faceswap.core.NoFaces: print("faceswap: no faces when generating swapped file {}".format( infile)) imsave(debug_file, face_image_array) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status # now save interpolations to recon for i in range(1, recon_steps): frac_orig = ((recon_steps - i) / (1.0 * recon_steps)) frac_recon = (i / (1.0 * recon_steps)) interpolated_im = frac_orig * body_image_array + frac_recon * recon_array filename = samples_sequence_filename.format(i + initial_steps) imsave(filename, interpolated_im) print("interpolated file: {}".format(filename)) final_face_index = len(samples_array) - 1 for i, sample in enumerate(samples_array): try: cur_index = i + initial_steps + recon_steps stack = np.dstack(sample) face_image_array = (255 * np.dstack(sample)).astype(np.uint8) # if i == final_face_index: # imsave(transformed_file, face_image_array) face_rect, face_landmarks = faceswap.core.get_landmarks( face_image_array) filename = samples_sequence_filename.format(cur_index) imsave(transformed_file, face_image_array) # faceswap.core.do_faceswap_from_face(infile, face_image_array, face_landmarks, filename) faceswap.core.do_faceswap(infile, transformed_file, filename) print("generated file: {}".format(filename)) except faceswap.core.NoFaces: print("faceswap: no faces in {}".format(infile)) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status # save optimal swapped output faceswap.core.do_faceswap(infile, transformed_file, optimal_output) if not enhance_optimal_output(): return failure_return_status last_sequence_index = initial_steps + recon_steps + offset_steps - 1 last_filename = samples_sequence_filename.format(last_sequence_index) copyfile(last_filename, final_image) final_recon_array = imread(final_image, mode='RGB') optimal_recon_array = imread(enhanced_output, mode='RGB') # now save interpolations to optimal for i in range(0, optimal_steps): frac_orig = ((optimal_steps - i) / (1.0 * optimal_steps)) frac_optimal = (i / (1.0 * optimal_steps)) interpolated_im = frac_orig * final_recon_array + frac_optimal * optimal_recon_array filename = samples_sequence_filename.format(i + last_sequence_index + 1) imsave(filename, interpolated_im) print("optimal interpolated file: {}".format(filename)) if wraparound: # copy last image back around to first first_filename = samples_sequence_filename.format(0) print("wraparound file: {} -> {}".format(enhanced_output, first_filename)) copyfile(enhanced_output, first_filename) last_optimal_index = initial_steps + recon_steps + offset_steps + optimal_steps - 1 # also add a final out bumper for i in range(last_optimal_index, last_optimal_index + end_bumper_steps): filename = samples_sequence_filename.format(i + 1) copyfile(enhanced_output, filename) print("end bumper file: {}".format(filename)) # convert everything to width 640 # resize and add fakemarks resize_command = "/usr/bin/convert -resize 640x {} {}".format( enhanced_output, enhanced_output) copy_comp = "/usr/bin/composite -gravity SouthEast -geometry +5+5 fakemark.png {} {}".format( enhanced_output, enhanced_output) os.system(resize_command) os.system(copy_comp) for i in range(0, last_optimal_index + end_bumper_steps + 1): filename = samples_sequence_filename.format(i) resize_command = "/usr/bin/convert -resize 640x {} {}".format( filename, filename) copy_comp = "/usr/bin/composite -gravity SouthEast -geometry +5+5 fakemark.png {} {}".format( filename, filename) os.system(resize_command) os.system(copy_comp) if os.path.exists(movie_file): os.remove(movie_file) command = "/usr/bin/ffmpeg -r 20 -f image2 -i \"{}\" -vf \"scale='min(1024,iw)':-2\" -c:v libx264 -crf 20 -pix_fmt yuv420p -tune fastdecode -y -tune zerolatency -profile:v baseline {}".format( ffmpeg_sequence_filename, movie_file) print("ffmpeg command: {}".format(command)) result = os.system(command) if result != 0: return failure_return_status if not os.path.isfile(movie_file): return failure_return_status return True, anchor_index, smile_detected, movie_compatible
def main(cliargs): parser = argparse.ArgumentParser(description="Plot model samples") # models are only for seeds-image parser.add_argument("--model", dest='model', type=str, default=None, help="name of model in plat zoo") parser.add_argument("--model-file", dest='model_file', type=str, default=None, help="path to the saved model") parser.add_argument("--model-type", dest='model_type', type=str, default=None, help="the type of model (usually inferred from filename)") parser.add_argument("--model-interface", dest='model_interface', type=str, default=None, help="class interface for model (usually inferred from model-type)") parser.add_argument('--build-annoy', dest='build_annoy', default=False, action='store_true') parser.add_argument("--jsons", type=str, default=None, help="Comma separated list of json arrays") parser.add_argument('--dataset', dest='dataset', default=None, help="Source dataset.") parser.add_argument('--dataset-image', dest='dataset_image', default=None, help="use image as source dataset") parser.add_argument("--dataset-offset", dest='dataset_offset', type=int, default=0, help="dataset offset to skip") parser.add_argument("--dataset-max", type=int, default=None, help="Source dataset.") parser.add_argument('--seeds-image', dest='seeds_image', default=None, help="image source of seeds") parser.add_argument('--drop-seeds', dest='drop_seeds', default=False, action='store_true') parser.add_argument('--annoy-index', dest='annoy_index', default=None, help="Annoy index.") parser.add_argument('--split', dest='split', default="all", help="Which split to use from the dataset (train/nontrain/valid/test/any).") parser.add_argument("--image-size", dest='image_size', type=int, default=64, help="size of (offset) images") parser.add_argument("--z-dim", dest='z_dim', type=int, default=100, help="z dimension") parser.add_argument('--outdir', dest='outdir', default="neighborgrids", help="Output dir for neighborgrids.") parser.add_argument('--outfile', dest='outfile', default="index_{:03d}.png", help="Output file (template) for neighborgrids.") parser.add_argument("--outgrid-width", dest='outgrid_width', type=int, default=5, help="width of output grid") parser.add_argument("--outgrid-height", dest='outgrid_height', type=int, default=3, help="height of output grid") parser.add_argument('--range', dest='range', default="0", help="Range of indexes to run.") args = parser.parse_args(cliargs) # check for model download first if args.model is not None: zoo.check_model_download(args.model) encoded = json_list_to_array(args.jsons) # print(encoded.shape) if args.build_annoy: aindex = build_annoy_index(encoded, args.annoy_index) sys.exit(0) # open annoy index and spit out some neighborgrids aindex = load_annoy_index(args.annoy_index, args.z_dim) if args.dataset is not None: anchor_images = get_anchor_images(args.dataset, args.split, offset=args.dataset_offset, numanchors=args.dataset_max, unit_scale=False) image_size = anchor_images.shape[2] # dataset_image requires image_size if args.dataset_image is not None: image_size = args.image_size _, _, anchor_images = anchors_from_image(args.dataset_image, image_size=(image_size, image_size), unit_scale=False) if args.dataset_offset > 0: anchor_images = anchor_images[args.dataset_offset:] if args.dataset_max is not None: anchor_images = anchor_images[:args.dataset_max] r = map(int, args.range.split(",")) core_dataset_size = len(anchor_images) if(len(encoded) != core_dataset_size): print("Warning: {} vectors and {} images".format(len(encoded), core_dataset_size)) if args.seeds_image is not None: image_size = args.image_size _, _, extra_images = anchors_from_image(args.seeds_image, image_size=(image_size, image_size), unit_scale=False) net_inputs = (extra_images / 255.0).astype('float32') print('Loading saved model') dmodel = zoo.load_model(args.model, args.model_file, args.model_type, args.model_interface) image_vectors = dmodel.encode_images(net_inputs) num_extras = len(extra_images) encoded = np.concatenate((encoded, image_vectors), axis=0) anchor_images = np.concatenate((anchor_images, extra_images), axis=0) # for now, override given range r = [core_dataset_size, core_dataset_size + num_extras] print anchor_images.shape if not os.path.exists(args.outdir): os.makedirs(args.outdir) if len(r) == 1: r = [r[0], r[0]+1] num_out_cells = args.outgrid_width * args.outgrid_height for i in range(r[0], r[1]): if i < core_dataset_size: # will find the N nearest neighbors neighbors = aindex.get_nns_by_item(i, num_out_cells, include_distances=True) file_num = i else: if args.drop_seeds: # just the N nearest neighbors neighbors = aindex.get_nns_by_vector(encoded[i], num_out_cells, include_distances=True) # will find the 20 nearest neighbors else: # original seed + (N-1) nearest neigbors neighbors = aindex.get_nns_by_vector(encoded[i], num_out_cells-1, include_distances=True) # will find the 20 nearest neighbors neighbors[0].append(i) neighbors[1].append(0) file_num = i - core_dataset_size g = neighbors_to_rfgrid(neighbors[0], encoded, anchor_images, image_size, args.outgrid_width, args.outgrid_height) out_template = "{}/{}".format(args.outdir, args.outfile) g.save(out_template.format(file_num))
def canvas(parser, context, args): parser = argparse.ArgumentParser(description="Plot model samples") parser.add_argument("--model", dest='model', type=str, default=None, help="name of model in plat zoo") parser.add_argument("--model-file", dest='model_file', type=str, default=None, help="path to the saved model") parser.add_argument( "--model-type", dest='model_type', type=str, default=None, help="the type of model (usually inferred from filename)") parser.add_argument( "--model-interface", dest='model_interface', type=str, default=None, help="class interface for model (usually inferred from model-type)") parser.add_argument("--width", type=int, default=512, help="width of canvas to render in pixels") parser.add_argument("--height", type=int, default=512, help="height of canvas to render in pixels") parser.add_argument("--rows", type=int, default=3, help="number of rows of anchors") parser.add_argument("--cols", type=int, default=3, help="number of columns of anchors") parser.add_argument("--xmin", type=int, default=0, help="min x in virtual space") parser.add_argument("--xmax", type=int, default=100, help="max x in virtual space") parser.add_argument("--ymin", type=int, default=0, help="min y in virtual space") parser.add_argument("--ymax", type=int, default=100, help="max y in virtual space") parser.add_argument("--outfile", dest='save_path', type=str, default="canvas_%DATE%_%MODEL%_%SEQ%.png", help="where to save the generated samples") parser.add_argument("--seed", type=int, default=None, help="Optional random seed") parser.add_argument('--do-check-bounds', dest='do_check_bounds', default=False, action='store_true', help="clip to drawing bounds") parser.add_argument('--anchor-image', dest='anchor_image', default=None, help="use image as source of anchors") parser.add_argument('--anchor-mine', dest='anchor_mine', default=None, help="use image as single source of mine coordinates") parser.add_argument( '--random-mine', dest='random_mine', default=False, action='store_true', help="use random sampling as source of mine coordinates") parser.add_argument('--additive', dest='additive', default=False, action='store_true', help="use additive compositing") parser.add_argument( '--mask-name', dest='mask_name', default=None, help="prefix name for alpha mask to use (full/rounded/hex") parser.add_argument('--mask-layout', dest='mask_layout', default=None, help="use image as source of mine grid points") parser.add_argument('--mask-scale', dest='mask_scale', default=1.0, type=float, help="Scale mask layout (squeeze)") parser.add_argument('--mask-width', dest='mask_width', type=int, default=15, help="width for computed mask") parser.add_argument('--mask-height', dest='mask_height', type=int, default=15, help="height for computed mask") parser.add_argument('--mask-radius', dest='mask_radius', default=None, type=float, help="radius for computed mask") parser.add_argument('--layout', dest='layout', default=None, help="layout json file") parser.add_argument('--layout-scale', dest='layout_scale', default=1, type=int, help="Scale layout") parser.add_argument('--batch-size', dest='batch_size', type=int, default=100, help="number of images to decode at once") parser.add_argument('--passthrough', dest='passthrough', default=False, action='store_true', help="Use originals instead of reconstructions") parser.add_argument('--anchor-offset', dest='anchor_offset', default=None, help="use json file as source of each anchors offsets") parser.add_argument('--anchor-offset-a', dest='anchor_offset_a', default="42", type=str, help="which indices to combine for offset a") parser.add_argument('--anchor-offset-b', dest='anchor_offset_b', default="31", type=str, help="which indices to combine for offset b") parser.add_argument("--image-size", dest='image_size', type=int, default=64, help="size of (offset) images") parser.add_argument('--global-offset', dest='global_offset', default=None, help="use json file as source of global offsets") parser.add_argument('--global-indices', dest='global_indices', default=None, type=str, help="offset indices to apply globally") parser.add_argument('--global-scale', dest='global_scale', default=1.0, type=float, help="scaling factor for global offset") args = parser.parse_args(args) template_dict = {} if args.seed: np.random.seed(args.seed) random.seed(args.seed) global_offset = None if args.global_offset is not None: offsets = get_json_vectors(args.global_offset) global_offset = plat.sampling.get_global_offset( offsets, args.global_indices, args.global_scale) anchor_images = None if args.anchor_image is not None: _, _, anchor_images = anchors_from_image(args.anchor_image, image_size=(args.image_size, args.image_size)) elif args.anchor_mine is not None: _, _, anchor_images = anchors_from_image(args.anchor_mine, image_size=(args.image_size, args.image_size)) basename = os.path.basename(args.anchor_mine) template_dict["BASENAME"] = os.path.splitext(basename)[0] anchors = None if not args.passthrough: dmodel = zoo.load_model(args.model, args.model_file, args.model_type, args.model_interface) workq = anchor_images[:] anchors_list = [] while (len(workq) > 0): print("Processing {} anchors".format(args.batch_size)) curq = workq[:args.batch_size] workq = workq[args.batch_size:] cur_anchors = dmodel.encode_images(curq) for c in cur_anchors: anchors_list.append(c) anchors = np.asarray(anchors_list) if anchors is None: anchors = np.random.normal(loc=0, scale=1, size=(args.cols * args.rows, 100)) anchor_offsets = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor anchor_offsets = get_json_vectors(args.anchor_offset) canvas = Canvas(args.width, args.height, args.xmin, args.xmax, args.ymin, args.ymax, args.mask_name, args.image_size, args.do_check_bounds) workq = [] do_hex = True if args.layout: with open(args.layout) as json_file: layout_data = json.load(json_file) xy = np.array(layout_data["xy"]) grid_size = layout_data["size"] roots = layout_data["r"] if "s" in layout_data: s = layout_data["s"] else: s = None for i, pair in enumerate(xy): x = pair[0] * canvas.canvas_xmax / grid_size[0] y = pair[1] * canvas.canvas_ymax / grid_size[1] a = (pair[0] + 0.5 * s[i]) / float(grid_size[0]) b = (pair[1] + 0.5 * s[i]) / float(grid_size[1]) r = roots[i] if s is None: scale = args.layout_scale else: scale = s[i] * args.layout_scale # print("Placing {} at {}, {} because {},{} and {}, {}".format(scale, x, y, canvas.canvas_xmax, canvas.canvas_ymax, grid_size[0], grid_size[1])) if args.passthrough: output_image = anchor_images[r] canvas.place_image(output_image, x, y, args.additive, scale=scale) else: if args.anchor_mine is not None or args.random_mine: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) elif anchor_offsets is not None: z = apply_anchor_offsets(anchors[r], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = anchors[r] if global_offset is not None: z = z + global_offset # print("Storing {},{} with {}".format(x, y, len(z))) workq.append({"z": z, "x": x, "y": y, "s": scale}) elif args.mask_layout or args.mask_radius: if args.mask_layout: rawim = imread(args.mask_layout) if len(rawim.shape) == 2: im_height, im_width = rawim.shape mask_layout = rawim else: im_height, im_width, _ = rawim.shape mask_layout = rawim[:, :, 0] else: im_height, im_width = args.mask_height, args.mask_width mask_layout = make_mask_layout(im_height, im_width, args.mask_radius) for xpos in range(im_width): for ypos in range(im_height): a = float(xpos) / (im_width - 1) if do_hex and ypos % 2 == 0: a = a + 0.5 / (im_width - 1) x = args.mask_scale * canvas.xmax * a b = float(ypos) / (im_height - 1) y = args.mask_scale * canvas.ymax * b if not mask_layout[ypos][xpos] > 128: pass elif args.passthrough: output_image = anchor_images[0] canvas.place_image(output_image, x, y, args.additive) else: if len(anchors) == 1 or anchor_offsets is not None: z = apply_anchor_offsets(anchors[0], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) if global_offset is not None: z = z + global_offset workq.append({"z": z, "x": x, "y": y, "s": 1.0}) while (len(workq) > 0): curq = workq[:args.batch_size] workq = workq[args.batch_size:] latents = [e["z"] for e in curq] images = dmodel.sample_at(np.array(latents)) for i in range(len(curq)): # print("Placing {},{} with {}".format(curq[i]["x"], curq[i]["y"], len(latents))) canvas.place_image(images[i], curq[i]["x"], curq[i]["y"], args.additive, scale=curq[i]["s"]) # print("Placed") template_dict["SIZE"] = args.image_size outfile = plat.sampling.emit_filename(args.save_path, template_dict, args) canvas.save(outfile)
def canvas(parser, context, args): parser = argparse.ArgumentParser(description="Plot model samples") parser.add_argument("--model", dest='model', type=str, default=None, help="name of model in plat zoo") parser.add_argument("--model-file", dest='model_file', type=str, default=None, help="path to the saved model") parser.add_argument("--model-type", dest='model_type', type=str, default=None, help="the type of model (usually inferred from filename)") parser.add_argument("--model-interface", dest='model_interface', type=str, default=None, help="class interface for model (usually inferred from model-type)") parser.add_argument("--width", type=int, default=512, help="width of canvas to render in pixels") parser.add_argument("--height", type=int, default=512, help="height of canvas to render in pixels") parser.add_argument("--rows", type=int, default=3, help="number of rows of anchors") parser.add_argument("--cols", type=int, default=3, help="number of columns of anchors") parser.add_argument("--xmin", type=int, default=0, help="min x in virtual space") parser.add_argument("--xmax", type=int, default=100, help="max x in virtual space") parser.add_argument("--ymin", type=int, default=0, help="min y in virtual space") parser.add_argument("--ymax", type=int, default=100, help="max y in virtual space") parser.add_argument("--outfile", dest='save_path', type=str, default="canvas_%DATE%_%MODEL%_%SEQ%.png", help="where to save the generated samples") parser.add_argument("--seed", type=int, default=None, help="Optional random seed") parser.add_argument('--do-check-bounds', dest='do_check_bounds', default=False, action='store_true', help="clip to drawing bounds") parser.add_argument('--background-image', dest='background_image', default=None, help="use image initial background") parser.add_argument('--anchor-image', dest='anchor_image', default=None, help="use image as source of anchors") parser.add_argument('--anchor-mine', dest='anchor_mine', default=None, help="use image as single source of mine coordinates") parser.add_argument('--anchor-canvas', dest='anchor_canvas', default=False, action='store_true', help="anchor image from canvas") parser.add_argument('--random-mine', dest='random_mine', default=False, action='store_true', help="use random sampling as source of mine coordinates") parser.add_argument('--additive', dest='additive', default=False, action='store_true', help="use additive compositing") parser.add_argument('--mask-name', dest='mask_name', default=None, help="prefix name for alpha mask to use (full/rounded/hex") parser.add_argument('--mask-layout', dest='mask_layout', default=None, help="use image as source of mine grid points") parser.add_argument('--mask-scale', dest='mask_scale', default=1.0, type=float, help="Scale mask layout (squeeze)") parser.add_argument('--mask-width', dest='mask_width', type=int, default=15, help="width for computed mask") parser.add_argument('--mask-height', dest='mask_height', type=int, default=15, help="height for computed mask") parser.add_argument('--mask-radius', dest='mask_radius', default=None, type=float, help="radius for computed mask") parser.add_argument('--layout', dest='layout', default=None, help="layout json file") parser.add_argument('--layout-scale', dest='layout_scale', default=1, type=int, help="Scale layout") parser.add_argument('--batch-size', dest='batch_size', type=int, default=100, help="number of images to decode at once") parser.add_argument('--passthrough', dest='passthrough', default=False, action='store_true', help="Use originals instead of reconstructions") parser.add_argument('--anchor-offset', dest='anchor_offset', default=None, help="use json file as source of each anchors offsets") parser.add_argument('--anchor-offset-a', dest='anchor_offset_a', default="42", type=str, help="which indices to combine for offset a") parser.add_argument('--anchor-offset-b', dest='anchor_offset_b', default="31", type=str, help="which indices to combine for offset b") parser.add_argument("--image-size", dest='image_size', type=int, default=64, help="size of (offset) images") parser.add_argument('--global-offset', dest='global_offset', default=None, help="use json file as source of global offsets") parser.add_argument('--global-indices', dest='global_indices', default=None, type=str, help="offset indices to apply globally") parser.add_argument('--global-scale', dest='global_scale', default=1.0, type=float, help="scaling factor for global offset") args = parser.parse_args(args) template_dict = {} if args.seed: np.random.seed(args.seed) random.seed(args.seed) global_offset = None if args.global_offset is not None: offsets = get_json_vectors(args.global_offset) global_offset = plat.sampling.get_global_offset(offsets, args.global_indices, args.global_scale) anchor_images = None if args.anchor_image is not None: _, _, anchor_images = anchors_from_image(args.anchor_image, image_size=(args.image_size, args.image_size)) elif args.anchor_mine is not None: _, _, anchor_images = anchors_from_image(args.anchor_mine, image_size=(args.image_size, args.image_size)) basename = os.path.basename(args.anchor_mine) template_dict["BASENAME"] = os.path.splitext(basename)[0] anchors = None if not args.passthrough: dmodel = zoo.load_model(args.model, args.model_file, args.model_type, args.model_interface) workq = anchor_images[:] anchors_list = [] while(len(workq) > 0): print("Processing {} anchors".format(args.batch_size)) curq = workq[:args.batch_size] workq = workq[args.batch_size:] cur_anchors = dmodel.encode_images(curq) for c in cur_anchors: anchors_list.append(c) anchors = np.asarray(anchors_list) if anchors is None: anchors = np.random.normal(loc=0, scale=1, size=(args.cols * args.rows, 100)) anchor_offsets = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor anchor_offsets = get_json_vectors(args.anchor_offset) canvas = Canvas(args.width, args.height, args.xmin, args.xmax, args.ymin, args.ymax, args.mask_name, args.image_size, args.do_check_bounds) if args.background_image is not None: canvas.set_background(args.background_image) workq = [] do_hex = True if args.layout: with open(args.layout) as json_file: layout_data = json.load(json_file) xy = np.array(layout_data["xy"]) grid_size = layout_data["size"] roots = layout_data["r"] if "s" in layout_data: s = layout_data["s"] else: s = None for i, pair in enumerate(xy): x = pair[0] * canvas.canvas_xmax / grid_size[0] y = pair[1] * canvas.canvas_ymax / grid_size[1] a = (pair[0] + 0.5 * s[i]) / float(grid_size[0]) b = (pair[1] + 0.5 * s[i]) / float(grid_size[1]) r = roots[i] if s is None: scale = args.layout_scale else: scale = s[i] * args.layout_scale # print("Placing {} at {}, {} because {},{} and {}, {}".format(scale, x, y, canvas.canvas_xmax, canvas.canvas_ymax, grid_size[0], grid_size[1])) if args.passthrough: output_image = anchor_images[r] canvas.place_image(output_image, x, y, args.additive, scale=scale) else: if args.anchor_mine is not None or args.random_mine: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) elif anchor_offsets is not None: z = apply_anchor_offsets(anchors[r], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = anchors[r] if global_offset is not None: z = z + global_offset # print("Storing {},{} with {}".format(x, y, len(z))) workq.append({ "z": z, "x": x, "y": y, "s": scale }) elif args.mask_layout or args.mask_radius: if args.mask_layout: rawim = imread(args.mask_layout); if len(rawim.shape) == 2: im_height, im_width = rawim.shape mask_layout = rawim else: im_height, im_width, _ = rawim.shape mask_layout = rawim[:,:,0] else: im_height, im_width = args.mask_height, args.mask_width mask_layout = make_mask_layout(im_height, im_width, args.mask_radius) for xpos in range(im_width): for ypos in range(im_height): a = float(xpos) / (im_width - 1) if do_hex and ypos % 2 == 0: a = a + 0.5 / (im_width - 1) x = args.mask_scale * canvas.xmax * a b = float(ypos) / (im_height - 1) y = args.mask_scale * canvas.ymax * b if not mask_layout[ypos][xpos] > 128: pass elif args.passthrough: if args.anchor_canvas: cur_anchor_image = canvas.get_anchor(x, y, args.image_size) else: cur_anchor_image = anchor_images[0] canvas.place_image(cur_anchor_image, x, y, args.additive, None) else: if args.anchor_canvas: cur_anchor_image = canvas.get_anchor(x, y, args.image_size) zs = dmodel.encode_images([cur_anchor_image]) z = zs[0] elif len(anchors) == 1 or anchor_offsets is not None: z = apply_anchor_offsets(anchors[0], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) if global_offset is not None: z = z + global_offset workq.append({ "z": z, "x": x, "y": y, "s": None }) while(len(workq) > 0): curq = workq[:args.batch_size] workq = workq[args.batch_size:] latents = [e["z"] for e in curq] images = dmodel.sample_at(np.array(latents)) for i in range(len(curq)): # print("Placing {},{} with {}".format(curq[i]["x"], curq[i]["y"], len(latents))) canvas.place_image(images[i], curq[i]["x"], curq[i]["y"], args.additive, scale=curq[i]["s"]) # print("Placed") template_dict["SIZE"] = args.image_size outfile = plat.sampling.emit_filename(args.save_path, template_dict, args); canvas.save(outfile)
def main(cliargs): parser = argparse.ArgumentParser(description="Plot model samples") parser.add_argument("--interface", dest='model_class', type=str, default="plat.interface.discgen.DiscGenModel", help="class encapsulating model") parser.add_argument("--model", dest='model', type=str, default=None, help="path to the saved model") parser.add_argument("--width", type=int, default=512, help="width of canvas to render in pixels") parser.add_argument("--height", type=int, default=512, help="height of canvas to render in pixels") parser.add_argument("--rows", type=int, default=3, help="number of rows of anchors") parser.add_argument("--cols", type=int, default=3, help="number of columns of anchors") parser.add_argument("--xmin", type=int, default=0, help="min x in virtual space") parser.add_argument("--xmax", type=int, default=100, help="max x in virtual space") parser.add_argument("--ymin", type=int, default=0, help="min y in virtual space") parser.add_argument("--ymax", type=int, default=100, help="max y in virtual space") parser.add_argument("--save-path", type=str, default="out.png", help="where to save the generated samples") parser.add_argument("--seed", type=int, default=None, help="Optional random seed") parser.add_argument('--anchor-image', dest='anchor_image', default=None, help="use image as source of anchors") parser.add_argument('--anchor-mine', dest='anchor_mine', default=None, help="use image as single source of mine coordinates") parser.add_argument( '--random-mine', dest='random_mine', default=False, action='store_true', help="use random sampling as source of mine coordinates") parser.add_argument('--additive', dest='additive', default=False, action='store_true', help="use additive compositing") parser.add_argument( '--mask-name', dest='mask_name', default="rounded", help="prefix name for alpha mask to use (full/rounded/hex") parser.add_argument('--mask-layout', dest='mask_layout', default=None, help="use image as source of mine grid points") parser.add_argument('--mask-scale', dest='mask_scale', default=1.0, type=float, help="Scale mask layout (squeeze)") parser.add_argument('--mask-width', dest='mask_width', type=int, default=15, help="width for computed mask") parser.add_argument('--mask-height', dest='mask_height', type=int, default=15, help="height for computed mask") parser.add_argument('--mask-radius', dest='mask_radius', default=None, type=float, help="radius for computed mask") parser.add_argument('--layout', dest='layout', default=None, help="layout json file") parser.add_argument('--batch-size', dest='batch_size', type=int, default=100, help="number of images to decode at once") parser.add_argument('--passthrough', dest='passthrough', default=False, action='store_true', help="Use originals instead of reconstructions") parser.add_argument('--anchor-offset', dest='anchor_offset', default=None, help="use json file as source of each anchors offsets") parser.add_argument('--anchor-offset-a', dest='anchor_offset_a', default="42", type=str, help="which indices to combine for offset a") parser.add_argument('--anchor-offset-b', dest='anchor_offset_b', default="31", type=str, help="which indices to combine for offset b") parser.add_argument("--image-size", dest='image_size', type=int, default=64, help="size of (offset) images") args = parser.parse_args(cliargs) if args.seed: np.random.seed(args.seed) random.seed(args.seed) anchor_images = None if args.anchor_image is not None: _, _, anchor_images = anchors_from_image(args.anchor_image, image_size=(args.image_size, args.image_size)) elif args.anchor_mine is not None: _, _, anchor_images = anchors_from_image(args.anchor_mine, image_size=(args.image_size, args.image_size)) anchors = None if not args.passthrough: model_class_parts = args.model_class.split(".") model_class_name = model_class_parts[-1] model_module_name = ".".join(model_class_parts[:-1]) print("Loading {} interface from {}".format(model_class_name, model_module_name)) ModelClass = getattr(importlib.import_module(model_module_name), model_class_name) print("Loading model from {}".format(args.model)) dmodel = ModelClass(filename=args.model) if anchor_images is not None: anchors = dmodel.encode_images(anchor_images) if anchors is None: anchors = np.random.normal(loc=0, scale=1, size=(args.cols * args.rows, 100)) anchor_offsets = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor anchor_offsets = get_json_vectors(args.anchor_offset) canvas = Canvas(args.width, args.height, args.xmin, args.xmax, args.ymin, args.ymax, args.mask_name, args.image_size) workq = [] do_hex = True if args.layout: with open(args.layout) as json_file: layout_data = json.load(json_file) xy = np.array(layout_data["xy"]) roots = layout_data["r"] for i, pair in enumerate(xy): x = pair[0] * canvas.xmax y = pair[1] * canvas.ymax a = pair[0] b = pair[1] r = roots[i] if args.passthrough: output_image = anchor_images[r] canvas.place_image(output_image, x, y, args.additive) else: if args.anchor_mine is not None or args.random_mine: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) elif anchor_offsets is not None: z = apply_anchor_offsets(anchors[r], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = anchors[r] workq.append({"z": z, "x": x, "y": y}) elif args.mask_layout or args.mask_radius: if args.mask_layout: rawim = imread(args.mask_layout) if len(rawim.shape) == 2: im_height, im_width = rawim.shape mask_layout = rawim else: im_height, im_width, _ = rawim.shape mask_layout = rawim[:, :, 0] else: im_height, im_width = args.mask_height, args.mask_width mask_layout = make_mask_layout(im_height, im_width, args.mask_radius) for xpos in range(im_width): for ypos in range(im_height): a = float(xpos) / (im_width - 1) if do_hex and ypos % 2 == 0: a = a + 0.5 / (im_width - 1) x = args.mask_scale * canvas.xmax * a b = float(ypos) / (im_height - 1) y = args.mask_scale * canvas.ymax * b if not mask_layout[ypos][xpos] > 128: pass elif args.passthrough: output_image = anchor_images[0] canvas.place_image(output_image, x, y, args.additive) else: if len(anchors) == 1 or anchor_offsets is not None: z = apply_anchor_offsets(anchors[0], anchor_offsets, a, b, args.anchor_offset_a, args.anchor_offset_b) else: z = create_mine_canvas(args.rows, args.cols, b, a, anchors) workq.append({"z": z, "x": x, "y": y}) while (len(workq) > 0): curq = workq[:args.batch_size] workq = workq[args.batch_size:] latents = [e["z"] for e in curq] images = dmodel.sample_at(np.array(latents)) for i in range(len(curq)): canvas.place_image(images[i], curq[i]["x"], curq[i]["y"], args.additive) canvas.save(args.save_path)
def do_convert(raw_infile, outfile, dmodel, do_smile, smile_offsets, image_size, min_span, initial_steps=1, recon_steps=1, offset_steps=2, check_extent=True): failure_return_status = False, False, False infile = resized_input_file did_resize, wide_image = resize_to_a_good_size(raw_infile, infile) if not did_resize: return failure_return_status # first align input face to canonical alignment and save result try: if not doalign.align_face(infile, aligned_file, image_size, min_span=min_span, max_extension_amount=0): return failure_return_status except Exception as e: # get_landmarks strangely fails sometimes (see bad_shriek test image) print("faceswap: doalign failure {}".format(e)) return failure_return_status # go ahead and cache the main (body) image and landmarks, and fail if face is too big try: body_image_array = imread(infile, mode='RGB') print(body_image_array.shape) body_rect, body_landmarks = faceswap.core.get_landmarks( body_image_array) max_extent = faceswap.core.get_max_extent(body_landmarks) except faceswap.core.NoFaces: print("faceswap: no faces in {}".format(infile)) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status if check_extent and max_extent > max_allowable_extent: print("face to large: {}".format(max_extent)) return failure_return_status elif check_extent and max_extent < min_allowable_extent: print("face to small: {}".format(max_extent)) return failure_return_status else: print("face not too large: {}".format(max_extent)) # read in aligned file to image array _, _, anchor_images = anchors_from_image(aligned_file, image_size=(image_size, image_size)) # encode aligned image array as vector, apply offset encoded = dmodel.encode_images(anchor_images)[0] if smile_offsets is not None: smile_vector = smile_offsets[0] smile_score = np.dot(smile_vector, encoded) smile_detected = (smile_score > 0) print("Smile vector detector:", smile_score, smile_detected) if do_smile is None: has_smile = smile_detected else: has_smile = not str2bool(do_smile) if has_smile: print("Smile detected, removing") chosen_anchor = [encoded, encoded - smile_vector] else: print("Smile not detected, providing") chosen_anchor = [encoded, encoded + smile_vector] else: has_smile = False chosen_anchor = [encoded, encoded] z_dim = dmodel.get_zdim() # TODO: fix variable renaming anchors, samples_sequence_dir, movie_file = chosen_anchor, sequence_dir, outfile # these are the output png files samples_sequence_filename = samples_sequence_dir + generic_sequence # prepare output directory make_or_cleanup(samples_sequence_dir) # generate latents from anchors z_latents = create_mine_grid(rows=1, cols=offset_steps, dim=z_dim, space=offset_steps - 1, anchors=anchors, spherical=True, gaussian=False) samples_array = dmodel.sample_at(z_latents) print("Samples array: ", samples_array.shape) # save original file as-is for i in range(initial_steps): filename = samples_sequence_filename.format(1 + i) imsave(filename, body_image_array) print("original file: {}".format(filename)) # build face swapped reconstruction sample = samples_array[0] try: # face_image_array = (255 * np.dstack(sample)).astype(np.uint8) face_image_array = (255 * np.dstack(sample)).astype(np.uint8) imsave(recon_file, face_image_array) # face_landmarks = faceswap.core.get_landmarks(face_image_array) # faceswap.core.do_faceswap_from_face(infile, face_image_array, face_landmarks, swapped_file) faceswap.core.do_faceswap(infile, recon_file, swapped_file) print("swapped file: {}".format(swapped_file)) recon_array = imread(swapped_file, mode='RGB') except faceswap.core.NoFaces: print("faceswap: no faces when generating swapped file {}".format( infile)) imsave(debug_file, face_image_array) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status # now save interpolations to recon for i in range(1, recon_steps): frac_orig = ((recon_steps - i) / (1.0 * recon_steps)) frac_recon = (i / (1.0 * recon_steps)) interpolated_im = frac_orig * body_image_array + frac_recon * recon_array filename = samples_sequence_filename.format(i + initial_steps) imsave(filename, interpolated_im) print("interpolated file: {}".format(filename)) final_face_index = len(samples_array) - 1 for i, sample in enumerate(samples_array): try: cur_index = i + initial_steps + recon_steps stack = np.dstack(sample) face_image_array = (255 * np.dstack(sample)).astype(np.uint8) # if i == final_face_index: # imsave(transformed_file, face_image_array) face_rect, face_landmarks = faceswap.core.get_landmarks( face_image_array) filename = samples_sequence_filename.format(cur_index) imsave(transformed_file, face_image_array) # faceswap.core.do_faceswap_from_face(infile, face_image_array, face_landmarks, filename) faceswap.core.do_faceswap(infile, transformed_file, filename) print("generated file: {}".format(filename)) except faceswap.core.NoFaces: print("faceswap: no faces in {}".format(infile)) return failure_return_status except faceswap.core.TooManyFaces: print("faceswap: too many faces in {}".format(infile)) return failure_return_status last_sequence_index = initial_steps + recon_steps + offset_steps - 1 last_filename = samples_sequence_filename.format(last_sequence_index) shutil.copyfile(last_filename, outfile) return True, has_smile, wide_image
def run_with_args(args, dmodel, cur_anchor_image, cur_save_path, cur_z_step): if args.seed is not None: np.random.seed(args.seed) random.seed(args.seed) anchor_images = None if args.anchors: _, get_anchor_images = lazy_init_fuel_dependencies() allowed = None prohibited = None include_targets = False if (args.allowed): include_targets = True allowed = map(int, args.allowed.split(",")) if (args.prohibited): include_targets = True prohibited = map(int, args.prohibited.split(",")) anchor_images = get_anchor_images(args.dataset, args.split, args.offset, args.stepsize, args.numanchors, allowed, prohibited, args.image_size, args.color_convert, include_targets=include_targets) if cur_anchor_image is not None: _, _, anchor_images = anchors_from_image(cur_anchor_image, image_size=(args.image_size, args.image_size)) if args.offset > 0: anchor_images = anchor_images[args.offset:] # untested if args.numanchors is not None: anchor_images = anchor_images[:args.numanchors] if args.passthrough: print('Preparing image grid...') img = grid2img(anchor_images, args.rows, args.cols, not args.tight) img.save(cur_save_path) sys.exit(0) if dmodel is None: model_class_parts = args.model_class.split(".") model_class_name = model_class_parts[-1] model_module_name = ".".join(model_class_parts[:-1]) print("Loading {} interface from {}".format(model_class_name, model_module_name)) ModelClass = getattr(importlib.import_module(model_module_name), model_class_name) print("Loading model from {}".format(args.model)) dmodel = ModelClass(filename=args.model) if anchor_images is not None: x_queue = anchor_images[:] anchors = None # print("========> ENCODING {} at a time".format(args.batch_size)) while (len(x_queue) > 0): cur_x = x_queue[:args.batch_size] x_queue = x_queue[args.batch_size:] encoded = dmodel.encode_images(cur_x) if anchors is None: anchors = encoded else: anchors = np.concatenate((anchors, encoded), axis=0) # anchors = dmodel.encode_images(anchor_images) elif args.anchor_vectors is not None: anchors = get_json_vectors(args.anchor_vectors) else: anchors = None if args.invert_anchors: anchors = -1 * anchors if args.encoder: if anchors is not None: output_vectors(anchors) else: stream_output_vectors(dmodel, args.dataset, args.split, batch_size=args.batch_size) sys.exit(0) global_offset = None if args.anchor_offset is not None: # compute anchors as offsets from existing anchor offsets = get_json_vectors(args.anchor_offset) if args.anchor_noise: anchors = anchors_noise_offsets( anchors, offsets, args.rows, args.cols, args.spacing, cur_z_step, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) else: anchors = anchors_from_offsets( anchors[0], offsets, args.anchor_offset_x, args.anchor_offset_y, args.anchor_offset_x_minscale, args.anchor_offset_y_minscale, args.anchor_offset_x_maxscale, args.anchor_offset_y_maxscale) if args.global_offset is not None: offsets = get_json_vectors(args.global_offset) if args.global_ramp: offsets = cur_z_step * offsets global_offset = get_global_offset(offsets, args.global_indices, args.global_scale) z_dim = dmodel.get_zdim() # I don't remember what partway/encircle do so they are not handling the chain layout # this handles the case (at least) of mines with random anchors if (args.partway is not None) or args.encircle or (args.mine and anchors is None): srows = ((args.rows // args.spacing) + 1) scols = ((args.cols // args.spacing) + 1) rand_anchors = generate_latent_grid(z_dim, rows=srows, cols=scols, fan=False, gradient=False, spherical=False, gaussian=False, anchors=None, anchor_images=None, mine=False, chain=False, spacing=args.spacing, analogy=False, rand_uniform=args.uniform) if args.partway is not None: l = len(rand_anchors) clipped_anchors = anchors[:l] anchors = (1.0 - args.partway ) * rand_anchors + args.partway * clipped_anchors elif args.encircle: anchors = surround_anchors(srows, scols, anchors, rand_anchors) else: anchors = rand_anchors z = generate_latent_grid(z_dim, args.rows, args.cols, args.fan, args.gradient, not args.linear, args.gaussian, anchors, anchor_images, args.mine, args.chain, args.spacing, args.analogy) if global_offset is not None: z = z + global_offset grid_from_latents(z, dmodel, args.rows, args.cols, anchor_images, args.tight, args.shoulders, cur_save_path, args.batch_size) return dmodel