From f331b53ac151def2e047457c6d16b654a42533fd Mon Sep 17 00:00:00 2001 From: TitasDas Date: Tue, 30 May 2023 00:37:43 +0530 Subject: [PATCH 01/17] Add a preview feature to view the face image and input video once uploaded --- core/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 137 bytes core/__pycache__/config.cpython-38.pyc | Bin 0 -> 714 bytes core/__pycache__/globals.cpython-38.pyc | Bin 0 -> 221 bytes core/__pycache__/processor.cpython-38.pyc | Bin 0 -> 1220 bytes core/__pycache__/utils.cpython-38.pyc | Bin 0 -> 2481 bytes run.py | 38 ++++++++++++++++++++-- 6 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 core/__pycache__/__init__.cpython-38.pyc create mode 100644 core/__pycache__/config.cpython-38.pyc create mode 100644 core/__pycache__/globals.cpython-38.pyc create mode 100644 core/__pycache__/processor.cpython-38.pyc create mode 100644 core/__pycache__/utils.cpython-38.pyc diff --git a/core/__pycache__/__init__.cpython-38.pyc b/core/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b3e7c43b481a129c8cc9b73faf9ff09e6c717e6 GIT binary patch literal 137 zcmWIL<>g`kf=gdZQka4CV-N=!FakLaKwQiMBvKfH88jLFRx%WUgb~CqJ!h+!(Bjmh z;+PPZ7?;%I?2`O~nDG3f?3ki_AS*e)C^aTNJ~J<~BtBlRpz;=nO>TZlX-=vg$ehnW G%m4tx#2>x@ literal 0 HcmV?d00001 diff --git a/core/__pycache__/config.cpython-38.pyc b/core/__pycache__/config.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..948f2fdc27be6fdc3689e821409d307f76d74342 GIT binary patch literal 714 zcmY*XJ#X7E5WS;hTmDLi6amtIAfWKrp)iaVNdt88;s$920|G75u4GvhC_1nW7s!w` zTYo@1_V0A$+9`9hV4bqEx2u&Zpg`kf=gdZQlf$MV-N=!FabFZKwK;VBvKes7;_k+7*d#`7*iP*FfC+=VoqTU zX3%7Q36y2@t0*eXE6L1Fjbbk?PK{45D2)Hq)$ literal 0 HcmV?d00001 diff --git a/core/__pycache__/processor.cpython-38.pyc b/core/__pycache__/processor.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b64d39912127bb7f2ee55aad0656ed39ccbcde1 GIT binary patch literal 1220 zcmY*ZOOF#r5bo-E&)CaiNQgod<>~{w3Q{B#MF@#S;t=hHMZn0BGq`)bV~=Ns?luo= z%w;)d{{aW~$b}!nv9CGt10qG7Qq?wMGgg1q^_ZEe@9Xiyem`Y+ef-CWe|^UOCgZun6-IsK%?JMV!aLB+QaoDtzhBvRO|AXFTtV zP(*K7z9V9hpuHsE0UM^D@Gb0c2sWNdGd?aRlJ-i;w!-~tP}cfI(Y8{Jf4+HZuc_;o zm`_^OJTHY*dcx`c?G>ZVaNWhFKOh)p;2rPSIh?|pcW}V|_-pOCn0F3qfAzazosYSo z3)IMXGr#k@pyL7rKl9fiRtBBdh36cY356$o%mim1uzCmm@T>obJsbGUMDtX=1-6cW ztp->TU99*8DOyLbqsQzCRzJpt6(Hg>Ao7rmH*LN*2QQh{W-hHR~a*HYyh{RB5CQT2zA+%~IhV%}k-_n;IXy8>#f-izwX98v!uCj_y=m1vEh=q& z@@(c}lcqi{r<+5Uy2#R$m39;4$)XXm8n2orPpEO{+GzV6MSm=tp{YC9%7qc!Fm8_c ZH@tCK$=gJrCPrdxoqj#&@vB~Z`9JN=Dp&vj literal 0 HcmV?d00001 diff --git a/core/__pycache__/utils.cpython-38.pyc b/core/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..221efb20d9393c10537fa1b262afcae178bf44ad GIT binary patch literal 2481 zcmZ`*Pj4GV6rb6DUfW3;($F>q!D32<0Vin{^$;}(sg=0-Qc%INur{7?vWdOBnjJfh zwLY~+J^?5wIri&t+$*Pk04}+}@69@Cn!>E+&3ogW+4p;Y{o~?djbZ%xw-(>~jQvHz z)nP;U4l_$Z1QUG7I_1hcTv#1TvIAS#hn8vxr(+3Mc&}K;5qE?ys;_v*6*W=Ejwcqx zBG!sn5;w5=Vp)8EwJKJ`O{_JsDn7(o7q`T1tP6raW6iZU_$q6k^Nqra^*QhMIc>}b z@ebw_%)E zJgfOGAl{7!S7k17MJ=K}s*G|q)U4dVOvxXB_WS8W->^Tr| z^Zd+W>nA2WAgr{fqro6m$*v4qlRzq!sGya}q3r7(JR`$V7EFRxG6;kmgyW&!iIWr# z)4d}VrYRh?^I$tp4(0LA1038>j(V`Wiewg)$9Gh3pu&;tsZh(Han2hi5)=i{8$%w0 zYkJ0SY7x95E2(9W!p4URH%o_+hMj9soQ`#moL+dzSVOpO?3$38R3D_-DlW+A7K)2o zm=?d!Jv{0o?DZ)UE(Y=BD`WL7Fs0Q&`AcrG8JqE|_RlSN0hR}KPAX@dBPn4^w|!n8 z3`VKk3tCaon65U0)*u>cskSEp6xyLVwStBs)tdGd#7pJI8kVA7A}e9qICC9iC6fl= zr+7P~)M9*vE0W#=RmY|Q^$-l;SO_I+4u#aW2#U51oD0r5sa}CJUAcf{yl9*_bxVNX ze6hJD*3)NTrjCNlIH3ntL|9Ke3 zDa~@?T^hq_tB-NT)NTMx^%A=Zu-UW}IZri+(1%K53c!+lp;bshNqLYp@#|Z+k=}jd zL@+ey$O5L(^bat|Ym`>xwYA1(PVPXOXZg&{ZFMiVpg|^A(H~(N1eBI>rw7QWUQFRclsY4Dg4YyqS(nLTRLHFm8(@)alpfw89U~_x2 zy;-skwnJhOJ0@YK^^LdZn^i?k=f9$;@S+T9CsD2UsZ&r@oN6baRI+d)dphaV=1gxe=q$dCPl(rDUk!!mg<}yV>$o9X z0bzUz&mE-fSLjyD+~H~iyYF-XDvLIzi2DNWEyZw~fm)YC4RoN1*S7BIP87rcvV-7*ZqW zxqW6K5G^!K$Ed^G_^zi+nT9e+6gS<1XN8>%MPbMCs8dV&{jpLq?#sd&M%R_`@ss&K zu!E1xa|4~6B&bhCthrdWhA+XJT2VNrMo_aiUDOnHQv^-&E6OWlSOd#kb>*ujLrrq} ikI}QoL-{S)Ji80xbKi1!jXSpQ)m*>syXIN&?SBC_Y%ACR literal 0 HcmV?d00001 diff --git a/run.py b/run.py index df34d56..e36b9d0 100644 --- a/run.py +++ b/run.py @@ -22,6 +22,8 @@ from core.config import get_face import webbrowser import psutil import cv2 +import threading +from PIL import Image, ImageTk pool = None args = {} @@ -59,13 +61,45 @@ def start_processing(): pool.join() +def preview_image(image_path): + img = Image.open(image_path) + img = img.resize((150, 150), Image.ANTIALIAS) + photo_img = ImageTk.PhotoImage(img) + left_frame = tk.Frame(window) + left_frame.pack(side=tk.LEFT, padx=10, pady=10) + img_label = tk.Label(left_frame, image=photo_img) + img_label.image = photo_img + img_label.pack() + + +def preview_video(video_path): + cap = cv2.VideoCapture(video_path) + if not cap.isOpened(): + print("Error opening video file") + return + ret, frame = cap.read() + if ret: + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + img = Image.fromarray(frame) + img = img.resize((150, 150), Image.ANTIALIAS) + photo_img = ImageTk.PhotoImage(img) + right_frame = tk.Frame(window) + right_frame.pack(side=tk.RIGHT, padx=10, pady=10) + img_label = tk.Label(right_frame, image=photo_img) + img_label.image = photo_img + img_label.pack() + + cap.release() + + def select_face(): args['source_img'] = filedialog.askopenfilename(title="Select a face") + preview_image(args['source_img']) def select_target(): args['target_path'] = filedialog.askopenfilename(title="Select a target") - + threading.Thread(target=preview_video, args=(args['target_path'],)).start() def toggle_fps_limit(): args['keep_fps'] = limit_fps.get() != True @@ -120,7 +154,7 @@ if __name__ == "__main__": start() quit() window = tk.Tk() - window.geometry("600x200") + window.geometry("600x350") window.title("roop") # Contact information From 9e7c3222f94e970a29d6d88bb1d020ebb23ac108 Mon Sep 17 00:00:00 2001 From: TitasDas Date: Tue, 30 May 2023 00:38:34 +0530 Subject: [PATCH 02/17] Update requirements.txt based on preview feature update --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index b4d8baa..ae90741 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,5 @@ onnxruntime==1.15.0 insightface==0.7.3 psutil==5.9.5 tk==0.1.0 +pillow==9.0.1 +opencv-python==4.5.5.64 \ No newline at end of file From d962afebcd980b4266a7ab03c74081d5737e76e2 Mon Sep 17 00:00:00 2001 From: TitasDas Date: Tue, 30 May 2023 01:28:03 +0530 Subject: [PATCH 03/17] remove pycache files --- core/__pycache__/__init__.cpython-38.pyc | Bin 137 -> 0 bytes core/__pycache__/config.cpython-38.pyc | Bin 714 -> 0 bytes core/__pycache__/globals.cpython-38.pyc | Bin 221 -> 0 bytes core/__pycache__/processor.cpython-38.pyc | Bin 1220 -> 0 bytes core/__pycache__/utils.cpython-38.pyc | Bin 2481 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 core/__pycache__/__init__.cpython-38.pyc delete mode 100644 core/__pycache__/config.cpython-38.pyc delete mode 100644 core/__pycache__/globals.cpython-38.pyc delete mode 100644 core/__pycache__/processor.cpython-38.pyc delete mode 100644 core/__pycache__/utils.cpython-38.pyc diff --git a/core/__pycache__/__init__.cpython-38.pyc b/core/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 6b3e7c43b481a129c8cc9b73faf9ff09e6c717e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmWIL<>g`kf=gdZQka4CV-N=!FakLaKwQiMBvKfH88jLFRx%WUgb~CqJ!h+!(Bjmh z;+PPZ7?;%I?2`O~nDG3f?3ki_AS*e)C^aTNJ~J<~BtBlRpz;=nO>TZlX-=vg$ehnW G%m4tx#2>x@ diff --git a/core/__pycache__/config.cpython-38.pyc b/core/__pycache__/config.cpython-38.pyc deleted file mode 100644 index 948f2fdc27be6fdc3689e821409d307f76d74342..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 714 zcmY*XJ#X7E5WS;hTmDLi6amtIAfWKrp)iaVNdt88;s$920|G75u4GvhC_1nW7s!w` zTYo@1_V0A$+9`9hV4bqEx2u&Zpg`kf=gdZQlf$MV-N=!FabFZKwK;VBvKes7;_k+7*d#`7*iP*FfC+=VoqTU zX3%7Q36y2@t0*eXE6L1Fjbbk?PK{45D2)Hq)$ diff --git a/core/__pycache__/processor.cpython-38.pyc b/core/__pycache__/processor.cpython-38.pyc deleted file mode 100644 index 0b64d39912127bb7f2ee55aad0656ed39ccbcde1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1220 zcmY*ZOOF#r5bo-E&)CaiNQgod<>~{w3Q{B#MF@#S;t=hHMZn0BGq`)bV~=Ns?luo= z%w;)d{{aW~$b}!nv9CGt10qG7Qq?wMGgg1q^_ZEe@9Xiyem`Y+ef-CWe|^UOCgZun6-IsK%?JMV!aLB+QaoDtzhBvRO|AXFTtV zP(*K7z9V9hpuHsE0UM^D@Gb0c2sWNdGd?aRlJ-i;w!-~tP}cfI(Y8{Jf4+HZuc_;o zm`_^OJTHY*dcx`c?G>ZVaNWhFKOh)p;2rPSIh?|pcW}V|_-pOCn0F3qfAzazosYSo z3)IMXGr#k@pyL7rKl9fiRtBBdh36cY356$o%mim1uzCmm@T>obJsbGUMDtX=1-6cW ztp->TU99*8DOyLbqsQzCRzJpt6(Hg>Ao7rmH*LN*2QQh{W-hHR~a*HYyh{RB5CQT2zA+%~IhV%}k-_n;IXy8>#f-izwX98v!uCj_y=m1vEh=q& z@@(c}lcqi{r<+5Uy2#R$m39;4$)XXm8n2orPpEO{+GzV6MSm=tp{YC9%7qc!Fm8_c ZH@tCK$=gJrCPrdxoqj#&@vB~Z`9JN=Dp&vj diff --git a/core/__pycache__/utils.cpython-38.pyc b/core/__pycache__/utils.cpython-38.pyc deleted file mode 100644 index 221efb20d9393c10537fa1b262afcae178bf44ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2481 zcmZ`*Pj4GV6rb6DUfW3;($F>q!D32<0Vin{^$;}(sg=0-Qc%INur{7?vWdOBnjJfh zwLY~+J^?5wIri&t+$*Pk04}+}@69@Cn!>E+&3ogW+4p;Y{o~?djbZ%xw-(>~jQvHz z)nP;U4l_$Z1QUG7I_1hcTv#1TvIAS#hn8vxr(+3Mc&}K;5qE?ys;_v*6*W=Ejwcqx zBG!sn5;w5=Vp)8EwJKJ`O{_JsDn7(o7q`T1tP6raW6iZU_$q6k^Nqra^*QhMIc>}b z@ebw_%)E zJgfOGAl{7!S7k17MJ=K}s*G|q)U4dVOvxXB_WS8W->^Tr| z^Zd+W>nA2WAgr{fqro6m$*v4qlRzq!sGya}q3r7(JR`$V7EFRxG6;kmgyW&!iIWr# z)4d}VrYRh?^I$tp4(0LA1038>j(V`Wiewg)$9Gh3pu&;tsZh(Han2hi5)=i{8$%w0 zYkJ0SY7x95E2(9W!p4URH%o_+hMj9soQ`#moL+dzSVOpO?3$38R3D_-DlW+A7K)2o zm=?d!Jv{0o?DZ)UE(Y=BD`WL7Fs0Q&`AcrG8JqE|_RlSN0hR}KPAX@dBPn4^w|!n8 z3`VKk3tCaon65U0)*u>cskSEp6xyLVwStBs)tdGd#7pJI8kVA7A}e9qICC9iC6fl= zr+7P~)M9*vE0W#=RmY|Q^$-l;SO_I+4u#aW2#U51oD0r5sa}CJUAcf{yl9*_bxVNX ze6hJD*3)NTrjCNlIH3ntL|9Ke3 zDa~@?T^hq_tB-NT)NTMx^%A=Zu-UW}IZri+(1%K53c!+lp;bshNqLYp@#|Z+k=}jd zL@+ey$O5L(^bat|Ym`>xwYA1(PVPXOXZg&{ZFMiVpg|^A(H~(N1eBI>rw7QWUQFRclsY4Dg4YyqS(nLTRLHFm8(@)alpfw89U~_x2 zy;-skwnJhOJ0@YK^^LdZn^i?k=f9$;@S+T9CsD2UsZ&r@oN6baRI+d)dphaV=1gxe=q$dCPl(rDUk!!mg<}yV>$o9X z0bzUz&mE-fSLjyD+~H~iyYF-XDvLIzi2DNWEyZw~fm)YC4RoN1*S7BIP87rcvV-7*ZqW zxqW6K5G^!K$Ed^G_^zi+nT9e+6gS<1XN8>%MPbMCs8dV&{jpLq?#sd&M%R_`@ss&K zu!E1xa|4~6B&bhCthrdWhA+XJT2VNrMo_aiUDOnHQv^-&E6OWlSOd#kb>*ujLrrq} ikI}QoL-{S)Ji80xbKi1!jXSpQ)m*>syXIN&?SBC_Y%ACR From 2c597a99545685efa87f8d37c95867e4f802f8bc Mon Sep 17 00:00:00 2001 From: TitasDas Date: Tue, 30 May 2023 04:10:09 +0530 Subject: [PATCH 04/17] Update with latest on main branch --- run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run.py b/run.py index f3f92f2..76dcb34 100644 --- a/run.py +++ b/run.py @@ -101,6 +101,7 @@ def select_target(): args['target_path'] = filedialog.askopenfilename(title="Select a target") threading.Thread(target=preview_video, args=(args['target_path'],)).start() + def toggle_fps_limit(): args['keep_fps'] = limit_fps.get() != True From 47105171a7b8a95097271f7b36fab688b6ee4e8c Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 06:40:46 +0530 Subject: [PATCH 05/17] fix positions and sizes of previews --- run.py | 79 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/run.py b/run.py index 76dcb34..1cecab2 100644 --- a/run.py +++ b/run.py @@ -1,4 +1,7 @@ +#!/usr/bin/env python3 import sys +import time +import torch import shutil import core.globals @@ -33,7 +36,8 @@ parser.add_argument('-f', '--face', help='use this face', dest='source_img') parser.add_argument('-t', '--target', help='replace this face', dest='target_path') parser.add_argument('-o', '--output', help='save output to this file', dest='output_file') parser.add_argument('--keep-fps', help='maintain original fps', dest='keep_fps', action='store_true', default=False) -parser.add_argument('--gpu', help='use gpu', dest='gpu', action='store_true', default=False) +if torch.cuda.is_available(): + parser.add_argument('--gpu', help='use gpu', dest='gpu', action='store_true', default=False) parser.add_argument('--keep-frames', help='keep frames directory', dest='keep_frames', action='store_true', default=False) for name, value in vars(parser.parse_args()).items(): @@ -46,8 +50,12 @@ if os.name == "nt": def start_processing(): + start_time = time.time() if args['gpu']: process_video(args['source_img'], args["frame_paths"]) + end_time = time.time() + print(flush=True) + print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) return frame_paths = args["frame_paths"] n = len(frame_paths)//(psutil.cpu_count()-1) @@ -59,14 +67,16 @@ def start_processing(): p.get() pool.close() pool.join() - + end_time = time.time() + print(flush=True) + print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) def preview_image(image_path): img = Image.open(image_path) - img = img.resize((150, 150), Image.ANTIALIAS) + img = img.resize((180, 180), Image.ANTIALIAS) photo_img = ImageTk.PhotoImage(img) left_frame = tk.Frame(window) - left_frame.pack(side=tk.LEFT, padx=10, pady=10) + left_frame.place(x=60, y=100) img_label = tk.Label(left_frame, image=photo_img) img_label.image = photo_img img_label.pack() @@ -81,10 +91,10 @@ def preview_video(video_path): if ret: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = Image.fromarray(frame) - img = img.resize((150, 150), Image.ANTIALIAS) + img = img.resize((180, 180), Image.ANTIALIAS) photo_img = ImageTk.PhotoImage(img) right_frame = tk.Frame(window) - right_frame.pack(side=tk.RIGHT, padx=10, pady=10) + right_frame.place(x=360, y=100) img_label = tk.Label(right_frame, image=photo_img) img_label.image = photo_img img_label.pack() @@ -106,12 +116,16 @@ def toggle_fps_limit(): args['keep_fps'] = limit_fps.get() != True +def toggle_keep_frames(): + args['keep_frames'] = keep_frames.get() != True + + def save_file(): - args['output_file'] = asksaveasfilename(initialfile='output.mp4', defaultextension=".mp4", filetypes=[("All Files","*.*"),("Videos","*.mp4")]) + args['output_file'] = asksaveasfilename(initialfile='output.mp4', defaultextension=".mp4", filetypes=[("All Files","*.*"),("Videos","*.mp4")]) def status(string): - status_label["text"] = string + status_label["text"] = "Status: " + string window.update() @@ -132,12 +146,12 @@ def start(): return if is_img(target_path): process_img(args['source_img'], target_path) - status("Swap successful!") + status("swap successful!") return video_name = target_path.split("/")[-1].split(".")[0] output_dir = target_path.replace(target_path.split("/")[-1], "").rstrip("/") + "/" + video_name Path(output_dir).mkdir(exist_ok=True) - status("Detecting video's FPS...") + status("detecting video's FPS...") fps = detect_fps(target_path) if not args['keep_fps'] and fps > 30: this_path = output_dir + "/" + video_name + ".mp4" @@ -145,21 +159,21 @@ def start(): target_path, fps = this_path, 30 else: shutil.copy(target_path, output_dir) - status("Extracting frames...") + status("extracting frames...") extract_frames(target_path, output_dir) args['frame_paths'] = tuple(sorted( glob.glob(output_dir + f"/*.png"), key=lambda x: int(x.split(sep)[-1].replace(".png", "")) )) - status("Swapping in progress...") + status("swapping in progress...") start_processing() - status("Creating video...") + status("creating video...") create_video(video_name, fps, output_dir) - status("Adding audio...") + status("adding audio...") add_audio(output_dir, target_path, args['keep_frames'], args['output_file']) save_path = args['output_file'] if args['output_file'] else output_dir + "/" + video_name + ".mp4" print("\n\nVideo saved as:", save_path, "\n\n") - status("Swap successful!") + status("swap successful!") if __name__ == "__main__": @@ -168,34 +182,41 @@ if __name__ == "__main__": start() quit() window = tk.Tk() - window.geometry("600x350") + window.geometry("600x700") window.title("roop") + window.configure(bg="#2d3436") + window.resizable(width=False, height=False) # Contact information - support_link = tk.Label(window, text="Support the project ^_^", fg="red", cursor="hand2") + support_link = tk.Label(window, text="Donate to project <3", fg="#fd79a8", bg="#2d3436", cursor="hand2", font=("Arial", 8)) + support_link.place(x=180,y=20,width=250,height=30) support_link.bind("", lambda e: webbrowser.open("https://github.com/sponsors/s0md3v")) - support_link.pack() # Select a face button - face_button = tk.Button(window, text="Select a face", command=select_face) - face_button.pack(padx=10, pady=20) + face_button = tk.Button(window, text="Select a face", command=select_face, bg="#2d3436", fg="#74b9ff", highlightthickness=4, relief="flat", highlightbackground="#74b9ff", activebackground="#74b9ff", borderwidth=4) + face_button.place(x=60,y=320,width=180,height=80) # Select a target button - target_button = tk.Button(window, text="Select a target", command=select_target) - target_button.pack(padx=10, pady=10) + target_button = tk.Button(window, text="Select a target", command=select_target, bg="#2d3436", fg="#74b9ff", highlightthickness=4, relief="flat", highlightbackground="#74b9ff", activebackground="#74b9ff", borderwidth=4) + target_button.place(x=360,y=320,width=180,height=80) # FPS limit checkbox limit_fps = tk.IntVar() - fps_checkbox = tk.Checkbutton(window, text="Limit FPS to 30", variable=limit_fps, command=toggle_fps_limit, font=("Arial", 8)) - fps_checkbox.pack() + fps_checkbox = tk.Checkbutton(window, relief="groove", activebackground="#2d3436", activeforeground="#74b9ff", selectcolor="black", text="Limit FPS to 30", fg="#dfe6e9", borderwidth=0, highlightthickness=0, bg="#2d3436", variable=limit_fps, command=toggle_fps_limit) + fps_checkbox.place(x=30,y=500,width=240,height=31) fps_checkbox.select() + # Keep frames checkbox + keep_frames = tk.IntVar() + frames_checkbox = tk.Checkbutton(window, relief="groove", activebackground="#2d3436", activeforeground="#74b9ff", selectcolor="black", text="Keep frames dir", fg="#dfe6e9", borderwidth=0, highlightthickness=0, bg="#2d3436", variable=keep_frames, command=toggle_keep_frames) + frames_checkbox.place(x=37,y=450,width=240,height=31) + # Start button - start_button = tk.Button(window, text="Start", bg="#f1c40f", command=lambda: [save_file(), start()]) - start_button.pack(padx=10, pady=20) + start_button = tk.Button(window, text="Start", bg="#f1c40f", relief="flat", borderwidth=0, highlightthickness=0, command=lambda: [save_file(), start()]) + start_button.place(x=240,y=560,width=120,height=49) # Status label - status_label = tk.Label(window, width=340, text="Waiting for input...", bg="black", fg="#2ecc71") - status_label.pack() - + status_label = tk.Label(window, width=580, justify="center", text="Status: waiting for input...", fg="#2ecc71", bg="#2d3436") + status_label.place(x=10,y=640,width=580,height=30) + window.mainloop() From 140f79ae6a7860f277a03d17df6f244bb53d7608 Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 06:42:19 +0530 Subject: [PATCH 06/17] removed duplicate dependency --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ae90741..b020dbc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,3 @@ insightface==0.7.3 psutil==5.9.5 tk==0.1.0 pillow==9.0.1 -opencv-python==4.5.5.64 \ No newline at end of file From 04c9b3987d98e300b482f5f4c24f9d12cf23053e Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 04:27:42 +0530 Subject: [PATCH 07/17] better gui --- run.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/run.py b/run.py index 1cecab2..deef18e 100644 --- a/run.py +++ b/run.py @@ -182,7 +182,11 @@ if __name__ == "__main__": start() quit() window = tk.Tk() +<<<<<<< HEAD window.geometry("600x700") +======= + window.geometry("600x500") +>>>>>>> a440cef (better gui) window.title("roop") window.configure(bg="#2d3436") window.resizable(width=False, height=False) @@ -194,21 +198,34 @@ if __name__ == "__main__": # Select a face button face_button = tk.Button(window, text="Select a face", command=select_face, bg="#2d3436", fg="#74b9ff", highlightthickness=4, relief="flat", highlightbackground="#74b9ff", activebackground="#74b9ff", borderwidth=4) +<<<<<<< HEAD face_button.place(x=60,y=320,width=180,height=80) # Select a target button target_button = tk.Button(window, text="Select a target", command=select_target, bg="#2d3436", fg="#74b9ff", highlightthickness=4, relief="flat", highlightbackground="#74b9ff", activebackground="#74b9ff", borderwidth=4) target_button.place(x=360,y=320,width=180,height=80) +======= + face_button.place(x=60,y=120,width=180,height=80) + + # Select a target button + target_button = tk.Button(window, text="Select a target", command=select_target, bg="#2d3436", fg="#74b9ff", highlightthickness=4, relief="flat", highlightbackground="#74b9ff", activebackground="#74b9ff", borderwidth=4) + target_button.place(x=360,y=120,width=180,height=80) +>>>>>>> a440cef (better gui) # FPS limit checkbox limit_fps = tk.IntVar() fps_checkbox = tk.Checkbutton(window, relief="groove", activebackground="#2d3436", activeforeground="#74b9ff", selectcolor="black", text="Limit FPS to 30", fg="#dfe6e9", borderwidth=0, highlightthickness=0, bg="#2d3436", variable=limit_fps, command=toggle_fps_limit) +<<<<<<< HEAD fps_checkbox.place(x=30,y=500,width=240,height=31) +======= + fps_checkbox.place(x=30,y=230,width=240,height=31) +>>>>>>> a440cef (better gui) fps_checkbox.select() # Keep frames checkbox keep_frames = tk.IntVar() frames_checkbox = tk.Checkbutton(window, relief="groove", activebackground="#2d3436", activeforeground="#74b9ff", selectcolor="black", text="Keep frames dir", fg="#dfe6e9", borderwidth=0, highlightthickness=0, bg="#2d3436", variable=keep_frames, command=toggle_keep_frames) +<<<<<<< HEAD frames_checkbox.place(x=37,y=450,width=240,height=31) # Start button @@ -219,4 +236,15 @@ if __name__ == "__main__": status_label = tk.Label(window, width=580, justify="center", text="Status: waiting for input...", fg="#2ecc71", bg="#2d3436") status_label.place(x=10,y=640,width=580,height=30) +======= + frames_checkbox.place(x=37,y=280,width=240,height=31) + + # Start button + start_button = tk.Button(window, text="Start", bg="#f1c40f", relief="flat", borderwidth=0, highlightthickness=0, command=lambda: [save_file(), start()]) + start_button.place(x=240,y=360,width=120,height=49) + + # Status label + status_label = tk.Label(window, width=580, justify="center", text="Status: waiting for input...", fg="#2ecc71", bg="#2d3436") + status_label.place(x=10,y=440,width=580,height=30) +>>>>>>> a440cef (better gui) window.mainloop() From 9ba67c6f2d49472e4f104d48299c26f626a20edb Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 04:36:04 +0530 Subject: [PATCH 08/17] new gui-demo --- gui-demo.png | Bin 19665 -> 30096 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gui-demo.png b/gui-demo.png index 4402013ffc8de3ae89353d44c3bf5fdf5e1793d8..128eaf625b6f135ec505f68b1ec93fbaff0178a9 100644 GIT binary patch literal 30096 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 literal 19665 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 Date: Tue, 30 May 2023 04:36:50 +0530 Subject: [PATCH 09/17] new gui-demo From 8701123ee3b2f1e77c3e1c6594f62c87dd694ada Mon Sep 17 00:00:00 2001 From: henryruhs Date: Tue, 30 May 2023 00:40:02 +0200 Subject: [PATCH 10/17] Add GPU support, Quit on missing model, Remove globals (sorry) --- core/config.py | 3 +-- core/globals.py | 4 ---- core/processor.py | 9 +++++++-- core/utils.py | 2 ++ requirements.txt | 6 +++++- run.py | 7 ++++--- 6 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 core/globals.py mode change 100644 => 100755 run.py diff --git a/core/config.py b/core/config.py index bbaad5e..df1c3ca 100644 --- a/core/config.py +++ b/core/config.py @@ -1,8 +1,7 @@ import insightface import onnxruntime -import core.globals -face_analyser = insightface.app.FaceAnalysis(name='buffalo_l', providers=core.globals.providers) +face_analyser = insightface.app.FaceAnalysis(name='buffalo_l', providers=onnxruntime.get_available_providers()) face_analyser.prepare(ctx_id=0, det_size=(640, 640)) diff --git a/core/globals.py b/core/globals.py deleted file mode 100644 index 83d7277..0000000 --- a/core/globals.py +++ /dev/null @@ -1,4 +0,0 @@ -import onnxruntime - -use_gpu = False -providers = onnxruntime.get_available_providers() diff --git a/core/processor.py b/core/processor.py index eb75975..29dc082 100644 --- a/core/processor.py +++ b/core/processor.py @@ -1,11 +1,15 @@ +import os import cv2 import insightface import onnxruntime -import core.globals from core.config import get_face from core.utils import rreplace -face_swapper = insightface.model_zoo.get_model('inswapper_128.onnx', providers=core.globals.providers) +if os.path.isfile('inswapper_128.onnx'): + face_swapper = insightface.model_zoo.get_model('inswapper_128.onnx', providers=onnxruntime.get_available_providers()) +else: + quit('File "inswapper_128.onnx" does not exist!') + def process_video(source_img, frame_paths): @@ -25,6 +29,7 @@ def process_video(source_img, frame_paths): pass print(flush=True) + def process_img(source_img, target_path): frame = cv2.imread(target_path) face = get_face(frame) diff --git a/core/utils.py b/core/utils.py index 9c5cd75..228d83b 100644 --- a/core/utils.py +++ b/core/utils.py @@ -17,6 +17,7 @@ def run_command(command, mode="silent"): return os.system(command) return os.popen(command).read() + def detect_fps(input_path): input_path = path(input_path) output = os.popen(f'ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate "{input_path}"').read() @@ -58,6 +59,7 @@ def add_audio(output_dir, target_path, keep_frames, output_file): def is_img(path): return path.lower().endswith(("png", "jpg", "jpeg", "bmp")) + def rreplace(s, old, new, occurrence): li = s.rsplit(old, occurrence) return new.join(li) diff --git a/requirements.txt b/requirements.txt index b020dbc..881fd35 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,12 @@ numpy==1.24.3 opencv-python==4.7.0.72 onnx==1.14.0 -onnxruntime==1.15.0 +onnxruntime-gpu==1.15.0 insightface==0.7.3 psutil==5.9.5 tk==0.1.0 +<<<<<<< HEAD pillow==9.0.1 +======= +torch==2.0.1 +>>>>>>> 54f800d (Add GPU support, Quit on missing model, Remove globals (sorry)) diff --git a/run.py b/run.py old mode 100644 new mode 100755 index deef18e..0724e19 --- a/run.py +++ b/run.py @@ -1,15 +1,16 @@ #!/usr/bin/env python3 +<<<<<<< HEAD import sys import time +======= + +>>>>>>> 54f800d (Add GPU support, Quit on missing model, Remove globals (sorry)) import torch import shutil -import core.globals if not shutil.which('ffmpeg'): print('ffmpeg is not installed. Read the docs: https://github.com/s0md3v/roop#installation.\n' * 10) quit() -if '--gpu' not in sys.argv: - core.globals.providers = ['CPUExecutionProvider'] import glob import argparse From d7f72f7c5a980509371739360409b182d95547ca Mon Sep 17 00:00:00 2001 From: henryruhs Date: Tue, 30 May 2023 01:03:43 +0200 Subject: [PATCH 11/17] Restore globals, add process time for better comparison --- core/config.py | 4 ++-- core/globals.py | 4 ++++ core/processor.py | 10 +++++++--- run.py | 7 +++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 core/globals.py diff --git a/core/config.py b/core/config.py index df1c3ca..151ad33 100644 --- a/core/config.py +++ b/core/config.py @@ -1,7 +1,7 @@ import insightface -import onnxruntime +import core.globals -face_analyser = insightface.app.FaceAnalysis(name='buffalo_l', providers=onnxruntime.get_available_providers()) +face_analyser = insightface.app.FaceAnalysis(name='buffalo_l', providers=core.globals.providers) face_analyser.prepare(ctx_id=0, det_size=(640, 640)) diff --git a/core/globals.py b/core/globals.py new file mode 100644 index 0000000..cbd26c2 --- /dev/null +++ b/core/globals.py @@ -0,0 +1,4 @@ +import onnxruntime + +use_gpu = False +providers = onnxruntime.get_available_providers() diff --git a/core/processor.py b/core/processor.py index 29dc082..631feab 100644 --- a/core/processor.py +++ b/core/processor.py @@ -1,18 +1,20 @@ import os +import time + import cv2 import insightface -import onnxruntime +import core.globals from core.config import get_face from core.utils import rreplace if os.path.isfile('inswapper_128.onnx'): - face_swapper = insightface.model_zoo.get_model('inswapper_128.onnx', providers=onnxruntime.get_available_providers()) + face_swapper = insightface.model_zoo.get_model('inswapper_128.onnx', providers=core.globals.providers) else: quit('File "inswapper_128.onnx" does not exist!') - def process_video(source_img, frame_paths): + start_time = time.time() source_face = get_face(cv2.imread(source_img)) for frame_path in frame_paths: frame = cv2.imread(frame_path) @@ -28,6 +30,8 @@ def process_video(source_img, frame_paths): print('E', end='', flush=True) pass print(flush=True) + end_time = time.time() + print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) def process_img(source_img, target_path): diff --git a/run.py b/run.py index 0724e19..cd543a2 100755 --- a/run.py +++ b/run.py @@ -1,16 +1,23 @@ #!/usr/bin/env python3 <<<<<<< HEAD +<<<<<<< HEAD import sys import time ======= >>>>>>> 54f800d (Add GPU support, Quit on missing model, Remove globals (sorry)) +======= +import sys +>>>>>>> dc0653a (Restore globals, add process time for better comparison) import torch import shutil +import core.globals if not shutil.which('ffmpeg'): print('ffmpeg is not installed. Read the docs: https://github.com/s0md3v/roop#installation.\n' * 10) quit() +if '--gpu' not in sys.argv: + core.globals.providers = ['CPUExecutionProvider'] import glob import argparse From b9d20c0bff431dd44ce503c0ee45bd9a27e17f60 Mon Sep 17 00:00:00 2001 From: henryruhs Date: Tue, 30 May 2023 01:28:16 +0200 Subject: [PATCH 12/17] Move process time to the correct place --- core/processor.py | 6 ------ run.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/processor.py b/core/processor.py index 631feab..d67b1cf 100644 --- a/core/processor.py +++ b/core/processor.py @@ -1,6 +1,4 @@ import os -import time - import cv2 import insightface import core.globals @@ -14,7 +12,6 @@ else: def process_video(source_img, frame_paths): - start_time = time.time() source_face = get_face(cv2.imread(source_img)) for frame_path in frame_paths: frame = cv2.imread(frame_path) @@ -29,9 +26,6 @@ def process_video(source_img, frame_paths): except Exception as e: print('E', end='', flush=True) pass - print(flush=True) - end_time = time.time() - print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) def process_img(source_img, target_path): diff --git a/run.py b/run.py index cd543a2..4245c39 100755 --- a/run.py +++ b/run.py @@ -3,12 +3,15 @@ <<<<<<< HEAD import sys import time +<<<<<<< HEAD ======= >>>>>>> 54f800d (Add GPU support, Quit on missing model, Remove globals (sorry)) ======= import sys >>>>>>> dc0653a (Restore globals, add process time for better comparison) +======= +>>>>>>> 2b14613 (Move process time to the correct place) import torch import shutil import core.globals @@ -61,8 +64,13 @@ def start_processing(): start_time = time.time() if args['gpu']: process_video(args['source_img'], args["frame_paths"]) +<<<<<<< HEAD end_time = time.time() print(flush=True) +======= + print(flush=True) + end_time = time.time() +>>>>>>> 2b14613 (Move process time to the correct place) print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) return frame_paths = args["frame_paths"] @@ -75,6 +83,7 @@ def start_processing(): p.get() pool.close() pool.join() +<<<<<<< HEAD end_time = time.time() print(flush=True) print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) @@ -108,6 +117,11 @@ def preview_video(video_path): img_label.pack() cap.release() +======= + print(flush=True) + end_time = time.time() + print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) +>>>>>>> 2b14613 (Move process time to the correct place) def select_face(): From 15cd4b8a222b7ba25f2681ce8158e15fd8ec5107 Mon Sep 17 00:00:00 2001 From: henryruhs Date: Tue, 30 May 2023 01:28:42 +0200 Subject: [PATCH 13/17] Move process time to the correct place --- run.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/run.py b/run.py index 4245c39..7568e55 100755 --- a/run.py +++ b/run.py @@ -64,6 +64,7 @@ def start_processing(): start_time = time.time() if args['gpu']: process_video(args['source_img'], args["frame_paths"]) +<<<<<<< HEAD <<<<<<< HEAD end_time = time.time() print(flush=True) @@ -71,6 +72,10 @@ def start_processing(): print(flush=True) end_time = time.time() >>>>>>> 2b14613 (Move process time to the correct place) +======= + end_time = time.time() + print(flush=True) +>>>>>>> 0f782ff (Move process time to the correct place) print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) return frame_paths = args["frame_paths"] @@ -83,6 +88,7 @@ def start_processing(): p.get() pool.close() pool.join() +<<<<<<< HEAD <<<<<<< HEAD end_time = time.time() print(flush=True) @@ -119,7 +125,10 @@ def preview_video(video_path): cap.release() ======= print(flush=True) +======= +>>>>>>> 0f782ff (Move process time to the correct place) end_time = time.time() + print(flush=True) print(f"Processing time: {end_time - start_time:.2f} seconds", flush=True) >>>>>>> 2b14613 (Move process time to the correct place) From a1b38b9eb5b71d2e6f44e1f6e088dcf242dcc9ee Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 05:33:54 +0530 Subject: [PATCH 14/17] restore onnxruntime --- requirements.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 881fd35..caaa1c3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,16 @@ numpy==1.24.3 opencv-python==4.7.0.72 onnx==1.14.0 -onnxruntime-gpu==1.15.0 +onnxruntime==1.15.0 insightface==0.7.3 psutil==5.9.5 tk==0.1.0 <<<<<<< HEAD +<<<<<<< HEAD pillow==9.0.1 ======= torch==2.0.1 >>>>>>> 54f800d (Add GPU support, Quit on missing model, Remove globals (sorry)) +======= +torch==2.0.1 +>>>>>>> 36e960e (restore onnxruntime) From d7abe79f59864aa44d6745359e9c06635078812c Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 05:34:26 +0530 Subject: [PATCH 15/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad7218f..d345906 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ If you plan on doing it, you will need to install the appropriate `onnxruntime-* #### NVIDIA Install `cuda` and then, ``` -pip install onnxruntime-gpu +pip install onnxruntime-gpu==1.15.0 ``` #### AMD Install ROCM-based torch packages from [here](https://pytorch.org/get-started/locally/) and then, From bd39e875bd498eed753a08a3bf581fd173d9f827 Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 06:09:41 +0530 Subject: [PATCH 16/17] remove onnxruntime --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index caaa1c3..a427188 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ numpy==1.24.3 opencv-python==4.7.0.72 onnx==1.14.0 -onnxruntime==1.15.0 insightface==0.7.3 psutil==5.9.5 tk==0.1.0 From 478238ba92b37292599c4172da092792d2469870 Mon Sep 17 00:00:00 2001 From: Somdev Sangwan Date: Tue, 30 May 2023 06:11:10 +0530 Subject: [PATCH 17/17] gpu instruction --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d345906..e61064b 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ pip install -r requirements.txt ``` 4. Download [this file](https://mega.nz/file/9l8mGDJA#FnPxHwpdhDovDo6OvbQjhHd2nDAk8_iVEgo3mpHLG6U) and keep it in **roop** directory. [Mirror #1](https://drive.google.com/file/d/1jbDUGrADco9A1MutWjO6d_1dwizh9w9P/view?usp=sharing), [Mirror #2](https://drive.google.com/file/d/1eu60OrRtn4WhKrzM4mQv4F3rIuyUXqfl/view?usp=drive_link), [Mirror #3](https://1drv.ms/u/s!AsHA3Xbnj6uAgxhb_tmQ7egHACOR?e=CPoThO) -5. If you are on windows, you will need to install `Microsoft Visual C++ 14.0`. Google how to do that. +5. If you plan on using CPU, install `onnxruntime` with `pip install onnxruntime==1.15.0`. If you have a good GPU, read ahead. ### GPU Accleration (Optional) If you have a good enough GPU, you can use it to speed-up the face-swapping process by running `run.py` with `--gpu` flag.