Compare commits
27 Commits
0133a489eb
...
e9f0006702
Author | SHA1 | Date |
---|---|---|
|
e9f0006702 | |
|
5db23597e9 | |
|
84ae5810bf | |
|
ebc30b1cac | |
|
9086072b8e | |
|
12fda0a3ed | |
|
d963430854 | |
|
5855d15c09 | |
|
fcc73d0add | |
|
8d4a386a27 | |
|
b98c5234d8 | |
|
8bdc14a789 | |
|
f121083bc8 | |
|
745d449ca6 | |
|
ec6d7d2995 | |
|
e791f2f18a | |
|
3795e41fd7 | |
|
ab8a1c82c1 | |
|
e1842ae0ba | |
|
989106e914 | |
|
de27fb8a81 | |
|
28109e93bb | |
|
fc312516e3 | |
|
72049f3e91 | |
|
6cb5de01f8 | |
|
0bcf340217 | |
|
994a63c546 |
31
README.md
31
README.md
|
@ -30,13 +30,13 @@ By using this software, you agree to these terms and commit to using it in a man
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Exclusive v2.0 Quick Start - Pre-built (Windows)
|
## Exclusive v2.1 Quick Start - Pre-built (Windows/Mac Silicon)
|
||||||
|
|
||||||
<a href="https://deeplivecam.net/index.php/quickstart"> <img src="media/Download.png" width="285" height="77" />
|
<a href="https://deeplivecam.net/index.php/quickstart"> <img src="media/Download.png" width="285" height="77" />
|
||||||
|
|
||||||
##### This is the fastest build you can get if you have a discrete NVIDIA or AMD GPU.
|
##### This is the fastest build you can get if you have a discrete NVIDIA or AMD GPU or Mac Silicon, And you'll receive special priority support.
|
||||||
|
|
||||||
###### These Pre-builts are perfect for non-technical users or those who don't have time to, or can't manually install all the requirements. Just a heads-up: this is an open-source project, so you can also install it manually. This will be 60 days ahead on the open source version.
|
###### These Pre-builts are perfect for non-technical users or those who don't have time to, or can't manually install all the requirements. Just a heads-up: this is an open-source project, so you can also install it manually.
|
||||||
|
|
||||||
## TLDR; Live Deepfake in just 3 Clicks
|
## TLDR; Live Deepfake in just 3 Clicks
|
||||||

|

|
||||||
|
@ -187,12 +187,16 @@ pip install -r requirements.txt
|
||||||
|
|
||||||
**CUDA Execution Provider (Nvidia)**
|
**CUDA Execution Provider (Nvidia)**
|
||||||
|
|
||||||
1. Install [CUDA Toolkit 11.8.0](https://developer.nvidia.com/cuda-11-8-0-download-archive)
|
1. Install [CUDA Toolkit 12.8.0](https://developer.nvidia.com/cuda-12-8-0-download-archive)
|
||||||
2. Install dependencies:
|
2. Install [cuDNN v8.9.7 for CUDA 12.x](https://developer.nvidia.com/rdp/cudnn-archive) (required for onnxruntime-gpu):
|
||||||
|
- Download cuDNN v8.9.7 for CUDA 12.x
|
||||||
|
- Make sure the cuDNN bin directory is in your system PATH
|
||||||
|
3. Install dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
|
||||||
pip uninstall onnxruntime onnxruntime-gpu
|
pip uninstall onnxruntime onnxruntime-gpu
|
||||||
pip install onnxruntime-gpu==1.16.3
|
pip install onnxruntime-gpu==1.21.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Usage:
|
3. Usage:
|
||||||
|
@ -300,19 +304,6 @@ python run.py --execution-provider openvino
|
||||||
- Use a screen capture tool like OBS to stream.
|
- Use a screen capture tool like OBS to stream.
|
||||||
- To change the face, select a new source image.
|
- To change the face, select a new source image.
|
||||||
|
|
||||||
## Tips and Tricks
|
|
||||||
|
|
||||||
Check out these helpful guides to get the most out of Deep-Live-Cam:
|
|
||||||
|
|
||||||
- [Unlocking the Secrets to the Perfect Deepfake Image](https://deeplivecam.net/index.php/blog/tips-and-tricks/unlocking-the-secrets-to-the-perfect-deepfake-image) - Learn how to create the best deepfake with full head coverage
|
|
||||||
- [Video Call with DeepLiveCam](https://deeplivecam.net/index.php/blog/tips-and-tricks/video-call-with-deeplivecam) - Make your meetings livelier by using DeepLiveCam with OBS and meeting software
|
|
||||||
- [Have a Special Guest!](https://deeplivecam.net/index.php/blog/tips-and-tricks/have-a-special-guest) - Tutorial on how to use face mapping to add special guests to your stream
|
|
||||||
- [Watch Deepfake Movies in Realtime](https://deeplivecam.net/index.php/blog/tips-and-tricks/watch-deepfake-movies-in-realtime) - See yourself star in any video without processing the video
|
|
||||||
- [Better Quality without Sacrificing Speed](https://deeplivecam.net/index.php/blog/tips-and-tricks/better-quality-without-sacrificing-speed) - Tips for achieving better results without impacting performance
|
|
||||||
- [Instant Vtuber!](https://deeplivecam.net/index.php/blog/tips-and-tricks/instant-vtuber) - Create a new persona/vtuber easily using Metahuman Creator
|
|
||||||
|
|
||||||
Visit our [official blog](https://deeplivecam.net/index.php/blog/tips-and-tricks) for more tips and tutorials.
|
|
||||||
|
|
||||||
## Command Line Arguments (Unmaintained)
|
## Command Line Arguments (Unmaintained)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -356,6 +347,8 @@ Looking for a CLI mode? Using the -s/--source argument will make the run program
|
||||||
- [*"This real-time webcam deepfake tool raises alarms about the future of identity theft"*](https://www.diyphotography.net/this-real-time-webcam-deepfake-tool-raises-alarms-about-the-future-of-identity-theft/) - DIYPhotography
|
- [*"This real-time webcam deepfake tool raises alarms about the future of identity theft"*](https://www.diyphotography.net/this-real-time-webcam-deepfake-tool-raises-alarms-about-the-future-of-identity-theft/) - DIYPhotography
|
||||||
- [*"That's Crazy, Oh God. That's Fucking Freaky Dude... That's So Wild Dude"*](https://www.youtube.com/watch?time_continue=1074&v=py4Tc-Y8BcY) - SomeOrdinaryGamers
|
- [*"That's Crazy, Oh God. That's Fucking Freaky Dude... That's So Wild Dude"*](https://www.youtube.com/watch?time_continue=1074&v=py4Tc-Y8BcY) - SomeOrdinaryGamers
|
||||||
- [*"Alright look look look, now look chat, we can do any face we want to look like chat"*](https://www.youtube.com/live/mFsCe7AIxq8?feature=shared&t=2686) - IShowSpeed
|
- [*"Alright look look look, now look chat, we can do any face we want to look like chat"*](https://www.youtube.com/live/mFsCe7AIxq8?feature=shared&t=2686) - IShowSpeed
|
||||||
|
- [*"They do a pretty good job matching poses, expression and even the lighting"*](https://www.youtube.com/watch?v=wnCghLjqv3s&t=551s) - TechLinked (LTT)
|
||||||
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "Mapeador de fuente x destino",
|
||||||
|
"select a source image": "Seleccionar imagen fuente",
|
||||||
|
"Preview": "Vista previa",
|
||||||
|
"select a target image or video": "elegir un video o una imagen fuente",
|
||||||
|
"save image output file": "guardar imagen final",
|
||||||
|
"save video output file": "guardar video final",
|
||||||
|
"select a target image": "elegir una imagen objetiva",
|
||||||
|
"source": "fuente",
|
||||||
|
"Select a target": "Elegir un destino",
|
||||||
|
"Select a face": "Elegir una cara",
|
||||||
|
"Keep audio": "Mantener audio original",
|
||||||
|
"Face Enhancer": "Potenciador de caras",
|
||||||
|
"Many faces": "Varias caras",
|
||||||
|
"Show FPS": "Mostrar fps",
|
||||||
|
"Keep fps": "Mantener fps",
|
||||||
|
"Keep frames": "Mantener frames",
|
||||||
|
"Fix Blueish Cam": "Corregir tono azul de video",
|
||||||
|
"Mouth Mask": "Máscara de boca",
|
||||||
|
"Show Mouth Mask Box": "Mostrar área de la máscara de boca",
|
||||||
|
"Start": "Iniciar",
|
||||||
|
"Live": "En vivo",
|
||||||
|
"Destroy": "Borrar",
|
||||||
|
"Map faces": "Mapear caras",
|
||||||
|
"Processing...": "Procesando...",
|
||||||
|
"Processing succeed!": "¡Proceso terminado con éxito!",
|
||||||
|
"Processing ignored!": "¡Procesamiento omitido!",
|
||||||
|
"Failed to start camera": "No se pudo iniciar la cámara",
|
||||||
|
"Please complete pop-up or close it.": "Complete o cierre el pop-up",
|
||||||
|
"Getting unique faces": "Buscando caras únicas",
|
||||||
|
"Please select a source image first": "Primero, seleccione una imagen fuente",
|
||||||
|
"No faces found in target": "No se encontró una cara en el destino",
|
||||||
|
"Add": "Agregar",
|
||||||
|
"Clear": "Limpiar",
|
||||||
|
"Submit": "Enviar",
|
||||||
|
"Select source image": "Seleccionar imagen fuente",
|
||||||
|
"Select target image": "Seleccionar imagen destino",
|
||||||
|
"Please provide mapping!": "Por favor, proporcione un mapeo",
|
||||||
|
"At least 1 source with target is required!": "Se requiere al menos una fuente con un destino.",
|
||||||
|
"At least 1 source with target is required!": "Se requiere al menos una fuente con un destino.",
|
||||||
|
"Face could not be detected in last upload!": "¡No se pudo encontrar una cara en el último video o imagen!",
|
||||||
|
"Select Camera:": "Elegir cámara:",
|
||||||
|
"All mappings cleared!": "¡Todos los mapeos fueron borrados!",
|
||||||
|
"Mappings successfully submitted!": "Mapeos enviados con éxito!",
|
||||||
|
"Source x Target Mapper is already open.": "El mapeador de fuente x destino ya está abierto."
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "ប្រភប x បន្ថែម Mapper",
|
||||||
|
"select a source image": "ជ្រើសរើសប្រភពរូបភាព",
|
||||||
|
"Preview": "បង្ហាញ",
|
||||||
|
"select a target image or video": "ជ្រើសរើសគោលដៅរូបភាពឬវីដេអូ",
|
||||||
|
"save image output file": "រក្សាទុកលទ្ធផលឯកសាររូបភាព",
|
||||||
|
"save video output file": "រក្សាទុកលទ្ធផលឯកសារវីដេអូ",
|
||||||
|
"select a target image": "ជ្រើសរើសគោលដៅរូបភាព",
|
||||||
|
"source": "ប្រភព",
|
||||||
|
"Select a target": "ជ្រើសរើសគោលដៅ",
|
||||||
|
"Select a face": "ជ្រើសរើសមុខ",
|
||||||
|
"Keep audio": "រម្លងសម្លេង",
|
||||||
|
"Face Enhancer": "ឧបករណ៍ពង្រឹងមុខ",
|
||||||
|
"Many faces": "ទម្រង់មុខច្រើន",
|
||||||
|
"Show FPS": "បង្ហាញ FPS",
|
||||||
|
"Keep fps": "រម្លង fps",
|
||||||
|
"Keep frames": "រម្លងទម្រង់",
|
||||||
|
"Fix Blueish Cam": "ជួសជុល Cam Blueish",
|
||||||
|
"Mouth Mask": "របាំងមាត់",
|
||||||
|
"Show Mouth Mask Box": "បង្ហាញប្រអប់របាំងមាត់",
|
||||||
|
"Start": "ចាប់ផ្ដើម",
|
||||||
|
"Live": "ផ្សាយផ្ទាល់",
|
||||||
|
"Destroy": "លុប",
|
||||||
|
"Map faces": "ផែនទីមុខ",
|
||||||
|
"Processing...": "កំពុងដំណើរការ...",
|
||||||
|
"Processing succeed!": "ការដំណើរការទទួលបានជោគជ័យ!",
|
||||||
|
"Processing ignored!": "ការដំណើរការមិនទទួលបានជោគជ័យ!",
|
||||||
|
"Failed to start camera": "បរាជ័យដើម្បីចាប់ផ្ដើមបើកកាមេរ៉ា",
|
||||||
|
"Please complete pop-up or close it.": "សូមបញ្ចប់ផ្ទាំងផុស ឬបិទវា.",
|
||||||
|
"Getting unique faces": "ការចាប់ផ្ដើមទម្រង់មុខប្លែក",
|
||||||
|
"Please select a source image first": "សូមជ្រើសរើសប្រភពរូបភាពដំបូង",
|
||||||
|
"No faces found in target": "រកអត់ឃើញមុខនៅក្នុងគោលដៅ",
|
||||||
|
"Add": "បន្ថែម",
|
||||||
|
"Clear": "សម្អាត",
|
||||||
|
"Submit": "បញ្ចូន",
|
||||||
|
"Select source image": "ជ្រើសរើសប្រភពរូបភាព",
|
||||||
|
"Select target image": "ជ្រើសរើសគោលដៅរូបភាព",
|
||||||
|
"Please provide mapping!": "សូមផ្ដល់នៅផែនទី",
|
||||||
|
"At least 1 source with target is required!": "ត្រូវការប្រភពយ៉ាងហោចណាស់ ១ ដែលមានគោលដៅ!",
|
||||||
|
"Face could not be detected in last upload!": "មុខមិនអាចភ្ជាប់នៅក្នុងការបង្ហេាះចុងក្រោយ!",
|
||||||
|
"Select Camera:": "ជ្រើសរើសកាមេរ៉ា",
|
||||||
|
"All mappings cleared!": "ផែនទីទាំងអស់ត្រូវបានសម្អាត!",
|
||||||
|
"Mappings successfully submitted!": "ផែនទីត្រូវបានបញ្ជូនជោគជ័យ!",
|
||||||
|
"Source x Target Mapper is already open.": "ប្រភព x Target Mapper បានបើករួចហើយ។"
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "소스 x 타겟 매퍼",
|
||||||
|
"select a source image": "소스 이미지 선택",
|
||||||
|
"Preview": "미리보기",
|
||||||
|
"select a target image or video": "타겟 이미지 또는 영상 선택",
|
||||||
|
"save image output file": "이미지 출력 파일 저장",
|
||||||
|
"save video output file": "영상 출력 파일 저장",
|
||||||
|
"select a target image": "타겟 이미지 선택",
|
||||||
|
"source": "소스",
|
||||||
|
"Select a target": "타겟 선택",
|
||||||
|
"Select a face": "얼굴 선택",
|
||||||
|
"Keep audio": "오디오 유지",
|
||||||
|
"Face Enhancer": "얼굴 향상",
|
||||||
|
"Many faces": "여러 얼굴",
|
||||||
|
"Show FPS": "FPS 표시",
|
||||||
|
"Keep fps": "FPS 유지",
|
||||||
|
"Keep frames": "프레임 유지",
|
||||||
|
"Fix Blueish Cam": "푸른빛 카메라 보정",
|
||||||
|
"Mouth Mask": "입 마스크",
|
||||||
|
"Show Mouth Mask Box": "입 마스크 박스 표시",
|
||||||
|
"Start": "시작",
|
||||||
|
"Live": "라이브",
|
||||||
|
"Destroy": "종료",
|
||||||
|
"Map faces": "얼굴 매핑",
|
||||||
|
"Processing...": "처리 중...",
|
||||||
|
"Processing succeed!": "처리 성공!",
|
||||||
|
"Processing ignored!": "처리 무시됨!",
|
||||||
|
"Failed to start camera": "카메라 시작 실패",
|
||||||
|
"Please complete pop-up or close it.": "팝업을 완료하거나 닫아주세요.",
|
||||||
|
"Getting unique faces": "고유 얼굴 가져오는 중",
|
||||||
|
"Please select a source image first": "먼저 소스 이미지를 선택해주세요",
|
||||||
|
"No faces found in target": "타겟에서 얼굴을 찾을 수 없음",
|
||||||
|
"Add": "추가",
|
||||||
|
"Clear": "지우기",
|
||||||
|
"Submit": "제출",
|
||||||
|
"Select source image": "소스 이미지 선택",
|
||||||
|
"Select target image": "타겟 이미지 선택",
|
||||||
|
"Please provide mapping!": "매핑을 입력해주세요!",
|
||||||
|
"At least 1 source with target is required!": "최소 하나의 소스와 타겟이 필요합니다!",
|
||||||
|
"Face could not be detected in last upload!": "최근 업로드에서 얼굴을 감지할 수 없습니다!",
|
||||||
|
"Select Camera:": "카메라 선택:",
|
||||||
|
"All mappings cleared!": "모든 매핑이 삭제되었습니다!",
|
||||||
|
"Mappings successfully submitted!": "매핑이 성공적으로 제출되었습니다!",
|
||||||
|
"Source x Target Mapper is already open.": "소스 x 타겟 매퍼가 이미 열려 있습니다."
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "Mapeador de Origem x Destino",
|
||||||
|
"select an source image": "Escolha uma imagem de origem",
|
||||||
|
"Preview": "Prévia",
|
||||||
|
"select an target image or video": "Escolha uma imagem ou vídeo de destino",
|
||||||
|
"save image output file": "Salvar imagem final",
|
||||||
|
"save video output file": "Salvar vídeo final",
|
||||||
|
"select an target image": "Escolha uma imagem de destino",
|
||||||
|
"source": "Origem",
|
||||||
|
"Select a target": "Escolha o destino",
|
||||||
|
"Select a face": "Escolha um rosto",
|
||||||
|
"Keep audio": "Manter o áudio original",
|
||||||
|
"Face Enhancer": "Melhorar rosto",
|
||||||
|
"Many faces": "Vários rostos",
|
||||||
|
"Show FPS": "Mostrar FPS",
|
||||||
|
"Keep fps": "Manter FPS",
|
||||||
|
"Keep frames": "Manter frames",
|
||||||
|
"Fix Blueish Cam": "Corrigir tom azulado da câmera",
|
||||||
|
"Mouth Mask": "Máscara da boca",
|
||||||
|
"Show Mouth Mask Box": "Mostrar área da máscara da boca",
|
||||||
|
"Start": "Começar",
|
||||||
|
"Live": "Ao vivo",
|
||||||
|
"Destroy": "Destruir",
|
||||||
|
"Map faces": "Mapear rostos",
|
||||||
|
"Processing...": "Processando...",
|
||||||
|
"Processing succeed!": "Tudo certo!",
|
||||||
|
"Processing ignored!": "Processamento ignorado!",
|
||||||
|
"Failed to start camera": "Não foi possível iniciar a câmera",
|
||||||
|
"Please complete pop-up or close it.": "Finalize ou feche o pop-up",
|
||||||
|
"Getting unique faces": "Buscando rostos diferentes",
|
||||||
|
"Please select a source image first": "Selecione primeiro uma imagem de origem",
|
||||||
|
"No faces found in target": "Nenhum rosto encontrado na imagem de destino",
|
||||||
|
"Add": "Adicionar",
|
||||||
|
"Clear": "Limpar",
|
||||||
|
"Submit": "Enviar",
|
||||||
|
"Select source image": "Escolha a imagem de origem",
|
||||||
|
"Select target image": "Escolha a imagem de destino",
|
||||||
|
"Please provide mapping!": "Você precisa realizar o mapeamento!",
|
||||||
|
"Atleast 1 source with target is required!": "É necessária pelo menos uma origem com um destino!",
|
||||||
|
"At least 1 source with target is required!": "É necessária pelo menos uma origem com um destino!",
|
||||||
|
"Face could not be detected in last upload!": "Não conseguimos detectar o rosto na última imagem!",
|
||||||
|
"Select Camera:": "Escolher câmera:",
|
||||||
|
"All mappings cleared!": "Todos os mapeamentos foram removidos!",
|
||||||
|
"Mappings successfully submitted!": "Mapeamentos enviados com sucesso!",
|
||||||
|
"Source x Target Mapper is already open.": "O Mapeador de Origem x Destino já está aberto."
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "Сопоставитель Источник x Цель",
|
||||||
|
"select a source image": "выберите исходное изображение",
|
||||||
|
"Preview": "Предпросмотр",
|
||||||
|
"select a target image or video": "выберите целевое изображение или видео",
|
||||||
|
"save image output file": "сохранить выходной файл изображения",
|
||||||
|
"save video output file": "сохранить выходной файл видео",
|
||||||
|
"select a target image": "выберите целевое изображение",
|
||||||
|
"source": "источник",
|
||||||
|
"Select a target": "Выберите целевое изображение",
|
||||||
|
"Select a face": "Выберите лицо",
|
||||||
|
"Keep audio": "Сохранить аудио",
|
||||||
|
"Face Enhancer": "Улучшение лица",
|
||||||
|
"Many faces": "Несколько лиц",
|
||||||
|
"Show FPS": "Показать FPS",
|
||||||
|
"Keep fps": "Сохранить FPS",
|
||||||
|
"Keep frames": "Сохранить кадры",
|
||||||
|
"Fix Blueish Cam": "Исправить синеву камеры",
|
||||||
|
"Mouth Mask": "Маска рта",
|
||||||
|
"Show Mouth Mask Box": "Показать рамку маски рта",
|
||||||
|
"Start": "Старт",
|
||||||
|
"Live": "В реальном времени",
|
||||||
|
"Destroy": "Остановить",
|
||||||
|
"Map faces": "Сопоставить лица",
|
||||||
|
"Processing...": "Обработка...",
|
||||||
|
"Processing succeed!": "Обработка успешна!",
|
||||||
|
"Processing ignored!": "Обработка проигнорирована!",
|
||||||
|
"Failed to start camera": "Не удалось запустить камеру",
|
||||||
|
"Please complete pop-up or close it.": "Пожалуйста, заполните всплывающее окно или закройте его.",
|
||||||
|
"Getting unique faces": "Получение уникальных лиц",
|
||||||
|
"Please select a source image first": "Сначала выберите исходное изображение, пожалуйста",
|
||||||
|
"No faces found in target": "В целевом изображении не найдено лиц",
|
||||||
|
"Add": "Добавить",
|
||||||
|
"Clear": "Очистить",
|
||||||
|
"Submit": "Отправить",
|
||||||
|
"Select source image": "Выбрать исходное изображение",
|
||||||
|
"Select target image": "Выбрать целевое изображение",
|
||||||
|
"Please provide mapping!": "Пожалуйста, укажите сопоставление!",
|
||||||
|
"At least 1 source with target is required!": "Требуется хотя бы 1 источник с целью!",
|
||||||
|
"Face could not be detected in last upload!": "Лицо не обнаружено в последнем загруженном изображении!",
|
||||||
|
"Select Camera:": "Выберите камеру:",
|
||||||
|
"All mappings cleared!": "Все сопоставления очищены!",
|
||||||
|
"Mappings successfully submitted!": "Сопоставления успешно отправлены!",
|
||||||
|
"Source x Target Mapper is already open.": "Сопоставитель Источник-Цель уже открыт."
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"Source x Target Mapper": "ตัวจับคู่ต้นทาง x ปลายทาง",
|
||||||
|
"select a source image": "เลือกรูปภาพต้นฉบับ",
|
||||||
|
"Preview": "ตัวอย่าง",
|
||||||
|
"select a target image or video": "เลือกรูปภาพหรือวิดีโอเป้าหมาย",
|
||||||
|
"save image output file": "บันทึกไฟล์รูปภาพ",
|
||||||
|
"save video output file": "บันทึกไฟล์วิดีโอ",
|
||||||
|
"select a target image": "เลือกรูปภาพเป้าหมาย",
|
||||||
|
"source": "ต้นฉบับ",
|
||||||
|
"Select a target": "เลือกเป้าหมาย",
|
||||||
|
"Select a face": "เลือกใบหน้า",
|
||||||
|
"Keep audio": "เก็บเสียง",
|
||||||
|
"Face Enhancer": "ปรับปรุงใบหน้า",
|
||||||
|
"Many faces": "หลายใบหน้า",
|
||||||
|
"Show FPS": "แสดง FPS",
|
||||||
|
"Keep fps": "คงค่า FPS",
|
||||||
|
"Keep frames": "คงค่าเฟรม",
|
||||||
|
"Fix Blueish Cam": "แก้ไขภาพอมฟ้าจากกล้อง",
|
||||||
|
"Mouth Mask": "มาสก์ปาก",
|
||||||
|
"Show Mouth Mask Box": "แสดงกรอบมาสก์ปาก",
|
||||||
|
"Start": "เริ่ม",
|
||||||
|
"Live": "สด",
|
||||||
|
"Destroy": "หยุด",
|
||||||
|
"Map faces": "จับคู่ใบหน้า",
|
||||||
|
"Processing...": "กำลังประมวลผล...",
|
||||||
|
"Processing succeed!": "ประมวลผลสำเร็จแล้ว!",
|
||||||
|
"Processing ignored!": "การประมวลผลถูกละเว้น",
|
||||||
|
"Failed to start camera": "ไม่สามารถเริ่มกล้องได้",
|
||||||
|
"Please complete pop-up or close it.": "โปรดดำเนินการในป๊อปอัปให้เสร็จสิ้น หรือปิด",
|
||||||
|
"Getting unique faces": "กำลังค้นหาใบหน้าที่ไม่ซ้ำกัน",
|
||||||
|
"Please select a source image first": "โปรดเลือกภาพต้นฉบับก่อน",
|
||||||
|
"No faces found in target": "ไม่พบใบหน้าในภาพเป้าหมาย",
|
||||||
|
"Add": "เพิ่ม",
|
||||||
|
"Clear": "ล้าง",
|
||||||
|
"Submit": "ส่ง",
|
||||||
|
"Select source image": "เลือกภาพต้นฉบับ",
|
||||||
|
"Select target image": "เลือกภาพเป้าหมาย",
|
||||||
|
"Please provide mapping!": "โปรดระบุการจับคู่!",
|
||||||
|
"At least 1 source with target is required!": "ต้องมีการจับคู่ต้นฉบับกับเป้าหมายอย่างน้อย 1 คู่!",
|
||||||
|
"Face could not be detected in last upload!": "ไม่สามารถตรวจพบใบหน้าในไฟล์อัปโหลดล่าสุด!",
|
||||||
|
"Select Camera:": "เลือกกล้อง:",
|
||||||
|
"All mappings cleared!": "ล้างการจับคู่ทั้งหมดแล้ว!",
|
||||||
|
"Mappings successfully submitted!": "ส่งการจับคู่สำเร็จแล้ว!",
|
||||||
|
"Source x Target Mapper is already open.": "ตัวจับคู่ต้นทาง x ปลายทาง เปิดอยู่แล้ว"
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
@ -2,6 +2,7 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
from typing import Any
|
from typing import Any
|
||||||
import insightface
|
import insightface
|
||||||
|
import logging # Added logging import
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -25,18 +26,27 @@ def get_face_analyser() -> Any:
|
||||||
|
|
||||||
|
|
||||||
def get_one_face(frame: Frame) -> Any:
|
def get_one_face(frame: Frame) -> Any:
|
||||||
face = get_face_analyser().get(frame)
|
faces = get_face_analyser().get(frame)
|
||||||
|
if not faces:
|
||||||
|
logging.debug("Face_analyser: get_one_face: No faces found by insightface.")
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
return min(face, key=lambda x: x.bbox[0])
|
return min(faces, key=lambda x: x.bbox[0])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
logging.debug("Face_analyser: get_one_face: ValueError, likely no faces after all.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_many_faces(frame: Frame) -> Any:
|
def get_many_faces(frame: Frame) -> Any:
|
||||||
try:
|
faces = get_face_analyser().get(frame)
|
||||||
return get_face_analyser().get(frame)
|
if not faces: # Check if faces is None or an empty list
|
||||||
except IndexError:
|
logging.debug("Face_analyser: get_many_faces: No faces found by insightface.")
|
||||||
return None
|
# Depending on what insightface returns for no faces,
|
||||||
|
# you might return None or an empty list.
|
||||||
|
# If .get() returns an empty list for no faces, this check is sufficient.
|
||||||
|
# If .get() returns None, this is also fine.
|
||||||
|
return faces # Return original (None or empty list)
|
||||||
|
return faces
|
||||||
|
|
||||||
def has_valid_map() -> bool:
|
def has_valid_map() -> bool:
|
||||||
for map in modules.globals.source_target_map:
|
for map in modules.globals.source_target_map:
|
||||||
|
|
|
@ -82,7 +82,8 @@ def get_face_enhancer() -> Any:
|
||||||
selected_device = torch.device("cpu")
|
selected_device = torch.device("cpu")
|
||||||
device_priority.append("CPU")
|
device_priority.append("CPU")
|
||||||
|
|
||||||
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=2, device=selected_device)
|
upscale_factor = getattr(modules.globals, 'gfpgan_upscale_factor', 2)
|
||||||
|
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=upscale_factor, device=selected_device)
|
||||||
|
|
||||||
# for debug:
|
# for debug:
|
||||||
print(f"Selected device: {selected_device} and device priority: {device_priority}")
|
print(f"Selected device: {selected_device} and device priority: {device_priority}")
|
||||||
|
|
|
@ -21,6 +21,16 @@ FACE_SWAPPER = None
|
||||||
THREAD_LOCK = threading.Lock()
|
THREAD_LOCK = threading.Lock()
|
||||||
NAME = "DLC.FACE-SWAPPER"
|
NAME = "DLC.FACE-SWAPPER"
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_kernel_size(kernel_tuple, default_kernel_tuple):
|
||||||
|
if isinstance(kernel_tuple, tuple) and len(kernel_tuple) == 2 and \
|
||||||
|
isinstance(kernel_tuple[0], int) and kernel_tuple[0] > 0 and kernel_tuple[0] % 2 == 1 and \
|
||||||
|
isinstance(kernel_tuple[1], int) and kernel_tuple[1] > 0 and kernel_tuple[1] % 2 == 1:
|
||||||
|
return kernel_tuple
|
||||||
|
else:
|
||||||
|
logging.warning(f"Invalid kernel size {kernel_tuple} received. Must be a tuple of two positive odd integers. Falling back to default {default_kernel_tuple}.")
|
||||||
|
return default_kernel_tuple
|
||||||
|
|
||||||
abs_dir = os.path.dirname(os.path.abspath(__file__))
|
abs_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
models_dir = os.path.join(
|
models_dir = os.path.join(
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(abs_dir))), "models"
|
os.path.dirname(os.path.dirname(os.path.dirname(abs_dir))), "models"
|
||||||
|
@ -83,8 +93,12 @@ def swap_face(source_face: Face, target_face: Face, temp_frame: Frame) -> Frame:
|
||||||
if original_target_face_roi.size > 0:
|
if original_target_face_roi.size > 0:
|
||||||
swapped_face_roi = swapped_frame[y1:y2, x1:x2].copy()
|
swapped_face_roi = swapped_frame[y1:y2, x1:x2].copy()
|
||||||
if swapped_face_roi.size > 0:
|
if swapped_face_roi.size > 0:
|
||||||
|
try:
|
||||||
corrected_swapped_face_roi = apply_color_transfer(swapped_face_roi, original_target_face_roi)
|
corrected_swapped_face_roi = apply_color_transfer(swapped_face_roi, original_target_face_roi)
|
||||||
swapped_frame[y1:y2, x1:x2] = corrected_swapped_face_roi
|
swapped_frame[y1:y2, x1:x2] = corrected_swapped_face_roi
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Failed to apply statistical color transfer: {e}. Using original swapped ROI.")
|
||||||
|
# swapped_frame already contains the uncorrected swapped_face_roi in this region
|
||||||
else:
|
else:
|
||||||
# Apply the face swap without statistical color correction
|
# Apply the face swap without statistical color correction
|
||||||
swapped_frame = face_swapper.get(
|
swapped_frame = face_swapper.get(
|
||||||
|
@ -122,16 +136,26 @@ def process_frame(source_face: Face, temp_frame: Frame) -> Frame:
|
||||||
many_faces = get_many_faces(temp_frame)
|
many_faces = get_many_faces(temp_frame)
|
||||||
if many_faces:
|
if many_faces:
|
||||||
for target_face in many_faces:
|
for target_face in many_faces:
|
||||||
if source_face and target_face:
|
if source_face and target_face: # target_face from many_faces will always be valid here
|
||||||
temp_frame = swap_face(source_face, target_face, temp_frame)
|
temp_frame = swap_face(source_face, target_face, temp_frame)
|
||||||
else:
|
elif not source_face: # Check source_face specifically
|
||||||
print("Face detection failed for target/source.")
|
logging.error("Source face is not available or no face detected in source image. Skipping swap for this target face.")
|
||||||
|
# Optionally `continue` or `break` if source_face is essential for all
|
||||||
|
elif not source_face : # if many_faces is empty AND source_face is also an issue
|
||||||
|
logging.error("Source face is not available AND no faces detected in target frame.")
|
||||||
|
else: # many_faces is empty, but source_face is ok
|
||||||
|
logging.info(f"No faces detected in the current target frame for 'many_faces' mode.")
|
||||||
else:
|
else:
|
||||||
target_face = get_one_face(temp_frame)
|
target_face = get_one_face(temp_frame)
|
||||||
if target_face and source_face:
|
if target_face and source_face:
|
||||||
temp_frame = swap_face(source_face, target_face, temp_frame)
|
temp_frame = swap_face(source_face, target_face, temp_frame)
|
||||||
else:
|
else:
|
||||||
logging.error("Face detection failed for target or source.")
|
if not source_face:
|
||||||
|
logging.error("Source face is not available or no face detected in source image.")
|
||||||
|
elif not target_face:
|
||||||
|
logging.error(f"No face detected in the current target frame.")
|
||||||
|
else: # Should not happen if logic is right, but as a fallback
|
||||||
|
logging.error("Face detection failed for an unknown reason concerning target or source.")
|
||||||
return temp_frame
|
return temp_frame
|
||||||
|
|
||||||
|
|
||||||
|
@ -383,8 +407,12 @@ def create_lower_mouth_mask(
|
||||||
cv2.fillPoly(mask_roi, [expanded_landmarks - [min_x, min_y]], 255)
|
cv2.fillPoly(mask_roi, [expanded_landmarks - [min_x, min_y]], 255)
|
||||||
|
|
||||||
# Apply Gaussian blur to soften the mask edges
|
# Apply Gaussian blur to soften the mask edges
|
||||||
kernel_size_mouth = getattr(modules.globals, 'mouth_mask_blur_kernel_size', (9, 9))
|
# Default kernel size for mouth mask blur is (9,9) as a balance between performance and smoothing.
|
||||||
mask_roi = cv2.GaussianBlur(mask_roi, kernel_size_mouth, 0)
|
# Larger values (e.g., (15,15) - the previous hardcoded value) provide more smoothing but are slower.
|
||||||
|
# This is configurable via modules.globals.mouth_mask_blur_kernel_size.
|
||||||
|
kernel_size_mouth_config = getattr(modules.globals, 'mouth_mask_blur_kernel_size', (9, 9))
|
||||||
|
valid_kernel_mouth = _validate_kernel_size(kernel_size_mouth_config, (9, 9))
|
||||||
|
mask_roi = cv2.GaussianBlur(mask_roi, valid_kernel_mouth, 0)
|
||||||
|
|
||||||
# Place the mask ROI in the full-sized mask
|
# Place the mask ROI in the full-sized mask
|
||||||
mask[min_y:max_y, min_x:max_x] = mask_roi
|
mask[min_y:max_y, min_x:max_x] = mask_roi
|
||||||
|
@ -525,7 +553,13 @@ def apply_mouth_area(
|
||||||
feathered_mask = cv2.GaussianBlur(
|
feathered_mask = cv2.GaussianBlur(
|
||||||
polygon_mask.astype(float), (0, 0), feather_amount
|
polygon_mask.astype(float), (0, 0), feather_amount
|
||||||
)
|
)
|
||||||
feathered_mask = feathered_mask / feathered_mask.max()
|
|
||||||
|
mask_max_value = feathered_mask.max()
|
||||||
|
if mask_max_value < 1e-6: # Check if max is effectively zero
|
||||||
|
logging.warning("Mouth mask's feathered_mask is all zeros or near-zeros after blur. Resulting mask will be black.")
|
||||||
|
feathered_mask = np.zeros_like(polygon_mask, dtype=np.uint8)
|
||||||
|
else:
|
||||||
|
feathered_mask = (feathered_mask / mask_max_value * 255).astype(np.uint8)
|
||||||
|
|
||||||
face_mask_roi = face_mask[min_y:max_y, min_x:max_x]
|
face_mask_roi = face_mask[min_y:max_y, min_x:max_x]
|
||||||
combined_mask = feathered_mask * (face_mask_roi / 255.0)
|
combined_mask = feathered_mask * (face_mask_roi / 255.0)
|
||||||
|
@ -613,8 +647,9 @@ def create_face_mask(face: Face, frame: Frame) -> np.ndarray:
|
||||||
cv2.fillConvexPoly(mask, hull_padded, 255)
|
cv2.fillConvexPoly(mask, hull_padded, 255)
|
||||||
|
|
||||||
# Smooth the mask edges
|
# Smooth the mask edges
|
||||||
kernel_size_face = getattr(modules.globals, 'face_mask_blur_kernel_size', (5, 5))
|
kernel_size_face_config = getattr(modules.globals, 'face_mask_blur_kernel_size', (5, 5))
|
||||||
mask = cv2.GaussianBlur(mask, kernel_size_face, 0)
|
valid_kernel_face = _validate_kernel_size(kernel_size_face_config, (5, 5))
|
||||||
|
mask = cv2.GaussianBlur(mask, valid_kernel_face, 0)
|
||||||
|
|
||||||
return mask
|
return mask
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue