import sys import random import json import numpy from pathlib import Path from PIL import Image from tinygrad.tensor import Tensor from tinygrad.nn.optim import SGD from tinygrad.nn.state import safe_save, safe_load, get_state_dict, load_state_dict from examples.vgg7_helpers.waifu2x import image_load, image_save, Vgg7 # amount of context erased by model CONTEXT = 7 def get_sample_count(samples_dir): try: samples_dir_count_file = open(samples_dir + "/sample_count.txt", "r") v = samples_dir_count_file.readline() samples_dir_count_file.close() return int(v) except: return 0 def set_sample_count(samples_dir, sc): with open(samples_dir + "/sample_count.txt", "w") as file: file.write(str(sc) + "\n") if len(sys.argv) < 2: print("python3 -m examples.vgg7 import MODELJSON MODEL") print(" imports a waifu2x JSON vgg_7 model, i.e. waifu2x/models/vgg_7/art/scale2.0x_model.json") print(" into a safetensors file") print(" weight tensors are ordered in tinygrad/ncnn form, as so: (outC,inC,H,W)") print(" *this format is used by most other commands in this program*") print("python3 -m examples.vgg7 import_kinne MODEL_KINNE MODEL_SAFETENSORS") print(" imports a model in 'KINNE' format (raw floats: used by older versions of this example) into safetensors") print("python3 -m examples.vgg7 execute MODEL IMG_IN IMG_OUT") print(" given an already-nearest-neighbour-scaled image, runs vgg7 on it") print(" output image has 7 pixels removed on all edges") print(" do not run on large images, will have *hilarious* RAM use") print("python3 -m examples.vgg7 execute_full MODEL IMG_IN IMG_OUT") print(" does the 'whole thing' (padding, tiling)") print(" safe for large images, etc.") print("python3 -m examples.vgg7 new MODEL") print(" creates a new model (experimental)") print("python3 -m examples.vgg7 train MODEL SAMPLES_DIR ROUNDS ROUNDS_SAVE") print(" trains a model (experimental)") print(" (how experimental? well, every time I tried it, it flooded w/ NaNs)") print(" note: ROUNDS < 0 means 'forever'. ROUNDS_SAVE <= 0 is not a good idea.") print(" expects roughly execute's input as SAMPLES_DIR/IDXa.png") print(" expects roughly execute's output as SAMPLES_DIR/IDXb.png") print(" (i.e. my_samples/0a.png is the first pre-nearest-scaled image,") print(" my_samples/0b.png is the first original image)") print(" in addition, SAMPLES_DIR/samples_count.txt indicates sample count") print(" won't pad or tile, so keep image sizes sane") print("python3 -m examples.vgg7 samplify IMG_A IMG_B SAMPLES_DIR SIZE") print(" creates overlapping micropatches (SIZExSIZE w/ 7-pixel border) for training") print(" maintains/creates samples_count.txt automatically") print(" unlike training, IMG_A must be exactly half the size of IMG_B") sys.exit(1) cmd = sys.argv[1] vgg7 = Vgg7() def nansbane(p): if numpy.isnan(numpy.min(p.numpy())): raise Exception("A NaN in the model has been detected. This model will not be interacted with to prevent further damage.") def load_and_save(path, save): if save: for v in vgg7.get_parameters(): nansbane(v) st = get_state_dict(vgg7) safe_save(st, path) else: st = safe_load(path) load_state_dict(vgg7, st) for v in vgg7.get_parameters(): nansbane(v) if cmd == "import": src = sys.argv[2] model = sys.argv[3] vgg7.load_waifu2x_json(json.load(open(src, "rb"))) load_and_save(model, True) elif cmd == "import_kinne": # tinygrad wasn't doing safetensors when this example was written # it's possible someone might have a model around using the resulting interim format src = sys.argv[2] model = sys.argv[3] index = 0 for t in vgg7.get_parameters(): fn = src + "/snoop_bin_" + str(index) + ".bin" t.assign(Tensor(numpy.fromfile(fn, "