Initial Before and Afters
ffmpeg.exe -hide_banner -y -i lazarus_man_the_95_pilot_part2_4trk_2997i_Q0034521_20230519_new_out.mov -map v:0 -vf dedot -c:v prores -c:a copy outtest.mov
Alchemist 29.97 to 23.98
ESRGAN uprez
python inference_realesrgan.py -n RealESRGAN_x4plus -i infile --outscale 3.5 --face_enhance
Wrap and audio synce per WB delivery spec
??????????? WIP
6/6/23
ffmpeg.exe -hide_banner -y -i input.mov -vf dedot=ct=0:tc=1 -c:v prores_ks -profile:v 3 -c:a copy output.mov
6/13/23
### Last edit 10:30am 06/13/23 - moved Queue process external to the class import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue queue = Queue() class Watcher: def __init__(self, directory): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} def run(self): event_handler = FileSystemEventHandler() event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) input_path = event.src_path output_path = input_path.replace("\wip", "\out") ## HARD coded res values. Could be better. width = 1920 height = 1080 ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -c:v prores_ks -profile:v 3 -vf dedot=ct=0:tc=1,tvai_up=model=prob-3:scale=4,scale={}:{} {}".format(input_path, width, height, output_path) print(ffmpeg_command) queue.put(ffmpeg_command) print("############################################################<- QUEUE") print (queue) print("############################################################<- QUEUE") while not queue.empty(): ffmpeg_command = queue.get() time.sleep(30) print ("running comand") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print("command done") def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) if __name__ == "__main__": directory = sys.argv[1] watcher = Watcher(directory) watcher.run()
06/16/23
### Last edit 01:07pm 06/16/23 v8 - added padding and 4x3 matte and hyper parameters import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue queue = Queue() class Watcher: def __init__(self, directory): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} def run(self): event_handler = FileSystemEventHandler() event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) input_path = event.src_path output_path = input_path.replace("\wip", "\out") ## HARD coded res values. Could be better. width = 1920 height = 1080 ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -c:a copy -c:v prores_ks -profile:v 3 -filter_complex dedot=ct=0:tc=1,tvai_up=model=prob-3:scale=4::w=3840:h=2160:preblur=50:noise=30:details=50:halo:20:blur=10:compression=0:estimate=20,scale={}:{}:out_color_matrix=bt709:flags=lanczos,crop=trunc({}*1.33333):{},pad={}:{}:-1:-1:color=black {}".format(input_path, width, height, height, height, width, height, output_path) print(ffmpeg_command) if queue.empty(): print ("Initializing, processing clip") time.sleep(5000) queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #Delay for Alchemist to finish while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) if __name__ == "__main__": directory = sys.argv[1] watcher = Watcher(directory) watcher.run()
06/26/23 - nlmean addition to ffmpeg command
ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i D:\Alchemist\out_2398_sd\AMERICAN_KICKBOXER_PART_1_245469C_15sec_2398.mov -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot=rainbows:lt=1.0:tl=0.0,nlmeans=1:5:5:3:3,tvai_up=model=prob-3:scale=0:w=1920:h=1080:preblur=1:noise=0.05:details=0.5:halo=0.2:blur=0.1:compression=0.12:prenoise=0.02:blend=0.2:device=0:vram=1:instances=1,scale=1920:1080:out_color_matrix=bt709:flags=lanczos D:\Alchemist\out_2398_sd\AMERICAN_KICKBOXER_PART_1_245469C_15sec_2398_tvai_test.mov
06/30/23 - SamurAI_v09.py, grain and LUT addition
### Last edit 10:00am 06/29/23 v9 - worked in denoise, grain, and LUT command import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue queue = Queue() class Watcher: def __init__(self, directory): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} def run(self): event_handler = FileSystemEventHandler() event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) input_path = event.src_path output_path = input_path.replace("\wip", "\out") ## HARD coded values. Could be better. width = 1920 height = 1080 lut = "samurai_unity_709_2_709_33x33_v01.cube" ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot,nlmeans=1:7:7:3:3,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,noise=c0s=25:c0f=t+u,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},crop=trunc({}*1.33333):{},pad={}:{}:-1:-1:color=black {}".format(input_path,width,height,width,height,lut,height,height,width,height,output_path) print(ffmpeg_command) if queue.empty(): print ("Initializing, processing clip") time.sleep(10) queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #Delay for Alchemist to finish while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) if __name__ == "__main__": directory = sys.argv[1] watcher = Watcher(directory) watcher.run()
7/11 - Gui addition
### Last edit 5:00pm 07/06/23 v12 - gui refined import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue import tkinter as tk import shutil ## initialize the queue queue = Queue() ##Define usage def usage(): print("Usage: python samurAI_v10.py [options]") print("Options: watch_folder_path height width LUT_path") print("-h, --help: Show this help message") print("-v, --version: Show the version number") class Watcher: def __init__(self, directory, xaxis, yaxis, lutpath ): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} ##JD Vars self.xaxis = xaxis self.yaxis = yaxis self.lutpath = lutpath def run(self, xaxis, yaxis, lutpath): event_handler = FileSystemEventHandler() ## this is the important one event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) input_path = event.src_path output_path = input_path.replace("\wip", "\out") ## HARD coded values. Could be better. width = self.xaxis height = self.yaxis ##copy and set lut print(self.lutpath) lutname = os.path.basename(self.lutpath) if not os.path.exists(os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)): shutil.copyfile(self.lutpath, os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)) lut = lutname ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot,nlmeans=1:7:7:3:3,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,noise=c0s=25:c0f=t+u,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},crop=trunc({}*1.33333):{},pad={}:{}:-1:-1:color=black {}".format(input_path,width,height,width,height,lut,height,height,width,height,output_path) print(ffmpeg_command) ## delay before processing if queue.empty(): print ("Initializing, processing clip") time.sleep(5000) queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #Delay for Alchemist to finish while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) ######################################################################################start main class WatcherGUI(tk.Frame): ##change these for deployment default_watch_directory = r"N:\engineering\alchemist\samurAI_watchfolders\wip" default_lutpath = r"C:\Program Files\Topaz Labs LLC\Topaz Video AI\samurai_unity_709_2_709_33x33_v01.cube" default_width = 1920 default_height = 1080 def __init__(self, master): super().__init__(master) self.master.title("SamurAI") # Set the window background to dark grey #self.master.config(bg="#323232") self.grid_columnconfigure(1, minsiz=700) # Create the widgets self.directory_label = tk.Label(self, text="Directory:") self.directory_entry = tk.Entry(self) self.directory_entry.insert(0, self.default_watch_directory) self.directory_entry.pack_propagate(False) self.directory_label.grid(row=0, column=0, sticky="w") self.directory_entry.grid(row=0, column=1, columnspan=4, sticky="ew") self.xaxis_label = tk.Label(self, text="X-axis:") self.xaxis_entry = tk.Entry(self) self.xaxis_entry.insert(0, self.default_width) self.xaxis_entry.pack_propagate(True) self.xaxis_label.grid(row=1, column=0, sticky="w") self.xaxis_entry.grid(row=1, column=1, sticky="w") self.yaxis_label = tk.Label(self, text="Y-axis:") self.yaxis_entry = tk.Entry(self) self.yaxis_entry.insert(0, self.default_height) self.yaxis_entry.pack_propagate(True) self.yaxis_label.grid(row=2, column=0, sticky="w") self.yaxis_entry.grid(row=2, column=1, sticky="w") self.lutpath_label = tk.Label(self, text="LUT path:") self.lutpath_entry = tk.Entry(self, state="normal") self.lutpath_entry.insert(0, self.default_lutpath) self.lutpath_entry.pack_propagate(True) self.lutpath_label.grid(row=3, column=0, sticky="w") self.lutpath_entry.grid(row=3, column=1, columnspan=4, sticky="ew") self.run_button = tk.Button(self, text="Run", command=self.run) self.run_button.config(background="red") self.run_button.grid(row=4, column=0, columnspan=2, sticky="ew") # Set the default size of the window self.master.geometry("800x150") def run(self): directory = self.directory_entry.get() xaxis = self.xaxis_entry.get() yaxis = self.yaxis_entry.get() lutpath = self.lutpath_entry.get() if lutpath is None: lutpath = self.default_lutpath if directory is None: directory = self.default_watch_directory watcher = Watcher(directory, xaxis, yaxis, lutpath) watcher.run(xaxis, yaxis, lutpath) def main(): root = tk.Tk() gui = WatcherGUI(root) gui.pack() root.mainloop() if __name__ == "__main__": main()
7/14 - Animation mode added
### Last edit 5:00pm 07/12/23 v16 - added animation button import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue import tkinter as tk import shutil ## initialize the queue queue = Queue() ##Define usage def usage(): print("Usage: python samurAI_v10.py [options]") print("Options: watch_folder_path height width LUT_path") print("-h, --help: Show this help message") print("-v, --version: Show the version number") class Watcher: def __init__(self, directory, xaxis, yaxis, lutpath, animation ): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} ##JD Vars self.xaxis = xaxis self.yaxis = yaxis self.lutpath = lutpath self.animation = animation def run(self, xaxis, yaxis, lutpath, animation): event_handler = FileSystemEventHandler() ## this is the important one event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) ##FFMPEG command variables input_path = event.src_path output_path = input_path.replace("\wip", "\out") temp_output = output_path.replace(".mov", "temp.mov") width = self.xaxis height = self.yaxis animation_toggle = self.animation ##copy and set lut print(self.lutpath) lutname = os.path.basename(self.lutpath) if not os.path.exists(os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)): shutil.copyfile(self.lutpath, os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)) lut = lutname ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot,nlmeans=1:7:7:3:3,dedot=ct=0:tc=1,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,noise=c0s=25:c0f=t+u,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},crop=trunc({}*1.33333):{},pad={}:{}:-1:-1:color=black {}".format(input_path,width,height,width,height,lut,height,height,width,height,output_path) if animation_toggle == True: print(animation_toggle) ffmpeg_command = "ffmpeg -hide_banner -nostdin -y -strict 2 -i {} -sws_flags spline+accurate_rnd+full_chroma_int -color_trc 1 -colorspace 1 -color_primaries 1 -filter_complex dedot,nlmeans=1:7:7:3:3,dedot=ct=0:tc=1,tvai_up=model=iris-1:scale=0:w={}:h={}:preblur=1:noise=1:details=0.4:halo=0.2:blur=0.35:compression=0:device=0:vram=1:instances=1,scale=w={}:h={}:flags=lanczos:threads=0,scale=out_color_matrix=bt709,lut3d={},crop=trunc({}*1.33333):{},pad={}:{}:-1:-1:color=black,split=2[out1][out2] -map [out1] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le {} -map [out2] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le -map 0:a -c:a copy {}".format(input_path,width,height,width,height,lut,height,height,width,height,temp_output,output_path) print(ffmpeg_command) ## delay before processing --------------------------------------------- if queue.empty(): print ("Initializing, processing clip") time.sleep(10) queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #Delay for Alchemist to finish while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) ######################################################################################start main class WatcherGUI(tk.Frame): ##change these for deployment default_watch_directory = r"N:\engineering\alchemist\samurAI_watchfolders\wip" default_lutpath = r"C:\Program Files\Topaz Labs LLC\Topaz Video AI\samurai_unity_709_2_709_33x33_v01.cube" default_width = 1920 default_height = 1080 def __init__(self, master): super().__init__(master) self.master.title("SamurAI") # Set the window background to dark grey #self.master.config(bg="#323232") self.grid_columnconfigure(1, minsiz=700) # Create the widgets self.directory_label = tk.Label(self, text="Directory:") self.directory_entry = tk.Entry(self) self.directory_entry.insert(0, self.default_watch_directory) self.directory_entry.pack_propagate(False) self.directory_label.grid(row=0, column=0, sticky="w") self.directory_entry.grid(row=0, column=1, columnspan=4, sticky="ew") self.xaxis_label = tk.Label(self, text="X-axis:") self.xaxis_entry = tk.Entry(self) self.xaxis_entry.insert(0, self.default_width) self.xaxis_entry.pack_propagate(True) self.xaxis_label.grid(row=1, column=0, sticky="w") self.xaxis_entry.grid(row=1, column=1, sticky="w") self.yaxis_label = tk.Label(self, text="Y-axis:") self.yaxis_entry = tk.Entry(self) self.yaxis_entry.insert(0, self.default_height) self.yaxis_entry.pack_propagate(True) self.yaxis_label.grid(row=2, column=0, sticky="w") self.yaxis_entry.grid(row=2, column=1, sticky="w") self.lutpath_label = tk.Label(self, text="LUT path:") self.lutpath_entry = tk.Entry(self, state="normal") self.lutpath_entry.insert(0, self.default_lutpath) self.lutpath_entry.pack_propagate(True) self.lutpath_label.grid(row=3, column=0, sticky="w") self.lutpath_entry.grid(row=3, column=1, columnspan=4, sticky="ew") # Add the checkbox self.animation_var = tk.BooleanVar() self.animation_checkbox = tk.Checkbutton(self, text="Animation", variable=self.animation_var) self.animation_checkbox.grid(row=4, column=0, sticky="w") self.run_button = tk.Button(self, text="Run", command=self.run) self.run_button.config(background="red") self.run_button.grid(row=5, column=0, columnspan=2, sticky="ew") # Set the default size of the window self.master.geometry("800x150") def run(self): directory = self.directory_entry.get() xaxis = self.xaxis_entry.get() yaxis = self.yaxis_entry.get() lutpath = self.lutpath_entry.get() animation = self.animation_var.get() if lutpath is None: lutpath = self.default_lutpath if directory is None: directory = self.default_watch_directory watcher = Watcher(directory, xaxis, yaxis, lutpath, animation) watcher.run(xaxis, yaxis, lutpath, animation) def main(): root = tk.Tk() gui = WatcherGUI(root) gui.pack() root.mainloop() if __name__ == "__main__": main()
Samurai V17 final
### Last edit 5:00pm 07/12/23 v16 - added animation button import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue import tkinter as tk import shutil ## initialize the queue queue = Queue() ##Define usage def usage(): print("Usage: python samurAI_v10.py [options]") print("Options: watch_folder_path height width LUT_path") print("-h, --help: Show this help message") print("-v, --version: Show the version number") class Watcher: def __init__(self, directory, xaxis, yaxis, lutpath, animation, a_ratio): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} ##JD Vars self.xaxis = xaxis self.yaxis = yaxis self.lutpath = lutpath self.animation = animation self.a_ratio = a_ratio def run(self, xaxis, yaxis, lutpath, animation, a_ratio): event_handler = FileSystemEventHandler() ## this is the important one event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): print("File created:", event.src_path) ##FFMPEG command variables input_path = event.src_path output_path = input_path.replace("\wip", "\out") temp_output = output_path.replace(".mov", "temp.mov") width = self.xaxis height = self.yaxis crop = self.a_ratio animation_toggle = self.animation ##copy and set lut print(self.lutpath) lutname = os.path.basename(self.lutpath) if not os.path.exists(os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)): shutil.copyfile(self.lutpath, os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)) lut = lutname ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot,nlmeans=1:7:7:3:3,dedot=ct=0:tc=1,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,noise=c0s=25:c0f=t+u,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black {}".format(input_path,width,height,width,height,lut,height,crop,height,width,height,output_path) if animation_toggle == True: print(animation_toggle) ffmpeg_command = "ffmpeg -hide_banner -nostdin -y -strict 2 -i {} -sws_flags spline+accurate_rnd+full_chroma_int -color_trc 1 -colorspace 1 -color_primaries 1 -filter_complex dedot,nlmeans=1:7:7:3:3,dedot=ct=0:tc=1,tvai_up=model=iris-1:scale=0:w={}:h={}:preblur=1:noise=1:details=0.4:halo=0.2:blur=0.35:compression=0:device=0:vram=1:instances=1,scale=w={}:h={}:flags=lanczos:threads=0,scale=out_color_matrix=bt709,lut3d={},noise=c0s=25:c0f=t+u,crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black,split=2[out1][out2] -map [out1] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le {} -map [out2] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le -map 0:a -c:a copy {}".format(input_path,width,height,width,height,lut,height,crop,height,width,height,temp_output,output_path) print(ffmpeg_command) ## delay before processing --------------------------------------------- if queue.empty(): print ("Initializing, processing clip") ## logic for waiting until Alchemist is done last_modified_time = os.path.getmtime(input_path) current_time = time.time() while current_time - last_modified_time < 60: time.sleep(10) current_time = time.time() last_modified_time = os.path.getmtime(input_path) ## queue the command after a minute of not growing queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #iter through the Queue while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") if os.path.exists(temp_output): os.remove(temp_output) def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) ######################################################################################start main class WatcherGUI(tk.Frame): ##change these for deployment default_watch_directory = r"N:\engineering\alchemist\samurAI_watchfolders\wip" default_lutpath = r"C:\Program Files\Topaz Labs LLC\Topaz Video AI\samurai_unity_709_2_709_33x33_v01.cube" default_width = 1920 default_height = 1080 default_a_ratio = 1.33333333333 def __init__(self, master): super().__init__(master) self.master.title("SamurAI") # Set the window background to dark grey #self.master.config(bg="#323232") self.grid_columnconfigure(1, minsiz=700) # Create the widgets self.directory_label = tk.Label(self, text="Watch Directory:") self.directory_entry = tk.Entry(self) self.directory_entry.insert(0, self.default_watch_directory) self.directory_entry.pack_propagate(False) self.directory_label.grid(row=0, column=0, sticky="w") self.directory_entry.grid(row=0, column=1, columnspan=4, sticky="ew") self.xaxis_label = tk.Label(self, text="Output X-axis:") self.xaxis_entry = tk.Entry(self) self.xaxis_entry.insert(0, self.default_width) self.xaxis_entry.pack_propagate(True) self.xaxis_label.grid(row=1, column=0, sticky="w") self.xaxis_entry.grid(row=1, column=1, sticky="w") self.yaxis_label = tk.Label(self, text="Output Y-axis:") self.yaxis_entry = tk.Entry(self) self.yaxis_entry.insert(0, self.default_height) self.yaxis_entry.pack_propagate(True) self.yaxis_label.grid(row=2, column=0, sticky="w") self.yaxis_entry.grid(row=2, column=1, sticky="w") self.a_ratio_label = tk.Label(self, text="Original Ratio:") self.a_ratio_entry = tk.Entry(self) self.a_ratio_entry.insert(0, self.default_a_ratio) self.a_ratio_entry.pack_propagate(True) self.a_ratio_label.grid(row=3, column=0, sticky="w") self.a_ratio_entry.grid(row=3, column=1, sticky="w") self.lutpath_label = tk.Label(self, text="LUT path:") self.lutpath_entry = tk.Entry(self, state="normal") self.lutpath_entry.insert(0, self.default_lutpath) self.lutpath_entry.pack_propagate(True) self.lutpath_label.grid(row=4, column=0, sticky="w") self.lutpath_entry.grid(row=4, column=1, columnspan=4, sticky="ew") # Add the checkbox self.animation_var = tk.BooleanVar() self.animation_checkbox = tk.Checkbutton(self, text="Animation", variable=self.animation_var) self.animation_checkbox.grid(row=5, column=0, sticky="w") self.run_button = tk.Button(self, text="Run", command=self.run) self.run_button.config(background="red") self.run_button.grid(row=6, column=0, columnspan=2, sticky="ew") # Set the default size of the window self.master.geometry("800x180") def run(self): directory = self.directory_entry.get() xaxis = self.xaxis_entry.get() yaxis = self.yaxis_entry.get() lutpath = self.lutpath_entry.get() animation = self.animation_var.get() a_ratio = self.a_ratio_entry.get() if lutpath is None: lutpath = self.default_lutpath if directory is None: directory = self.default_watch_directory watcher = Watcher(directory, xaxis, yaxis, lutpath, animation, a_ratio) watcher.run(xaxis, yaxis, lutpath, animation, a_ratio) def main(): root = tk.Tk() gui = WatcherGUI(root) gui.pack() root.mainloop() if __name__ == "__main__": main()
V23 smoke noise black artifact NG
### Last edit 12:15pm 09/06/23 v23 - reverting denoise to nlmeans=1:7:7:3:3 import time import os import sys from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess from subprocess import Popen from queue import Queue import tkinter as tk import shutil import datetime import logging import io ## initialize the queue queue = Queue() ##Define date_add def date_add(filename): """ This function adds the current date to the given filename and reconstructs the full path. Args: filename: The original filename. Returns: The new filename with the current date prepended to the head of the file and the full path reconstructed. """ # Get the current date in the format "YYYYMMDD". current_date = datetime.datetime.now().strftime("%Y%m%d") # Split the filename into the base path and the file name. base_path, file_name = os.path.split(filename) # Prepend the current date to the file name. new_filename = f"{current_date}_{file_name}" # Reconstruct the full path with the new filename. full_path = os.path.join(base_path, new_filename) return full_path ##This module converts a movie path to a dpx one def modify_path(path): """Modifies the given path to the desired path.""" folder_path = path.rsplit('.', 1)[0] last_directory = os.path.split(path)[1].rsplit('.', 1)[0] new_path = os.path.join(folder_path, last_directory + ".%07d.dpx") ## make the directory print ("new_path") print (new_path) if not os.path.exists(folder_path): os.makedirs(folder_path) return new_path class Watcher: def __init__(self, directory, xaxis, yaxis, lutpath, animation, a_ratio, dpx, noise, proc_xaxis, proc_yaxis, sharpen, denoise): self.directory = directory self.observer = Observer() self.last_size = {} self.last_size_stopped = {} ##JD Vars self.xaxis = xaxis self.yaxis = yaxis self.proc_xaxis = proc_xaxis self.proc_yaxis = proc_yaxis self.lutpath = lutpath self.animation = animation self.a_ratio = a_ratio self.dpx = dpx self.noise = noise self.sharpen = sharpen self.denoise = denoise def run(self, xaxis, yaxis, lutpath, animation, a_ratio, dpx, noise, proc_xaxis, proc_yaxis, sharpen, denoise): event_handler = FileSystemEventHandler() ## this is the important one event_handler.on_created = self.on_created event_handler.on_deleted = self.on_deleted event_handler.on_copied = self.on_copied event_handler.on_size_changed = self.on_size_changed event_handler.on_finished_rendering = self.on_finished_rendering self.observer.schedule(event_handler, self.directory, recursive=True) self.observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: self.observer.stop() print("Exiting...") ## this is the bit that does the most work. def on_created(self, event): # Create a logger logger = logging.getLogger(__name__) # Set the log level logger.setLevel(logging.INFO) # Create a file handler handler = logging.FileHandler(r"N:\engineering\alchemist\samurAI_watchfolders\samurai_support_files\log\samurai_log.txt") # Set the log format formatter = logging.Formatter('%(asctime)s - %(message)s') handler.setFormatter(formatter) # Add the handler to the logger logger.addHandler(handler) # Log a message #logger.info(sys.stdout) print("File created:", event.src_path) ##FFMPEG command variables input_path = event.src_path output_path = date_add(input_path.replace("\wip", "\out")) temp_output = output_path.replace(".mov", "temp.mov") width = self.xaxis height = self.yaxis crop = self.a_ratio animation_toggle = self.animation noise = self.noise sharpen = self.sharpen proc_xaxis = self.proc_xaxis proc_yaxis = self.proc_yaxis denoise = self.denoise ##copy and set lut print(self.lutpath) lutname = os.path.basename(self.lutpath) if not os.path.exists(os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)): shutil.copyfile(self.lutpath, os.path.join("C:\Program Files\Topaz Labs LLC\Topaz Video AI", lutname)) lut = lutname ## live action logic ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -c:a copy -c:v prores -profile:v 3 -vf dedot=ct=0:tc=1,unsharp=3:3:{}:3:3:0.0,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},noise=c0s={}:c0f=t,crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black {}".format(input_path,sharpen,proc_xaxis,proc_yaxis,width,height,lut,noise,height,crop,height,width,height,output_path) if self.dpx == True: dpx_output_path = modify_path(output_path) ffmpeg_command = "ffmpeg.exe -hide_banner -nostdin -y -strict 2 -hwaccel auto -i {} -flush_packets 1 -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -vf dedot=ct=0:tc=1,unsharp=3:3:{}:3:3:0.0,tvai_up=model=prob-3:scale=0:w={}:h={}:preblur=0:noise=0.2:details=0.25:halo=0:blur=0.2:compression=0:estimate=20:prenoise=0.03:device=0:vram=1:instances=1,scale={}:{}:out_color_matrix=bt709:flags=lanczos,lut3d={},noise=c0s={}:c0f=t,crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black -c:v dpx -pix_fmt gbrp10le -start_number 1 {}".format(input_path,sharpen,proc_xaxis,proc_yaxis,width,height,lut,noise,height,crop,height,width,height,dpx_output_path) ## animation logic if animation_toggle == True: print(animation_toggle) ffmpeg_command = "ffmpeg -hide_banner -nostdin -y -strict 2 -i {} -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -color_trc 1 -colorspace 1 -color_primaries 1 -filter_complex dedot=ct=0:tc=1,unsharp=3:3:{}:3:3:0.0,tvai_up=model=iris-1:scale=0:w={}:h={}:preblur=1:noise=1:details=0.4:halo=0.2:blur=0.35:compression=0:device=0:vram=1:instances=1,scale=w={}:h={}:flags=lanczos:threads=0,scale=out_color_matrix=bt709,lut3d={},noise=c0s={}:c0f=t,crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black,split=2[out1][out2] -map [out1] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le {} -map [out2] -c:v prores_ks -profile:v 3 -vendor apl0 -quant_mat hq -bits_per_mb 1350 -pix_fmt yuv422p10le -map 0:a -c:a copy {}".format(input_path,sharpen,proc_xaxis,proc_yaxis,width,height,lut,noise,height,crop,height,width,height,temp_output,output_path) if self.dpx == True: print(self.dpx) ffmpeg_command = "ffmpeg -hide_banner -nostdin -y -strict 2 -i {} -sws_flags spline+accurate_rnd+full_chroma_int -pix_fmt yuv422p10le -color_trc 1 -colorspace 1 -color_primaries 1 -filter_complex dedot=ct=0:tc=1,unsharp=3:3:{}:3:3:0.0,tvai_up=model=iris-1:scale=0:w={}:h={}:preblur=1:noise=1:details=0.4:halo=0.2:blur=0.35:compression=0:device=0:vram=1:instances=1,scale=w={}:h={}:flags=lanczos:threads=0,scale=out_color_matrix=bt709,lut3d={},noise=c0s={}:c0f=t,crop=trunc({}*{}):{},pad={}:{}:-1:-1:color=black -c:v dpx -pix_fmt gbrp10le -start_number 1 {}".format(input_path,sharpen,proc_xaxis,proc_yaxis,width,height,lut,noise,height,crop,height,width,height,dpx_output_path) if denoise == True: ffmpeg_command = ffmpeg_command.replace("unsharp=3:3:{}:3:3:0.0","nlmeans=1:7:7:3:3,dedot,unsharp=3:3:{}:3:3:0.0") print(ffmpeg_command) ## delay before processing --------------------------------------------- if queue.empty(): print ("Initializing, processing clip") ## logic for waiting until Alchemist is done last_modified_time = os.path.getmtime(input_path) current_time = time.time() while current_time - last_modified_time < 60: time.sleep(10) current_time = time.time() last_modified_time = os.path.getmtime(input_path) ## queue the command after a minute of not growing queue.put(ffmpeg_command) print("############################################################<- QUEUE") items = iter(queue.queue) print (list(items)) print("############################################################<- QUEUE") #iter through the Queue while not queue.empty(): ffmpeg_command = queue.get() print ("processing clip") ## use this if you want a new window #subprocess.Popen(ffmpeg_command, creationflags=subprocess.CREATE_NEW_CONSOLE) subprocess.run(ffmpeg_command) print(">>>>>>>>>>>>>>Render Done<<<<<<<<<<<<<") # Get the current time. current_time = str(datetime.datetime.now()) # Print the current time. print(output_path+" finished @ "+current_time) logger.info(output_path+" finished @ "+current_time+" rendered @ "+width+"X"+height) if os.path.exists(temp_output): os.remove(temp_output) def on_deleted(self, event): print("File deleted:", event.src_path) def on_copied(self, event): print("Copy done:", event.src_path) def on_size_changed(self, event): if event.src_path in Watcher.last_size: old_size = Watcher.last_size[event.src_path] new_size = event.src_size if new_size > old_size: print("File is growing:", event.src_path) else: if event.src_path not in Watcher.last_size_stopped: Watcher.last_size_stopped[event.src_path] = event.src_size print("File stopped growing:", event.src_path) del Watcher.last_size[event.src_path] Watcher.last_size[event.src_path] = event.src_size def on_finished_rendering(self, event): print("File finished rendering:", event.src_path) ######################################################################################start main class WatcherGUI(tk.Frame): ##change these for deployment default_watch_directory = r"N:\engineering\alchemist\samurAI_watchfolders\wip" default_lutpath = r"C:\Program Files\Topaz Labs LLC\Topaz Video AI\samurai_unity_709_2_709_33x33_v01.cube" default_width = 1920 default_height = 1080 default_proc_width = 3840 default_proc_height = 2160 default_a_ratio = 1.333333333 default_noise = 20 default_sharpen = 0.0 def __init__(self, master): super().__init__(master) self.master.title("SamurAI v23") # Set the window background to dark grey #self.master.config(bg="#323232") self.grid_columnconfigure(1, minsiz=700) # Create the widgets self.directory_label = tk.Label(self, text="Watch Directory:") self.directory_entry = tk.Entry(self) self.directory_entry.insert(0, self.default_watch_directory) self.directory_entry.pack_propagate(False) self.directory_label.grid(row=0, column=0, sticky="w") self.directory_entry.grid(row=0, column=1, columnspan=4, sticky="ew") self.xaxis_label = tk.Label(self, text="Output X-axis:") self.xaxis_entry = tk.Entry(self) self.xaxis_entry.insert(0, self.default_width) self.xaxis_entry.pack_propagate(True) self.xaxis_label.grid(row=1, column=0, sticky="w") self.xaxis_entry.grid(row=1, column=1, sticky="w") self.yaxis_label = tk.Label(self, text="Output Y-axis:") self.yaxis_entry = tk.Entry(self) self.yaxis_entry.insert(0, self.default_height) self.yaxis_entry.pack_propagate(True) self.yaxis_label.grid(row=2, column=0, sticky="w") self.yaxis_entry.grid(row=2, column=1, sticky="w") self.proc_xaxis_label = tk.Label(self, text="AI X-axis:") self.proc_xaxis_entry = tk.Entry(self) self.proc_xaxis_entry.insert(0, self.default_proc_width) self.proc_xaxis_entry.pack_propagate(True) self.proc_xaxis_label.grid(row=3, column=0, sticky="w") self.proc_xaxis_entry.grid(row=3, column=1, sticky="w") self.proc_yaxis_label = tk.Label(self, text="AI Y-axis:") self.proc_yaxis_entry = tk.Entry(self) self.proc_yaxis_entry.insert(0, self.default_proc_height) self.proc_yaxis_entry.pack_propagate(True) self.proc_yaxis_label.grid(row=4, column=0, sticky="w") self.proc_yaxis_entry.grid(row=4, column=1, sticky="w") self.a_ratio_label = tk.Label(self, text="Original Ratio:") self.a_ratio_entry = tk.Entry(self) self.a_ratio_entry.insert(0, self.default_a_ratio) self.a_ratio_entry.pack_propagate(True) self.a_ratio_label.grid(row=5, column=0, sticky="w") self.a_ratio_entry.grid(row=5, column=1, sticky="w") self.lutpath_label = tk.Label(self, text="LUT path:") self.lutpath_entry = tk.Entry(self, state="normal") self.lutpath_entry.insert(0, self.default_lutpath) self.lutpath_entry.pack_propagate(True) self.lutpath_label.grid(row=6, column=0, sticky="w") self.lutpath_entry.grid(row=6, column=1, columnspan=4, sticky="ew") self.noise_label = tk.Label(self, text="Noise Value:") self.noise_entry = tk.Entry(self, state="normal") self.noise_entry.insert(0, self.default_noise) self.noise_entry.pack_propagate(True) self.noise_label.grid(row=7, column=0, sticky="w") self.noise_entry.grid(row=7, column=1, sticky="w") self.sharpen_label = tk.Label(self, text="Sharpen Value:") self.sharpen_entry = tk.Entry(self, state="normal") self.sharpen_entry.insert(0, self.default_sharpen) self.sharpen_entry.pack_propagate(True) self.sharpen_label.grid(row=8, column=0, sticky="w") self.sharpen_entry.grid(row=8, column=1, sticky="w") # Add the Animation checkbox self.animation_var = tk.BooleanVar() self.animation_checkbox = tk.Checkbutton(self, text="Animation", variable=self.animation_var) self.animation_checkbox.grid(row=10, column=0, sticky="w") # Add the DPX checkbox self.dpx_var = tk.BooleanVar() self.dpx_checkbox = tk.Checkbutton(self, text="DPX", variable=self.dpx_var) self.dpx_checkbox.grid(row=9, column=0, sticky="w") # Add the denoise checkbox self.denoise_var = tk.BooleanVar() self.denoise_checkbox = tk.Checkbutton(self, text="Denoise", variable=self.denoise_var) self.denoise_checkbox.select() self.denoise_checkbox.grid(row=11, column=0, sticky="w") self.run_button = tk.Button(self, text="Run", command=self.run) self.run_button.config(background="red") self.run_button.grid(row=12, column=0, columnspan=2, sticky="ew") # Set the default size of the window self.master.geometry("800x315") def run(self): directory = self.directory_entry.get() xaxis = self.xaxis_entry.get() yaxis = self.yaxis_entry.get() proc_xaxis = self.proc_xaxis_entry.get() proc_yaxis = self.proc_yaxis_entry.get() lutpath = self.lutpath_entry.get() animation = self.animation_var.get() a_ratio = self.a_ratio_entry.get() dpx = self.dpx_var.get() noise = self.noise_entry.get() sharpen = self.sharpen_entry.get() denoise = self.denoise_var.get() if lutpath is None: lutpath = self.default_lutpath if directory is None: directory = self.default_watch_directory watcher = Watcher(directory, xaxis, yaxis, lutpath, animation, a_ratio, dpx, noise, proc_xaxis, proc_yaxis, sharpen, denoise) watcher.run(xaxis, yaxis, lutpath, animation, a_ratio, dpx, noise, proc_xaxis, proc_yaxis, sharpen, denoise) def main(): root = tk.Tk() gui = WatcherGUI(root) gui.pack() root.mainloop() if __name__ == "__main__": main()