def upload(): """Runs a pix2pix image upload and processing job on Spell. Expects image pair files in images/pix2pix-dataset. These can be built using the image_pairs function. After upload, images are processed to remove alpha channel since pix2pix fails on images with alpha channels. Args: machine_type: The machine type to use for the run. Defaults to 'CPU'. Raises: RuntimeError: If image files are missing. ValueError: If any image file name is illegal. """ log("Preparing to upload images...") if localfs.isempty(paths["datasetlocal"]): raise RuntimeError("Missing images in {}".format( paths["datasetlocal"])) for filename in localfs.ls(paths["datasetlocal"]): if " " in filename: # TODO check for non-alphanumeric characters raise ValueError("Image file names cannot contain spaces.") log("Removing alpha channel from images...") imageutils.strip_alpha_channel(paths["datasetlocal"]) log("Uploading. Please wait...") spell.upload(paths["datasetlocal"], paths["datasetremote"]) log("Upload complete.")
def hyperparam_search(args): log("Building hyperparameter grid. Please wait...") img_group_name = getstr(args, 0) imgs_base_dir = localfs.filepath(paths["imagesBaseLocal"], img_group_name) style_imgs_dir = localfs.filepath(imgs_base_dir, "styles") style_imgs = localfs.ls(style_imgs_dir) content_img_dir = localfs.filepath(imgs_base_dir, "content") content_img = localfs.ls(content_img_dir)[0] neural_args = params.neural_style_hypergrid neural_style_cmd = _neural_style_cmd(neural_args, style_imgs, content_img) neural_style_cmd += " --style_weight :STYLE_WEIGHT:" neural_style_cmd += " --temporal_weight :TEMPORAL_WEIGHT:" search = spell.client.hyper.new_grid_search( { #"STYLE_WEIGHT": spell.get_value_spec(["1e4","1e1","1e7"]), #"TEMPORAL_WEIGHT": spell.get_value_spec(["2e2","2e6","2e-2"]) "STYLE_WEIGHT": spell.get_value_spec(neural_args.style_weights), "TEMPORAL_WEIGHT": spell.get_value_spec( neural_args.temporal_weights) }, command=neural_style_cmd, machine_type="K80", github_url="https://github.com/cysmith/neural-style-tf", attached_resources=_mounts(img_group_name)) for run in search.runs: spell.label_run(run, "Style Transfer hyperparams") logFilePath = localfs.filepath(paths["resultsDirLocal"], "log-hyperparams-{}.txt".format(search.id)) with open(logFilePath, "w") as f: f.write("{} = {}\n".format("Search ID", search.id)) f.write("{} = {}\n".format( "Command", "python " + sys.argv[0] + " sthyperparams " + (" ".join(args)))) f.write("{} = {}\n".format("Image group", img_group_name)) f.write("{} = {}\n".format("Parameters", neural_args)) f.write("{} = {}\n".format("Style images", " ".join(style_imgs))) f.write("{} = {}\n".format("Content image", content_img)) msg = "Hyperparameter search {} has started. Visit https://web.spell.run/{}/hyper-searches/{} for progress." msg += "\nWhen all runs have completed, execute 'python run.py stdownload {}-{}'" msg += "\nto download the result files." log( msg.format(search.id, spell.get_username(), search.id, search.runs[0].id, search.runs[-1].id))
def _validate_local(): for d in localfs.ls(paths["imagesBaseLocal"]): style_images = localfs.ls( localfs.filepath(paths["imagesBaseLocal"], d, "styles")) content_images = localfs.ls( localfs.filepath(paths["imagesBaseLocal"], d, "content")) if not style_images: raise FileNotFoundError( "Style images folder [{}] is empty.".format( paths["stylesDirLocal"])) if not content_images: raise FileNotFoundError( "Content images folder [{}] is empty.".format( paths["contentDirLocal"])) def validate_filenames(names): for n in names: if " " in n: raise ValueError( "Image file names cannot contain spaces." ) # TODO add non-alphanumeric character checking validate_filenames(style_images) validate_filenames(content_images)
def upload(args): """ Runs a BigGAN image upload job on Spell. """ log("Preparing to upload images...") d = localfs.filepath(paths["datasetLocal"], paths["datasetName"]) if localfs.isempty(d): raise RuntimeError("Missing images in dataset folder "+d) def validate_filenames(names): for n in names: if " " in n: raise ValueError("Image file names cannot contain spaces. [{}]".format(n)) # TODO add non-alphanumeric character checking validate_filenames(localfs.ls(d)) log("Uploading. Please wait...") spell.upload(paths["datasetLocal"], paths["datasetRemoteDir"]) log("Upload complete.")
def extract_subimages(img_path, output_dir_path, subimage_width, subimage_height, num_subimages_x, num_subimages_y, append=False, rotation=0, flip_h=False, flip_v=False): if num_subimages_x < 2 or num_subimages_y < 2: raise ValueError( "number of subimages arguments must be a value greater than 1") if not append: fs.rm(output_dir_path) if not fs.exists(output_dir_path): fs.mkdir(output_dir_path) img = Image.open(img_path) img = rotate(img, rotation) img = flip(img, flip_h, flip_v) img_width, img_height = img.size dx = float(img_width - subimage_width) / (num_subimages_x - 1) dy = float(img_height - subimage_height) / (num_subimages_y - 1) max_num_subimages = num_subimages_x * num_subimages_y counter = len(fs.ls(output_dir_path)) + 1 for j in range(num_subimages_y): for i in range(num_subimages_x): xo = int(round(dx * i)) yo = int(round(dy * j)) subimage = img.crop( (xo, yo, xo + subimage_width, yo + subimage_height)) num_leading_zeros = len(str(max_num_subimages)) + 1 filename = ("{:0" + str(num_leading_zeros) + "d}.png").format(counter) subimage.save(fs.filepath(output_dir_path, filename)) counter += 1
def image_pairs(args): """Builds pairs of images on local computer. Expects two input images, png or jpg, named A and B in the directory images/pix2pix-sources. Exports image pair files to images/pix2pix-dataset. Args: args: The arguments subimage width subimage height number of subimages in x number of subimages in y rotate 180 (default False) flip horizontal (default False) flip vertical (default False) Raises: RuntimeError: If arguments are missing """ log("Preparing to make image pairs...") source_dir = paths["sourceslocal"] source_a = localfs.findfirst(source_dir, ["A.jpg", "A.jpeg", "A.png"]) source_b = localfs.findfirst(source_dir, ["B.jpg", "B.jpeg", "B.png"]) img_path_a = localfs.filepath(source_dir, source_a) img_path_b = localfs.filepath(source_dir, source_b) log(" Image A: {}".format(img_path_a)) log(" Image B: {}".format(img_path_b)) sub_w = getint(args, 0, 0) sub_h = getint(args, 1, 0) num_x = getint(args, 2, 0) num_y = getint(args, 3, 0) rotate = getboolean(args, 4) flip_h = getboolean(args, 5) output_dir_a = localfs.filepath(paths["datasetlocal"], "A") output_dir_b = localfs.filepath(paths["datasetlocal"], "B") log("Extracting subimages...") localfs.rm(paths["datasetlocal"]) localfs.mkdir(paths["datasetlocal"]) def process(img_path, out_dir): imageutils.extract_subimages(img_path, out_dir, sub_w, sub_h, num_x, num_y, False, 0) if rotate: imageutils.extract_subimages(img_path, out_dir, sub_w, sub_h, num_x, num_y, True, 180) if flip_h: imageutils.extract_subimages(img_path, out_dir, sub_w, sub_h, num_x, num_y, True, 180, True) elif flip_h: imageutils.extract_subimages(img_path, out_dir, sub_w, sub_h, num_x, num_y, True, 0, True) process(img_path_a, output_dir_a) process(img_path_b, output_dir_b) log("Building image pairs...") pairs_dir_path = localfs.filepath(paths["datasetlocal"], "pairs") if not localfs.exists(pairs_dir_path): localfs.mkdir(pairs_dir_path) for a, b in zip(localfs.ls(output_dir_a), localfs.ls(output_dir_b)): img_a_path = localfs.filepath(output_dir_a, a) img_b_path = localfs.filepath(output_dir_b, b) imageutils.create_pair(pairs_dir_path, img_a_path, img_b_path, a, b) #localfs.rm(output_dir_a) #localfs.rm(output_dir_b) for fname in localfs.ls(pairs_dir_path): fpath = localfs.filepath(pairs_dir_path, fname) fpath_new = localfs.filepath(paths["datasetlocal"], fname) localfs.mv(fpath, fpath_new) localfs.rm(pairs_dir_path) log("Done. Image pairs are in the directory '{}'".format( paths["datasetlocal"])) log("You can now send the upload command to send the images to Spell.")