Compare commits

...

190 Commits

Author SHA1 Message Date
KRSHH 51b38fe253 Revert "Slight Performance Improvement"
This reverts commit 9a472e2435.
2024-11-07 14:58:03 +05:30
KRSHH 97a76c5e5b Revert "Update ui.py"
This reverts commit df72a5431b.
2024-11-07 14:57:47 +05:30
KRSHH df72a5431b Update ui.py 2024-10-29 14:53:19 +05:30
KRSHH 9a472e2435 Slight Performance Improvement
avg 9.5 to avg 10
2024-10-29 14:07:47 +05:30
KRSHH a581b81bd9 Change Switch/Slider positions 2024-10-28 16:53:55 +05:30
KRSHH 69b7970b87 Improved Camera Selection Menu 2024-10-28 13:50:44 +05:30
KRSHH 7fce1fd8b4 Update instructions.txt
Links to Models in Instructions
2024-10-28 13:15:13 +05:30
KRSHH c2918a52df Minimum Windows Size 2024-10-28 13:12:02 +05:30
KRSHH 64c0f085b1 Change Switch positions 2024-10-28 12:20:54 +05:30
KRSHH 3c30ab8a5d Opacity 2024-10-28 11:45:50 +05:30
KRSHH acc8e778b6 Mouth Mask And UI 2024-10-28 10:56:01 +05:30
KRSHH 4b6f60f59b Delete files from main 2024-10-21 19:15:21 +05:30
KRSHH 1178232268 Upload images to folder 2024-10-21 19:12:46 +05:30
KRSHH ad918c5523 Shift Media to a folder 2024-10-21 19:10:21 +05:30
KRSHH 7b8d6171b7 Frame by Frame Navigation 2024-10-19 14:04:05 +05:30
KRSHH 6b86b0a72d Preview Window Slider 2024-10-19 13:58:55 +05:30
KRSHH 936e78f93b Fix Mapper for Live 2024-10-17 13:06:00 +05:30
KRSHH aca0bcb7ce Formatting Fix 2024-10-14 21:48:57 +05:30
KRSHH 966cb5a7df Removed Package Repetition 2024-10-14 21:46:22 +05:30
KRSHH 1ab4bf06b1 Tips for DLC 2024-10-14 21:26:34 +05:30
KRSHH 6649e2a5df remember/save switch states 2024-10-14 20:32:17 +05:30
KRSHH 72d4c9e9c4 Update metadata.py - 1.6 2024-10-14 19:50:09 +05:30
KRSHH 76d65247b7 improved performance enhancement 2024-10-14 19:49:51 +05:30
KRSHH 37f224cb47 FPS Counter 2024-10-14 19:46:48 +05:30
KRSHH b58ffffd37 Fix the button position and bugs 2024-10-14 19:11:44 +05:30
KRSHH 75decc5838 Hotswap Source image - switch faces without closing live 2024-10-04 18:17:22 +05:30
Kenneth Estanislao f38ebb485a Update ui.py
removed opacity, will work on it later to optimize
2024-10-04 15:39:08 +08:00
Kenneth Estanislao 95742c8fd5 Merge pull request #686 from GhoulBoii/main
BOUNTY - Webcam Merged (tested)
2024-10-04 14:46:06 +08:00
Kenneth Estanislao 60e27f4755 Revert "Merge pull request #685 from KRSHH/main"
This reverts commit d4e5b8078d, reversing
changes made to c08bec22e3.
2024-10-03 14:51:38 +08:00
KRSHH 3d741bd269 Update README.md 2024-10-02 18:38:37 +05:30
KRSHH d4e5b8078d Merge pull request #685 from KRSHH/main
Live faceswap opacity slider
2024-10-02 15:24:53 +05:30
KRSHH 61b51fc5d4 Move the slider from live to root 2024-10-02 14:37:19 +05:30
KRSHH f19e425143 Update ui.py 2024-10-02 14:20:56 +05:30
KRSHH 7d6bdad086 Default opacity global 2024-10-02 13:24:23 +05:30
KRSHH 12c0a7ac86 Faceswap live opacity slider 2024-10-02 13:23:39 +05:30
Kenneth Estanislao c08bec22e3 Update issue templates 2024-10-01 14:26:03 +08:00
KRSHH bdd7c593e1 Update README.md 2024-09-28 20:53:29 +05:30
KRSHH 6e618baf34 Update README.md 2024-09-28 17:22:21 +05:30
KRSHH 0edcaae713 Merge pull request #650 from KRSHH/main
Preview video Frame by Frame using left and right arrow keys
2024-09-28 12:37:40 +05:30
KRSHH dff6cec2f9 Comment Indention fix 2024-09-27 20:59:48 +05:30
KRSHH 4d1d2c86af Preview video Frame by Frame using left and right arrow keys 2024-09-27 20:40:32 +05:30
KRSHH e00c398825 Merge branch 'hacksider:main' into main 2024-09-27 20:20:22 +05:30
KRSHH 0e481609ea Update README.md 2024-09-27 19:59:13 +05:30
KRSHH 683481804c Delete outdated docs directory 2024-09-26 11:03:46 +05:30
KRSHH 5845b9c480 Update README.md 2024-09-26 00:57:11 +05:30
Kenneth Estanislao 71cf39fd98 Update metadata.py
changes of version from 1.4 to 1.5 (UI modified)
2024-09-26 00:57:45 +08:00
KRSHH 92db20eba4 Merge pull request #632 from KRSHH/main
Unreverting New UI after Fixes, Unreverted README
2024-09-25 17:51:30 +05:30
KRSHH f1e365799e Updated README, (Images - TBU) 2024-09-25 17:42:09 +05:30
KRSHH 6d1238212a New Fixed UI 2024-09-25 17:36:50 +05:30
Kenneth Estanislao 92a0994f01 Update README.md 2024-09-21 19:56:00 +08:00
Kenneth Estanislao cad40b25dc Update face_swapper.py
added the missing ' , my bad on this...
2024-09-19 21:00:29 +08:00
Kenneth Estanislao 1b4c0ce43e Update face_swapper.py
should fix issues for those who dont have nvidia cards
2024-09-19 17:43:05 +08:00
Kenneth Estanislao fd4e3f546d reverted to the old version
fixing the issue #597
2024-09-19 17:38:02 +08:00
Kenneth Estanislao 5bcd6dabde Update ui.py 2024-09-19 15:54:57 +08:00
Kenneth Estanislao 3e1f333e5e Revert "Merge pull request #594 from KRSHH/main"
This reverts commit 2641f9e344, reversing
changes made to 9bf2080ac8.
2024-09-19 02:36:35 +08:00
Kenneth Estanislao 1f71d274b5 Revert "Merge pull request #599 from KRSHH/main"
This reverts commit 80de3dc32e, reversing
changes made to 375d4ae620.
2024-09-19 02:01:47 +08:00
Kenneth Estanislao bbfdf83267 Update requirements.txt 2024-09-19 00:38:41 +08:00
Kenneth Estanislao 88254c3952 Merge pull request #604 from bkosowski/bugfix/fix_onnxruntime_version
Downgrade onnxruntime version to 1.16.0 to fix requirements installation
2024-09-19 00:33:05 +08:00
bkosowski 069e9b46e6 Downgrade onnxruntime version to 1.16.0 to fix requirements installation 2024-09-18 15:58:50 +02:00
Kenneth Estanislao 80de3dc32e Merge pull request #599 from KRSHH/main
Update README.md
2024-09-17 21:47:44 +08:00
KRSHH 911148cc6b README.md Update
Thanks to all the contributors
2024-09-17 19:03:06 +05:30
KRSHH b229545454 Update README.md
Fix formatting, structure etc.
2024-09-17 18:24:43 +05:30
Kenneth Estanislao 375d4ae620 Update README.md
added KRSHH
2024-09-17 20:27:27 +08:00
Kenneth Estanislao bcfb9f24ea Merge pull request #598 from KRSHH/main
Fixed the Face mapper issue in Live Cam - New UI PR
2024-09-17 20:25:33 +08:00
KRSHH a905d161e5 Add files via upload 2024-09-17 20:25:08 +08:00
KRSHH d78df54721 Fixed the Face Mapper issue on live cam 2024-09-17 20:20:14 +08:00
KRSHH 4067d24c26 Fix Popup Live width 2024-09-17 20:18:59 +08:00
KRSHH 9c22e63d7b Fix Popup Live width 2024-09-17 17:46:14 +05:30
KRSHH 0350f23519 Fixed the Face Mapper issue on live cam 2024-09-17 16:51:28 +05:30
KRSHH d1ec0a17b2 Minor Fixes 2024-09-16 21:58:24 +05:30
KRSHH bd8ed6e7eb Add files via upload 2024-09-16 21:48:13 +05:30
Kenneth Estanislao ea7bbd49fe Revert "Merge pull request #592 from KRSHH/main"
This reverts commit 2f29d323d9.
2024-09-16 23:34:35 +08:00
Kenneth Estanislao 2f29d323d9 Merge pull request #592 from KRSHH/main
Better UI
2024-09-16 23:32:39 +08:00
Kenneth Estanislao c6e00796c8 Merge pull request #588 from KRSHH/main
Enhance UI with drag and drop, modern look using customtkinter, and improved webcam mapping
2024-09-16 23:30:12 +08:00
Kenneth Estanislao 2641f9e344 Merge pull request #594 from KRSHH/main
UI Change
2024-09-16 23:26:29 +08:00
KRSHH 5dd621b2b0 Fixed Typo 2024-09-16 20:47:02 +05:30
KRSHH 05413cc989 Update README.md
For avoiding ToS violation
2024-09-16 20:38:56 +05:30
KRSHH c49d0e0e3c Bug fixes 2024-09-16 20:36:28 +05:30
unknown 88e3274d96 Backk 2024-09-16 20:24:04 +05:30
Kenneth Estanislao 9bf2080ac8 Revert "Merge pull request #588 from KRSHH/main"
This reverts commit 8c6d0134a8, reversing
changes made to 621c3f035e.
2024-09-16 22:18:59 +08:00
Kenneth Estanislao 5ab00388b7 Revert "Merge pull request #592 from KRSHH/main"
This reverts commit 4768488653, reversing
changes made to 8c6d0134a8.
2024-09-16 22:18:53 +08:00
Kenneth Estanislao 4768488653 Merge pull request #592 from KRSHH/main
Better UI
2024-09-16 22:10:42 +08:00
KRSHH 569c9ca25a Resizable Root window 2024-09-16 19:13:54 +05:30
KRSHH c9f8537a15 Switch alignment 2024-09-16 18:53:19 +05:30
KRSHH 2d99e392ff Vertical switches 2024-09-16 18:48:05 +05:30
KRSHH 1725ba95e9 Accurate Average PC Performance GIF 2024-09-16 18:32:29 +05:30
KRSHH abe1e67c0e adding avg pc performance demo 2024-09-16 18:31:18 +05:30
KRSHH 2b9d10f182 Donation button, close option button 2024-09-16 16:54:49 +05:30
K 674f584895 UI Change
Changes in UI
2024-09-16 13:31:20 +05:30
K 325187b513 Fix Text
Font Change, Larger, Bolder
2024-09-16 11:22:38 +05:30
Kenneth Estanislao 8c6d0134a8 Merge pull request #588 from KRSHH/main
Enhance UI with drag and drop, modern look using customtkinter, and improved webcam mapping
2024-09-16 12:21:39 +08:00
K d2f57fa4dd Minor UI Fixes 2024-09-16 01:46:40 +05:30
K 2f2380b98d Delete modules/ui.json 2024-09-16 01:00:03 +05:30
K e5c29749bb UI Redone 2024-09-16 00:37:34 +05:30
K b505ae7b90 Add customtkinter in requirements.txt 2024-09-16 00:33:49 +05:30
CH. Krish 373134cfa1 Add tkinterdnd2 to requirements.txt 2024-09-15 23:02:25 +05:30
CH. Krish 523d80550d Adding Drag and Drop feature to Face Mapper and Source and Target 2024-09-15 23:00:28 +05:30
Kenneth Estanislao 621c3f035e Update README.md
fixed the gumroad link
2024-09-15 19:15:02 +08:00
Vic P. 83529c8ca8 Update README.md 2024-09-15 14:57:31 +07:00
Kenneth Estanislao d38a816b55 Update README.md 2024-09-14 02:17:34 +08:00
Kenneth Estanislao 9fccb069df Update README.md 2024-09-14 02:15:51 +08:00
Kenneth Estanislao 1829d5650b easy installer link 2024-09-14 02:08:33 +08:00
Kenneth Estanislao be36016a69 Update metadata.py 2024-09-14 01:58:34 +08:00
Kenneth Estanislao 26e764c842 Create gumroad.png 2024-09-14 01:56:27 +08:00
Kenneth Estanislao 08b7d56b47 Update README.md 2024-09-13 16:57:46 +08:00
Kenneth Estanislao 969c8796d5 Update README.md 2024-09-13 16:57:09 +08:00
Kenneth Estanislao 0d8fe7f930 Merge branch 'main' of https://github.com/hacksider/Deep-Live-Cam 2024-09-13 16:53:16 +08:00
Kenneth Estanislao 7be92ac3e5 Update face_mapping2.png 2024-09-13 16:52:59 +08:00
Kenneth Estanislao 24414e8d75 Update README.md 2024-09-13 16:40:45 +08:00
Kenneth Estanislao c6309136ad Update README.md 2024-09-13 16:39:34 +08:00
Kenneth Estanislao cec588f1c1 Update README.md
added features
2024-09-13 16:38:47 +08:00
Kenneth Estanislao e899707542 facemapping data
demo data for facemapping
2024-09-13 16:30:44 +08:00
Kenneth Estanislao 336ce2d0d6 Update README.md 2024-09-13 15:49:03 +08:00
Kenneth Estanislao 3f58bdc714 Create resizable.gif 2024-09-13 15:48:47 +08:00
Kenneth Estanislao a2d2f20b5a Update README.md 2024-09-13 14:27:22 +08:00
Kenneth Estanislao 1415493327 Update README.md 2024-09-13 14:16:28 +08:00
Kenneth Estanislao c8851038fa Update README.md 2024-09-13 14:15:51 +08:00
Kenneth Estanislao e74b6ebe42 Update README.md
completed multiple face feature, thanks to @pereiraroland26 for this
2024-09-13 14:12:45 +08:00
Kenneth Estanislao b2fa95e2fc Merge pull request #572 from pereiraroland26/main
Updates to multiple face support (webcam scenario)
2024-09-12 22:27:07 +08:00
Roland Pereira f133d48f60 handled webcam scenario where detected faces are greater than maps provided 2024-09-11 21:42:38 +05:30
Kenneth Estanislao e1a01cfba2 Merge pull request #568 from cyf1r3/main
Update README.md
2024-09-11 13:24:10 +08:00
Anant Singh 06e5e76797 Update README.md
Changed the keyword 'roop' to 'Deep-Live-Cam'.
2024-09-11 10:37:11 +05:30
Kenneth Estanislao 16c1b44927 Revert "recommit webcam option"
This reverts commit 49d3f9a3cc.
2024-09-11 02:49:53 +08:00
Kenneth Estanislao 229375465d Update README.md
added some credits
2024-09-11 00:05:06 +08:00
Kenneth Estanislao 49d3f9a3cc recommit webcam option 2024-09-11 00:02:45 +08:00
Kenneth Estanislao 39238ee80f Merge pull request #566 from pereiraroland26/main
Added support for multiple faces
2024-09-10 23:35:19 +08:00
Roland Pereira d7c6226eb7 updated button widths on popup 2024-09-10 18:53:25 +05:30
Roland Pereira eb140e59c2 commiting gitignore 2024-09-10 16:00:24 +05:30
pereiraroland26 f122006024 updated README.md and created variables for pop dimensions 2024-09-10 14:28:33 +05:30
Roland Pereira 0a144ec57f Merge branch 'hacksider:main' into main 2024-09-10 13:48:40 +05:30
Kenneth Estanislao 9acf77b6ed Revert "Merge pull request #556 from Highpressure/main"
This reverts commit fd07185043, reversing
changes made to f762b61a12.
2024-09-10 14:59:05 +08:00
Kenneth Estanislao fd07185043 Merge pull request #556 from Highpressure/main
multi camera device support
2024-09-10 13:47:43 +08:00
pereiraroland26 da3498c36f Merge branch 'main' of https://github.com/pereiraroland26/Deep-Live-Cam_v2.0 2024-09-10 05:41:46 +05:30
pereiraroland26@gmail.com 53fc65ca7c Added ability to map faces 2024-09-10 05:40:55 +05:30
james 397c84fa8b Added ability to map faces 2024-09-10 04:37:58 +05:30
Highpressure 6381f63722 Update ui.py
option switches went missing in last commit
2024-09-06 21:56:13 +02:00
Highpressure 83ca917c66 Update capturer.py
added change to support multi camera device support as my device 0 is a virtual cam for iphone redirection, device 1 is obs and device 2 is my real camera
2024-09-06 20:59:35 +02:00
Highpressure 2d34201cfc Update ui.py
added dropdown for multi camera device selection
2024-09-06 20:58:38 +02:00
Kenneth Estanislao f762b61a12 Update README.md 2024-09-05 16:09:31 +08:00
Kenneth Estanislao 14625dbfde Update README.md
includes licensing of insightface
2024-09-05 16:01:11 +08:00
Vic P. dc8563372d Update README.md to collapse optional sections for better readability 2024-09-01 01:29:57 +07:00
Vic P. 5dcd30e587 Merge pull request #507 from duhow/patch-1
Update README.md to add an additional model file for the face swapper function
2024-09-01 00:55:36 +07:00
Vic P. e84369862e Update README.md 2024-09-01 00:47:45 +07:00
Vic P. a9f869e491 Merge pull request #510 from underlines/feature/color_space_conversion
Feature/color space conversion
2024-09-01 00:34:46 +07:00
underlines 03fb6bf619 Update readme.md with Windows 11 WSL2 Ubuntu tutorial for Webcams 2024-08-30 23:49:14 +02:00
underlines c91ab8bbd2 add toggle button for blueish cam fix (Force OpenCV2 BGR2RGB) 2024-08-30 22:02:23 +02:00
underlines 79c6615a68 use mjpeg and convert bgr to rgb 2024-08-30 21:49:01 +02:00
David Girón 3c708b0fcb fix model face-swapper 2024-08-30 16:21:57 +02:00
Kenneth Estanislao 3107f74165 Merge pull request #506 from duhow/patch-1
fix: requirements ResolutionImpossible
2024-08-30 19:09:02 +08:00
David Girón 99704f3a18 fix: requirements ResolutionImpossible 2024-08-30 09:07:40 +02:00
Kenneth Estanislao 40598daea9 Merge pull request #455 from barongello/main
Adding a swap faces button to easily swap source/target images
2024-08-27 12:29:55 +08:00
barongello 528c30e3ba Adding a swap faces button to easily swap source/target images 2024-08-25 12:25:19 -03:00
Kenneth Estanislao 446487a70c Update ui.py
Disable NSFW in accordance to github rules
2024-08-24 17:38:49 +08:00
Vic P. 7f95b69bc5 Add TODO to README.md 2024-08-24 00:45:14 +07:00
Kenneth Estanislao 540dad346e Update README.md 2024-08-23 01:56:13 +08:00
Vic P. aa94f2ae7e Merge pull request #429 from vic4key/main
@refer to the PR https://github.com/hacksider/Deep-Live-Cam/pull/293 in the `experimental` branch.
2024-08-22 00:54:10 +07:00
Vic P 3755198ecd Update codes following the comments of @sourcery-ai.
Signed-off-by: Vic P <vic4key@gmail.com>
2024-08-22 00:50:14 +07:00
Vic P 4f62119c2e Support the following options:
- The live camera display as you see it in the front-facing camera frame (like iPhone's Mirror Front Camera).
- The live camera frame is resizable.
Note: These options are turned off by default. Enabling both options may reduce performance by ~2%.

Signed-off-by: Vic P <vic4key@gmail.com>
2024-08-22 00:35:05 +07:00
Vic P. 42b54ef330 Merge pull request #421 from vic4key/main
Re-enabled the NSFW function (turn-off by default) with its bug fixes at PR https://github.com/hacksider/Deep-Live-Cam/pull/237.
2024-08-21 02:22:12 +07:00
Vic P 6d28a52869 Update codes following the comments of @sourcery-ai.
Signed-off-by: Vic P <vic4key@gmail.com>
2024-08-21 02:16:06 +07:00
Vic P 7313a332c8 Re-enabled the NSFW function (turn-off by default).
@refer to the PR #237 in the `experimental` branch.

Signed-off-by: Vic P <vic4key@gmail.com>
2024-08-21 02:02:00 +07:00
Kenneth Estanislao e4b494174d Merge pull request #324 from vietjovi/main
Update README.md to address the issue with the GTK package on MAC OS
2024-08-18 13:47:57 +08:00
Kenneth Estanislao 69d863b44a Revert "Merge remote-tracking branch 'parent/experimental' into experimental"
This reverts commit df99f6ca17.
2024-08-16 21:03:14 +08:00
Kenneth Estanislao d10314c8d6 Revert "Update ui.py"
This reverts commit 9d20e04336.
2024-08-16 21:03:07 +08:00
Kenneth Estanislao 9d20e04336 Update ui.py
Hides NSFW
2024-08-16 20:29:55 +08:00
Aleksandr Spiridonov df99f6ca17 Merge remote-tracking branch 'parent/experimental' into experimental 2024-08-16 20:28:57 +08:00
Kenneth Estanislao 22abb8c25f Revert "Merge pull request #293 from vic4key/experimental"
This reverts commit eab5ba7027.
2024-08-16 13:47:12 +08:00
Kenneth Estanislao eab5ba7027 Merge pull request #293 from vic4key/experimental
To fix bugs and support more options for the Live function (see details in Commits tab)
2024-08-15 14:21:58 +08:00
Viet Nguyen c288d82713 Fix spelling 'package' 2024-08-15 02:36:01 +07:00
Viet Nguyen c8d526157a Update README.md 2024-08-15 02:22:06 +07:00
Kenneth Estanislao 4324b41b9e Update ui.py
hides NSFW button
2024-08-15 03:03:57 +08:00
Kenneth Estanislao a6e00211f0 Merge pull request #321 from gianpaj/stop-live-mode-if-preview-is-closed
Stop live mode when the preview window is closed
2024-08-15 03:01:37 +08:00
Gianfranco Palumbo 99214c7ab1 Stop live mode the preview window is closed 2024-08-14 17:52:42 +02:00
Kenneth Estanislao 080d6f5110 Merge pull request #282 from jasonkneen/main-macos-metal-gpu-optimisation
macOS optimisations for Silicon Macs for GPU / Metal usage (reduced CPU load from 600% to 150%)
2024-08-13 20:30:26 +08:00
Jason Kneen 155546b937 Update .gitignore 2024-08-13 13:23:13 +01:00
Kenneth Estanislao 79fbb7998c Merge pull request #281 from snewell92/patch-1 2024-08-13 20:09:04 +08:00
Sean Newell 5ce2fd298b sourcery update
Grammar updates

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2024-08-13 14:03:05 +02:00
Sean Newell 740410dd73 Strengthen ethical consideration
Nothing we say is legally binding in here, but it
behooves us to be stronger in our language - getting consent
to be digitally reproduced should be required
and standard procedure.
2024-08-13 13:50:02 +02:00
Kenneth Estanislao cbc7c22f1c Create CONTRIBUTING.md 2024-08-13 03:12:58 +08:00
Kenneth Estanislao a31e81fa66 Update README.md
https://www.reddit.com/r/singularity/comments/1eo4sne/comment/lhl7odv/
2024-08-11 21:59:31 +08:00
Kenneth Estanislao e8a8acca9f Update README.md 2024-08-11 21:17:04 +08:00
Kenneth Estanislao a9d4564726 Update README.md
relinking this to the old repo
2024-08-11 21:08:38 +08:00
Kenneth Estanislao fc47cffb18 Update README.md 2024-08-11 16:35:38 +08:00
Kenneth Estanislao fff3009c80 Merge pull request #152 from Saharsha-N/patch-1
Update README.md
2024-08-10 22:08:08 +08:00
Saharsha-N 84c10400b9 Update README.md
Fixed a typo.
2024-08-10 09:55:36 -04:00
Kenneth Estanislao 9f58dfeee1 Merge pull request #140 from rahulbansal16/main
Fix this cyclic dependency issue which was coming while installing rquirements
2024-08-10 20:29:59 +08:00
Rahul Bansal 04e72a85c3 Fix this cyclic dependency issue which was coming while doing the pip install requirements. Now the code is working. You are able to run it on your Windows machine. 2024-08-10 17:43:39 +05:30
Kenneth Estanislao 6a17297e2f Update README.md 2024-08-10 14:19:20 +08:00
Kenneth Estanislao ddd19474da Merge pull request #115 from hacksider/revert-88-main
Revert "Enable to choose a camera device in UI" Will put it on experimental as of this moment
2024-08-10 13:57:37 +08:00
Kenneth Estanislao d49a77b3a3 Revert "Enable to choose a camera device in UI" 2024-08-10 13:54:12 +08:00
31 changed files with 2670 additions and 304 deletions
+38
View File
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+5 -1
View File
@@ -6,17 +6,21 @@ __pycache__/
.todo
*.log
*.backup
tf_env/
*.png
*.mp4
*.mkv
.tmp/
temp/
.venv/
venv/
env/
workflow/
gfpgan/
models/inswapper_128.onnx
models/GFPGANv1.4.pth
*.onnx
models/DMDNet.pth
faceswap/
.vscode/
+1
View File
@@ -0,0 +1 @@
Please always push on the experimental to ensure we don't mess with the main branch. All the test will be done on the experimental and will be pushed to the main branch after few days of testing.
+327 -90
View File
@@ -1,163 +1,217 @@
![demo-gif](demo.gif)
<h1 align="center">Deep-Live-Cam</h1>
<p align="center">
Real-time face swap and video deepfake with a single click and only a single image.
</p>
<p align="center">
<img src="media/demo.gif" alt="Demo GIF">
<img src="media/avgpcperformancedemo.gif" alt="Performance Demo GIF">
</p>
## Disclaimer
This software is meant to be a productive contribution to the rapidly growing AI-generated media industry. It will help artists with tasks such as animating a custom character or using the character as a model for clothing etc.
The developers of this software are aware of its possible unethical applications and are committed to take preventative measures against them. It has a built-in check which prevents the program from working on inappropriate media including but not limited to nudity, graphic content, sensitive material such as war footage etc. We will continue to develop this project in the positive direction while adhering to law and ethics. This project may be shut down or include watermarks on the output if requested by law.
This software is intended as a productive contribution to the AI-generated media industry. It aims to assist artists with tasks like animating custom characters or using them as models for clothing, etc.
Users of this software are expected to use this software responsibly while abiding the local law. If face of a real person is being used, users are suggested to get consent from the concerned person and clearly mention that it is a deepfake when posting content online. Developers of this software will not be responsible for actions of end-users.
We are aware of the potential for unethical applications and are committed to preventative measures. A built-in check prevents the program from processing inappropriate media (nudity, graphic content, sensitive material like war footage, etc.). We will continue to develop this project responsibly, adhering to law and ethics. We may shut down the project or add watermarks if legally required.
## How do I install it?
Users are expected to use this software responsibly and legally. If using a real person's face, obtain their consent and clearly label any output as a deepfake when sharing online. We are not responsible for end-user actions.
### Basic: It is more likely to work on your computer but it will also be very slow. You can follow instructions for the basic install (This usually runs via **CPU**)
#### 1.Setup your platform
- python (3.10 recommended)
## Quick Start (Windows / Nvidia)
[![Download](media/download.png)](https://hacksider.gumroad.com/l/vccdmm)
[Download latest pre-built version with CUDA support](https://hacksider.gumroad.com/l/vccdmm) - No Manual Installation/Downloading required.
## Installation (Manual)
**Please be aware that the installation needs technical skills and is NOT for beginners, consider downloading the prebuilt. Please do NOT open platform and installation related issues on GitHub before discussing it on the discord server.**
### Basic Installation (CPU)
This is more likely to work on your computer but will be slower as it utilizes the CPU.
**1. Setup Your Platform**
- Python (3.10 recommended)
- pip
- git
- [ffmpeg](https://www.youtube.com/watch?v=OlNWCpFdVMA)
- [visual studio 2022 runtimes (windows)](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
#### 2. Clone Repository
https://github.com/hacksider/Deep-Live-Cam.git
- [Visual Studio 2022 Runtimes (Windows)](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
#### 3. Download Models
**2. Clone Repository**
```bash
https://github.com/hacksider/Deep-Live-Cam.git
```
**3. Download Models**
1. [GFPGANv1.4](https://huggingface.co/hacksider/deep-live-cam/resolve/main/GFPGANv1.4.pth)
2. [inswapper_128_fp16.onnx](https://huggingface.co/hacksider/deep-live-cam/resolve/main/inswapper_128_fp16.onnx)
2. [inswapper_128_fp16.onnx](https://huggingface.co/hacksider/deep-live-cam/resolve/main/inswapper_128.onnx) (Note: Use this [replacement version](https://github.com/facefusion/facefusion-assets/releases/download/models/inswapper_128.onnx) if you encounter issues)
Then put those 2 files on the "**models**" folder
Place these files in the "**models**" folder.
#### 4. Install dependency
We highly recommend to work with a `venv` to avoid issues.
```
**4. Install Dependencies**
We highly recommend using a `venv` to avoid issues.
```bash
pip install -r requirements.txt
```
##### DONE!!! If you dont have any GPU, You should be able to run roop using `python run.py` command. Keep in mind that while running the program for first time, it will download some models which can take time depending on your network connection.
### *Proceed if you want to use GPU Acceleration
### CUDA Execution Provider (Nvidia)*
**For macOS:** Install or upgrade the `python-tk` package:
```bash
brew install python-tk@3.10
```
**Run:** If you don't have a GPU, you can run Deep-Live-Cam using `python run.py`. Note that initial execution will download models (~300MB).
### GPU Acceleration (Optional)
<details>
<summary>Click to see the details</summary>
**CUDA Execution Provider (Nvidia)**
1. Install [CUDA Toolkit 11.8](https://developer.nvidia.com/cuda-11-8-0-download-archive)
2. Install dependencies:
```
```bash
pip uninstall onnxruntime onnxruntime-gpu
pip install onnxruntime-gpu==1.16.3
```
3. Usage in case the provider is available:
```
3. Usage:
```bash
python run.py --execution-provider cuda
```
### [](https://github.com/s0md3v/roop/wiki/2.-Acceleration#coreml-execution-provider-apple-silicon)CoreML Execution Provider (Apple Silicon)
**CoreML Execution Provider (Apple Silicon)**
1. Install dependencies:
```
```bash
pip uninstall onnxruntime onnxruntime-silicon
pip install onnxruntime-silicon==1.13.1
```
2. Usage in case the provider is available:
```
2. Usage:
```bash
python run.py --execution-provider coreml
```
### [](https://github.com/s0md3v/roop/wiki/2.-Acceleration#coreml-execution-provider-apple-legacy)CoreML Execution Provider (Apple Legacy)
**CoreML Execution Provider (Apple Legacy)**
1. Install dependencies:
```
```bash
pip uninstall onnxruntime onnxruntime-coreml
pip install onnxruntime-coreml==1.13.1
```
2. Usage in case the provider is available:
```
2. Usage:
```bash
python run.py --execution-provider coreml
```
### [](https://github.com/s0md3v/roop/wiki/2.-Acceleration#directml-execution-provider-windows)DirectML Execution Provider (Windows)
**DirectML Execution Provider (Windows)**
1. Install dependencies:
```
```bash
pip uninstall onnxruntime onnxruntime-directml
pip install onnxruntime-directml==1.15.1
```
2. Usage in case the provider is available:
```
2. Usage:
```bash
python run.py --execution-provider directml
```
### [](https://github.com/s0md3v/roop/wiki/2.-Acceleration#openvino-execution-provider-intel)OpenVINO™ Execution Provider (Intel)
**OpenVINO™ Execution Provider (Intel)**
1. Install dependencies:
```
```bash
pip uninstall onnxruntime onnxruntime-openvino
pip install onnxruntime-openvino==1.15.0
```
2. Usage in case the provider is available:
```
2. Usage:
```bash
python run.py --execution-provider openvino
```
## How do I use it?
> Note: When you run this program for the first time, it will download some models ~300MB in size.
Executing `python run.py` command will launch this window:
![gui-demo](instruction.png)
Choose a face (image with desired face) and the target image/video (image/video in which you want to replace the face) and click on `Start`. Open file explorer and navigate to the directory you select your output to be in. You will find a directory named `<video_title>` where you can see the frames being swapped in realtime. Once the processing is done, it will create the output file. That's it.
## For the webcam mode
Just follow the clicks on the screenshot
1. Select a face
2. Click live
3. Wait for a few second (it takes a longer time, usually 10 to 30 seconds before the preview shows up)
![demo-gif](demo.gif)
Just use your favorite screencapture to stream like OBS
> Note: In case you want to change your face, just select another picture, the preview mode will then restart (so just wait a bit).
</details>
Additional command line arguments are given below. To learn out what they do, check [this guide](https://github.com/s0md3v/roop/wiki/Advanced-Options).
## Usage
**1. Image/Video Mode**
- Execute `python run.py`.
- Choose a source face image and a target image/video.
- Click "Start".
- The output will be saved in a directory named after the target video.
**2. Webcam Mode**
- Execute `python run.py`.
- Select a source face image.
- Click "Live".
- Wait for the preview to appear (10-30 seconds).
- Use a screen capture tool like OBS to stream.
- To change the face, select a new source image.
![demo-gif](media/demo.gif)
## Features
### Resizable Preview Window
Dynamically improve performance using the `--live-resizable` parameter.
![resizable-gif](media/resizable.gif)
### Face Mapping
Track and change faces on the fly.
![face_mapping_source](media/face_mapping_source.gif)
**Source Video:**
![face-mapping](media/face_mapping.png)
**Enable Face Mapping:**
![face-mapping2](media/face_mapping2.png)
**Map the Faces:**
![face_mapping_result](media/face_mapping_result.gif)
**See the Magic!**
![movie](media/movie.gif)
**Watch movies in realtime:**
It's as simple as opening a movie on the screen, and selecting OBS as your camera!
![image](media/movie_img.png)
## Command Line Arguments
```
options:
-h, --help show this help message and exit
-s SOURCE_PATH, --source SOURCE_PATH select an source image
-t TARGET_PATH, --target TARGET_PATH select an target image or video
-s SOURCE_PATH, --source SOURCE_PATH select a source image
-t TARGET_PATH, --target TARGET_PATH select a target image or video
-o OUTPUT_PATH, --output OUTPUT_PATH select output file or directory
--frame-processor FRAME_PROCESSOR [FRAME_PROCESSOR ...] frame processors (choices: face_swapper, face_enhancer, ...)
--keep-fps keep original fps
--keep-audio keep original audio
--keep-frames keep temporary frames
--many-faces process every face
--map-faces map source target faces
--nsfw-filter filter the NSFW image or video
--video-encoder {libx264,libx265,libvpx-vp9} adjust output video encoder
--video-quality [0-51] adjust output video quality
--live-mirror the live camera display as you see it in the front-facing camera frame
--live-resizable the live camera frame is resizable
--max-memory MAX_MEMORY maximum amount of RAM in GB
--execution-provider {cpu} [{cpu} ...] available execution provider (choices: cpu, ...)
--execution-threads EXECUTION_THREADS number of execution threads
@@ -166,10 +220,193 @@ options:
Looking for a CLI mode? Using the -s/--source argument will make the run program in cli mode.
## Webcam Mode on WSL2 Ubuntu (Optional)
<details>
<summary>Click to see the details</summary>
If you want to use WSL2 on Windows 11 you will notice, that Ubuntu WSL2 doesn't come with USB-Webcam support in the Kernel. You need to do two things: Compile the Kernel with the right modules integrated and forward your USB Webcam from Windows to Ubuntu with the usbipd app. Here are detailed Steps:
This tutorial will guide you through the process of setting up WSL2 Ubuntu with USB webcam support, rebuilding the kernel, and preparing the environment for the Deep-Live-Cam project.
**1. Install WSL2 Ubuntu**
Install WSL2 Ubuntu from the Microsoft Store or using PowerShell:
**2. Enable USB Support in WSL2**
1. Install the USB/IP tool for Windows:
[https://learn.microsoft.com/en-us/windows/wsl/connect-usb](https://learn.microsoft.com/en-us/windows/wsl/connect-usb)
2. In Windows PowerShell (as Administrator), connect your webcam to WSL:
```powershell
usbipd list
usbipd bind --busid x-x # Replace x-x with your webcam's bus ID
usbipd attach --wsl --busid x-x # Replace x-x with your webcam's bus ID
```
You need to redo the above every time you reboot wsl or re-connect your webcam/usb device.
**3. Rebuild WSL2 Ubuntu Kernel with USB and Webcam Modules**
Follow these steps to rebuild the kernel:
1. Start with this guide: [https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf](https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf)
2. When you reach the `sudo wget [github.com](http://github.com/)...PINTO0309` step, which won't work for newer kernel versions, follow this video instead or alternatively follow the video tutorial from the beginning:
[https://www.youtube.com/watch?v=t_YnACEPmrM](https://www.youtube.com/watch?v=t_YnACEPmrM)
Additional info: [https://askubuntu.com/questions/1413377/camera-not-working-in-cheese-in-wsl2](https://askubuntu.com/questions/1413377/camera-not-working-in-cheese-in-wsl2)
3. After rebuilding, restart WSL with the new kernel.
**4. Set Up Deep-Live-Cam Project**
Within Ubuntu:
1. Clone the repository:
```bash
git clone [https://github.com/hacksider/Deep-Live-Cam](https://github.com/hacksider/Deep-Live-Cam)
```
2. Follow the installation instructions in the repository, including cuda toolkit 11.8, make 100% sure it's not cuda toolkit 12.x.
**5. Verify and Load Kernel Modules**
1. Check if USB and webcam modules are built into the kernel:
```bash
zcat /proc/config.gz | grep -i "CONFIG_USB_VIDEO_CLASS"
```
2. If modules are loadable (m), not built-in (y), check if the file exists:
```bash
ls /lib/modules/$(uname -r)/kernel/drivers/media/usb/uvc/
```
3. Load the module and check for errors (optional if built-in):
```bash
sudo modprobe uvcvideo
dmesg | tail
```
4. Verify video devices:
```bash
sudo ls -al /dev/video*
```
**6. Set Up Permissions**
1. Add user to video group and set permissions:
```bash
sudo usermod -a -G video $USER
sudo chgrp video /dev/video0 /dev/video1
sudo chmod 660 /dev/video0 /dev/video1
```
2. Create a udev rule for permanent permissions:
```bash
sudo nano /etc/udev/rules.d/81-webcam.rules
```
Add this content:
```
KERNEL=="video[0-9]*", GROUP="video", MODE="0660"
```
3. Reload udev rules:
```bash
sudo udevadm control --reload-rules && sudo udevadm trigger
```
4. Log out and log back into your WSL session.
5. Start Deep-Live-Cam with `python run.py --execution-provider cuda --max-memory 8` where 8 can be changed to the number of GB VRAM of your GPU has, minus 1-2GB. If you have a RTX3080 with 10GB I suggest adding 8GB. Leave some left for Windows.
**Final Notes**
- Steps 6 and 7 may be optional if the modules are built into the kernel and permissions are already set correctly.
- Always ensure you're using compatible versions of CUDA, ONNX, and other dependencies.
- If issues persist, consider checking the Deep-Live-Cam project's specific requirements and troubleshooting steps.
By following these steps, you should have a WSL2 Ubuntu environment with USB webcam support ready for the Deep-Live-Cam project. If you encounter any issues, refer back to the specific error messages and troubleshooting steps provided.
**Troubleshooting CUDA Issues**
If you encounter this error:
```
[ONNXRuntimeError] : 1 : FAIL : Failed to load library [libonnxruntime_providers_cuda.so](http://libonnxruntime_providers_cuda.so/) with error: libcufft.so.10: cannot open shared object file: No such file or directory
```
Follow these steps:
1. Install CUDA Toolkit 11.8 (ONNX 1.16.3 requires CUDA 11.x, not 12.x):
[https://developer.nvidia.com/cuda-11-8-0-download-archive](https://developer.nvidia.com/cuda-11-8-0-download-archive)
select: Linux, x86_64, WSL-Ubuntu, 2.0, deb (local)
2. Check CUDA version:
```bash
/usr/local/cuda/bin/nvcc --version
```
3. If the wrong version is installed, remove it completely:
[https://askubuntu.com/questions/530043/removing-nvidia-cuda-toolkit-and-installing-new-one](https://askubuntu.com/questions/530043/removing-nvidia-cuda-toolkit-and-installing-new-one)
4. Install CUDA Toolkit 11.8 again [https://developer.nvidia.com/cuda-11-8-0-download-archive](https://developer.nvidia.com/cuda-11-8-0-download-archive), select: Linux, x86_64, WSL-Ubuntu, 2.0, deb (local)
```bash
sudo apt-get -y install cuda-toolkit-11-8
```
</details>
## Future Updates & Roadmap
For the latest experimental builds and features, see the [experimental branch](https://github.com/hacksider/Deep-Live-Cam/tree/experimental).
**TODO:**
- [ ] Develop a version for web app/service
- [ ] Speed up model loading
- [ ] Speed up real-time face swapping
- [x] Support multiple faces
- [x] UI/UX enhancements for desktop app
This is an open-source project developed in our free time. Updates may be delayed.
**Tips and Links:**
- [How to make the most of Deep-Live-Cam](https://hacksider.gumroad.com/p/how-to-make-the-most-on-deep-live-cam)
- Face enhancer is good, but still very slow for any live streaming purpose.
## Credits
- [henryruhs](https://github.com/henryruhs): for being an irreplaceable contributor to the project
- [ffmpeg](https://ffmpeg.org/): for making video related operations easy
- [deepinsight](https://github.com/deepinsight): for their [insightface](https://github.com/deepinsight/insightface) project which provided a well-made library and models.
- [deepinsight](https://github.com/deepinsight): for their [insightface](https://github.com/deepinsight/insightface) project which provided a well-made library and models. Please be reminded that the [use of the model is for non-commercial research purposes only](https://github.com/deepinsight/insightface?tab=readme-ov-file#license).
- [havok2-htwo](https://github.com/havok2-htwo) : for sharing the code for webcam
- [GosuDRM](https://github.com/GosuDRM/nsfw-roop) : for uncensoring roop
- and all developers behind libraries used in this project.
- [GosuDRM](https://github.com/GosuDRM) : for open version of roop
- [pereiraroland26](https://github.com/pereiraroland26) : Multiple faces support
- [vic4key](https://github.com/vic4key) : For supporting/contributing on this project
- [KRSHH](https://github.com/KRSHH) : For updating the UI
- and [all developers](https://github.com/hacksider/Deep-Live-Cam/graphs/contributors) behind libraries used in this project.
- Foot Note: [This is originally roop-cam, see the full history of the code here.](https://github.com/hacksider/roop-cam) Please be informed that the base author of the code is [s0md3v](https://github.com/s0md3v/roop)
## Contributions
![Alt](https://repobeats.axiom.co/api/embed/fec8e29c45dfdb9c5916f3a7830e1249308d20e1.svg "Repobeats analytics image")
## Star History
<a href="https://star-history.com/#hacksider/deep-live-cam&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" />
</picture>
</a>
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 MiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

View File

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 MiB

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

+4 -1
View File
@@ -1 +1,4 @@
just put the models in this folder
just put the models in this folder -
https://huggingface.co/hacksider/deep-live-cam/resolve/main/inswapper_128_fp16.onnx?download=true
https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.4.pth
+15 -3
View File
@@ -1,16 +1,28 @@
from typing import Any
import cv2
import modules.globals # Import the globals to check the color correction toggle
def get_video_frame(video_path: str, frame_number: int = 0) -> Any:
capture = cv2.VideoCapture(video_path)
# Set MJPEG format to ensure correct color space handling
capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
# Only force RGB conversion if color correction is enabled
if modules.globals.color_correction:
capture.set(cv2.CAP_PROP_CONVERT_RGB, 1)
frame_total = capture.get(cv2.CAP_PROP_FRAME_COUNT)
capture.set(cv2.CAP_PROP_POS_FRAMES, min(frame_total, frame_number - 1))
has_frame, frame = capture.read()
if has_frame and modules.globals.color_correction:
# Convert the frame color if necessary
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
capture.release()
if has_frame:
return frame
return None
return frame if has_frame else None
def get_video_frame_total(video_path: str) -> int:
+32
View File
@@ -0,0 +1,32 @@
import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from typing import Any
def find_cluster_centroids(embeddings, max_k=10) -> Any:
inertia = []
cluster_centroids = []
K = range(1, max_k+1)
for k in K:
kmeans = KMeans(n_clusters=k, random_state=0)
kmeans.fit(embeddings)
inertia.append(kmeans.inertia_)
cluster_centroids.append({"k": k, "centroids": kmeans.cluster_centers_})
diffs = [inertia[i] - inertia[i+1] for i in range(len(inertia)-1)]
optimal_centroids = cluster_centroids[diffs.index(max(diffs)) + 1]['centroids']
return optimal_centroids
def find_closest_centroid(centroids: list, normed_face_embedding) -> list:
try:
centroids = np.array(centroids)
normed_face_embedding = np.array(normed_face_embedding)
similarities = np.dot(centroids, normed_face_embedding)
closest_centroid_index = np.argmax(similarities)
return closest_centroid_index, centroids[closest_centroid_index]
except ValueError:
return None
+21 -13
View File
@@ -39,8 +39,12 @@ def parse_args() -> None:
program.add_argument('--keep-audio', help='keep original audio', dest='keep_audio', action='store_true', default=True)
program.add_argument('--keep-frames', help='keep temporary frames', dest='keep_frames', action='store_true', default=False)
program.add_argument('--many-faces', help='process every face', dest='many_faces', action='store_true', default=False)
program.add_argument('--nsfw-filter', help='filter the NSFW image or video', dest='nsfw_filter', action='store_true', default=False)
program.add_argument('--map-faces', help='map source target faces', dest='map_faces', action='store_true', default=False)
program.add_argument('--video-encoder', help='adjust output video encoder', dest='video_encoder', default='libx264', choices=['libx264', 'libx265', 'libvpx-vp9'])
program.add_argument('--video-quality', help='adjust output video quality', dest='video_quality', type=int, default=18, choices=range(52), metavar='[0-51]')
program.add_argument('--live-mirror', help='The live camera display as you see it in the front-facing camera frame', dest='live_mirror', action='store_true', default=False)
program.add_argument('--live-resizable', help='The live camera frame is resizable', dest='live_resizable', action='store_true', default=False)
program.add_argument('--max-memory', help='maximum amount of RAM in GB', dest='max_memory', type=int, default=suggest_max_memory())
program.add_argument('--execution-provider', help='execution provider', dest='execution_provider', default=['cpu'], choices=suggest_execution_providers(), nargs='+')
program.add_argument('--execution-threads', help='number of execution threads', dest='execution_threads', type=int, default=suggest_execution_threads())
@@ -63,8 +67,12 @@ def parse_args() -> None:
modules.globals.keep_audio = args.keep_audio
modules.globals.keep_frames = args.keep_frames
modules.globals.many_faces = args.many_faces
modules.globals.nsfw_filter = args.nsfw_filter
modules.globals.map_faces = args.map_faces
modules.globals.video_encoder = args.video_encoder
modules.globals.video_quality = args.video_quality
modules.globals.live_mirror = args.live_mirror
modules.globals.live_resizable = args.live_resizable
modules.globals.max_memory = args.max_memory
modules.globals.execution_providers = decode_execution_providers(args.execution_provider)
modules.globals.execution_threads = args.execution_threads
@@ -75,8 +83,6 @@ def parse_args() -> None:
else:
modules.globals.fp_ui['face_enhancer'] = False
modules.globals.nsfw = False
# translate deprecated args
if args.source_path_deprecated:
print('\033[33mArgument -f and --face are deprecated. Use -s and --source instead.\033[0m')
@@ -165,18 +171,19 @@ def update_status(message: str, scope: str = 'DLC.CORE') -> None:
if not modules.globals.headless:
ui.update_status(message)
def start() -> None:
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
if not frame_processor.pre_start():
return
update_status('Processing...')
# process image to image
if has_image_extension(modules.globals.target_path):
if modules.globals.nsfw == False:
from modules.predicter import predict_image
if predict_image(modules.globals.target_path):
destroy()
if modules.globals.nsfw_filter and ui.check_and_ignore_nsfw(modules.globals.target_path, destroy):
return
try:
shutil.copy2(modules.globals.target_path, modules.globals.output_path)
except Exception as e:
print("Error copying file:", str(e))
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME)
frame_processor.process_image(modules.globals.source_path, modules.globals.output_path, modules.globals.output_path)
@@ -187,14 +194,15 @@ def start() -> None:
update_status('Processing to image failed!')
return
# process image to videos
if modules.globals.nsfw == False:
from modules.predicter import predict_video
if predict_video(modules.globals.target_path):
destroy()
if modules.globals.nsfw_filter and ui.check_and_ignore_nsfw(modules.globals.target_path, destroy):
return
if not modules.globals.map_faces:
update_status('Creating temp resources...')
create_temp(modules.globals.target_path)
update_status('Extracting frames...')
extract_frames(modules.globals.target_path)
temp_frame_paths = get_temp_frame_paths(modules.globals.target_path)
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME)
@@ -226,10 +234,10 @@ def start() -> None:
update_status('Processing to video failed!')
def destroy() -> None:
def destroy(to_quit=True) -> None:
if modules.globals.target_path:
clean_temp(modules.globals.target_path)
quit()
if to_quit: quit()
def run() -> None:
+158
View File
@@ -1,8 +1,16 @@
import os
import shutil
from typing import Any
import insightface
import cv2
import numpy as np
import modules.globals
from tqdm import tqdm
from modules.typing import Frame
from modules.cluster_analysis import find_cluster_centroids, find_closest_centroid
from modules.utilities import get_temp_directory_path, create_temp, extract_frames, clean_temp, get_temp_frame_paths
from pathlib import Path
FACE_ANALYSER = None
@@ -29,3 +37,153 @@ def get_many_faces(frame: Frame) -> Any:
return get_face_analyser().get(frame)
except IndexError:
return None
def has_valid_map() -> bool:
for map in modules.globals.souce_target_map:
if "source" in map and "target" in map:
return True
return False
def default_source_face() -> Any:
for map in modules.globals.souce_target_map:
if "source" in map:
return map['source']['face']
return None
def simplify_maps() -> Any:
centroids = []
faces = []
for map in modules.globals.souce_target_map:
if "source" in map and "target" in map:
centroids.append(map['target']['face'].normed_embedding)
faces.append(map['source']['face'])
modules.globals.simple_map = {'source_faces': faces, 'target_embeddings': centroids}
return None
def add_blank_map() -> Any:
try:
max_id = -1
if len(modules.globals.souce_target_map) > 0:
max_id = max(modules.globals.souce_target_map, key=lambda x: x['id'])['id']
modules.globals.souce_target_map.append({
'id' : max_id + 1
})
except ValueError:
return None
def get_unique_faces_from_target_image() -> Any:
try:
modules.globals.souce_target_map = []
target_frame = cv2.imread(modules.globals.target_path)
many_faces = get_many_faces(target_frame)
i = 0
for face in many_faces:
x_min, y_min, x_max, y_max = face['bbox']
modules.globals.souce_target_map.append({
'id' : i,
'target' : {
'cv2' : target_frame[int(y_min):int(y_max), int(x_min):int(x_max)],
'face' : face
}
})
i = i + 1
except ValueError:
return None
def get_unique_faces_from_target_video() -> Any:
try:
modules.globals.souce_target_map = []
frame_face_embeddings = []
face_embeddings = []
print('Creating temp resources...')
clean_temp(modules.globals.target_path)
create_temp(modules.globals.target_path)
print('Extracting frames...')
extract_frames(modules.globals.target_path)
temp_frame_paths = get_temp_frame_paths(modules.globals.target_path)
i = 0
for temp_frame_path in tqdm(temp_frame_paths, desc="Extracting face embeddings from frames"):
temp_frame = cv2.imread(temp_frame_path)
many_faces = get_many_faces(temp_frame)
for face in many_faces:
face_embeddings.append(face.normed_embedding)
frame_face_embeddings.append({'frame': i, 'faces': many_faces, 'location': temp_frame_path})
i += 1
centroids = find_cluster_centroids(face_embeddings)
for frame in frame_face_embeddings:
for face in frame['faces']:
closest_centroid_index, _ = find_closest_centroid(centroids, face.normed_embedding)
face['target_centroid'] = closest_centroid_index
for i in range(len(centroids)):
modules.globals.souce_target_map.append({
'id' : i
})
temp = []
for frame in tqdm(frame_face_embeddings, desc=f"Mapping frame embeddings to centroids-{i}"):
temp.append({'frame': frame['frame'], 'faces': [face for face in frame['faces'] if face['target_centroid'] == i], 'location': frame['location']})
modules.globals.souce_target_map[i]['target_faces_in_frame'] = temp
# dump_faces(centroids, frame_face_embeddings)
default_target_face()
except ValueError:
return None
def default_target_face():
for map in modules.globals.souce_target_map:
best_face = None
best_frame = None
for frame in map['target_faces_in_frame']:
if len(frame['faces']) > 0:
best_face = frame['faces'][0]
best_frame = frame
break
for frame in map['target_faces_in_frame']:
for face in frame['faces']:
if face['det_score'] > best_face['det_score']:
best_face = face
best_frame = frame
x_min, y_min, x_max, y_max = best_face['bbox']
target_frame = cv2.imread(best_frame['location'])
map['target'] = {
'cv2' : target_frame[int(y_min):int(y_max), int(x_min):int(x_max)],
'face' : best_face
}
def dump_faces(centroids: Any, frame_face_embeddings: list):
temp_directory_path = get_temp_directory_path(modules.globals.target_path)
for i in range(len(centroids)):
if os.path.exists(temp_directory_path + f"/{i}") and os.path.isdir(temp_directory_path + f"/{i}"):
shutil.rmtree(temp_directory_path + f"/{i}")
Path(temp_directory_path + f"/{i}").mkdir(parents=True, exist_ok=True)
for frame in tqdm(frame_face_embeddings, desc=f"Copying faces to temp/./{i}"):
temp_frame = cv2.imread(frame['location'])
j = 0
for face in frame['faces']:
if face['target_centroid'] == i:
x_min, y_min, x_max, y_max = face['bbox']
if temp_frame[int(y_min):int(y_max), int(x_min):int(x_max)].size > 0:
cv2.imwrite(temp_directory_path + f"/{i}/{frame['frame']}_{j}.png", temp_frame[int(y_min):int(y_max), int(x_min):int(x_max)])
j += 1
+27 -11
View File
@@ -1,30 +1,46 @@
import os
from typing import List, Dict
from typing import List, Dict, Any
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
WORKFLOW_DIR = os.path.join(ROOT_DIR, 'workflow')
WORKFLOW_DIR = os.path.join(ROOT_DIR, "workflow")
file_types = [
('Image', ('*.png','*.jpg','*.jpeg','*.gif','*.bmp')),
('Video', ('*.mp4','*.mkv'))
("Image", ("*.png", "*.jpg", "*.jpeg", "*.gif", "*.bmp")),
("Video", ("*.mp4", "*.mkv")),
]
souce_target_map = []
simple_map = {}
source_path = None
target_path = None
output_path = None
frame_processors: List[str] = []
keep_fps = None
keep_audio = None
keep_frames = None
many_faces = None
keep_fps = True # Initialize with default value
keep_audio = True # Initialize with default value
keep_frames = False # Initialize with default value
many_faces = False # Initialize with default value
map_faces = False # Initialize with default value
color_correction = False # Initialize with default value
nsfw_filter = False # Initialize with default value
video_encoder = None
video_quality = None
live_mirror = False # Initialize with default value
live_resizable = False # Initialize with default value
max_memory = None
execution_providers: List[str] = []
execution_threads = None
headless = None
log_level = 'error'
fp_ui: Dict[str, bool] = {}
nsfw = None
log_level = "error"
fp_ui: Dict[str, bool] = {"face_enhancer": False} # Initialize with default value
camera_input_combobox = None
webcam_preview_running = False
show_fps = False # Initialize with default value
mouth_mask = False
show_mouth_mask_box = False
mask_down_size = 0.5
mask_size = 1.0
mask_feather_ratio = 8
opacity_switch = False
face_opacity = 100
selected_camera = None
+1 -1
View File
@@ -1,3 +1,3 @@
name = 'Deep Live Cam'
version = '1.3.0'
version = '1.6.0'
edition = 'Portable'
+11
View File
@@ -1,16 +1,27 @@
import numpy
import opennsfw2
from PIL import Image
import cv2 # Add OpenCV import
import modules.globals # Import globals to access the color correction toggle
from modules.typing import Frame
MAX_PROBABILITY = 0.85
# Preload the model once for efficiency
model = None
def predict_frame(target_frame: Frame) -> bool:
# Convert the frame to RGB before processing if color correction is enabled
if modules.globals.color_correction:
target_frame = cv2.cvtColor(target_frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(target_frame)
image = opennsfw2.preprocess_image(image, opennsfw2.Preprocessing.YAHOO)
global model
if model is None:
model = opennsfw2.make_open_nsfw_model()
views = numpy.expand_dims(image, axis=0)
_, probability = model.predict(views)[0]
return probability > MAX_PROBABILITY
+424 -17
View File
@@ -2,34 +2,49 @@ from typing import Any, List
import cv2
import insightface
import threading
import numpy as np
import modules.globals
import modules.processors.frame.core
from modules.core import update_status
from modules.face_analyser import get_one_face, get_many_faces
from modules.face_analyser import get_one_face, get_many_faces, default_source_face
from modules.typing import Face, Frame
from modules.utilities import conditional_download, resolve_relative_path, is_image, is_video
from modules.utilities import (
conditional_download,
resolve_relative_path,
is_image,
is_video,
)
from modules.cluster_analysis import find_closest_centroid
FACE_SWAPPER = None
THREAD_LOCK = threading.Lock()
NAME = 'DLC.FACE-SWAPPER'
NAME = "DLC.FACE-SWAPPER"
def pre_check() -> bool:
download_directory_path = resolve_relative_path('../models')
conditional_download(download_directory_path, ['https://huggingface.co/hacksider/deep-live-cam/blob/main/inswapper_128_fp16.onnx'])
download_directory_path = resolve_relative_path("../models")
conditional_download(
download_directory_path,
[
"https://huggingface.co/hacksider/deep-live-cam/blob/main/inswapper_128_fp16.onnx"
],
)
return True
def pre_start() -> bool:
if not is_image(modules.globals.source_path):
update_status('Select an image for source path.', NAME)
if not modules.globals.map_faces and not is_image(modules.globals.source_path):
update_status("Select an image for source path.", NAME)
return False
elif not get_one_face(cv2.imread(modules.globals.source_path)):
update_status('No face in source path detected.', NAME)
elif not modules.globals.map_faces and not get_one_face(
cv2.imread(modules.globals.source_path)
):
update_status("No face in source path detected.", NAME)
return False
if not is_image(modules.globals.target_path) and not is_video(modules.globals.target_path):
update_status('Select an image or video for target path.', NAME)
if not is_image(modules.globals.target_path) and not is_video(
modules.globals.target_path
):
update_status("Select an image or video for target path.", NAME)
return False
return True
@@ -39,16 +54,49 @@ def get_face_swapper() -> Any:
with THREAD_LOCK:
if FACE_SWAPPER is None:
model_path = resolve_relative_path('../models/inswapper_128_fp16.onnx')
FACE_SWAPPER = insightface.model_zoo.get_model(model_path, providers=modules.globals.execution_providers)
model_path = resolve_relative_path("../models/inswapper_128_fp16.onnx")
FACE_SWAPPER = insightface.model_zoo.get_model(
model_path, providers=modules.globals.execution_providers
)
return FACE_SWAPPER
def swap_face(source_face: Face, target_face: Face, temp_frame: Frame) -> Frame:
return get_face_swapper().get(temp_frame, target_face, source_face, paste_back=True)
swapped_frame = get_face_swapper().get(
temp_frame, target_face, source_face, paste_back=True
)
# Apply opacity if enabled
if modules.globals.opacity_switch:
opacity = modules.globals.face_opacity / 100
swapped_frame = cv2.addWeighted(
swapped_frame, opacity, temp_frame, 1 - opacity, 0
)
# Apply mouth mask if enabled
if modules.globals.mouth_mask:
face_mask = create_face_mask(target_face, temp_frame)
mouth_mask_data = create_lower_mouth_mask(target_face, temp_frame)
mouth_mask, mouth_cutout, mouth_box, lower_lip_polygon = mouth_mask_data
if mouth_box is not None:
swapped_frame = apply_mouth_area(
swapped_frame, mouth_cutout, mouth_box, face_mask, lower_lip_polygon
)
if modules.globals.show_mouth_mask_box:
swapped_frame = draw_mouth_mask_visualization(
swapped_frame, target_face, mouth_mask_data
)
return swapped_frame
def process_frame(source_face: Face, temp_frame: Frame) -> Frame:
# Ensure the frame is in RGB format if color correction is enabled
if modules.globals.color_correction:
temp_frame = cv2.cvtColor(temp_frame, cv2.COLOR_BGR2RGB)
if modules.globals.many_faces:
many_faces = get_many_faces(temp_frame)
if many_faces:
@@ -61,7 +109,99 @@ def process_frame(source_face: Face, temp_frame: Frame) -> Frame:
return temp_frame
def process_frames(source_path: str, temp_frame_paths: List[str], progress: Any = None) -> None:
def process_frame_v2(temp_frame: Frame, temp_frame_path: str = "") -> Frame:
if is_image(modules.globals.target_path):
if modules.globals.many_faces:
source_face = default_source_face()
for map in modules.globals.souce_target_map:
target_face = map["target"]["face"]
temp_frame = swap_face(source_face, target_face, temp_frame)
elif not modules.globals.many_faces:
for map in modules.globals.souce_target_map:
if "source" in map:
source_face = map["source"]["face"]
target_face = map["target"]["face"]
temp_frame = swap_face(source_face, target_face, temp_frame)
elif is_video(modules.globals.target_path):
if modules.globals.many_faces:
source_face = default_source_face()
for map in modules.globals.souce_target_map:
target_frame = [
f
for f in map["target_faces_in_frame"]
if f["location"] == temp_frame_path
]
for frame in target_frame:
for target_face in frame["faces"]:
temp_frame = swap_face(source_face, target_face, temp_frame)
elif not modules.globals.many_faces:
for map in modules.globals.souce_target_map:
if "source" in map:
target_frame = [
f
for f in map["target_faces_in_frame"]
if f["location"] == temp_frame_path
]
source_face = map["source"]["face"]
for frame in target_frame:
for target_face in frame["faces"]:
temp_frame = swap_face(source_face, target_face, temp_frame)
else:
detected_faces = get_many_faces(temp_frame)
if modules.globals.many_faces:
if detected_faces:
source_face = default_source_face()
for target_face in detected_faces:
temp_frame = swap_face(source_face, target_face, temp_frame)
elif not modules.globals.many_faces:
if detected_faces:
if len(detected_faces) <= len(
modules.globals.simple_map["target_embeddings"]
):
for detected_face in detected_faces:
closest_centroid_index, _ = find_closest_centroid(
modules.globals.simple_map["target_embeddings"],
detected_face.normed_embedding,
)
temp_frame = swap_face(
modules.globals.simple_map["source_faces"][
closest_centroid_index
],
detected_face,
temp_frame,
)
else:
detected_faces_centroids = []
for face in detected_faces:
detected_faces_centroids.append(face.normed_embedding)
i = 0
for target_embedding in modules.globals.simple_map[
"target_embeddings"
]:
closest_centroid_index, _ = find_closest_centroid(
detected_faces_centroids, target_embedding
)
temp_frame = swap_face(
modules.globals.simple_map["source_faces"][i],
detected_faces[closest_centroid_index],
temp_frame,
)
i += 1
return temp_frame
def process_frames(
source_path: str, temp_frame_paths: List[str], progress: Any = None
) -> None:
if not modules.globals.map_faces:
source_face = get_one_face(cv2.imread(source_path))
for temp_frame_path in temp_frame_paths:
temp_frame = cv2.imread(temp_frame_path)
@@ -73,14 +213,281 @@ def process_frames(source_path: str, temp_frame_paths: List[str], progress: Any
pass
if progress:
progress.update(1)
else:
for temp_frame_path in temp_frame_paths:
temp_frame = cv2.imread(temp_frame_path)
try:
result = process_frame_v2(temp_frame, temp_frame_path)
cv2.imwrite(temp_frame_path, result)
except Exception as exception:
print(exception)
pass
if progress:
progress.update(1)
def process_image(source_path: str, target_path: str, output_path: str) -> None:
if not modules.globals.map_faces:
source_face = get_one_face(cv2.imread(source_path))
target_frame = cv2.imread(target_path)
result = process_frame(source_face, target_frame)
cv2.imwrite(output_path, result)
else:
if modules.globals.many_faces:
update_status(
"Many faces enabled. Using first source image. Progressing...", NAME
)
target_frame = cv2.imread(output_path)
result = process_frame_v2(target_frame)
cv2.imwrite(output_path, result)
def process_video(source_path: str, temp_frame_paths: List[str]) -> None:
modules.processors.frame.core.process_video(source_path, temp_frame_paths, process_frames)
if modules.globals.map_faces and modules.globals.many_faces:
update_status(
"Many faces enabled. Using first source image. Progressing...", NAME
)
modules.processors.frame.core.process_video(
source_path, temp_frame_paths, process_frames
)
def create_face_mask(face: Face, frame: Frame) -> np.ndarray:
mask = np.zeros(frame.shape[:2], dtype=np.uint8)
landmarks = face.landmark_2d_106
if landmarks is not None:
landmarks = landmarks.astype(np.int32)
right_side_face = landmarks[0:16]
left_side_face = landmarks[17:32]
right_eye = landmarks[33:42]
right_eye_brow = landmarks[43:51]
left_eye = landmarks[87:96]
left_eye_brow = landmarks[97:105]
right_eyebrow_top = np.min(right_eye_brow[:, 1])
left_eyebrow_top = np.min(left_eye_brow[:, 1])
eyebrow_top = min(right_eyebrow_top, left_eyebrow_top)
face_top = np.min([right_side_face[0, 1], left_side_face[-1, 1]])
forehead_height = face_top - eyebrow_top
extended_forehead_height = int(forehead_height * 5.0)
forehead_left = right_side_face[0].copy()
forehead_right = left_side_face[-1].copy()
forehead_left[1] -= extended_forehead_height
forehead_right[1] -= extended_forehead_height
face_outline = np.vstack(
[
[forehead_left],
right_side_face,
left_side_face[::-1],
[forehead_right],
]
)
padding = int(np.linalg.norm(right_side_face[0] - left_side_face[-1]) * 0.05)
hull = cv2.convexHull(face_outline)
hull_padded = []
for point in hull:
x, y = point[0]
center = np.mean(face_outline, axis=0)
direction = np.array([x, y]) - center
direction = direction / np.linalg.norm(direction)
padded_point = np.array([x, y]) + direction * padding
hull_padded.append(padded_point)
hull_padded = np.array(hull_padded, dtype=np.int32)
cv2.fillConvexPoly(mask, hull_padded, 255)
mask = cv2.GaussianBlur(mask, (5, 5), 3)
return mask
def create_lower_mouth_mask(face: Face, frame: Frame) -> tuple:
mask = np.zeros(frame.shape[:2], dtype=np.uint8)
mouth_cutout = None
landmarks = face.landmark_2d_106
if landmarks is not None:
lower_lip_order = [
65,
66,
62,
70,
69,
18,
19,
20,
21,
22,
23,
24,
0,
8,
7,
6,
5,
4,
3,
2,
65,
]
lower_lip_landmarks = landmarks[lower_lip_order].astype(np.float32)
center = np.mean(lower_lip_landmarks, axis=0)
expansion_factor = 1 + modules.globals.mask_down_size
expanded_landmarks = (lower_lip_landmarks - center) * expansion_factor + center
toplip_indices = [20, 0, 1, 2, 3, 4, 5]
toplip_extension = modules.globals.mask_size * 0.5
for idx in toplip_indices:
direction = expanded_landmarks[idx] - center
direction = direction / np.linalg.norm(direction)
expanded_landmarks[idx] += direction * toplip_extension
chin_indices = [11, 12, 13, 14, 15, 16]
chin_extension = 2 * 0.2
for idx in chin_indices:
expanded_landmarks[idx][1] += (
expanded_landmarks[idx][1] - center[1]
) * chin_extension
expanded_landmarks = expanded_landmarks.astype(np.int32)
min_x, min_y = np.min(expanded_landmarks, axis=0)
max_x, max_y = np.max(expanded_landmarks, axis=0)
padding = int((max_x - min_x) * 0.1)
min_x = max(0, min_x - padding)
min_y = max(0, min_y - padding)
max_x = min(frame.shape[1], max_x + padding)
max_y = min(frame.shape[0], max_y + padding)
if max_x <= min_x or max_y <= min_y:
if (max_x - min_x) <= 1:
max_x = min_x + 1
if (max_y - min_y) <= 1:
max_y = min_y + 1
mask_roi = np.zeros((max_y - min_y, max_x - min_x), dtype=np.uint8)
cv2.fillPoly(mask_roi, [expanded_landmarks - [min_x, min_y]], 255)
mask_roi = cv2.GaussianBlur(mask_roi, (15, 15), 5)
mask[min_y:max_y, min_x:max_x] = mask_roi
mouth_cutout = frame[min_y:max_y, min_x:max_x].copy()
return mask, mouth_cutout, (min_x, min_y, max_x, max_y), expanded_landmarks
return mask, mouth_cutout, None, None
def apply_mouth_area(
frame: Frame,
mouth_cutout: np.ndarray,
mouth_box: tuple,
face_mask: np.ndarray,
mouth_polygon: np.ndarray,
) -> Frame:
min_x, min_y, max_x, max_y = mouth_box
box_width = max_x - min_x
box_height = max_y - min_y
if (
mouth_cutout is None
or box_width is None
or box_height is None
or face_mask is None
or mouth_polygon is None
):
return frame
try:
resized_mouth_cutout = cv2.resize(mouth_cutout, (box_width, box_height))
roi = frame[min_y:max_y, min_x:max_x]
if roi.shape != resized_mouth_cutout.shape:
resized_mouth_cutout = cv2.resize(
resized_mouth_cutout, (roi.shape[1], roi.shape[0])
)
color_corrected_mouth = apply_color_transfer(resized_mouth_cutout, roi)
polygon_mask = np.zeros(roi.shape[:2], dtype=np.uint8)
adjusted_polygon = mouth_polygon - [min_x, min_y]
cv2.fillPoly(polygon_mask, [adjusted_polygon], 255)
feather_amount = min(
30,
box_width // modules.globals.mask_feather_ratio,
box_height // modules.globals.mask_feather_ratio,
)
feathered_mask = cv2.GaussianBlur(
polygon_mask.astype(float), (0, 0), feather_amount
)
feathered_mask = feathered_mask / feathered_mask.max()
face_mask_roi = face_mask[min_y:max_y, min_x:max_x]
combined_mask = feathered_mask * (face_mask_roi / 255.0)
combined_mask = combined_mask[:, :, np.newaxis]
blended = (
color_corrected_mouth * combined_mask + roi * (1 - combined_mask)
).astype(np.uint8)
face_mask_3channel = (
np.repeat(face_mask_roi[:, :, np.newaxis], 3, axis=2) / 255.0
)
final_blend = blended * face_mask_3channel + roi * (1 - face_mask_3channel)
frame[min_y:max_y, min_x:max_x] = final_blend.astype(np.uint8)
except Exception as e:
pass
return frame
def apply_color_transfer(source: np.ndarray, target: np.ndarray) -> np.ndarray:
source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB).astype("float32")
target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB).astype("float32")
source_mean, source_std = cv2.meanStdDev(source)
target_mean, target_std = cv2.meanStdDev(target)
source_mean = source_mean.reshape(1, 1, 3)
source_std = source_std.reshape(1, 1, 3)
target_mean = target_mean.reshape(1, 1, 3)
target_std = target_std.reshape(1, 1, 3)
source = (source - source_mean) * (target_std / source_std) + target_mean
return cv2.cvtColor(np.clip(source, 0, 255).astype("uint8"), cv2.COLOR_LAB2BGR)
def draw_mouth_mask_visualization(
frame: Frame, face: Face, mouth_mask_data: tuple
) -> Frame:
landmarks = face.landmark_2d_106
if landmarks is not None and mouth_mask_data is not None:
mask, mouth_cutout, (min_x, min_y, max_x, max_y), lower_lip_polygon = (
mouth_mask_data
)
vis_frame = frame.copy()
# Draw the lower lip polygon
cv2.polylines(vis_frame, [lower_lip_polygon], True, (0, 255, 0), 2)
# Add labels
cv2.putText(
vis_frame,
"Mouth Mask",
(min_x, min_y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(255, 255, 255),
1,
)
return vis_frame
return frame
+1560 -121
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+5 -5
View File
@@ -1,23 +1,23 @@
--extra-index-url https://download.pytorch.org/whl/cu118
numpy==1.23.5
numpy>=1.23.5,<2
opencv-python==4.8.1.78
cv2_enumerate_cameras==1.1.15
onnx==1.16.0
insightface==0.7.3
psutil==5.9.8
tk==0.1.0
customtkinter==5.2.2
pillow==9.5.0
torch==2.0.1+cu118; sys_platform != 'darwin'
torch==2.0.1; sys_platform == 'darwin'
torchvision==0.15.2+cu118; sys_platform != 'darwin'
torchvision==0.15.2; sys_platform == 'darwin'
onnxruntime==1.18.0; sys_platform == 'darwin' and platform_machine != 'arm64'
onnxruntime-silicon==1.16.3; sys_platform == 'darwin' and platform_machine == 'arm64'
onnxruntime-gpu==1.18.0; sys_platform != 'darwin'
tensorflow==2.13.0rc1; sys_platform == 'darwin'
onnxruntime-gpu==1.16.3; sys_platform != 'darwin'
tensorflow==2.12.1; sys_platform != 'darwin'
opennsfw2==0.10.2
protobuf==4.23.2
tqdm==4.66.4
gfpgan==1.3.8
tkinterdnd2==0.4.2
customtkinter==5.2.2