mirror of
https://github.com/facefusion/facefusion.git
synced 2026-07-28 21:08:54 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b7d145aa7 | ||
|
|
519360bcd6 | ||
|
|
57fcb86b82 | ||
|
|
2cc05d4fba | ||
|
|
a498f3d618 | ||
|
|
c7976ec9d4 | ||
|
|
8801668562 | ||
|
|
a7f3de3dbc | ||
|
|
666c15f9da | ||
|
|
420d738a6b |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
OpenRAIL-AS license
|
OpenRAIL-AS license
|
||||||
|
|
||||||
Copyright (c) 2025 Henry Ruhs
|
Copyright (c) 2026 Henry Ruhs
|
||||||
|
|||||||
+2
-1
@@ -67,7 +67,8 @@ processors =
|
|||||||
age_modifier_model =
|
age_modifier_model =
|
||||||
age_modifier_direction =
|
age_modifier_direction =
|
||||||
background_remover_model =
|
background_remover_model =
|
||||||
background_remover_color =
|
background_remover_fill_color =
|
||||||
|
background_remover_despill_color =
|
||||||
deep_swapper_model =
|
deep_swapper_model =
|
||||||
deep_swapper_morph =
|
deep_swapper_morph =
|
||||||
expression_restorer_model =
|
expression_restorer_model =
|
||||||
|
|||||||
+2
-1
@@ -4,7 +4,8 @@ import os
|
|||||||
|
|
||||||
os.environ['OMP_NUM_THREADS'] = '1'
|
os.environ['OMP_NUM_THREADS'] = '1'
|
||||||
|
|
||||||
from facefusion import core
|
from facefusion import conda, core
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
conda.setup()
|
||||||
core.cli()
|
core.cli()
|
||||||
|
|||||||
+78
-92
@@ -7,6 +7,84 @@ from facefusion.types import ApplyStateItem, Args
|
|||||||
from facefusion.vision import detect_video_fps
|
from facefusion.vision import detect_video_fps
|
||||||
|
|
||||||
|
|
||||||
|
def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
|
||||||
|
apply_state_item('command', args.get('command'))
|
||||||
|
apply_state_item('temp_path', args.get('temp_path'))
|
||||||
|
apply_state_item('jobs_path', args.get('jobs_path'))
|
||||||
|
apply_state_item('source_paths', args.get('source_paths'))
|
||||||
|
apply_state_item('target_path', args.get('target_path'))
|
||||||
|
apply_state_item('output_path', args.get('output_path'))
|
||||||
|
apply_state_item('source_pattern', args.get('source_pattern'))
|
||||||
|
apply_state_item('target_pattern', args.get('target_pattern'))
|
||||||
|
apply_state_item('output_pattern', args.get('output_pattern'))
|
||||||
|
apply_state_item('face_detector_model', args.get('face_detector_model'))
|
||||||
|
apply_state_item('face_detector_size', args.get('face_detector_size'))
|
||||||
|
apply_state_item('face_detector_margin', normalize_space(args.get('face_detector_margin')))
|
||||||
|
apply_state_item('face_detector_angles', args.get('face_detector_angles'))
|
||||||
|
apply_state_item('face_detector_score', args.get('face_detector_score'))
|
||||||
|
apply_state_item('face_landmarker_model', args.get('face_landmarker_model'))
|
||||||
|
apply_state_item('face_landmarker_score', args.get('face_landmarker_score'))
|
||||||
|
apply_state_item('face_selector_mode', args.get('face_selector_mode'))
|
||||||
|
apply_state_item('face_selector_order', args.get('face_selector_order'))
|
||||||
|
apply_state_item('face_selector_age_start', args.get('face_selector_age_start'))
|
||||||
|
apply_state_item('face_selector_age_end', args.get('face_selector_age_end'))
|
||||||
|
apply_state_item('face_selector_gender', args.get('face_selector_gender'))
|
||||||
|
apply_state_item('face_selector_race', args.get('face_selector_race'))
|
||||||
|
apply_state_item('reference_face_position', args.get('reference_face_position'))
|
||||||
|
apply_state_item('reference_face_distance', args.get('reference_face_distance'))
|
||||||
|
apply_state_item('reference_frame_number', args.get('reference_frame_number'))
|
||||||
|
apply_state_item('face_occluder_model', args.get('face_occluder_model'))
|
||||||
|
apply_state_item('face_parser_model', args.get('face_parser_model'))
|
||||||
|
apply_state_item('face_mask_types', args.get('face_mask_types'))
|
||||||
|
apply_state_item('face_mask_areas', args.get('face_mask_areas'))
|
||||||
|
apply_state_item('face_mask_regions', args.get('face_mask_regions'))
|
||||||
|
apply_state_item('face_mask_blur', args.get('face_mask_blur'))
|
||||||
|
apply_state_item('face_mask_padding', normalize_space(args.get('face_mask_padding')))
|
||||||
|
apply_state_item('voice_extractor_model', args.get('voice_extractor_model'))
|
||||||
|
apply_state_item('trim_frame_start', args.get('trim_frame_start'))
|
||||||
|
apply_state_item('trim_frame_end', args.get('trim_frame_end'))
|
||||||
|
apply_state_item('temp_frame_format', args.get('temp_frame_format'))
|
||||||
|
apply_state_item('keep_temp', args.get('keep_temp'))
|
||||||
|
apply_state_item('output_image_quality', args.get('output_image_quality'))
|
||||||
|
apply_state_item('output_image_scale', args.get('output_image_scale'))
|
||||||
|
apply_state_item('output_audio_encoder', args.get('output_audio_encoder'))
|
||||||
|
apply_state_item('output_audio_quality', args.get('output_audio_quality'))
|
||||||
|
apply_state_item('output_audio_volume', args.get('output_audio_volume'))
|
||||||
|
apply_state_item('output_video_encoder', args.get('output_video_encoder'))
|
||||||
|
apply_state_item('output_video_preset', args.get('output_video_preset'))
|
||||||
|
apply_state_item('output_video_quality', args.get('output_video_quality'))
|
||||||
|
apply_state_item('output_video_scale', args.get('output_video_scale'))
|
||||||
|
|
||||||
|
if args.get('output_video_fps') or is_video(args.get('target_path')):
|
||||||
|
output_video_fps = normalize_fps(args.get('output_video_fps')) or detect_video_fps(args.get('target_path'))
|
||||||
|
apply_state_item('output_video_fps', output_video_fps)
|
||||||
|
|
||||||
|
available_processors = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/processors/modules') ]
|
||||||
|
apply_state_item('processors', args.get('processors'))
|
||||||
|
|
||||||
|
for processor_module in get_processors_modules(available_processors):
|
||||||
|
processor_module.apply_args(args, apply_state_item)
|
||||||
|
|
||||||
|
apply_state_item('open_browser', args.get('open_browser'))
|
||||||
|
apply_state_item('ui_layouts', args.get('ui_layouts'))
|
||||||
|
apply_state_item('ui_workflow', args.get('ui_workflow'))
|
||||||
|
apply_state_item('execution_device_ids', args.get('execution_device_ids'))
|
||||||
|
apply_state_item('execution_providers', args.get('execution_providers'))
|
||||||
|
apply_state_item('execution_thread_count', args.get('execution_thread_count'))
|
||||||
|
apply_state_item('download_providers', args.get('download_providers'))
|
||||||
|
apply_state_item('download_scope', args.get('download_scope'))
|
||||||
|
apply_state_item('benchmark_mode', args.get('benchmark_mode'))
|
||||||
|
apply_state_item('benchmark_resolutions', args.get('benchmark_resolutions'))
|
||||||
|
apply_state_item('benchmark_cycle_count', args.get('benchmark_cycle_count'))
|
||||||
|
apply_state_item('video_memory_strategy', args.get('video_memory_strategy'))
|
||||||
|
apply_state_item('system_memory_limit', args.get('system_memory_limit'))
|
||||||
|
apply_state_item('log_level', args.get('log_level'))
|
||||||
|
apply_state_item('halt_on_error', args.get('halt_on_error'))
|
||||||
|
apply_state_item('job_id', args.get('job_id'))
|
||||||
|
apply_state_item('job_status', args.get('job_status'))
|
||||||
|
apply_state_item('step_index', args.get('step_index'))
|
||||||
|
|
||||||
|
|
||||||
def reduce_step_args(args : Args) -> Args:
|
def reduce_step_args(args : Args) -> Args:
|
||||||
step_args =\
|
step_args =\
|
||||||
{
|
{
|
||||||
@@ -37,95 +115,3 @@ def collect_job_args() -> Args:
|
|||||||
key: state_manager.get_item(key) for key in job_store.get_job_keys() #type:ignore[arg-type]
|
key: state_manager.get_item(key) for key in job_store.get_job_keys() #type:ignore[arg-type]
|
||||||
}
|
}
|
||||||
return job_args
|
return job_args
|
||||||
|
|
||||||
|
|
||||||
def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
|
|
||||||
# general
|
|
||||||
apply_state_item('command', args.get('command'))
|
|
||||||
# paths
|
|
||||||
apply_state_item('temp_path', args.get('temp_path'))
|
|
||||||
apply_state_item('jobs_path', args.get('jobs_path'))
|
|
||||||
apply_state_item('source_paths', args.get('source_paths'))
|
|
||||||
apply_state_item('target_path', args.get('target_path'))
|
|
||||||
apply_state_item('output_path', args.get('output_path'))
|
|
||||||
# patterns
|
|
||||||
apply_state_item('source_pattern', args.get('source_pattern'))
|
|
||||||
apply_state_item('target_pattern', args.get('target_pattern'))
|
|
||||||
apply_state_item('output_pattern', args.get('output_pattern'))
|
|
||||||
# face detector
|
|
||||||
apply_state_item('face_detector_model', args.get('face_detector_model'))
|
|
||||||
apply_state_item('face_detector_size', args.get('face_detector_size'))
|
|
||||||
apply_state_item('face_detector_margin', normalize_space(args.get('face_detector_margin')))
|
|
||||||
apply_state_item('face_detector_angles', args.get('face_detector_angles'))
|
|
||||||
apply_state_item('face_detector_score', args.get('face_detector_score'))
|
|
||||||
# face landmarker
|
|
||||||
apply_state_item('face_landmarker_model', args.get('face_landmarker_model'))
|
|
||||||
apply_state_item('face_landmarker_score', args.get('face_landmarker_score'))
|
|
||||||
# face selector
|
|
||||||
apply_state_item('face_selector_mode', args.get('face_selector_mode'))
|
|
||||||
apply_state_item('face_selector_order', args.get('face_selector_order'))
|
|
||||||
apply_state_item('face_selector_age_start', args.get('face_selector_age_start'))
|
|
||||||
apply_state_item('face_selector_age_end', args.get('face_selector_age_end'))
|
|
||||||
apply_state_item('face_selector_gender', args.get('face_selector_gender'))
|
|
||||||
apply_state_item('face_selector_race', args.get('face_selector_race'))
|
|
||||||
apply_state_item('reference_face_position', args.get('reference_face_position'))
|
|
||||||
apply_state_item('reference_face_distance', args.get('reference_face_distance'))
|
|
||||||
apply_state_item('reference_frame_number', args.get('reference_frame_number'))
|
|
||||||
# face masker
|
|
||||||
apply_state_item('face_occluder_model', args.get('face_occluder_model'))
|
|
||||||
apply_state_item('face_parser_model', args.get('face_parser_model'))
|
|
||||||
apply_state_item('face_mask_types', args.get('face_mask_types'))
|
|
||||||
apply_state_item('face_mask_areas', args.get('face_mask_areas'))
|
|
||||||
apply_state_item('face_mask_regions', args.get('face_mask_regions'))
|
|
||||||
apply_state_item('face_mask_blur', args.get('face_mask_blur'))
|
|
||||||
apply_state_item('face_mask_padding', normalize_space(args.get('face_mask_padding')))
|
|
||||||
# voice extractor
|
|
||||||
apply_state_item('voice_extractor_model', args.get('voice_extractor_model'))
|
|
||||||
# frame extraction
|
|
||||||
apply_state_item('trim_frame_start', args.get('trim_frame_start'))
|
|
||||||
apply_state_item('trim_frame_end', args.get('trim_frame_end'))
|
|
||||||
apply_state_item('temp_frame_format', args.get('temp_frame_format'))
|
|
||||||
apply_state_item('keep_temp', args.get('keep_temp'))
|
|
||||||
# output creation
|
|
||||||
apply_state_item('output_image_quality', args.get('output_image_quality'))
|
|
||||||
apply_state_item('output_image_scale', args.get('output_image_scale'))
|
|
||||||
apply_state_item('output_audio_encoder', args.get('output_audio_encoder'))
|
|
||||||
apply_state_item('output_audio_quality', args.get('output_audio_quality'))
|
|
||||||
apply_state_item('output_audio_volume', args.get('output_audio_volume'))
|
|
||||||
apply_state_item('output_video_encoder', args.get('output_video_encoder'))
|
|
||||||
apply_state_item('output_video_preset', args.get('output_video_preset'))
|
|
||||||
apply_state_item('output_video_quality', args.get('output_video_quality'))
|
|
||||||
apply_state_item('output_video_scale', args.get('output_video_scale'))
|
|
||||||
if args.get('output_video_fps') or is_video(args.get('target_path')):
|
|
||||||
output_video_fps = normalize_fps(args.get('output_video_fps')) or detect_video_fps(args.get('target_path'))
|
|
||||||
apply_state_item('output_video_fps', output_video_fps)
|
|
||||||
# processors
|
|
||||||
available_processors = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/processors/modules') ]
|
|
||||||
apply_state_item('processors', args.get('processors'))
|
|
||||||
for processor_module in get_processors_modules(available_processors):
|
|
||||||
processor_module.apply_args(args, apply_state_item)
|
|
||||||
# uis
|
|
||||||
apply_state_item('open_browser', args.get('open_browser'))
|
|
||||||
apply_state_item('ui_layouts', args.get('ui_layouts'))
|
|
||||||
apply_state_item('ui_workflow', args.get('ui_workflow'))
|
|
||||||
# execution
|
|
||||||
apply_state_item('execution_device_ids', args.get('execution_device_ids'))
|
|
||||||
apply_state_item('execution_providers', args.get('execution_providers'))
|
|
||||||
apply_state_item('execution_thread_count', args.get('execution_thread_count'))
|
|
||||||
# download
|
|
||||||
apply_state_item('download_providers', args.get('download_providers'))
|
|
||||||
apply_state_item('download_scope', args.get('download_scope'))
|
|
||||||
# benchmark
|
|
||||||
apply_state_item('benchmark_mode', args.get('benchmark_mode'))
|
|
||||||
apply_state_item('benchmark_resolutions', args.get('benchmark_resolutions'))
|
|
||||||
apply_state_item('benchmark_cycle_count', args.get('benchmark_cycle_count'))
|
|
||||||
# memory
|
|
||||||
apply_state_item('video_memory_strategy', args.get('video_memory_strategy'))
|
|
||||||
apply_state_item('system_memory_limit', args.get('system_memory_limit'))
|
|
||||||
# misc
|
|
||||||
apply_state_item('log_level', args.get('log_level'))
|
|
||||||
apply_state_item('halt_on_error', args.get('halt_on_error'))
|
|
||||||
# jobs
|
|
||||||
apply_state_item('job_id', args.get('job_id'))
|
|
||||||
apply_state_item('job_status', args.get('job_status'))
|
|
||||||
apply_state_item('step_index', args.get('step_index'))
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import os
|
|||||||
import statistics
|
import statistics
|
||||||
import tempfile
|
import tempfile
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import Generator, List
|
from typing import Iterator, List
|
||||||
|
|
||||||
import facefusion.choices
|
import facefusion.choices
|
||||||
from facefusion import content_analyser, core, state_manager
|
from facefusion import content_analyser, core, state_manager
|
||||||
@@ -31,7 +31,7 @@ def pre_check() -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def run() -> Generator[List[BenchmarkCycleSet], None, None]:
|
def run() -> Iterator[List[BenchmarkCycleSet]]:
|
||||||
benchmark_resolutions = state_manager.get_item('benchmark_resolutions')
|
benchmark_resolutions = state_manager.get_item('benchmark_resolutions')
|
||||||
benchmark_cycle_count = state_manager.get_item('benchmark_cycle_count')
|
benchmark_cycle_count = state_manager.get_item('benchmark_cycle_count')
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ def cycle(cycle_count : int) -> BenchmarkCycleSet:
|
|||||||
|
|
||||||
def suggest_output_path(target_path : str) -> str:
|
def suggest_output_path(target_path : str) -> str:
|
||||||
target_file_extension = get_file_extension(target_path)
|
target_file_extension = get_file_extension(target_path)
|
||||||
return os.path.join(tempfile.gettempdir(), hashlib.sha1().hexdigest()[:8] + target_file_extension)
|
return os.path.join(tempfile.gettempdir(), hashlib.sha1(target_path.encode()).hexdigest() + target_file_extension)
|
||||||
|
|
||||||
|
|
||||||
def render() -> None:
|
def render() -> None:
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ def detect_local_camera_ids(id_start : int, id_end : int) -> List[int]:
|
|||||||
local_camera_ids = []
|
local_camera_ids = []
|
||||||
|
|
||||||
for camera_id in range(id_start, id_end):
|
for camera_id in range(id_start, id_end):
|
||||||
cv2.setLogLevel(0)
|
cv2.utils.logging.setLogLevel(0)
|
||||||
camera_capture = get_local_camera_capture(camera_id)
|
camera_capture = get_local_camera_capture(camera_id)
|
||||||
cv2.setLogLevel(3)
|
cv2.utils.logging.setLogLevel(3)
|
||||||
|
|
||||||
if camera_capture and camera_capture.isOpened():
|
if camera_capture and camera_capture.isOpened():
|
||||||
local_camera_ids.append(camera_id)
|
local_camera_ids.append(camera_id)
|
||||||
|
|||||||
+34
-33
@@ -1,5 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_float_range, create_int_range
|
from facefusion.common_helper import create_float_range, create_int_range
|
||||||
from facefusion.types import Angle, AudioEncoder, AudioFormat, AudioTypeSet, BenchmarkMode, BenchmarkResolution, BenchmarkSet, DownloadProvider, DownloadProviderSet, DownloadScope, EncoderSet, ExecutionProvider, ExecutionProviderSet, FaceDetectorModel, FaceDetectorSet, FaceLandmarkerModel, FaceMaskArea, FaceMaskAreaSet, FaceMaskRegion, FaceMaskRegionSet, FaceMaskType, FaceOccluderModel, FaceParserModel, FaceSelectorMode, FaceSelectorOrder, Gender, ImageFormat, ImageTypeSet, JobStatus, LogLevel, LogLevelSet, Race, Score, TempFrameFormat, UiWorkflow, VideoEncoder, VideoFormat, VideoMemoryStrategy, VideoPreset, VideoTypeSet, VoiceExtractorModel
|
from facefusion.types import Angle, AudioEncoder, AudioFormat, AudioTypeSet, BenchmarkMode, BenchmarkResolution, BenchmarkSet, DownloadProvider, DownloadProviderSet, DownloadScope, EncoderSet, ExecutionProvider, ExecutionProviderSet, FaceDetectorModel, FaceDetectorSet, FaceLandmarkerModel, FaceMaskArea, FaceMaskAreaSet, FaceMaskRegion, FaceMaskRegionSet, FaceMaskType, FaceOccluderModel, FaceParserModel, FaceSelectorMode, FaceSelectorOrder, Gender, ImageFormat, ImageTypeSet, JobStatus, LogLevel, LogLevelSet, Race, Score, TempFrameFormat, UiWorkflow, VideoEncoder, VideoFormat, VideoMemoryStrategy, VideoPreset, VideoTypeSet, VoiceExtractorModel
|
||||||
@@ -12,15 +12,15 @@ face_detector_set : FaceDetectorSet =\
|
|||||||
'yolo_face': [ '640x640' ],
|
'yolo_face': [ '640x640' ],
|
||||||
'yunet': [ '640x640' ]
|
'yunet': [ '640x640' ]
|
||||||
}
|
}
|
||||||
face_detector_models : List[FaceDetectorModel] = list(face_detector_set.keys())
|
face_detector_models : List[FaceDetectorModel] = list(get_args(FaceDetectorModel))
|
||||||
face_landmarker_models : List[FaceLandmarkerModel] = [ 'many', '2dfan4', 'peppa_wutz' ]
|
face_landmarker_models : List[FaceLandmarkerModel] = list(get_args(FaceLandmarkerModel))
|
||||||
face_selector_modes : List[FaceSelectorMode] = [ 'many', 'one', 'reference' ]
|
face_selector_modes : List[FaceSelectorMode] = list(get_args(FaceSelectorMode))
|
||||||
face_selector_orders : List[FaceSelectorOrder] = [ 'left-right', 'right-left', 'top-bottom', 'bottom-top', 'small-large', 'large-small', 'best-worst', 'worst-best' ]
|
face_selector_orders : List[FaceSelectorOrder] = list(get_args(FaceSelectorOrder))
|
||||||
face_selector_genders : List[Gender] = [ 'female', 'male' ]
|
face_selector_genders : List[Gender] = list(get_args(Gender))
|
||||||
face_selector_races : List[Race] = [ 'white', 'black', 'latino', 'asian', 'indian', 'arabic' ]
|
face_selector_races : List[Race] = list(get_args(Race))
|
||||||
face_occluder_models : List[FaceOccluderModel] = [ 'many', 'xseg_1', 'xseg_2', 'xseg_3' ]
|
face_occluder_models : List[FaceOccluderModel] = list(get_args(FaceOccluderModel))
|
||||||
face_parser_models : List[FaceParserModel] = [ 'bisenet_resnet_18', 'bisenet_resnet_34' ]
|
face_parser_models : List[FaceParserModel] = list(get_args(FaceParserModel))
|
||||||
face_mask_types : List[FaceMaskType] = [ 'box', 'occlusion', 'area', 'region' ]
|
face_mask_types : List[FaceMaskType] = list(get_args(FaceMaskType))
|
||||||
face_mask_area_set : FaceMaskAreaSet =\
|
face_mask_area_set : FaceMaskAreaSet =\
|
||||||
{
|
{
|
||||||
'upper-face': [ 0, 1, 2, 31, 32, 33, 34, 35, 14, 15, 16, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17 ],
|
'upper-face': [ 0, 1, 2, 31, 32, 33, 34, 35, 14, 15, 16, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17 ],
|
||||||
@@ -40,10 +40,10 @@ face_mask_region_set : FaceMaskRegionSet =\
|
|||||||
'upper-lip': 12,
|
'upper-lip': 12,
|
||||||
'lower-lip': 13
|
'lower-lip': 13
|
||||||
}
|
}
|
||||||
face_mask_areas : List[FaceMaskArea] = list(face_mask_area_set.keys())
|
face_mask_areas : List[FaceMaskArea] = list(get_args(FaceMaskArea))
|
||||||
face_mask_regions : List[FaceMaskRegion] = list(face_mask_region_set.keys())
|
face_mask_regions : List[FaceMaskRegion] = list(get_args(FaceMaskRegion))
|
||||||
|
|
||||||
voice_extractor_models : List[VoiceExtractorModel] = [ 'kim_vocal_1', 'kim_vocal_2', 'uvr_mdxnet' ]
|
voice_extractor_models : List[VoiceExtractorModel] = list(get_args(VoiceExtractorModel))
|
||||||
|
|
||||||
audio_type_set : AudioTypeSet =\
|
audio_type_set : AudioTypeSet =\
|
||||||
{
|
{
|
||||||
@@ -74,21 +74,21 @@ video_type_set : VideoTypeSet =\
|
|||||||
'webm': 'video/webm',
|
'webm': 'video/webm',
|
||||||
'wmv': 'video/x-ms-wmv'
|
'wmv': 'video/x-ms-wmv'
|
||||||
}
|
}
|
||||||
audio_formats : List[AudioFormat] = list(audio_type_set.keys())
|
audio_formats : List[AudioFormat] = list(get_args(AudioFormat))
|
||||||
image_formats : List[ImageFormat] = list(image_type_set.keys())
|
image_formats : List[ImageFormat] = list(get_args(ImageFormat))
|
||||||
video_formats : List[VideoFormat] = list(video_type_set.keys())
|
video_formats : List[VideoFormat] = list(get_args(VideoFormat))
|
||||||
temp_frame_formats : List[TempFrameFormat] = [ 'bmp', 'jpeg', 'png', 'tiff' ]
|
temp_frame_formats : List[TempFrameFormat] = list(get_args(TempFrameFormat))
|
||||||
|
|
||||||
|
output_audio_encoders : List[AudioEncoder] = list(get_args(AudioEncoder))
|
||||||
|
output_video_encoders : List[VideoEncoder] = list(get_args(VideoEncoder))
|
||||||
output_encoder_set : EncoderSet =\
|
output_encoder_set : EncoderSet =\
|
||||||
{
|
{
|
||||||
'audio': [ 'flac', 'aac', 'libmp3lame', 'libopus', 'libvorbis', 'pcm_s16le', 'pcm_s32le' ],
|
'audio': output_audio_encoders,
|
||||||
'video': [ 'libx264', 'libx264rgb', 'libx265', 'libvpx-vp9', 'h264_nvenc', 'hevc_nvenc', 'h264_amf', 'hevc_amf', 'h264_qsv', 'hevc_qsv', 'h264_videotoolbox', 'hevc_videotoolbox', 'rawvideo' ]
|
'video': output_video_encoders
|
||||||
}
|
}
|
||||||
output_audio_encoders : List[AudioEncoder] = output_encoder_set.get('audio')
|
output_video_presets : List[VideoPreset] = list(get_args(VideoPreset))
|
||||||
output_video_encoders : List[VideoEncoder] = output_encoder_set.get('video')
|
|
||||||
output_video_presets : List[VideoPreset] = [ 'ultrafast', 'superfast', 'veryfast', 'faster', 'fast', 'medium', 'slow', 'slower', 'veryslow' ]
|
|
||||||
|
|
||||||
benchmark_modes : List[BenchmarkMode] = [ 'warm', 'cold' ]
|
benchmark_modes : List[BenchmarkMode] = list(get_args(BenchmarkMode))
|
||||||
benchmark_set : BenchmarkSet =\
|
benchmark_set : BenchmarkSet =\
|
||||||
{
|
{
|
||||||
'240p': '.assets/examples/target-240p.mp4',
|
'240p': '.assets/examples/target-240p.mp4',
|
||||||
@@ -99,20 +99,21 @@ benchmark_set : BenchmarkSet =\
|
|||||||
'1440p': '.assets/examples/target-1440p.mp4',
|
'1440p': '.assets/examples/target-1440p.mp4',
|
||||||
'2160p': '.assets/examples/target-2160p.mp4'
|
'2160p': '.assets/examples/target-2160p.mp4'
|
||||||
}
|
}
|
||||||
benchmark_resolutions : List[BenchmarkResolution] = list(benchmark_set.keys())
|
benchmark_resolutions : List[BenchmarkResolution] = list(get_args(BenchmarkResolution))
|
||||||
|
|
||||||
execution_provider_set : ExecutionProviderSet =\
|
execution_provider_set : ExecutionProviderSet =\
|
||||||
{
|
{
|
||||||
'cuda': 'CUDAExecutionProvider',
|
'cuda': 'CUDAExecutionProvider',
|
||||||
'tensorrt': 'TensorrtExecutionProvider',
|
'tensorrt': 'TensorrtExecutionProvider',
|
||||||
'directml': 'DmlExecutionProvider',
|
|
||||||
'rocm': 'ROCMExecutionProvider',
|
'rocm': 'ROCMExecutionProvider',
|
||||||
'migraphx': 'MIGraphXExecutionProvider',
|
'migraphx': 'MIGraphXExecutionProvider',
|
||||||
'openvino': 'OpenVINOExecutionProvider',
|
|
||||||
'coreml': 'CoreMLExecutionProvider',
|
'coreml': 'CoreMLExecutionProvider',
|
||||||
|
'openvino': 'OpenVINOExecutionProvider',
|
||||||
|
'qnn': 'QNNExecutionProvider',
|
||||||
|
'directml': 'DmlExecutionProvider',
|
||||||
'cpu': 'CPUExecutionProvider'
|
'cpu': 'CPUExecutionProvider'
|
||||||
}
|
}
|
||||||
execution_providers : List[ExecutionProvider] = list(execution_provider_set.keys())
|
execution_providers : List[ExecutionProvider] = list(get_args(ExecutionProvider))
|
||||||
download_provider_set : DownloadProviderSet =\
|
download_provider_set : DownloadProviderSet =\
|
||||||
{
|
{
|
||||||
'github':
|
'github':
|
||||||
@@ -133,10 +134,10 @@ download_provider_set : DownloadProviderSet =\
|
|||||||
'path': '/facefusion/{base_name}/resolve/main/{file_name}'
|
'path': '/facefusion/{base_name}/resolve/main/{file_name}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
download_providers : List[DownloadProvider] = list(download_provider_set.keys())
|
download_providers : List[DownloadProvider] = list(get_args(DownloadProvider))
|
||||||
download_scopes : List[DownloadScope] = [ 'lite', 'full' ]
|
download_scopes : List[DownloadScope] = list(get_args(DownloadScope))
|
||||||
|
|
||||||
video_memory_strategies : List[VideoMemoryStrategy] = [ 'strict', 'moderate', 'tolerant' ]
|
video_memory_strategies : List[VideoMemoryStrategy] = list(get_args(VideoMemoryStrategy))
|
||||||
|
|
||||||
log_level_set : LogLevelSet =\
|
log_level_set : LogLevelSet =\
|
||||||
{
|
{
|
||||||
@@ -145,10 +146,10 @@ log_level_set : LogLevelSet =\
|
|||||||
'info': logging.INFO,
|
'info': logging.INFO,
|
||||||
'debug': logging.DEBUG
|
'debug': logging.DEBUG
|
||||||
}
|
}
|
||||||
log_levels : List[LogLevel] = list(log_level_set.keys())
|
log_levels : List[LogLevel] = list(get_args(LogLevel))
|
||||||
|
|
||||||
ui_workflows : List[UiWorkflow] = [ 'instant_runner', 'job_runner', 'job_manager' ]
|
ui_workflows : List[UiWorkflow] = list(get_args(UiWorkflow))
|
||||||
job_statuses : List[JobStatus] = [ 'drafted', 'queued', 'completed', 'failed' ]
|
job_statuses : List[JobStatus] = list(get_args(JobStatus))
|
||||||
|
|
||||||
benchmark_cycle_count_range : Sequence[int] = create_int_range(1, 10, 1)
|
benchmark_cycle_count_range : Sequence[int] = create_int_range(1, 10, 1)
|
||||||
execution_thread_count_range : Sequence[int] = create_int_range(1, 32, 1)
|
execution_thread_count_range : Sequence[int] = create_int_range(1, 32, 1)
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from facefusion.common_helper import is_linux, is_windows
|
||||||
|
|
||||||
|
|
||||||
|
def setup() -> None:
|
||||||
|
conda_prefix = os.getenv('CONDA_PREFIX')
|
||||||
|
conda_ready = os.getenv('CONDA_READY')
|
||||||
|
|
||||||
|
if conda_prefix and not conda_ready:
|
||||||
|
if is_linux():
|
||||||
|
python_id = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
|
||||||
|
library_paths : List[str] =\
|
||||||
|
[
|
||||||
|
os.path.join(conda_prefix, 'lib'),
|
||||||
|
os.path.join(conda_prefix, 'lib', python_id, 'site-packages', 'tensorrt_libs')
|
||||||
|
]
|
||||||
|
library_paths = list(filter(os.path.exists, library_paths))
|
||||||
|
|
||||||
|
if library_paths:
|
||||||
|
if os.getenv('LD_LIBRARY_PATH'):
|
||||||
|
library_paths.append(os.getenv('LD_LIBRARY_PATH'))
|
||||||
|
os.environ['LD_LIBRARY_PATH'] = os.pathsep.join(library_paths)
|
||||||
|
os.environ['CONDA_READY'] = '1'
|
||||||
|
os.execv(sys.executable, [ sys.executable ] + sys.argv)
|
||||||
|
|
||||||
|
if is_windows():
|
||||||
|
library_paths =\
|
||||||
|
[
|
||||||
|
os.path.join(conda_prefix, 'Lib'),
|
||||||
|
os.path.join(conda_prefix, 'Lib', 'site-packages', 'tensorrt_libs')
|
||||||
|
]
|
||||||
|
library_paths = list(filter(os.path.exists, library_paths))
|
||||||
|
|
||||||
|
if library_paths:
|
||||||
|
if os.getenv('PATH'):
|
||||||
|
library_paths.append(os.getenv('PATH'))
|
||||||
|
os.environ['PATH'] = os.pathsep.join(library_paths)
|
||||||
|
os.environ['CONDA_READY'] = '1'
|
||||||
@@ -9,14 +9,14 @@ from facefusion.types import Command
|
|||||||
def run(commands : List[Command]) -> List[Command]:
|
def run(commands : List[Command]) -> List[Command]:
|
||||||
user_agent = metadata.get('name') + '/' + metadata.get('version')
|
user_agent = metadata.get('name') + '/' + metadata.get('version')
|
||||||
|
|
||||||
return [ shutil.which('curl'), '--user-agent', user_agent, '--insecure', '--location', '--silent' ] + commands
|
return [ shutil.which('curl'), '--user-agent', user_agent, '--location', '--silent', '--ssl-no-revoke' ] + commands
|
||||||
|
|
||||||
|
|
||||||
def chain(*commands : List[Command]) -> List[Command]:
|
def chain(*commands : List[Command]) -> List[Command]:
|
||||||
return list(itertools.chain(*commands))
|
return list(itertools.chain(*commands))
|
||||||
|
|
||||||
|
|
||||||
def head(url : str) -> List[Command]:
|
def ping(url : str) -> List[Command]:
|
||||||
return [ '-I', url ]
|
return [ '-I', url ]
|
||||||
|
|
||||||
|
|
||||||
@@ -26,3 +26,7 @@ def download(url : str, download_file_path : str) -> List[Command]:
|
|||||||
|
|
||||||
def set_timeout(timeout : int) -> List[Command]:
|
def set_timeout(timeout : int) -> List[Command]:
|
||||||
return [ '--connect-timeout', str(timeout) ]
|
return [ '--connect-timeout', str(timeout) ]
|
||||||
|
|
||||||
|
|
||||||
|
def set_retry(retry : int) -> List[Command]:
|
||||||
|
return [ '--retry', str(retry) ]
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ def conditional_download(download_directory_path : str, urls : List[str]) -> Non
|
|||||||
with tqdm(total = download_size, initial = initial_size, desc = translator.get('downloading'), unit = 'B', unit_scale = True, unit_divisor = 1024, ascii = ' =', disable = state_manager.get_item('log_level') in [ 'warn', 'error' ]) as progress:
|
with tqdm(total = download_size, initial = initial_size, desc = translator.get('downloading'), unit = 'B', unit_scale = True, unit_divisor = 1024, ascii = ' =', disable = state_manager.get_item('log_level') in [ 'warn', 'error' ]) as progress:
|
||||||
commands = curl_builder.chain(
|
commands = curl_builder.chain(
|
||||||
curl_builder.download(url, download_file_path),
|
curl_builder.download(url, download_file_path),
|
||||||
curl_builder.set_timeout(5)
|
curl_builder.set_timeout(5),
|
||||||
|
curl_builder.set_retry(5)
|
||||||
)
|
)
|
||||||
open_curl(commands)
|
open_curl(commands)
|
||||||
current_size = initial_size
|
current_size = initial_size
|
||||||
@@ -44,7 +45,7 @@ def conditional_download(download_directory_path : str, urls : List[str]) -> Non
|
|||||||
@lru_cache(maxsize = 64)
|
@lru_cache(maxsize = 64)
|
||||||
def get_static_download_size(url : str) -> int:
|
def get_static_download_size(url : str) -> int:
|
||||||
commands = curl_builder.chain(
|
commands = curl_builder.chain(
|
||||||
curl_builder.head(url),
|
curl_builder.ping(url),
|
||||||
curl_builder.set_timeout(5)
|
curl_builder.set_timeout(5)
|
||||||
)
|
)
|
||||||
process = open_curl(commands)
|
process = open_curl(commands)
|
||||||
@@ -62,7 +63,7 @@ def get_static_download_size(url : str) -> int:
|
|||||||
@lru_cache(maxsize = 64)
|
@lru_cache(maxsize = 64)
|
||||||
def ping_static_url(url : str) -> bool:
|
def ping_static_url(url : str) -> bool:
|
||||||
commands = curl_builder.chain(
|
commands = curl_builder.chain(
|
||||||
curl_builder.head(url),
|
curl_builder.ping(url),
|
||||||
curl_builder.set_timeout(5)
|
curl_builder.set_timeout(5)
|
||||||
)
|
)
|
||||||
process = open_curl(commands)
|
process = open_curl(commands)
|
||||||
|
|||||||
+64
-30
@@ -1,15 +1,17 @@
|
|||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import xml.etree.ElementTree as ElementTree
|
import xml.etree.ElementTree as ElementTree
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from onnxruntime import get_available_providers, set_default_logger_severity
|
import onnxruntime
|
||||||
|
|
||||||
import facefusion.choices
|
import facefusion.choices
|
||||||
from facefusion.types import ExecutionDevice, ExecutionProvider, InferenceSessionProvider, ValueAndUnit
|
from facefusion.filesystem import create_directory, is_directory
|
||||||
|
from facefusion.types import ExecutionDevice, ExecutionProvider, InferenceOptionSet, InferenceProvider, ValueAndUnit
|
||||||
|
|
||||||
set_default_logger_severity(3)
|
onnxruntime.set_default_logger_severity(3)
|
||||||
|
|
||||||
|
|
||||||
def has_execution_provider(execution_provider : ExecutionProvider) -> bool:
|
def has_execution_provider(execution_provider : ExecutionProvider) -> bool:
|
||||||
@@ -17,7 +19,7 @@ def has_execution_provider(execution_provider : ExecutionProvider) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def get_available_execution_providers() -> List[ExecutionProvider]:
|
def get_available_execution_providers() -> List[ExecutionProvider]:
|
||||||
inference_session_providers = get_available_providers()
|
inference_session_providers = onnxruntime.get_available_providers()
|
||||||
available_execution_providers : List[ExecutionProvider] = []
|
available_execution_providers : List[ExecutionProvider] = []
|
||||||
|
|
||||||
for execution_provider, execution_provider_value in facefusion.choices.execution_provider_set.items():
|
for execution_provider, execution_provider_value in facefusion.choices.execution_provider_set.items():
|
||||||
@@ -28,54 +30,86 @@ def get_available_execution_providers() -> List[ExecutionProvider]:
|
|||||||
return available_execution_providers
|
return available_execution_providers
|
||||||
|
|
||||||
|
|
||||||
def create_inference_session_providers(execution_device_id : str, execution_providers : List[ExecutionProvider]) -> List[InferenceSessionProvider]:
|
def create_inference_providers(execution_device_id : int, execution_providers : List[ExecutionProvider]) -> List[InferenceProvider]:
|
||||||
inference_session_providers : List[InferenceSessionProvider] = []
|
inference_providers : List[InferenceProvider] = []
|
||||||
|
cache_path = resolve_cache_path()
|
||||||
|
|
||||||
for execution_provider in execution_providers:
|
for execution_provider in execution_providers:
|
||||||
if execution_provider == 'cuda':
|
if execution_provider == 'cuda':
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
||||||
{
|
{
|
||||||
'device_id': execution_device_id,
|
'device_id': execution_device_id,
|
||||||
'cudnn_conv_algo_search': resolve_cudnn_conv_algo_search()
|
'cudnn_conv_algo_search': resolve_cudnn_conv_algo_search()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if execution_provider == 'tensorrt':
|
if execution_provider == 'tensorrt':
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
inference_option_set : InferenceOptionSet =\
|
||||||
{
|
{
|
||||||
'device_id': execution_device_id,
|
'device_id': execution_device_id
|
||||||
'trt_engine_cache_enable': True,
|
}
|
||||||
'trt_engine_cache_path': '.caches',
|
if is_directory(cache_path) or create_directory(cache_path):
|
||||||
'trt_timing_cache_enable': True,
|
inference_option_set.update(
|
||||||
'trt_timing_cache_path': '.caches',
|
{
|
||||||
'trt_builder_optimization_level': 5
|
'trt_engine_cache_enable': True,
|
||||||
}))
|
'trt_engine_cache_path': cache_path,
|
||||||
|
'trt_timing_cache_enable': True,
|
||||||
|
'trt_timing_cache_path': cache_path,
|
||||||
|
'trt_builder_optimization_level': 4
|
||||||
|
})
|
||||||
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set))
|
||||||
|
|
||||||
if execution_provider in [ 'directml', 'rocm' ]:
|
if execution_provider in [ 'directml', 'rocm' ]:
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
||||||
{
|
{
|
||||||
'device_id': execution_device_id
|
'device_id': execution_device_id
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if execution_provider == 'migraphx':
|
if execution_provider == 'migraphx':
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
inference_option_set =\
|
||||||
{
|
{
|
||||||
'device_id': execution_device_id,
|
'device_id': execution_device_id
|
||||||
'migraphx_model_cache_dir': '.caches'
|
}
|
||||||
}))
|
if is_directory(cache_path) or create_directory(cache_path):
|
||||||
|
inference_option_set.update(
|
||||||
|
{
|
||||||
|
'migraphx_model_cache_dir': cache_path
|
||||||
|
})
|
||||||
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set))
|
||||||
|
|
||||||
|
if execution_provider == 'coreml':
|
||||||
|
inference_option_set =\
|
||||||
|
{
|
||||||
|
'SpecializationStrategy': 'FastPrediction'
|
||||||
|
}
|
||||||
|
if is_directory(cache_path) or create_directory(cache_path):
|
||||||
|
inference_option_set.update(
|
||||||
|
{
|
||||||
|
'ModelCacheDirectory': cache_path
|
||||||
|
})
|
||||||
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider), inference_option_set))
|
||||||
|
|
||||||
if execution_provider == 'openvino':
|
if execution_provider == 'openvino':
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
||||||
{
|
{
|
||||||
'device_type': resolve_openvino_device_type(execution_device_id),
|
'device_type': resolve_openvino_device_type(execution_device_id),
|
||||||
'precision': 'FP32'
|
'precision': 'FP32'
|
||||||
}))
|
}))
|
||||||
if execution_provider == 'coreml':
|
|
||||||
inference_session_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
if execution_provider == 'qnn':
|
||||||
|
inference_providers.append((facefusion.choices.execution_provider_set.get(execution_provider),
|
||||||
{
|
{
|
||||||
'SpecializationStrategy': 'FastPrediction',
|
'device_id': execution_device_id,
|
||||||
'ModelCacheDirectory': '.caches'
|
'backend_type': 'htp'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if 'cpu' in execution_providers:
|
if 'cpu' in execution_providers:
|
||||||
inference_session_providers.append(facefusion.choices.execution_provider_set.get('cpu'))
|
inference_providers.append(facefusion.choices.execution_provider_set.get('cpu'))
|
||||||
|
|
||||||
return inference_session_providers
|
return inference_providers
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_cache_path() -> str:
|
||||||
|
return os.path.join('.caches', onnxruntime.get_version_string())
|
||||||
|
|
||||||
|
|
||||||
def resolve_cudnn_conv_algo_search() -> str:
|
def resolve_cudnn_conv_algo_search() -> str:
|
||||||
@@ -89,10 +123,10 @@ def resolve_cudnn_conv_algo_search() -> str:
|
|||||||
return 'EXHAUSTIVE'
|
return 'EXHAUSTIVE'
|
||||||
|
|
||||||
|
|
||||||
def resolve_openvino_device_type(execution_device_id : str) -> str:
|
def resolve_openvino_device_type(execution_device_id : int) -> str:
|
||||||
if execution_device_id == '0':
|
if execution_device_id == 0:
|
||||||
return 'GPU'
|
return 'GPU'
|
||||||
return 'GPU.' + execution_device_id
|
return 'GPU.' + str(execution_device_id)
|
||||||
|
|
||||||
|
|
||||||
def run_nvidia_smi() -> subprocess.Popen[bytes]:
|
def run_nvidia_smi() -> subprocess.Popen[bytes]:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'__metadata__':
|
'__metadata__':
|
||||||
{
|
{
|
||||||
'vendor': 'dchen236',
|
'vendor': 'dchen236',
|
||||||
'license': 'Non-Commercial',
|
'license': 'CC-BY-4.0',
|
||||||
'year': 2021
|
'year': 2021
|
||||||
},
|
},
|
||||||
'hashes':
|
'hashes':
|
||||||
|
|||||||
@@ -381,11 +381,11 @@ def detect_with_yunet(vision_frame : VisionFrame, face_detector_size : str) -> T
|
|||||||
face_scores.extend(face_scores_raw[keep_indices])
|
face_scores.extend(face_scores_raw[keep_indices])
|
||||||
face_landmarks_5_raw = numpy.concatenate(
|
face_landmarks_5_raw = numpy.concatenate(
|
||||||
[
|
[
|
||||||
face_landmarks_5_raw[:, [0, 1]] * feature_stride + anchors,
|
face_landmarks_5_raw[:, [ 0, 1 ]] * feature_stride + anchors,
|
||||||
face_landmarks_5_raw[:, [2, 3]] * feature_stride + anchors,
|
face_landmarks_5_raw[:, [ 2, 3 ]] * feature_stride + anchors,
|
||||||
face_landmarks_5_raw[:, [4, 5]] * feature_stride + anchors,
|
face_landmarks_5_raw[:, [ 4, 5 ]] * feature_stride + anchors,
|
||||||
face_landmarks_5_raw[:, [6, 7]] * feature_stride + anchors,
|
face_landmarks_5_raw[:, [ 6, 7 ]] * feature_stride + anchors,
|
||||||
face_landmarks_5_raw[:, [8, 9]] * feature_stride + anchors
|
face_landmarks_5_raw[:, [ 8, 9 ]] * feature_stride + anchors
|
||||||
], axis = -1).reshape(-1, 5, 2)
|
], axis = -1).reshape(-1, 5, 2)
|
||||||
|
|
||||||
for face_landmark_raw_5 in face_landmarks_5_raw[keep_indices]:
|
for face_landmark_raw_5 in face_landmarks_5_raw[keep_indices]:
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ def warp_face_by_face_landmark_5(temp_vision_frame : VisionFrame, face_landmark_
|
|||||||
|
|
||||||
|
|
||||||
def warp_face_by_bounding_box(temp_vision_frame : VisionFrame, bounding_box : BoundingBox, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
def warp_face_by_bounding_box(temp_vision_frame : VisionFrame, bounding_box : BoundingBox, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
||||||
source_points = numpy.array([ [ bounding_box[0], bounding_box[1] ], [bounding_box[2], bounding_box[1] ], [ bounding_box[0], bounding_box[3] ] ]).astype(numpy.float32)
|
source_points = numpy.array([ [ bounding_box[0], bounding_box[1] ], [ bounding_box[2], bounding_box[1] ], [ bounding_box[0], bounding_box[3] ] ]).astype(numpy.float32)
|
||||||
target_points = numpy.array([ [ 0, 0 ], [ crop_size[0], 0 ], [ 0, crop_size[1] ] ]).astype(numpy.float32)
|
target_points = numpy.array([ [ 0, 0 ], [ crop_size[0], 0 ], [ 0, crop_size[1] ] ]).astype(numpy.float32)
|
||||||
affine_matrix = cv2.getAffineTransform(source_points, target_points)
|
affine_matrix = cv2.getAffineTransform(source_points, target_points)
|
||||||
if bounding_box[2] - bounding_box[0] > crop_size[0] or bounding_box[3] - bounding_box[1] > crop_size[1]:
|
if bounding_box[2] - bounding_box[0] > crop_size[0] or bounding_box[3] - bounding_box[1] > crop_size[1]:
|
||||||
@@ -247,7 +247,7 @@ def get_nms_threshold(face_detector_model : FaceDetectorModel, face_detector_ang
|
|||||||
|
|
||||||
|
|
||||||
def merge_matrix(temp_matrices : List[Matrix]) -> Matrix:
|
def merge_matrix(temp_matrices : List[Matrix]) -> Matrix:
|
||||||
matrix = numpy.vstack([temp_matrices[0], [0, 0, 1]])
|
matrix = numpy.vstack([ temp_matrices[0], [ 0, 0, 1 ] ])
|
||||||
|
|
||||||
for temp_matrix in temp_matrices[1:]:
|
for temp_matrix in temp_matrices[1:]:
|
||||||
temp_matrix = numpy.vstack([ temp_matrix, [ 0, 0, 1 ] ])
|
temp_matrix = numpy.vstack([ temp_matrix, [ 0, 0, 1 ] ])
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ def create_area_mask(crop_vision_frame : VisionFrame, face_landmark_68 : FaceLan
|
|||||||
|
|
||||||
convex_hull = cv2.convexHull(face_landmark_68[landmark_points].astype(numpy.int32))
|
convex_hull = cv2.convexHull(face_landmark_68[landmark_points].astype(numpy.int32))
|
||||||
area_mask = numpy.zeros(crop_size).astype(numpy.float32)
|
area_mask = numpy.zeros(crop_size).astype(numpy.float32)
|
||||||
cv2.fillConvexPoly(area_mask, convex_hull, 1.0) # type: ignore[call-overload]
|
cv2.fillConvexPoly(area_mask, convex_hull, 1.0) #type:ignore[call-overload]
|
||||||
area_mask = (cv2.GaussianBlur(area_mask.clip(0, 1), (0, 0), 5).clip(0.5, 1) - 0.5) * 2
|
area_mask = (cv2.GaussianBlur(area_mask.clip(0, 1), (0, 0), 5).clip(0.5, 1) - 0.5) * 2
|
||||||
return area_mask
|
return area_mask
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ def extract_frames(target_path : str, temp_video_resolution : Resolution, temp_v
|
|||||||
ffmpeg_builder.set_input(target_path),
|
ffmpeg_builder.set_input(target_path),
|
||||||
ffmpeg_builder.set_media_resolution(pack_resolution(temp_video_resolution)),
|
ffmpeg_builder.set_media_resolution(pack_resolution(temp_video_resolution)),
|
||||||
ffmpeg_builder.set_frame_quality(0),
|
ffmpeg_builder.set_frame_quality(0),
|
||||||
|
ffmpeg_builder.enforce_pixel_format('rgb24'),
|
||||||
ffmpeg_builder.select_frame_range(trim_frame_start, trim_frame_end, temp_video_fps),
|
ffmpeg_builder.select_frame_range(trim_frame_start, trim_frame_end, temp_video_fps),
|
||||||
ffmpeg_builder.prevent_frame_drop(),
|
ffmpeg_builder.prevent_frame_drop(),
|
||||||
ffmpeg_builder.set_output(temp_frames_pattern)
|
ffmpeg_builder.set_output(temp_frames_pattern)
|
||||||
@@ -243,7 +244,8 @@ def merge_video(target_path : str, temp_video_fps : Fps, output_video_resolution
|
|||||||
|
|
||||||
|
|
||||||
def concat_video(output_path : str, temp_output_paths : List[str]) -> bool:
|
def concat_video(output_path : str, temp_output_paths : List[str]) -> bool:
|
||||||
concat_video_path = tempfile.mktemp()
|
file_descriptor, concat_video_path = tempfile.mkstemp()
|
||||||
|
os.close(file_descriptor)
|
||||||
|
|
||||||
with open(concat_video_path, 'w') as concat_video_file:
|
with open(concat_video_path, 'w') as concat_video_file:
|
||||||
for temp_output_path in temp_output_paths:
|
for temp_output_path in temp_output_paths:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ def set_input(input_path : str) -> List[Command]:
|
|||||||
|
|
||||||
|
|
||||||
def set_input_fps(input_fps : Fps) -> List[Command]:
|
def set_input_fps(input_fps : Fps) -> List[Command]:
|
||||||
return [ '-r', str(input_fps)]
|
return [ '-r', str(input_fps) ]
|
||||||
|
|
||||||
|
|
||||||
def set_output(output_path : str) -> List[Command]:
|
def set_output(output_path : str) -> List[Command]:
|
||||||
@@ -79,6 +79,10 @@ def unsafe_concat() -> List[Command]:
|
|||||||
return [ '-f', 'concat', '-safe', '0' ]
|
return [ '-f', 'concat', '-safe', '0' ]
|
||||||
|
|
||||||
|
|
||||||
|
def enforce_pixel_format(pixel_format : str) -> List[Command]:
|
||||||
|
return [ '-pix_fmt', pixel_format ]
|
||||||
|
|
||||||
|
|
||||||
def set_pixel_format(video_encoder : VideoEncoder) -> List[Command]:
|
def set_pixel_format(video_encoder : VideoEncoder) -> List[Command]:
|
||||||
if video_encoder == 'rawvideo':
|
if video_encoder == 'rawvideo':
|
||||||
return [ '-pix_fmt', 'rgb24' ]
|
return [ '-pix_fmt', 'rgb24' ]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from onnxruntime import InferenceSession
|
|||||||
from facefusion import logger, process_manager, state_manager, translator
|
from facefusion import logger, process_manager, state_manager, translator
|
||||||
from facefusion.app_context import detect_app_context
|
from facefusion.app_context import detect_app_context
|
||||||
from facefusion.common_helper import is_windows
|
from facefusion.common_helper import is_windows
|
||||||
from facefusion.execution import create_inference_session_providers, has_execution_provider
|
from facefusion.execution import create_inference_providers, has_execution_provider
|
||||||
from facefusion.exit_helper import fatal_exit
|
from facefusion.exit_helper import fatal_exit
|
||||||
from facefusion.filesystem import get_file_name, is_file
|
from facefusion.filesystem import get_file_name, is_file
|
||||||
from facefusion.time_helper import calculate_end_time
|
from facefusion.time_helper import calculate_end_time
|
||||||
@@ -42,7 +42,7 @@ def get_inference_pool(module_name : str, model_names : List[str], model_source_
|
|||||||
return INFERENCE_POOL_SET.get(app_context).get(current_inference_context)
|
return INFERENCE_POOL_SET.get(app_context).get(current_inference_context)
|
||||||
|
|
||||||
|
|
||||||
def create_inference_pool(model_source_set : DownloadSet, execution_device_id : str, execution_providers : List[ExecutionProvider]) -> InferencePool:
|
def create_inference_pool(model_source_set : DownloadSet, execution_device_id : int, execution_providers : List[ExecutionProvider]) -> InferencePool:
|
||||||
inference_pool : InferencePool = {}
|
inference_pool : InferencePool = {}
|
||||||
|
|
||||||
for model_name in model_source_set.keys():
|
for model_name in model_source_set.keys():
|
||||||
@@ -67,13 +67,13 @@ def clear_inference_pool(module_name : str, model_names : List[str]) -> None:
|
|||||||
del INFERENCE_POOL_SET[app_context][inference_context]
|
del INFERENCE_POOL_SET[app_context][inference_context]
|
||||||
|
|
||||||
|
|
||||||
def create_inference_session(model_path : str, execution_device_id : str, execution_providers : List[ExecutionProvider]) -> InferenceSession:
|
def create_inference_session(model_path : str, execution_device_id : int, execution_providers : List[ExecutionProvider]) -> InferenceSession:
|
||||||
model_file_name = get_file_name(model_path)
|
model_file_name = get_file_name(model_path)
|
||||||
start_time = time()
|
start_time = time()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
inference_session_providers = create_inference_session_providers(execution_device_id, execution_providers)
|
inference_providers = create_inference_providers(execution_device_id, execution_providers)
|
||||||
inference_session = InferenceSession(model_path, providers = inference_session_providers)
|
inference_session = InferenceSession(model_path, providers = inference_providers)
|
||||||
logger.debug(translator.get('loading_model_succeeded').format(model_name = model_file_name, seconds = calculate_end_time(start_time)), __name__)
|
logger.debug(translator.get('loading_model_succeeded').format(model_name = model_file_name, seconds = calculate_end_time(start_time)), __name__)
|
||||||
return inference_session
|
return inference_session
|
||||||
|
|
||||||
@@ -82,8 +82,8 @@ def create_inference_session(model_path : str, execution_device_id : str, execut
|
|||||||
fatal_exit(1)
|
fatal_exit(1)
|
||||||
|
|
||||||
|
|
||||||
def get_inference_context(module_name : str, model_names : List[str], execution_device_id : str, execution_providers : List[ExecutionProvider]) -> str:
|
def get_inference_context(module_name : str, model_names : List[str], execution_device_id : int, execution_providers : List[ExecutionProvider]) -> str:
|
||||||
inference_context = '.'.join([ module_name ] + model_names + [ execution_device_id ] + list(execution_providers))
|
inference_context = '.'.join([ module_name ] + model_names + [ str(execution_device_id) ] + list(execution_providers))
|
||||||
return inference_context
|
return inference_context
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+23
-49
@@ -10,30 +10,34 @@ from types import FrameType
|
|||||||
from facefusion import metadata
|
from facefusion import metadata
|
||||||
from facefusion.common_helper import is_linux, is_windows
|
from facefusion.common_helper import is_linux, is_windows
|
||||||
|
|
||||||
LOCALS =\
|
LOCALES =\
|
||||||
{
|
{
|
||||||
'install_dependency': 'install the {dependency} package',
|
'install_dependency': 'install the {dependency} package',
|
||||||
|
'force_reinstall': 'force reinstall of packages',
|
||||||
'skip_conda': 'skip the conda environment check',
|
'skip_conda': 'skip the conda environment check',
|
||||||
'conda_not_activated': 'conda is not activated'
|
'conda_not_activated': 'conda is not activated'
|
||||||
}
|
}
|
||||||
ONNXRUNTIME_SET =\
|
ONNXRUNTIME_SET =\
|
||||||
{
|
{
|
||||||
'default': ('onnxruntime', '1.23.2')
|
'default': ('onnxruntime', '1.24.4')
|
||||||
}
|
}
|
||||||
if is_windows() or is_linux():
|
if is_windows() or is_linux():
|
||||||
ONNXRUNTIME_SET['cuda'] = ('onnxruntime-gpu', '1.23.2')
|
ONNXRUNTIME_SET['cuda'] = ('onnxruntime-gpu', '1.24.4')
|
||||||
ONNXRUNTIME_SET['openvino'] = ('onnxruntime-openvino', '1.23.0')
|
ONNXRUNTIME_SET['openvino'] = ('onnxruntime-openvino', '1.24.1')
|
||||||
if is_windows():
|
if is_windows():
|
||||||
ONNXRUNTIME_SET['directml'] = ('onnxruntime-directml', '1.23.0')
|
ONNXRUNTIME_SET['directml'] = ('onnxruntime-directml', '1.24.4')
|
||||||
|
ONNXRUNTIME_SET['qnn'] = ('onnxruntime-qnn', '1.24.4')
|
||||||
if is_linux():
|
if is_linux():
|
||||||
ONNXRUNTIME_SET['rocm'] = ('onnxruntime-rocm', '1.21.0')
|
ONNXRUNTIME_SET['migraphx'] = ('onnxruntime-migraphx', '1.24.2')
|
||||||
|
ONNXRUNTIME_SET['rocm'] = ('onnxruntime-rocm', '1.22.2.post1')
|
||||||
|
|
||||||
|
|
||||||
def cli() -> None:
|
def cli() -> None:
|
||||||
signal.signal(signal.SIGINT, signal_exit)
|
signal.signal(signal.SIGINT, signal_exit)
|
||||||
program = ArgumentParser(formatter_class = partial(HelpFormatter, max_help_position = 50))
|
program = ArgumentParser(formatter_class = partial(HelpFormatter, max_help_position = 50))
|
||||||
program.add_argument('--onnxruntime', help = LOCALS.get('install_dependency').format(dependency = 'onnxruntime'), choices = ONNXRUNTIME_SET.keys(), required = True)
|
program.add_argument('--onnxruntime', help = LOCALES.get('install_dependency').format(dependency = 'onnxruntime'), choices = ONNXRUNTIME_SET.keys(), required = True)
|
||||||
program.add_argument('--skip-conda', help = LOCALS.get('skip_conda'), action = 'store_true')
|
program.add_argument('--force-reinstall', help = LOCALES.get('force_reinstall'), action = 'store_true')
|
||||||
|
program.add_argument('--skip-conda', help = LOCALES.get('skip_conda'), action = 'store_true')
|
||||||
program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version')
|
program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version')
|
||||||
run(program)
|
run(program)
|
||||||
|
|
||||||
@@ -45,56 +49,26 @@ def signal_exit(signum : int, frame : FrameType) -> None:
|
|||||||
def run(program : ArgumentParser) -> None:
|
def run(program : ArgumentParser) -> None:
|
||||||
args = program.parse_args()
|
args = program.parse_args()
|
||||||
has_conda = 'CONDA_PREFIX' in os.environ
|
has_conda = 'CONDA_PREFIX' in os.environ
|
||||||
onnxruntime_name, onnxruntime_version = ONNXRUNTIME_SET.get(args.onnxruntime)
|
|
||||||
|
|
||||||
if not args.skip_conda and not has_conda:
|
if not args.skip_conda and not has_conda:
|
||||||
sys.stdout.write(LOCALS.get('conda_not_activated') + os.linesep)
|
sys.stdout.write(LOCALES.get('conda_not_activated') + os.linesep)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
commands = [ shutil.which('pip'), 'install' ]
|
||||||
|
|
||||||
|
if args.force_reinstall:
|
||||||
|
commands.append('--force-reinstall')
|
||||||
|
|
||||||
with open('requirements.txt') as file:
|
with open('requirements.txt') as file:
|
||||||
|
|
||||||
for line in file.readlines():
|
for line in file.readlines():
|
||||||
__line__ = line.strip()
|
__line__ = line.strip()
|
||||||
if not __line__.startswith('onnxruntime'):
|
if not __line__.startswith('onnxruntime'):
|
||||||
subprocess.call([ shutil.which('pip'), 'install', line, '--force-reinstall' ])
|
commands.append(__line__)
|
||||||
|
|
||||||
if args.onnxruntime == 'rocm':
|
onnxruntime_name, onnxruntime_version = ONNXRUNTIME_SET.get(args.onnxruntime)
|
||||||
python_id = 'cp' + str(sys.version_info.major) + str(sys.version_info.minor)
|
commands.append(onnxruntime_name + '==' + onnxruntime_version)
|
||||||
|
|
||||||
if python_id in [ 'cp310', 'cp312' ]:
|
subprocess.call([ shutil.which('pip'), 'uninstall', 'onnxruntime', onnxruntime_name, '-y', '-q' ])
|
||||||
wheel_name = 'onnxruntime_rocm-' + onnxruntime_version + '-' + python_id + '-' + python_id + '-linux_x86_64.whl'
|
|
||||||
wheel_url = 'https://repo.radeon.com/rocm/manylinux/rocm-rel-6.4/' + wheel_name
|
|
||||||
subprocess.call([ shutil.which('pip'), 'install', wheel_url, '--force-reinstall' ])
|
|
||||||
else:
|
|
||||||
subprocess.call([ shutil.which('pip'), 'install', onnxruntime_name + '==' + onnxruntime_version, '--force-reinstall' ])
|
|
||||||
|
|
||||||
if args.onnxruntime == 'cuda' and has_conda:
|
|
||||||
library_paths = []
|
|
||||||
|
|
||||||
if is_linux():
|
|
||||||
if os.getenv('LD_LIBRARY_PATH'):
|
|
||||||
library_paths = os.getenv('LD_LIBRARY_PATH').split(os.pathsep)
|
|
||||||
|
|
||||||
python_id = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
|
|
||||||
library_paths.extend(
|
|
||||||
[
|
|
||||||
os.path.join(os.getenv('CONDA_PREFIX'), 'lib'),
|
|
||||||
os.path.join(os.getenv('CONDA_PREFIX'), 'lib', python_id, 'site-packages', 'tensorrt_libs')
|
|
||||||
])
|
|
||||||
library_paths = list(dict.fromkeys([ library_path for library_path in library_paths if os.path.exists(library_path) ]))
|
|
||||||
|
|
||||||
subprocess.call([ shutil.which('conda'), 'env', 'config', 'vars', 'set', 'LD_LIBRARY_PATH=' + os.pathsep.join(library_paths) ])
|
|
||||||
|
|
||||||
if is_windows():
|
|
||||||
if os.getenv('PATH'):
|
|
||||||
library_paths = os.getenv('PATH').split(os.pathsep)
|
|
||||||
|
|
||||||
library_paths.extend(
|
|
||||||
[
|
|
||||||
os.path.join(os.getenv('CONDA_PREFIX'), 'Lib'),
|
|
||||||
os.path.join(os.getenv('CONDA_PREFIX'), 'Lib', 'site-packages', 'tensorrt_libs')
|
|
||||||
])
|
|
||||||
library_paths = list(dict.fromkeys([ library_path for library_path in library_paths if os.path.exists(library_path) ]))
|
|
||||||
|
|
||||||
subprocess.call([ shutil.which('conda'), 'env', 'config', 'vars', 'set', 'PATH=' + os.pathsep.join(library_paths) ])
|
|
||||||
|
|
||||||
|
subprocess.call(commands)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -189,7 +189,7 @@ LOCALS : Locals =\
|
|||||||
},
|
},
|
||||||
'about':
|
'about':
|
||||||
{
|
{
|
||||||
'fund': 'fund training server',
|
'fund': 'fund ai workstation',
|
||||||
'subscribe': 'become a member',
|
'subscribe': 'become a member',
|
||||||
'join': 'join our community'
|
'join': 'join our community'
|
||||||
},
|
},
|
||||||
@@ -4,7 +4,7 @@ METADATA =\
|
|||||||
{
|
{
|
||||||
'name': 'FaceFusion',
|
'name': 'FaceFusion',
|
||||||
'description': 'Industry leading face manipulation platform',
|
'description': 'Industry leading face manipulation platform',
|
||||||
'version': '3.5.0',
|
'version': '3.6.1',
|
||||||
'license': 'OpenRAIL-AS',
|
'license': 'OpenRAIL-AS',
|
||||||
'author': 'Henry Ruhs',
|
'author': 'Henry Ruhs',
|
||||||
'url': 'https://facefusion.io'
|
'url': 'https://facefusion.io'
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ def normalize_space(spaces : Optional[List[int]]) -> Optional[Padding]:
|
|||||||
if spaces and len(spaces) == 1:
|
if spaces and len(spaces) == 1:
|
||||||
return tuple([spaces[0]] * 4) #type:ignore[return-value]
|
return tuple([spaces[0]] * 4) #type:ignore[return-value]
|
||||||
if spaces and len(spaces) == 2:
|
if spaces and len(spaces) == 2:
|
||||||
return tuple([spaces[0], spaces[1], spaces[0], spaces[1]]) #type:ignore[return-value]
|
return tuple([ spaces[0], spaces[1], spaces[0], spaces[1] ]) #type:ignore[return-value]
|
||||||
if spaces and len(spaces) == 3:
|
if spaces and len(spaces) == 3:
|
||||||
return tuple([spaces[0], spaces[1], spaces[2], spaces[1]]) #type:ignore[return-value]
|
return tuple([ spaces[0], spaces[1], spaces[2], spaces[1] ]) #type:ignore[return-value]
|
||||||
if spaces and len(spaces) == 4:
|
if spaces and len(spaces) == 4:
|
||||||
return tuple(spaces) #type:ignore[return-value]
|
return tuple(spaces) #type:ignore[return-value]
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
from facefusion.processors.modules.age_modifier.choices import age_modifier_direction_range, age_modifier_models # noqa: F401
|
|
||||||
from facefusion.processors.modules.background_remover.choices import background_remover_color_range, background_remover_models # noqa: F401
|
|
||||||
from facefusion.processors.modules.deep_swapper.choices import deep_swapper_models, deep_swapper_morph_range # noqa: F401
|
|
||||||
from facefusion.processors.modules.expression_restorer.choices import expression_restorer_areas, expression_restorer_factor_range, expression_restorer_models # noqa: F401
|
|
||||||
from facefusion.processors.modules.face_debugger.choices import face_debugger_items # noqa: F401
|
|
||||||
from facefusion.processors.modules.face_editor.choices import ( # noqa: F401
|
|
||||||
face_editor_eye_gaze_horizontal_range,
|
|
||||||
face_editor_eye_gaze_vertical_range,
|
|
||||||
face_editor_eye_open_ratio_range,
|
|
||||||
face_editor_eyebrow_direction_range,
|
|
||||||
face_editor_head_pitch_range,
|
|
||||||
face_editor_head_roll_range,
|
|
||||||
face_editor_head_yaw_range,
|
|
||||||
face_editor_lip_open_ratio_range,
|
|
||||||
face_editor_models,
|
|
||||||
face_editor_mouth_grim_range,
|
|
||||||
face_editor_mouth_position_horizontal_range,
|
|
||||||
face_editor_mouth_position_vertical_range,
|
|
||||||
face_editor_mouth_pout_range,
|
|
||||||
face_editor_mouth_purse_range,
|
|
||||||
face_editor_mouth_smile_range,
|
|
||||||
)
|
|
||||||
from facefusion.processors.modules.face_enhancer.choices import face_enhancer_blend_range, face_enhancer_models, face_enhancer_weight_range # noqa: F401
|
|
||||||
from facefusion.processors.modules.face_swapper.choices import face_swapper_models, face_swapper_set, face_swapper_weight_range # noqa: F401
|
|
||||||
from facefusion.processors.modules.frame_colorizer.choices import frame_colorizer_blend_range, frame_colorizer_models, frame_colorizer_sizes # noqa: F401
|
|
||||||
from facefusion.processors.modules.frame_enhancer.choices import frame_enhancer_blend_range, frame_enhancer_models # noqa: F401
|
|
||||||
from facefusion.processors.modules.lip_syncer.choices import lip_syncer_models, lip_syncer_weight_range # noqa: F401
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_int_range
|
from facefusion.common_helper import create_int_range
|
||||||
from facefusion.processors.modules.age_modifier.types import AgeModifierModel
|
from facefusion.processors.modules.age_modifier.types import AgeModifierModel
|
||||||
|
|
||||||
age_modifier_models : List[AgeModifierModel] = [ 'styleganex_age' ]
|
age_modifier_models : List[AgeModifierModel] = list(get_args(AgeModifierModel))
|
||||||
|
|
||||||
age_modifier_direction_range : Sequence[int] = create_int_range(-100, 100, 1)
|
age_modifier_direction_range : Sequence[int] = create_int_range(-100, 100, 1)
|
||||||
|
|||||||
@@ -29,6 +29,41 @@ from facefusion.vision import match_frame_color, read_static_image, read_static_
|
|||||||
def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
||||||
return\
|
return\
|
||||||
{
|
{
|
||||||
|
'fran':
|
||||||
|
{
|
||||||
|
'__metadata__':
|
||||||
|
{
|
||||||
|
'vendor': 'ry-lu',
|
||||||
|
'license': 'mit',
|
||||||
|
'year': 2024
|
||||||
|
},
|
||||||
|
'hashes':
|
||||||
|
{
|
||||||
|
'age_modifier':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'fran.hash'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/fran.hash')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'sources':
|
||||||
|
{
|
||||||
|
'age_modifier':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'fran.onnx'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/fran.onnx')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'templates':
|
||||||
|
{
|
||||||
|
'target': 'ffhq_512',
|
||||||
|
},
|
||||||
|
'sizes':
|
||||||
|
{
|
||||||
|
'target': (1024, 1024),
|
||||||
|
},
|
||||||
|
'mean': [ 0.0, 0.0, 0.0 ],
|
||||||
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
|
},
|
||||||
'styleganex_age':
|
'styleganex_age':
|
||||||
{
|
{
|
||||||
'__metadata__':
|
'__metadata__':
|
||||||
@@ -62,7 +97,9 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
{
|
{
|
||||||
'target': (256, 256),
|
'target': (256, 256),
|
||||||
'target_with_background': (384, 384)
|
'target_with_background': (384, 384)
|
||||||
}
|
},
|
||||||
|
'mean': [ 0.5, 0.5, 0.5 ],
|
||||||
|
'standard_deviation': [ 0.5, 0.5, 0.5 ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +124,7 @@ def get_model_options() -> ModelOptions:
|
|||||||
def register_args(program : ArgumentParser) -> None:
|
def register_args(program : ArgumentParser) -> None:
|
||||||
group_processors = find_argument_group(program, 'processors')
|
group_processors = find_argument_group(program, 'processors')
|
||||||
if group_processors:
|
if group_processors:
|
||||||
group_processors.add_argument('--age-modifier-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'age_modifier_model', 'styleganex_age'), choices = age_modifier_choices.age_modifier_models)
|
group_processors.add_argument('--age-modifier-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'age_modifier_model', 'fran'), choices = age_modifier_choices.age_modifier_models)
|
||||||
group_processors.add_argument('--age-modifier-direction', help = translator.get('help.direction', __package__), type = int, default = config.get_int_value('processors', 'age_modifier_direction', '0'), choices = age_modifier_choices.age_modifier_direction_range, metavar = create_int_metavar(age_modifier_choices.age_modifier_direction_range))
|
group_processors.add_argument('--age-modifier-direction', help = translator.get('help.direction', __package__), type = int, default = config.get_int_value('processors', 'age_modifier_direction', '0'), choices = age_modifier_choices.age_modifier_direction_range, metavar = create_int_metavar(age_modifier_choices.age_modifier_direction_range))
|
||||||
facefusion.jobs.job_store.register_step_keys([ 'age_modifier_model', 'age_modifier_direction' ])
|
facefusion.jobs.job_store.register_step_keys([ 'age_modifier_model', 'age_modifier_direction' ])
|
||||||
|
|
||||||
@@ -137,32 +174,57 @@ def modify_age(target_face : Face, temp_vision_frame : VisionFrame) -> VisionFra
|
|||||||
model_sizes = get_model_options().get('sizes')
|
model_sizes = get_model_options().get('sizes')
|
||||||
face_landmark_5 = target_face.landmark_set.get('5/68').copy()
|
face_landmark_5 = target_face.landmark_set.get('5/68').copy()
|
||||||
crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, face_landmark_5, model_templates.get('target'), model_sizes.get('target'))
|
crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, face_landmark_5, model_templates.get('target'), model_sizes.get('target'))
|
||||||
extend_face_landmark_5 = scale_face_landmark_5(face_landmark_5, 0.875)
|
|
||||||
extend_vision_frame, extend_affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, extend_face_landmark_5, model_templates.get('target_with_background'), model_sizes.get('target_with_background'))
|
|
||||||
extend_vision_frame_raw = extend_vision_frame.copy()
|
|
||||||
box_mask = create_box_mask(extend_vision_frame, state_manager.get_item('face_mask_blur'), (0, 0, 0, 0))
|
|
||||||
crop_masks =\
|
|
||||||
[
|
|
||||||
box_mask
|
|
||||||
]
|
|
||||||
|
|
||||||
if 'occlusion' in state_manager.get_item('face_mask_types'):
|
if state_manager.get_item('age_modifier_model') == 'fran':
|
||||||
occlusion_mask = create_occlusion_mask(crop_vision_frame)
|
box_mask = create_box_mask(crop_vision_frame, state_manager.get_item('face_mask_blur'), (0, 0, 0, 0))
|
||||||
temp_matrix = merge_matrix([ extend_affine_matrix, cv2.invertAffineTransform(affine_matrix) ])
|
crop_masks =\
|
||||||
occlusion_mask = cv2.warpAffine(occlusion_mask, temp_matrix, model_sizes.get('target_with_background'))
|
[
|
||||||
crop_masks.append(occlusion_mask)
|
box_mask
|
||||||
|
]
|
||||||
|
|
||||||
crop_vision_frame = prepare_vision_frame(crop_vision_frame)
|
if 'occlusion' in state_manager.get_item('face_mask_types'):
|
||||||
extend_vision_frame = prepare_vision_frame(extend_vision_frame)
|
occlusion_mask = create_occlusion_mask(crop_vision_frame)
|
||||||
age_modifier_direction = numpy.array(numpy.interp(state_manager.get_item('age_modifier_direction'), [ -100, 100 ], [ 2.5, -2.5 ])).astype(numpy.float32)
|
crop_masks.append(occlusion_mask)
|
||||||
extend_vision_frame = forward(crop_vision_frame, extend_vision_frame, age_modifier_direction)
|
|
||||||
extend_vision_frame = normalize_extend_frame(extend_vision_frame)
|
crop_vision_frame = prepare_vision_frame(crop_vision_frame)
|
||||||
extend_vision_frame = match_frame_color(extend_vision_frame_raw, extend_vision_frame)
|
target_age = numpy.mean(target_face.age)
|
||||||
extend_affine_matrix *= (model_sizes.get('target')[0] * 4) / model_sizes.get('target_with_background')[0]
|
age_modifier_direction = numpy.array([ target_age, target_age + state_manager.get_item('age_modifier_direction') ], dtype = numpy.float32) / 100
|
||||||
crop_mask = numpy.minimum.reduce(crop_masks).clip(0, 1)
|
age_modifier_direction = age_modifier_direction.clip(0, 1)
|
||||||
crop_mask = cv2.resize(crop_mask, (model_sizes.get('target')[0] * 4, model_sizes.get('target')[1] * 4))
|
crop_vision_frame = forward(crop_vision_frame, crop_vision_frame, age_modifier_direction)
|
||||||
paste_vision_frame = paste_back(temp_vision_frame, extend_vision_frame, crop_mask, extend_affine_matrix)
|
crop_vision_frame = normalize_vision_frame(crop_vision_frame)
|
||||||
return paste_vision_frame
|
crop_mask = numpy.minimum.reduce(crop_masks).clip(0, 1)
|
||||||
|
paste_vision_frame = paste_back(temp_vision_frame, crop_vision_frame, crop_mask, affine_matrix)
|
||||||
|
return paste_vision_frame
|
||||||
|
|
||||||
|
if state_manager.get_item('age_modifier_model') == 'styleganex_age':
|
||||||
|
extend_face_landmark_5 = scale_face_landmark_5(face_landmark_5, 0.875)
|
||||||
|
extend_vision_frame, extend_affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, extend_face_landmark_5, model_templates.get('target_with_background'), model_sizes.get('target_with_background'))
|
||||||
|
extend_vision_frame_raw = extend_vision_frame.copy()
|
||||||
|
box_mask = create_box_mask(extend_vision_frame, state_manager.get_item('face_mask_blur'), (0, 0, 0, 0))
|
||||||
|
crop_masks =\
|
||||||
|
[
|
||||||
|
box_mask
|
||||||
|
]
|
||||||
|
|
||||||
|
if 'occlusion' in state_manager.get_item('face_mask_types'):
|
||||||
|
occlusion_mask = create_occlusion_mask(crop_vision_frame)
|
||||||
|
temp_matrix = merge_matrix([ extend_affine_matrix, cv2.invertAffineTransform(affine_matrix) ])
|
||||||
|
occlusion_mask = cv2.warpAffine(occlusion_mask, temp_matrix, model_sizes.get('target_with_background'))
|
||||||
|
crop_masks.append(occlusion_mask)
|
||||||
|
|
||||||
|
crop_vision_frame = prepare_vision_frame(crop_vision_frame)
|
||||||
|
extend_vision_frame = prepare_vision_frame(extend_vision_frame)
|
||||||
|
age_modifier_direction = numpy.array(numpy.interp(state_manager.get_item('age_modifier_direction'), [ -100, 100 ], [ 2.5, -2.5 ])).astype(numpy.float32)
|
||||||
|
extend_vision_frame = forward(crop_vision_frame, extend_vision_frame, age_modifier_direction)
|
||||||
|
extend_vision_frame = normalize_extend_frame(extend_vision_frame)
|
||||||
|
extend_vision_frame = match_frame_color(extend_vision_frame_raw, extend_vision_frame)
|
||||||
|
extend_affine_matrix *= (model_sizes.get('target')[0] * 4) / model_sizes.get('target_with_background')[0]
|
||||||
|
crop_mask = numpy.minimum.reduce(crop_masks).clip(0, 1)
|
||||||
|
crop_mask = cv2.resize(crop_mask, (model_sizes.get('target')[0] * 4, model_sizes.get('target')[1] * 4))
|
||||||
|
paste_vision_frame = paste_back(temp_vision_frame, extend_vision_frame, crop_mask, extend_affine_matrix)
|
||||||
|
return paste_vision_frame
|
||||||
|
|
||||||
|
return temp_vision_frame
|
||||||
|
|
||||||
|
|
||||||
def forward(crop_vision_frame : VisionFrame, extend_vision_frame : VisionFrame, age_modifier_direction : AgeModifierDirection) -> VisionFrame:
|
def forward(crop_vision_frame : VisionFrame, extend_vision_frame : VisionFrame, age_modifier_direction : AgeModifierDirection) -> VisionFrame:
|
||||||
@@ -187,12 +249,24 @@ def forward(crop_vision_frame : VisionFrame, extend_vision_frame : VisionFrame,
|
|||||||
|
|
||||||
|
|
||||||
def prepare_vision_frame(vision_frame : VisionFrame) -> VisionFrame:
|
def prepare_vision_frame(vision_frame : VisionFrame) -> VisionFrame:
|
||||||
|
model_mean = get_model_options().get('mean')
|
||||||
|
model_standard_deviation = get_model_options().get('standard_deviation')
|
||||||
vision_frame = vision_frame[:, :, ::-1] / 255.0
|
vision_frame = vision_frame[:, :, ::-1] / 255.0
|
||||||
vision_frame = (vision_frame - 0.5) / 0.5
|
vision_frame = (vision_frame - model_mean) / model_standard_deviation
|
||||||
vision_frame = numpy.expand_dims(vision_frame.transpose(2, 0, 1), axis = 0).astype(numpy.float32)
|
vision_frame = numpy.expand_dims(vision_frame.transpose(2, 0, 1), axis = 0).astype(numpy.float32)
|
||||||
return vision_frame
|
return vision_frame
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_vision_frame(vision_frame : VisionFrame) -> VisionFrame:
|
||||||
|
model_mean = get_model_options().get('mean')
|
||||||
|
model_standard_deviation = get_model_options().get('standard_deviation')
|
||||||
|
vision_frame = vision_frame.transpose(1, 2, 0)
|
||||||
|
vision_frame = vision_frame * model_standard_deviation + model_mean
|
||||||
|
vision_frame = vision_frame.clip(0, 1)
|
||||||
|
vision_frame = vision_frame[:, :, ::-1] * 255
|
||||||
|
return vision_frame
|
||||||
|
|
||||||
|
|
||||||
def normalize_extend_frame(extend_vision_frame : VisionFrame) -> VisionFrame:
|
def normalize_extend_frame(extend_vision_frame : VisionFrame) -> VisionFrame:
|
||||||
model_sizes = get_model_options().get('sizes')
|
model_sizes = get_model_options().get('sizes')
|
||||||
extend_vision_frame = numpy.clip(extend_vision_frame, -1, 1)
|
extend_vision_frame = numpy.clip(extend_vision_frame, -1, 1)
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -12,6 +12,6 @@ AgeModifierInputs = TypedDict('AgeModifierInputs',
|
|||||||
'temp_vision_mask' : Mask
|
'temp_vision_mask' : Mask
|
||||||
})
|
})
|
||||||
|
|
||||||
AgeModifierModel = Literal['styleganex_age']
|
AgeModifierModel = Literal['fran', 'styleganex_age']
|
||||||
|
|
||||||
AgeModifierDirection : TypeAlias = NDArray[Any]
|
AgeModifierDirection : TypeAlias = NDArray[Any]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_int_range
|
from facefusion.common_helper import create_int_range
|
||||||
from facefusion.processors.modules.background_remover.types import BackgroundRemoverModel
|
from facefusion.processors.modules.background_remover.types import BackgroundRemoverModel
|
||||||
|
|
||||||
background_remover_models : List[BackgroundRemoverModel] = [ 'ben_2', 'birefnet_general', 'birefnet_portrait', 'isnet_general', 'modnet', 'ormbg', 'rmbg_1.4', 'rmbg_2.0', 'silueta', 'u2net_cloth', 'u2net_general', 'u2net_human', 'u2netp' ]
|
background_remover_models : List[BackgroundRemoverModel] = list(get_args(BackgroundRemoverModel))
|
||||||
|
|
||||||
background_remover_color_range : Sequence[int] = create_int_range(0, 255, 1)
|
background_remover_color_range : Sequence[int] = create_int_range(0, 255, 1)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import numpy
|
|||||||
import facefusion.jobs.job_manager
|
import facefusion.jobs.job_manager
|
||||||
import facefusion.jobs.job_store
|
import facefusion.jobs.job_store
|
||||||
from facefusion import config, content_analyser, inference_manager, logger, state_manager, translator, video_manager
|
from facefusion import config, content_analyser, inference_manager, logger, state_manager, translator, video_manager
|
||||||
from facefusion.common_helper import is_macos
|
from facefusion.common_helper import is_macos, is_windows
|
||||||
from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url
|
from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url
|
||||||
from facefusion.execution import has_execution_provider
|
from facefusion.execution import has_execution_provider
|
||||||
from facefusion.filesystem import in_directory, is_image, is_video, resolve_relative_path, same_file_extension
|
from facefusion.filesystem import in_directory, is_image, is_video, resolve_relative_path, same_file_extension
|
||||||
@@ -51,6 +51,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/ben_2.onnx')
|
'path': resolve_relative_path('../.assets/models/ben_2.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'ben',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.0, 0.0, 0.0 ],
|
'mean': [ 0.0, 0.0, 0.0 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
@@ -79,6 +80,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/birefnet_general.onnx')
|
'path': resolve_relative_path('../.assets/models/birefnet_general.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'birefnet',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.0, 0.0, 0.0 ],
|
'mean': [ 0.0, 0.0, 0.0 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
@@ -107,10 +109,69 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/birefnet_portrait.onnx')
|
'path': resolve_relative_path('../.assets/models/birefnet_portrait.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'birefnet',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.0, 0.0, 0.0 ],
|
'mean': [ 0.0, 0.0, 0.0 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
},
|
},
|
||||||
|
'corridor_key_1024':
|
||||||
|
{
|
||||||
|
'__metadata__':
|
||||||
|
{
|
||||||
|
'vendor': 'nikopueringer',
|
||||||
|
'license': 'Non-Commercial',
|
||||||
|
'year': 2025
|
||||||
|
},
|
||||||
|
'hashes':
|
||||||
|
{
|
||||||
|
'background_remover':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'corridor_key_1024.hash'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/corridor_key_1024.hash')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'sources':
|
||||||
|
{
|
||||||
|
'background_remover':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'corridor_key_1024.onnx'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/corridor_key_1024.onnx')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'type': 'corridor_key',
|
||||||
|
'size': (1024, 1024),
|
||||||
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
|
},
|
||||||
|
'corridor_key_2048':
|
||||||
|
{
|
||||||
|
'__metadata__':
|
||||||
|
{
|
||||||
|
'vendor': 'nikopueringer',
|
||||||
|
'license': 'Non-Commercial',
|
||||||
|
'year': 2025
|
||||||
|
},
|
||||||
|
'hashes':
|
||||||
|
{
|
||||||
|
'background_remover':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'corridor_key_2048.hash'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/corridor_key_2048.hash')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'sources':
|
||||||
|
{
|
||||||
|
'background_remover':
|
||||||
|
{
|
||||||
|
'url': resolve_download_url('models-3.6.0', 'corridor_key_2048.onnx'),
|
||||||
|
'path': resolve_relative_path('../.assets/models/corridor_key_2048.onnx')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'type': 'corridor_key',
|
||||||
|
'size': (2048, 2048),
|
||||||
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
|
},
|
||||||
'isnet_general':
|
'isnet_general':
|
||||||
{
|
{
|
||||||
'__metadata__':
|
'__metadata__':
|
||||||
@@ -135,6 +196,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/isnet_general.onnx')
|
'path': resolve_relative_path('../.assets/models/isnet_general.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'isnet',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.5, 0.5, 0.5 ],
|
'mean': [ 0.5, 0.5, 0.5 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
@@ -163,6 +225,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/modnet.onnx')
|
'path': resolve_relative_path('../.assets/models/modnet.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'modnet',
|
||||||
'size': (512, 512),
|
'size': (512, 512),
|
||||||
'mean': [ 0.5, 0.5, 0.5 ],
|
'mean': [ 0.5, 0.5, 0.5 ],
|
||||||
'standard_deviation': [ 0.5, 0.5, 0.5 ]
|
'standard_deviation': [ 0.5, 0.5, 0.5 ]
|
||||||
@@ -191,6 +254,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/ormbg.onnx')
|
'path': resolve_relative_path('../.assets/models/ormbg.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'ormbg',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.0, 0.0, 0.0 ],
|
'mean': [ 0.0, 0.0, 0.0 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
@@ -219,6 +283,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/rmbg_1.4.onnx')
|
'path': resolve_relative_path('../.assets/models/rmbg_1.4.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'rmbg',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.5, 0.5, 0.5 ],
|
'mean': [ 0.5, 0.5, 0.5 ],
|
||||||
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
'standard_deviation': [ 1.0, 1.0, 1.0 ]
|
||||||
@@ -247,6 +312,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/rmbg_2.0.onnx')
|
'path': resolve_relative_path('../.assets/models/rmbg_2.0.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'rmbg',
|
||||||
'size': (1024, 1024),
|
'size': (1024, 1024),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -275,6 +341,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/silueta.onnx')
|
'path': resolve_relative_path('../.assets/models/silueta.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'silueta',
|
||||||
'size': (320, 320),
|
'size': (320, 320),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -303,6 +370,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/u2net_cloth.onnx')
|
'path': resolve_relative_path('../.assets/models/u2net_cloth.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'u2net_cloth',
|
||||||
'size': (768, 768),
|
'size': (768, 768),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -331,6 +399,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/u2net_general.onnx')
|
'path': resolve_relative_path('../.assets/models/u2net_general.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'u2net',
|
||||||
'size': (320, 320),
|
'size': (320, 320),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -359,6 +428,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/u2net_human.onnx')
|
'path': resolve_relative_path('../.assets/models/u2net_human.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'u2net',
|
||||||
'size': (320, 320),
|
'size': (320, 320),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -387,6 +457,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/u2netp.onnx')
|
'path': resolve_relative_path('../.assets/models/u2netp.onnx')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'type': 'u2netp',
|
||||||
'size': (320, 320),
|
'size': (320, 320),
|
||||||
'mean': [ 0.485, 0.456, 0.406 ],
|
'mean': [ 0.485, 0.456, 0.406 ],
|
||||||
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
'standard_deviation': [ 0.229, 0.224, 0.225 ]
|
||||||
@@ -407,7 +478,9 @@ def clear_inference_pool() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def resolve_execution_providers() -> List[ExecutionProvider]:
|
def resolve_execution_providers() -> List[ExecutionProvider]:
|
||||||
if is_macos() and has_execution_provider('coreml'):
|
model_type = get_model_options().get('type')
|
||||||
|
|
||||||
|
if is_macos() and has_execution_provider('coreml') or is_windows() and has_execution_provider('directml') and model_type == 'corridor_key':
|
||||||
return [ 'cpu' ]
|
return [ 'cpu' ]
|
||||||
return state_manager.get_item('execution_providers')
|
return state_manager.get_item('execution_providers')
|
||||||
|
|
||||||
@@ -420,14 +493,16 @@ def get_model_options() -> ModelOptions:
|
|||||||
def register_args(program : ArgumentParser) -> None:
|
def register_args(program : ArgumentParser) -> None:
|
||||||
group_processors = find_argument_group(program, 'processors')
|
group_processors = find_argument_group(program, 'processors')
|
||||||
if group_processors:
|
if group_processors:
|
||||||
group_processors.add_argument('--background-remover-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'background_remover_model', 'rmbg_2.0'), choices = background_remover_choices.background_remover_models)
|
group_processors.add_argument('--background-remover-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'background_remover_model', 'modnet'), choices = background_remover_choices.background_remover_models)
|
||||||
group_processors.add_argument('--background-remover-color', help = translator.get('help.color', __package__), type = partial(sanitize_int_range, int_range = background_remover_choices.background_remover_color_range), default = config.get_int_list('processors', 'background_remover_color', '0 0 0 0'), nargs ='+')
|
group_processors.add_argument('--background-remover-fill-color', help = translator.get('help.fill_color', __package__), type = partial(sanitize_int_range, int_range = background_remover_choices.background_remover_color_range), default = config.get_int_list('processors', 'background_remover_fill_color', '0 0 0 0'), nargs = '+')
|
||||||
facefusion.jobs.job_store.register_step_keys([ 'background_remover_model', 'background_remover_color' ])
|
group_processors.add_argument('--background-remover-despill-color', help = translator.get('help.despill_color', __package__), type = partial(sanitize_int_range, int_range = background_remover_choices.background_remover_color_range), default = config.get_int_list('processors', 'background_remover_despill_color', '0 0 0 0'), nargs = '+')
|
||||||
|
facefusion.jobs.job_store.register_step_keys([ 'background_remover_model', 'background_remover_fill_color', 'background_remover_despill_color' ])
|
||||||
|
|
||||||
|
|
||||||
def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
|
def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
|
||||||
apply_state_item('background_remover_model', args.get('background_remover_model'))
|
apply_state_item('background_remover_model', args.get('background_remover_model'))
|
||||||
apply_state_item('background_remover_color', normalize_color(args.get('background_remover_color')))
|
apply_state_item('background_remover_fill_color', normalize_color(args.get('background_remover_fill_color')))
|
||||||
|
apply_state_item('background_remover_despill_color', normalize_color(args.get('background_remover_despill_color')))
|
||||||
|
|
||||||
|
|
||||||
def pre_check() -> bool:
|
def pre_check() -> bool:
|
||||||
@@ -461,16 +536,26 @@ def post_process() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def remove_background(temp_vision_frame : VisionFrame) -> Tuple[VisionFrame, Mask]:
|
def remove_background(temp_vision_frame : VisionFrame) -> Tuple[VisionFrame, Mask]:
|
||||||
temp_vision_mask = forward(prepare_temp_frame(temp_vision_frame))
|
model_type = get_model_options().get('type')
|
||||||
temp_vision_mask = normalize_vision_mask(temp_vision_mask)
|
|
||||||
temp_vision_mask = cv2.resize(temp_vision_mask, temp_vision_frame.shape[:2][::-1])
|
if model_type == 'corridor_key':
|
||||||
temp_vision_frame = apply_background_color(temp_vision_frame, temp_vision_mask)
|
remove_vision_mask, remove_vision_frame = forward_corridor_key(prepare_temp_frame(temp_vision_frame))
|
||||||
return temp_vision_frame, temp_vision_mask
|
remove_vision_frame = numpy.squeeze(remove_vision_frame).transpose(1, 2, 0)
|
||||||
|
remove_vision_frame = numpy.clip(remove_vision_frame * 255, 0, 255).astype(numpy.uint8)
|
||||||
|
temp_vision_frame = cv2.resize(remove_vision_frame[:, :, ::-1], temp_vision_frame.shape[:2][::-1])
|
||||||
|
else:
|
||||||
|
remove_vision_mask = forward(prepare_temp_frame(temp_vision_frame))
|
||||||
|
|
||||||
|
remove_vision_mask = normalize_vision_mask(remove_vision_mask)
|
||||||
|
remove_vision_mask = cv2.resize(remove_vision_mask, temp_vision_frame.shape[:2][::-1])
|
||||||
|
temp_vision_frame = apply_despill_color(temp_vision_frame)
|
||||||
|
temp_vision_frame = apply_fill_color(temp_vision_frame, remove_vision_mask)
|
||||||
|
return temp_vision_frame, remove_vision_mask
|
||||||
|
|
||||||
|
|
||||||
def forward(temp_vision_frame : VisionFrame) -> VisionFrame:
|
def forward(temp_vision_frame : VisionFrame) -> VisionFrame:
|
||||||
background_remover = get_inference_pool().get('background_remover')
|
background_remover = get_inference_pool().get('background_remover')
|
||||||
model_name = state_manager.get_item('background_remover_model')
|
model_type = get_model_options().get('type')
|
||||||
|
|
||||||
with thread_semaphore():
|
with thread_semaphore():
|
||||||
remove_vision_frame = background_remover.run(None,
|
remove_vision_frame = background_remover.run(None,
|
||||||
@@ -478,20 +563,42 @@ def forward(temp_vision_frame : VisionFrame) -> VisionFrame:
|
|||||||
'input': temp_vision_frame
|
'input': temp_vision_frame
|
||||||
})[0]
|
})[0]
|
||||||
|
|
||||||
if model_name == 'u2net_cloth':
|
if model_type == 'u2net_cloth':
|
||||||
remove_vision_frame = numpy.argmax(remove_vision_frame, axis = 1)
|
remove_vision_frame = numpy.argmax(remove_vision_frame, axis = 1)
|
||||||
|
|
||||||
return remove_vision_frame
|
return remove_vision_frame
|
||||||
|
|
||||||
|
|
||||||
|
def forward_corridor_key(temp_vision_frame : VisionFrame) -> Tuple[Mask, VisionFrame]:
|
||||||
|
background_remover = get_inference_pool().get('background_remover')
|
||||||
|
|
||||||
|
with thread_semaphore():
|
||||||
|
remove_vision_mask, remove_vision_frame = background_remover.run(None,
|
||||||
|
{
|
||||||
|
'input': temp_vision_frame
|
||||||
|
})
|
||||||
|
|
||||||
|
return remove_vision_mask, remove_vision_frame
|
||||||
|
|
||||||
|
|
||||||
def prepare_temp_frame(temp_vision_frame : VisionFrame) -> VisionFrame:
|
def prepare_temp_frame(temp_vision_frame : VisionFrame) -> VisionFrame:
|
||||||
|
model_type = get_model_options().get('type')
|
||||||
model_size = get_model_options().get('size')
|
model_size = get_model_options().get('size')
|
||||||
model_mean = get_model_options().get('mean')
|
model_mean = get_model_options().get('mean')
|
||||||
model_standard_deviation = get_model_options().get('standard_deviation')
|
model_standard_deviation = get_model_options().get('standard_deviation')
|
||||||
|
|
||||||
|
if model_type == 'corridor_key':
|
||||||
|
coarse_color = temp_vision_frame[:, :, ::-1].astype(numpy.float32) / 255.0
|
||||||
|
coarse_bias = coarse_color[:, :, 1] - numpy.maximum(coarse_color[:, :, 0], coarse_color[:, :, 2])
|
||||||
|
coarse_vision_mask = cv2.resize(1.0 - numpy.clip(coarse_bias * 2.0, 0, 1), model_size)[:, :, numpy.newaxis]
|
||||||
|
|
||||||
temp_vision_frame = cv2.resize(temp_vision_frame, model_size)
|
temp_vision_frame = cv2.resize(temp_vision_frame, model_size)
|
||||||
temp_vision_frame = temp_vision_frame[:, :, ::-1] / 255.0
|
temp_vision_frame = temp_vision_frame[:, :, ::-1] / 255.0
|
||||||
temp_vision_frame = (temp_vision_frame - model_mean) / model_standard_deviation
|
temp_vision_frame = (temp_vision_frame - model_mean) / model_standard_deviation
|
||||||
|
|
||||||
|
if model_type == 'corridor_key':
|
||||||
|
temp_vision_frame = numpy.concatenate([ temp_vision_frame, coarse_vision_mask ], axis = 2)
|
||||||
|
|
||||||
temp_vision_frame = temp_vision_frame.transpose(2, 0, 1)
|
temp_vision_frame = temp_vision_frame.transpose(2, 0, 1)
|
||||||
temp_vision_frame = numpy.expand_dims(temp_vision_frame, axis = 0).astype(numpy.float32)
|
temp_vision_frame = numpy.expand_dims(temp_vision_frame, axis = 0).astype(numpy.float32)
|
||||||
return temp_vision_frame
|
return temp_vision_frame
|
||||||
@@ -503,16 +610,32 @@ def normalize_vision_mask(temp_vision_mask : Mask) -> Mask:
|
|||||||
return temp_vision_mask
|
return temp_vision_mask
|
||||||
|
|
||||||
|
|
||||||
def apply_background_color(temp_vision_frame : VisionFrame, temp_vision_mask : Mask) -> VisionFrame:
|
def apply_fill_color(temp_vision_frame : VisionFrame, temp_vision_mask : Mask) -> VisionFrame:
|
||||||
background_remover_color = state_manager.get_item('background_remover_color')
|
background_remover_fill_color = state_manager.get_item('background_remover_fill_color')
|
||||||
temp_vision_mask = temp_vision_mask.astype(numpy.float32) / 255
|
temp_vision_mask = temp_vision_mask.astype(numpy.float32) / 255
|
||||||
temp_vision_mask = numpy.expand_dims(temp_vision_mask, axis = 2)
|
temp_vision_mask = numpy.expand_dims(temp_vision_mask, axis = 2)
|
||||||
temp_vision_mask = (1 - temp_vision_mask) * background_remover_color[-1] / 255
|
temp_vision_mask = (1 - temp_vision_mask) * background_remover_fill_color[-1] / 255
|
||||||
color_frame = numpy.zeros_like(temp_vision_frame)
|
fill_vision_frame = numpy.zeros_like(temp_vision_frame)
|
||||||
color_frame[:, :, 0] = background_remover_color[2]
|
fill_vision_frame[:, :, 0] = background_remover_fill_color[2]
|
||||||
color_frame[:, :, 1] = background_remover_color[1]
|
fill_vision_frame[:, :, 1] = background_remover_fill_color[1]
|
||||||
color_frame[:, :, 2] = background_remover_color[0]
|
fill_vision_frame[:, :, 2] = background_remover_fill_color[0]
|
||||||
temp_vision_frame = temp_vision_frame * (1 - temp_vision_mask) + color_frame * temp_vision_mask
|
temp_vision_frame = temp_vision_frame * (1 - temp_vision_mask) + fill_vision_frame * temp_vision_mask
|
||||||
|
temp_vision_frame = temp_vision_frame.astype(numpy.uint8)
|
||||||
|
return temp_vision_frame
|
||||||
|
|
||||||
|
|
||||||
|
def apply_despill_color(temp_vision_frame : VisionFrame) -> VisionFrame:
|
||||||
|
background_remover_despill_color = state_manager.get_item('background_remover_despill_color')
|
||||||
|
temp_vision_frame = temp_vision_frame.astype(numpy.float32)
|
||||||
|
color_alpha = background_remover_despill_color[3] / 255.0
|
||||||
|
despill_vision_frame = numpy.zeros_like(temp_vision_frame)
|
||||||
|
despill_vision_frame[:, :, 0] = background_remover_despill_color[2]
|
||||||
|
despill_vision_frame[:, :, 1] = background_remover_despill_color[1]
|
||||||
|
despill_vision_frame[:, :, 2] = background_remover_despill_color[0]
|
||||||
|
color_weight = despill_vision_frame / numpy.maximum(numpy.max(background_remover_despill_color[:3]), 1)
|
||||||
|
color_limit = numpy.roll(temp_vision_frame, 1, 2) + numpy.roll(temp_vision_frame, -1, 2)
|
||||||
|
limit_vision_frame = numpy.minimum(temp_vision_frame, color_limit * 0.5)
|
||||||
|
temp_vision_frame = temp_vision_frame + (limit_vision_frame - temp_vision_frame) * color_alpha * color_weight
|
||||||
temp_vision_frame = temp_vision_frame.astype(numpy.uint8)
|
temp_vision_frame = temp_vision_frame.astype(numpy.uint8)
|
||||||
return temp_vision_frame
|
return temp_vision_frame
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from facefusion.types import Locales
|
||||||
|
|
||||||
|
LOCALES : Locales =\
|
||||||
|
{
|
||||||
|
'en':
|
||||||
|
{
|
||||||
|
'help':
|
||||||
|
{
|
||||||
|
'model': 'choose the model responsible for removing the background',
|
||||||
|
'fill_color': 'apply red, green, blue and alpha values to the background',
|
||||||
|
'despill_color': 'remove red, green, blue and alpha values from the foreground'
|
||||||
|
},
|
||||||
|
'uis':
|
||||||
|
{
|
||||||
|
'model_dropdown': 'BACKGROUND REMOVER MODEL',
|
||||||
|
'fill_color_red_number': 'FILL COLOR RED',
|
||||||
|
'fill_color_green_number': 'FILL COLOR GREEN',
|
||||||
|
'fill_color_blue_number': 'FILL COLOR BLUE',
|
||||||
|
'fill_color_alpha_number': 'FILL COLOR ALPHA',
|
||||||
|
'despill_color_red_number': 'DESPILL COLOR RED',
|
||||||
|
'despill_color_green_number': 'DESPILL COLOR GREEN',
|
||||||
|
'despill_color_blue_number': 'DESPILL COLOR BLUE',
|
||||||
|
'despill_color_alpha_number': 'DESPILL COLOR ALPHA'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
from facefusion.types import Locals
|
|
||||||
|
|
||||||
LOCALS : Locals =\
|
|
||||||
{
|
|
||||||
'en':
|
|
||||||
{
|
|
||||||
'help':
|
|
||||||
{
|
|
||||||
'model': 'choose the model responsible for removing the background',
|
|
||||||
'color': 'apply red, green blue and alpha values to the background'
|
|
||||||
},
|
|
||||||
'uis':
|
|
||||||
{
|
|
||||||
'model_dropdown': 'BACKGROUND REMOVER MODEL',
|
|
||||||
'color_red_number': 'BACKGROUND COLOR RED',
|
|
||||||
'color_green_number': 'BACKGROUND COLOR GREEN',
|
|
||||||
'color_blue_number': 'BACKGROUND COLOR BLUE',
|
|
||||||
'color_alpha_number': 'BACKGROUND COLOR ALPHA'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,4 +9,4 @@ BackgroundRemoverInputs = TypedDict('BackgroundRemoverInputs',
|
|||||||
'temp_vision_mask' : Mask
|
'temp_vision_mask' : Mask
|
||||||
})
|
})
|
||||||
|
|
||||||
BackgroundRemoverModel = Literal['ben_2', 'birefnet_general', 'birefnet_portrait', 'isnet_general', 'modnet', 'ormbg', 'rmbg_1.4', 'rmbg_2.0', 'silueta', 'u2net_cloth', 'u2net_general', 'u2net_human', 'u2netp']
|
BackgroundRemoverModel = Literal['ben_2', 'birefnet_general', 'birefnet_portrait', 'corridor_key_1024', 'corridor_key_2048', 'isnet_general', 'modnet', 'ormbg', 'rmbg_1.4', 'rmbg_2.0', 'silueta', 'u2net_cloth', 'u2net_general', 'u2net_human', 'u2netp']
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_int_range
|
from facefusion.common_helper import create_int_range
|
||||||
from facefusion.processors.modules.expression_restorer.types import ExpressionRestorerArea, ExpressionRestorerModel
|
from facefusion.processors.modules.expression_restorer.types import ExpressionRestorerArea, ExpressionRestorerModel
|
||||||
|
|
||||||
expression_restorer_models : List[ExpressionRestorerModel] = [ 'live_portrait' ]
|
expression_restorer_models : List[ExpressionRestorerModel] = list(get_args(ExpressionRestorerModel))
|
||||||
|
|
||||||
expression_restorer_areas : List[ExpressionRestorerArea] = [ 'upper-face', 'lower-face' ]
|
expression_restorer_areas : List[ExpressionRestorerArea] = list(get_args(ExpressionRestorerArea))
|
||||||
|
|
||||||
expression_restorer_factor_range : Sequence[int] = create_int_range(0, 100, 1)
|
expression_restorer_factor_range : Sequence[int] = create_int_range(0, 100, 1)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ def register_args(program : ArgumentParser) -> None:
|
|||||||
if group_processors:
|
if group_processors:
|
||||||
group_processors.add_argument('--expression-restorer-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'expression_restorer_model', 'live_portrait'), choices = expression_restorer_choices.expression_restorer_models)
|
group_processors.add_argument('--expression-restorer-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'expression_restorer_model', 'live_portrait'), choices = expression_restorer_choices.expression_restorer_models)
|
||||||
group_processors.add_argument('--expression-restorer-factor', help = translator.get('help.factor', __package__), type = int, default = config.get_int_value('processors', 'expression_restorer_factor', '80'), choices = expression_restorer_choices.expression_restorer_factor_range, metavar = create_int_metavar(expression_restorer_choices.expression_restorer_factor_range))
|
group_processors.add_argument('--expression-restorer-factor', help = translator.get('help.factor', __package__), type = int, default = config.get_int_value('processors', 'expression_restorer_factor', '80'), choices = expression_restorer_choices.expression_restorer_factor_range, metavar = create_int_metavar(expression_restorer_choices.expression_restorer_factor_range))
|
||||||
group_processors.add_argument('--expression-restorer-areas', help = translator.get('help.areas', __package__).format(choices = ', '.join(expression_restorer_choices.expression_restorer_areas)), default = config.get_str_list('processors', 'expression_restorer_areas', ' '.join(expression_restorer_choices.expression_restorer_areas)), choices = expression_restorer_choices.expression_restorer_areas, nargs ='+', metavar ='EXPRESSION_RESTORER_AREAS')
|
group_processors.add_argument('--expression-restorer-areas', help = translator.get('help.areas', __package__).format(choices = ', '.join(expression_restorer_choices.expression_restorer_areas)), default = config.get_str_list('processors', 'expression_restorer_areas', ' '.join(expression_restorer_choices.expression_restorer_areas)), choices = expression_restorer_choices.expression_restorer_areas, nargs = '+', metavar = 'EXPRESSION_RESTORER_AREAS')
|
||||||
facefusion.jobs.job_store.register_step_keys([ 'expression_restorer_model', 'expression_restorer_factor', 'expression_restorer_areas' ])
|
facefusion.jobs.job_store.register_step_keys([ 'expression_restorer_model', 'expression_restorer_factor', 'expression_restorer_areas' ])
|
||||||
|
|
||||||
|
|
||||||
@@ -192,12 +192,12 @@ def restrict_expression_areas(temp_expression : LivePortraitExpression, target_e
|
|||||||
expression_restorer_areas = state_manager.get_item('expression_restorer_areas')
|
expression_restorer_areas = state_manager.get_item('expression_restorer_areas')
|
||||||
|
|
||||||
if 'upper-face' not in expression_restorer_areas:
|
if 'upper-face' not in expression_restorer_areas:
|
||||||
target_expression[:, [1, 2, 6, 10, 11, 12, 13, 15, 16]] = temp_expression[:, [1, 2, 6, 10, 11, 12, 13, 15, 16]]
|
target_expression[:, [ 1, 2, 6, 10, 11, 12, 13, 15, 16 ]] = temp_expression[:, [ 1, 2, 6, 10, 11, 12, 13, 15, 16 ]]
|
||||||
|
|
||||||
if 'lower-face' not in expression_restorer_areas:
|
if 'lower-face' not in expression_restorer_areas:
|
||||||
target_expression[:, [3, 7, 14, 17, 18, 19, 20]] = temp_expression[:, [3, 7, 14, 17, 18, 19, 20]]
|
target_expression[:, [ 3, 7, 14, 17, 18, 19, 20 ]] = temp_expression[:, [ 3, 7, 14, 17, 18, 19, 20 ]]
|
||||||
|
|
||||||
target_expression[:, [0, 4, 5, 8, 9]] = temp_expression[:, [0, 4, 5, 8, 9]]
|
target_expression[:, [ 0, 4, 5, 8, 9 ]] = temp_expression[:, [ 0, 4, 5, 8, 9 ]]
|
||||||
return target_expression
|
return target_expression
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from typing import List
|
from typing import List, get_args
|
||||||
|
|
||||||
from facefusion.processors.modules.face_debugger.types import FaceDebuggerItem
|
from facefusion.processors.modules.face_debugger.types import FaceDebuggerItem
|
||||||
|
|
||||||
face_debugger_items : List[FaceDebuggerItem] = [ 'bounding-box', 'face-landmark-5', 'face-landmark-5/68', 'face-landmark-68', 'face-landmark-68/5', 'face-mask' ]
|
face_debugger_items : List[FaceDebuggerItem] = list(get_args(FaceDebuggerItem))
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_float_range
|
from facefusion.common_helper import create_float_range
|
||||||
from facefusion.processors.modules.face_editor.types import FaceEditorModel
|
from facefusion.processors.modules.face_editor.types import FaceEditorModel
|
||||||
|
|
||||||
face_editor_models : List[FaceEditorModel] = [ 'live_portrait' ]
|
face_editor_models : List[FaceEditorModel] = list(get_args(FaceEditorModel))
|
||||||
|
|
||||||
face_editor_eyebrow_direction_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05)
|
face_editor_eyebrow_direction_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05)
|
||||||
face_editor_eye_gaze_horizontal_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05)
|
face_editor_eye_gaze_horizontal_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05)
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_float_range, create_int_range
|
from facefusion.common_helper import create_float_range, create_int_range
|
||||||
from facefusion.processors.modules.face_enhancer.types import FaceEnhancerModel
|
from facefusion.processors.modules.face_enhancer.types import FaceEnhancerModel
|
||||||
|
|
||||||
face_enhancer_models : List[FaceEnhancerModel] = [ 'codeformer', 'gfpgan_1.2', 'gfpgan_1.3', 'gfpgan_1.4', 'gpen_bfr_256', 'gpen_bfr_512', 'gpen_bfr_1024', 'gpen_bfr_2048', 'restoreformer_plus_plus' ]
|
face_enhancer_models : List[FaceEnhancerModel] = list(get_args(FaceEnhancerModel))
|
||||||
|
|
||||||
face_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1)
|
face_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_float_range
|
from facefusion.common_helper import create_float_range
|
||||||
from facefusion.processors.modules.face_swapper.types import FaceSwapperModel, FaceSwapperSet, FaceSwapperWeight
|
from facefusion.processors.modules.face_swapper.types import FaceSwapperModel, FaceSwapperSet, FaceSwapperWeight
|
||||||
|
|
||||||
|
|
||||||
face_swapper_set : FaceSwapperSet =\
|
face_swapper_set : FaceSwapperSet =\
|
||||||
{
|
{
|
||||||
'blendswap_256': [ '256x256', '384x384', '512x512', '768x768', '1024x1024' ],
|
'blendswap_256': [ '256x256', '384x384', '512x512', '768x768', '1024x1024' ],
|
||||||
@@ -20,6 +21,6 @@ face_swapper_set : FaceSwapperSet =\
|
|||||||
'uniface_256': [ '256x256', '512x512', '768x768', '1024x1024' ]
|
'uniface_256': [ '256x256', '512x512', '768x768', '1024x1024' ]
|
||||||
}
|
}
|
||||||
|
|
||||||
face_swapper_models : List[FaceSwapperModel] = list(face_swapper_set.keys())
|
face_swapper_models : List[FaceSwapperModel] = list(get_args(FaceSwapperModel))
|
||||||
|
|
||||||
face_swapper_weight_range : Sequence[FaceSwapperWeight] = create_float_range(0.0, 1.0, 0.05)
|
face_swapper_weight_range : Sequence[FaceSwapperWeight] = create_float_range(0.0, 1.0, 0.05)
|
||||||
|
|||||||
@@ -540,8 +540,8 @@ def pre_process(mode : ProcessMode) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
source_image_paths = filter_image_paths(state_manager.get_item('source_paths'))
|
source_image_paths = filter_image_paths(state_manager.get_item('source_paths'))
|
||||||
source_frames = read_static_images(source_image_paths)
|
source_vision_frames = read_static_images(source_image_paths)
|
||||||
source_faces = get_many_faces(source_frames)
|
source_faces = get_many_faces(source_vision_frames)
|
||||||
|
|
||||||
if not get_one_face(source_faces):
|
if not get_one_face(source_faces):
|
||||||
logger.error(translator.get('no_source_face_detected') + translator.get('exclamation_mark'), __name__)
|
logger.error(translator.get('no_source_face_detected') + translator.get('exclamation_mark'), __name__)
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_int_range
|
from facefusion.common_helper import create_int_range
|
||||||
from facefusion.processors.modules.frame_colorizer.types import FrameColorizerModel
|
from facefusion.processors.modules.frame_colorizer.types import FrameColorizerModel
|
||||||
|
|
||||||
frame_colorizer_models : List[FrameColorizerModel] = [ 'ddcolor', 'ddcolor_artistic', 'deoldify', 'deoldify_artistic', 'deoldify_stable' ]
|
frame_colorizer_models : List[FrameColorizerModel] = list(get_args(FrameColorizerModel))
|
||||||
|
|
||||||
frame_colorizer_sizes : List[str] = [ '192x192', '256x256', '384x384', '512x512' ]
|
frame_colorizer_sizes : List[str] = [ '192x192', '256x256', '384x384', '512x512' ]
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_int_range
|
from facefusion.common_helper import create_int_range
|
||||||
from facefusion.processors.modules.frame_enhancer.types import FrameEnhancerModel
|
from facefusion.processors.modules.frame_enhancer.types import FrameEnhancerModel
|
||||||
|
|
||||||
frame_enhancer_models : List[FrameEnhancerModel] = [ 'clear_reality_x4', 'face_dat_x4', 'lsdir_x4', 'nomos8k_sc_x4', 'real_esrgan_x2', 'real_esrgan_x2_fp16', 'real_esrgan_x4', 'real_esrgan_x4_fp16', 'real_esrgan_x8', 'real_esrgan_x8_fp16', 'real_hatgan_x4', 'real_web_photo_x4', 'realistic_rescaler_x4', 'remacri_x4', 'siax_x4', 'span_kendata_x4', 'swin2_sr_x4', 'tghq_face_x8', 'ultra_sharp_x4', 'ultra_sharp_2_x4' ]
|
frame_enhancer_models : List[FrameEnhancerModel] = list(get_args(FrameEnhancerModel))
|
||||||
|
|
||||||
frame_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1)
|
frame_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'__metadata__':
|
'__metadata__':
|
||||||
{
|
{
|
||||||
'vendor': 'Helaman',
|
'vendor': 'Helaman',
|
||||||
'license': 'Non-Commercial',
|
'license': 'CC-BY-4.0',
|
||||||
'year': 2023
|
'year': 2023
|
||||||
},
|
},
|
||||||
'hashes':
|
'hashes':
|
||||||
@@ -83,7 +83,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'__metadata__':
|
'__metadata__':
|
||||||
{
|
{
|
||||||
'vendor': 'Phhofm',
|
'vendor': 'Phhofm',
|
||||||
'license': 'Non-Commercial',
|
'license': 'CC-BY-4.0',
|
||||||
'year': 2023
|
'year': 2023
|
||||||
},
|
},
|
||||||
'hashes':
|
'hashes':
|
||||||
@@ -299,7 +299,7 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
'__metadata__':
|
'__metadata__':
|
||||||
{
|
{
|
||||||
'vendor': 'Helaman',
|
'vendor': 'Helaman',
|
||||||
'license': 'Non-Commercial',
|
'license': 'CC-BY-4.0',
|
||||||
'year': 2024
|
'year': 2024
|
||||||
},
|
},
|
||||||
'hashes':
|
'hashes':
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from typing import List, Sequence
|
from typing import List, Sequence, get_args
|
||||||
|
|
||||||
from facefusion.common_helper import create_float_range
|
from facefusion.common_helper import create_float_range
|
||||||
from facefusion.processors.modules.lip_syncer.types import LipSyncerModel
|
from facefusion.processors.modules.lip_syncer.types import LipSyncerModel
|
||||||
|
|
||||||
lip_syncer_models : List[LipSyncerModel] = [ 'edtalk_256', 'wav2lip_96', 'wav2lip_gan_96' ]
|
lip_syncer_models : List[LipSyncerModel] = list(get_args(LipSyncerModel))
|
||||||
|
|
||||||
lip_syncer_weight_range : Sequence[float] = create_float_range(0.0, 1.0, 0.05)
|
lip_syncer_weight_range : Sequence[float] = create_float_range(0.0, 1.0, 0.05)
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from facefusion.types import Locals
|
from facefusion.types import Locales
|
||||||
|
|
||||||
LOCALS : Locals =\
|
LOCALES : Locales =\
|
||||||
{
|
{
|
||||||
'en':
|
'en':
|
||||||
{
|
{
|
||||||
@@ -10,7 +10,7 @@ from facefusion.ffmpeg import get_available_encoder_set
|
|||||||
from facefusion.filesystem import get_file_name, resolve_file_paths
|
from facefusion.filesystem import get_file_name, resolve_file_paths
|
||||||
from facefusion.jobs import job_store
|
from facefusion.jobs import job_store
|
||||||
from facefusion.processors.core import get_processors_modules
|
from facefusion.processors.core import get_processors_modules
|
||||||
from facefusion.sanitizer import sanitize_int_range
|
from facefusion.sanitizer import sanitize_int_range, sanitize_job_id
|
||||||
|
|
||||||
|
|
||||||
def create_help_formatter_small(prog : str) -> HelpFormatter:
|
def create_help_formatter_small(prog : str) -> HelpFormatter:
|
||||||
@@ -188,7 +188,7 @@ def create_processors_program() -> ArgumentParser:
|
|||||||
program = ArgumentParser(add_help = False)
|
program = ArgumentParser(add_help = False)
|
||||||
available_processors = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/processors/modules') ]
|
available_processors = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/processors/modules') ]
|
||||||
group_processors = program.add_argument_group('processors')
|
group_processors = program.add_argument_group('processors')
|
||||||
group_processors.add_argument('--processors', help = translator.get('help.processors').format(choices = ', '.join(available_processors)), default = config.get_str_list('processors', 'processors', 'face_swapper'), nargs = '+')
|
group_processors.add_argument('--processors', help = translator.get('help.processors').format(choices = ', '.join(available_processors)), default = config.get_str_list('processors', 'processors', 'face_swapper'), choices = available_processors, nargs = '+', metavar = 'PROCESSORS')
|
||||||
job_store.register_step_keys([ 'processors' ])
|
job_store.register_step_keys([ 'processors' ])
|
||||||
for processor_module in get_processors_modules(available_processors):
|
for processor_module in get_processors_modules(available_processors):
|
||||||
processor_module.register_args(program)
|
processor_module.register_args(program)
|
||||||
@@ -200,7 +200,7 @@ def create_uis_program() -> ArgumentParser:
|
|||||||
available_ui_layouts = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/uis/layouts') ]
|
available_ui_layouts = [ get_file_name(file_path) for file_path in resolve_file_paths('facefusion/uis/layouts') ]
|
||||||
group_uis = program.add_argument_group('uis')
|
group_uis = program.add_argument_group('uis')
|
||||||
group_uis.add_argument('--open-browser', help = translator.get('help.open_browser'), action = 'store_true', default = config.get_bool_value('uis', 'open_browser'))
|
group_uis.add_argument('--open-browser', help = translator.get('help.open_browser'), action = 'store_true', default = config.get_bool_value('uis', 'open_browser'))
|
||||||
group_uis.add_argument('--ui-layouts', help = translator.get('help.ui_layouts').format(choices = ', '.join(available_ui_layouts)), default = config.get_str_list('uis', 'ui_layouts', 'default'), nargs = '+')
|
group_uis.add_argument('--ui-layouts', help = translator.get('help.ui_layouts').format(choices = ', '.join(available_ui_layouts)), default = config.get_str_list('uis', 'ui_layouts', 'default'), choices = available_ui_layouts, nargs = '+', metavar = 'UI_LAYOUTS')
|
||||||
group_uis.add_argument('--ui-workflow', help = translator.get('help.ui_workflow'), default = config.get_str_value('uis', 'ui_workflow', 'instant_runner'), choices = facefusion.choices.ui_workflows)
|
group_uis.add_argument('--ui-workflow', help = translator.get('help.ui_workflow'), default = config.get_str_value('uis', 'ui_workflow', 'instant_runner'), choices = facefusion.choices.ui_workflows)
|
||||||
return program
|
return program
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ def create_execution_program() -> ArgumentParser:
|
|||||||
program = ArgumentParser(add_help = False)
|
program = ArgumentParser(add_help = False)
|
||||||
available_execution_providers = get_available_execution_providers()
|
available_execution_providers = get_available_execution_providers()
|
||||||
group_execution = program.add_argument_group('execution')
|
group_execution = program.add_argument_group('execution')
|
||||||
group_execution.add_argument('--execution-device-ids', help = translator.get('help.execution_device_ids'), type = int, default = config.get_str_list('execution', 'execution_device_ids', '0'), nargs = '+', metavar = 'EXECUTION_DEVICE_IDS')
|
group_execution.add_argument('--execution-device-ids', help = translator.get('help.execution_device_ids'), type = int, default = config.get_int_list('execution', 'execution_device_ids', '0'), nargs = '+', metavar = 'EXECUTION_DEVICE_IDS')
|
||||||
group_execution.add_argument('--execution-providers', help = translator.get('help.execution_providers').format(choices = ', '.join(available_execution_providers)), default = config.get_str_list('execution', 'execution_providers', get_first(available_execution_providers)), choices = available_execution_providers, nargs = '+', metavar = 'EXECUTION_PROVIDERS')
|
group_execution.add_argument('--execution-providers', help = translator.get('help.execution_providers').format(choices = ', '.join(available_execution_providers)), default = config.get_str_list('execution', 'execution_providers', get_first(available_execution_providers)), choices = available_execution_providers, nargs = '+', metavar = 'EXECUTION_PROVIDERS')
|
||||||
group_execution.add_argument('--execution-thread-count', help = translator.get('help.execution_thread_count'), type = int, default = config.get_int_value('execution', 'execution_thread_count', '8'), choices = facefusion.choices.execution_thread_count_range, metavar = create_int_metavar(facefusion.choices.execution_thread_count_range))
|
group_execution.add_argument('--execution-thread-count', help = translator.get('help.execution_thread_count'), type = int, default = config.get_int_value('execution', 'execution_thread_count', '8'), choices = facefusion.choices.execution_thread_count_range, metavar = create_int_metavar(facefusion.choices.execution_thread_count_range))
|
||||||
job_store.register_job_keys([ 'execution_device_ids', 'execution_providers', 'execution_thread_count' ])
|
job_store.register_job_keys([ 'execution_device_ids', 'execution_providers', 'execution_thread_count' ])
|
||||||
@@ -268,8 +268,7 @@ def create_halt_on_error_program() -> ArgumentParser:
|
|||||||
|
|
||||||
def create_job_id_program() -> ArgumentParser:
|
def create_job_id_program() -> ArgumentParser:
|
||||||
program = ArgumentParser(add_help = False)
|
program = ArgumentParser(add_help = False)
|
||||||
program.add_argument('job_id', help = translator.get('help.job_id'))
|
program.add_argument('job_id', help = translator.get('help.job_id'), type = sanitize_job_id)
|
||||||
job_store.register_job_keys([ 'job_id' ])
|
|
||||||
return program
|
return program
|
||||||
|
|
||||||
|
|
||||||
@@ -298,13 +297,11 @@ def create_program() -> ArgumentParser:
|
|||||||
program._positionals.title = 'commands'
|
program._positionals.title = 'commands'
|
||||||
program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version')
|
program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version')
|
||||||
sub_program = program.add_subparsers(dest = 'command')
|
sub_program = program.add_subparsers(dest = 'command')
|
||||||
# general
|
|
||||||
sub_program.add_parser('run', help = translator.get('help.run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), create_uis_program(), create_benchmark_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('run', help = translator.get('help.run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), create_uis_program(), create_benchmark_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('headless-run', help = translator.get('help.headless_run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('headless-run', help = translator.get('help.headless_run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('batch-run', help = translator.get('help.batch_run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_pattern_program(), create_target_pattern_program(), create_output_pattern_program(), collect_step_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('batch-run', help = translator.get('help.batch_run'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), create_source_pattern_program(), create_target_pattern_program(), create_output_pattern_program(), collect_step_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('force-download', help = translator.get('help.force_download'), parents = [ create_download_providers_program(), create_download_scope_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('force-download', help = translator.get('help.force_download'), parents = [ create_download_providers_program(), create_download_scope_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('benchmark', help = translator.get('help.benchmark'), parents = [ create_temp_path_program(), collect_step_program(), create_benchmark_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('benchmark', help = translator.get('help.benchmark'), parents = [ create_temp_path_program(), collect_step_program(), create_benchmark_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
# job manager
|
|
||||||
sub_program.add_parser('job-list', help = translator.get('help.job_list'), parents = [ create_job_status_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-list', help = translator.get('help.job_list'), parents = [ create_job_status_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-create', help = translator.get('help.job_create'), parents = [ create_job_id_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-create', help = translator.get('help.job_create'), parents = [ create_job_id_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-submit', help = translator.get('help.job_submit'), parents = [ create_job_id_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-submit', help = translator.get('help.job_submit'), parents = [ create_job_id_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
@@ -315,7 +312,6 @@ def create_program() -> ArgumentParser:
|
|||||||
sub_program.add_parser('job-remix-step', help = translator.get('help.job_remix_step'), parents = [ create_job_id_program(), create_step_index_program(), create_config_path_program(), create_jobs_path_program(), create_source_paths_program(), create_output_path_program(), collect_step_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-remix-step', help = translator.get('help.job_remix_step'), parents = [ create_job_id_program(), create_step_index_program(), create_config_path_program(), create_jobs_path_program(), create_source_paths_program(), create_output_path_program(), collect_step_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-insert-step', help = translator.get('help.job_insert_step'), parents = [ create_job_id_program(), create_step_index_program(), create_config_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-insert-step', help = translator.get('help.job_insert_step'), parents = [ create_job_id_program(), create_step_index_program(), create_config_path_program(), create_jobs_path_program(), create_source_paths_program(), create_target_path_program(), create_output_path_program(), collect_step_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-remove-step', help = translator.get('help.job_remove_step'), parents = [ create_job_id_program(), create_step_index_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-remove-step', help = translator.get('help.job_remove_step'), parents = [ create_job_id_program(), create_step_index_program(), create_jobs_path_program(), create_log_level_program() ], formatter_class = create_help_formatter_large)
|
||||||
# job runner
|
|
||||||
sub_program.add_parser('job-run', help = translator.get('help.job_run'), parents = [ create_job_id_program(), create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-run', help = translator.get('help.job_run'), parents = [ create_job_id_program(), create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-run-all', help = translator.get('help.job_run_all'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program(), create_halt_on_error_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-run-all', help = translator.get('help.job_run_all'), parents = [ create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program(), create_halt_on_error_program() ], formatter_class = create_help_formatter_large)
|
||||||
sub_program.add_parser('job-retry', help = translator.get('help.job_retry'), parents = [ create_job_id_program(), create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
sub_program.add_parser('job-retry', help = translator.get('help.job_retry'), parents = [ create_job_id_program(), create_config_path_program(), create_temp_path_program(), create_jobs_path_program(), collect_job_program() ], formatter_class = create_help_formatter_large)
|
||||||
|
|||||||
+15
-2
@@ -1,7 +1,20 @@
|
|||||||
from typing import Sequence
|
import hashlib
|
||||||
|
from typing import Any, Sequence
|
||||||
|
|
||||||
|
from facefusion.common_helper import cast_int
|
||||||
|
|
||||||
|
|
||||||
def sanitize_int_range(value : int, int_range : Sequence[int]) -> int:
|
def sanitize_job_id(job_id : str) -> str:
|
||||||
|
__job_id__ = job_id.replace('-', '')
|
||||||
|
|
||||||
|
if __job_id__.isalnum():
|
||||||
|
return job_id
|
||||||
|
return hashlib.sha1(job_id.encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_int_range(value : Any, int_range : Sequence[int]) -> int:
|
||||||
|
value = cast_int(value)
|
||||||
|
|
||||||
if value in int_range:
|
if value in int_range:
|
||||||
return value
|
return value
|
||||||
return int_range[0]
|
return int_range[0]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from typing import Deque, Generator
|
from typing import Deque, Iterator
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy
|
import numpy
|
||||||
@@ -18,7 +18,7 @@ from facefusion.types import Fps, StreamMode, VisionFrame
|
|||||||
from facefusion.vision import extract_vision_mask, read_static_images
|
from facefusion.vision import extract_vision_mask, read_static_images
|
||||||
|
|
||||||
|
|
||||||
def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -> Generator[VisionFrame, None, None]:
|
def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -> Iterator[VisionFrame]:
|
||||||
capture_deque : Deque[VisionFrame] = deque()
|
capture_deque : Deque[VisionFrame] = deque()
|
||||||
|
|
||||||
with tqdm(desc = translator.get('streaming'), unit = 'frame', disable = state_manager.get_item('log_level') in [ 'warn', 'error' ]) as progress:
|
with tqdm(desc = translator.get('streaming'), unit = 'frame', disable = state_manager.get_item('log_level') in [ 'warn', 'error' ]) as progress:
|
||||||
@@ -26,17 +26,17 @@ def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -
|
|||||||
futures = []
|
futures = []
|
||||||
|
|
||||||
while camera_capture and camera_capture.isOpened():
|
while camera_capture and camera_capture.isOpened():
|
||||||
_, capture_frame = camera_capture.read()
|
_, capture_vision_frame = camera_capture.read()
|
||||||
if analyse_stream(capture_frame, camera_fps):
|
if analyse_stream(capture_vision_frame, camera_fps):
|
||||||
camera_capture.release()
|
camera_capture.release()
|
||||||
|
|
||||||
if numpy.any(capture_frame):
|
if numpy.any(capture_vision_frame):
|
||||||
future = executor.submit(process_stream_frame, capture_frame)
|
future = executor.submit(process_stream_frame, capture_vision_frame)
|
||||||
futures.append(future)
|
futures.append(future)
|
||||||
|
|
||||||
for future_done in [ future for future in futures if future.done() ]:
|
for future_done in [ future for future in futures if future.done() ]:
|
||||||
capture_frame = future_done.result()
|
capture_vision_frame = future_done.result()
|
||||||
capture_deque.append(capture_frame)
|
capture_deque.append(capture_vision_frame)
|
||||||
futures.remove(future_done)
|
futures.remove(future_done)
|
||||||
|
|
||||||
while capture_deque:
|
while capture_deque:
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
import importlib
|
import importlib
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from facefusion.types import Language, LocalPoolSet, Locals
|
from facefusion.types import Language, LocalePoolSet, Locales
|
||||||
|
|
||||||
LOCAL_POOL_SET : LocalPoolSet = {}
|
LOCALE_POOL_SET : LocalePoolSet = {}
|
||||||
CURRENT_LANGUAGE : Language = 'en'
|
CURRENT_LANGUAGE : Language = 'en'
|
||||||
|
|
||||||
|
|
||||||
def __autoload__(module_name : str) -> None:
|
def __autoload__(module_name : str) -> None:
|
||||||
try:
|
try:
|
||||||
__locals__ = importlib.import_module(module_name + '.locals')
|
__locales__ = importlib.import_module(module_name + '.locales')
|
||||||
load(__locals__.LOCALS, module_name)
|
load(__locales__.LOCALES, module_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def load(__locals__ : Locals, module_name : str) -> None:
|
def load(__locales__ : Locales, module_name : str) -> None:
|
||||||
LOCAL_POOL_SET[module_name] = __locals__
|
LOCALE_POOL_SET[module_name] = __locales__
|
||||||
|
|
||||||
|
|
||||||
def get(notation : str, module_name : str = 'facefusion') -> Optional[str]:
|
def get(notation : str, module_name : str = 'facefusion') -> Optional[str]:
|
||||||
if module_name not in LOCAL_POOL_SET:
|
if module_name not in LOCALE_POOL_SET:
|
||||||
__autoload__(module_name)
|
__autoload__(module_name)
|
||||||
|
|
||||||
current = LOCAL_POOL_SET.get(module_name).get(CURRENT_LANGUAGE)
|
current = LOCALE_POOL_SET.get(module_name).get(CURRENT_LANGUAGE)
|
||||||
|
|
||||||
for fragment in notation.split('.'):
|
for fragment in notation.split('.'):
|
||||||
if fragment in current:
|
if fragment in current:
|
||||||
|
|||||||
+7
-6
@@ -51,8 +51,8 @@ FaceStore = TypedDict('FaceStore',
|
|||||||
})
|
})
|
||||||
|
|
||||||
Language = Literal['en']
|
Language = Literal['en']
|
||||||
Locals : TypeAlias = Dict[Language, Dict[str, Any]]
|
Locales : TypeAlias = Dict[Language, Dict[str, Any]]
|
||||||
LocalPoolSet : TypeAlias = Dict[str, Locals]
|
LocalePoolSet : TypeAlias = Dict[str, Locales]
|
||||||
|
|
||||||
VideoCaptureSet : TypeAlias = Dict[str, cv2.VideoCapture]
|
VideoCaptureSet : TypeAlias = Dict[str, cv2.VideoCapture]
|
||||||
VideoWriterSet : TypeAlias = Dict[str, cv2.VideoWriter]
|
VideoWriterSet : TypeAlias = Dict[str, cv2.VideoWriter]
|
||||||
@@ -167,10 +167,11 @@ ModelOptions : TypeAlias = Dict[str, Any]
|
|||||||
ModelSet : TypeAlias = Dict[str, ModelOptions]
|
ModelSet : TypeAlias = Dict[str, ModelOptions]
|
||||||
ModelInitializer : TypeAlias = NDArray[Any]
|
ModelInitializer : TypeAlias = NDArray[Any]
|
||||||
|
|
||||||
ExecutionProvider = Literal['cpu', 'coreml', 'cuda', 'directml', 'openvino', 'migraphx', 'rocm', 'tensorrt']
|
ExecutionProvider = Literal['cuda', 'tensorrt', 'rocm', 'migraphx', 'coreml', 'openvino', 'qnn', 'directml', 'cpu']
|
||||||
ExecutionProviderValue = Literal['CPUExecutionProvider', 'CoreMLExecutionProvider', 'CUDAExecutionProvider', 'DmlExecutionProvider', 'OpenVINOExecutionProvider', 'MIGraphXExecutionProvider', 'ROCMExecutionProvider', 'TensorrtExecutionProvider']
|
ExecutionProviderValue = Literal['CPUExecutionProvider', 'CoreMLExecutionProvider', 'CUDAExecutionProvider', 'DmlExecutionProvider', 'OpenVINOExecutionProvider', 'MIGraphXExecutionProvider', 'QNNExecutionProvider', 'ROCMExecutionProvider', 'TensorrtExecutionProvider']
|
||||||
ExecutionProviderSet : TypeAlias = Dict[ExecutionProvider, ExecutionProviderValue]
|
ExecutionProviderSet : TypeAlias = Dict[ExecutionProvider, ExecutionProviderValue]
|
||||||
InferenceSessionProvider : TypeAlias = Any
|
InferenceProvider : TypeAlias = Any
|
||||||
|
InferenceOptionSet : TypeAlias = Dict[str, Any]
|
||||||
ValueAndUnit = TypedDict('ValueAndUnit',
|
ValueAndUnit = TypedDict('ValueAndUnit',
|
||||||
{
|
{
|
||||||
'value' : int,
|
'value' : int,
|
||||||
@@ -385,7 +386,7 @@ State = TypedDict('State',
|
|||||||
'open_browser' : bool,
|
'open_browser' : bool,
|
||||||
'ui_layouts' : List[str],
|
'ui_layouts' : List[str],
|
||||||
'ui_workflow' : UiWorkflow,
|
'ui_workflow' : UiWorkflow,
|
||||||
'execution_device_ids' : List[str],
|
'execution_device_ids' : List[int],
|
||||||
'execution_providers' : List[ExecutionProvider],
|
'execution_providers' : List[ExecutionProvider],
|
||||||
'execution_thread_count' : int,
|
'execution_thread_count' : int,
|
||||||
'video_memory_strategy' : VideoMemoryStrategy,
|
'video_memory_strategy' : VideoMemoryStrategy,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ preview_resolutions : List[str] = [ '512x512', '768x768', '1024x1024' ]
|
|||||||
webcam_modes : List[WebcamMode] = [ 'inline', 'udp', 'v4l2' ]
|
webcam_modes : List[WebcamMode] = [ 'inline', 'udp', 'v4l2' ]
|
||||||
webcam_resolutions : List[str] = [ '320x240', '640x480', '800x600', '1024x768', '1280x720', '1280x960', '1920x1080' ]
|
webcam_resolutions : List[str] = [ '320x240', '640x480', '800x600', '1024x768', '1280x720', '1280x960', '1920x1080' ]
|
||||||
|
|
||||||
background_remover_colors : Dict[str, Color] =\
|
background_remover_fill_colors : Dict[str, Color] =\
|
||||||
{
|
{
|
||||||
'red' : (255, 0, 0, 255),
|
'red' : (255, 0, 0, 255),
|
||||||
'green' : (0, 255, 0, 255),
|
'green' : (0, 255, 0, 255),
|
||||||
|
|||||||
@@ -11,82 +11,132 @@ from facefusion.sanitizer import sanitize_int_range
|
|||||||
from facefusion.uis.core import get_ui_component, register_ui_component
|
from facefusion.uis.core import get_ui_component, register_ui_component
|
||||||
|
|
||||||
BACKGROUND_REMOVER_MODEL_DROPDOWN : Optional[gradio.Dropdown] = None
|
BACKGROUND_REMOVER_MODEL_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||||
BACKGROUND_REMOVER_COLOR_WRAPPER : Optional[gradio.Group] = None
|
BACKGROUND_REMOVER_FILL_COLOR_WRAPPER : Optional[gradio.Group] = None
|
||||||
BACKGROUND_REMOVER_COLOR_RED_NUMBER : Optional[gradio.Number] = None
|
BACKGROUND_REMOVER_FILL_COLOR_RED_NUMBER : Optional[gradio.Number] = None
|
||||||
BACKGROUND_REMOVER_COLOR_GREEN_NUMBER : Optional[gradio.Number] = None
|
BACKGROUND_REMOVER_FILL_COLOR_GREEN_NUMBER : Optional[gradio.Number] = None
|
||||||
BACKGROUND_REMOVER_COLOR_BLUE_NUMBER : Optional[gradio.Number] = None
|
BACKGROUND_REMOVER_FILL_COLOR_BLUE_NUMBER : Optional[gradio.Number] = None
|
||||||
BACKGROUND_REMOVER_COLOR_ALPHA_NUMBER : Optional[gradio.Number] = None
|
BACKGROUND_REMOVER_FILL_COLOR_ALPHA_NUMBER : Optional[gradio.Number] = None
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_WRAPPER : Optional[gradio.Group] = None
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_RED_NUMBER : Optional[gradio.Number] = None
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_GREEN_NUMBER : Optional[gradio.Number] = None
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_BLUE_NUMBER : Optional[gradio.Number] = None
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_ALPHA_NUMBER : Optional[gradio.Number] = None
|
||||||
|
|
||||||
|
|
||||||
def render() -> None:
|
def render() -> None:
|
||||||
global BACKGROUND_REMOVER_MODEL_DROPDOWN
|
global BACKGROUND_REMOVER_MODEL_DROPDOWN
|
||||||
global BACKGROUND_REMOVER_COLOR_WRAPPER
|
global BACKGROUND_REMOVER_FILL_COLOR_WRAPPER
|
||||||
global BACKGROUND_REMOVER_COLOR_RED_NUMBER
|
global BACKGROUND_REMOVER_FILL_COLOR_RED_NUMBER
|
||||||
global BACKGROUND_REMOVER_COLOR_GREEN_NUMBER
|
global BACKGROUND_REMOVER_FILL_COLOR_GREEN_NUMBER
|
||||||
global BACKGROUND_REMOVER_COLOR_BLUE_NUMBER
|
global BACKGROUND_REMOVER_FILL_COLOR_BLUE_NUMBER
|
||||||
global BACKGROUND_REMOVER_COLOR_ALPHA_NUMBER
|
global BACKGROUND_REMOVER_FILL_COLOR_ALPHA_NUMBER
|
||||||
|
global BACKGROUND_REMOVER_DESPILL_COLOR_WRAPPER
|
||||||
|
global BACKGROUND_REMOVER_DESPILL_COLOR_RED_NUMBER
|
||||||
|
global BACKGROUND_REMOVER_DESPILL_COLOR_GREEN_NUMBER
|
||||||
|
global BACKGROUND_REMOVER_DESPILL_COLOR_BLUE_NUMBER
|
||||||
|
global BACKGROUND_REMOVER_DESPILL_COLOR_ALPHA_NUMBER
|
||||||
|
|
||||||
has_background_remover = 'background_remover' in state_manager.get_item('processors')
|
has_background_remover = 'background_remover' in state_manager.get_item('processors')
|
||||||
background_remover_color = state_manager.get_item('background_remover_color')
|
background_remover_fill_color = state_manager.get_item('background_remover_fill_color')
|
||||||
|
background_remover_despill_color = state_manager.get_item('background_remover_despill_color')
|
||||||
BACKGROUND_REMOVER_MODEL_DROPDOWN = gradio.Dropdown(
|
BACKGROUND_REMOVER_MODEL_DROPDOWN = gradio.Dropdown(
|
||||||
label = translator.get('uis.model_dropdown', 'facefusion.processors.modules.background_remover'),
|
label = translator.get('uis.model_dropdown', 'facefusion.processors.modules.background_remover'),
|
||||||
choices = background_remover_choices.background_remover_models,
|
choices = background_remover_choices.background_remover_models,
|
||||||
value = state_manager.get_item('background_remover_model'),
|
value = state_manager.get_item('background_remover_model'),
|
||||||
visible = has_background_remover
|
visible = has_background_remover
|
||||||
)
|
)
|
||||||
with gradio.Group(visible = has_background_remover) as BACKGROUND_REMOVER_COLOR_WRAPPER:
|
with gradio.Group(visible = has_background_remover) as BACKGROUND_REMOVER_FILL_COLOR_WRAPPER:
|
||||||
with gradio.Row():
|
with gradio.Row():
|
||||||
BACKGROUND_REMOVER_COLOR_RED_NUMBER = gradio.Number(
|
BACKGROUND_REMOVER_FILL_COLOR_RED_NUMBER = gradio.Number(
|
||||||
label = translator.get('uis.color_red_number', 'facefusion.processors.modules.background_remover'),
|
label = translator.get('uis.fill_color_red_number', 'facefusion.processors.modules.background_remover'),
|
||||||
value = background_remover_color[0],
|
value = background_remover_fill_color[0],
|
||||||
minimum = background_remover_choices.background_remover_color_range[0],
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
maximum = background_remover_choices.background_remover_color_range[-1],
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
)
|
)
|
||||||
BACKGROUND_REMOVER_COLOR_GREEN_NUMBER = gradio.Number(
|
BACKGROUND_REMOVER_FILL_COLOR_GREEN_NUMBER = gradio.Number(
|
||||||
label = translator.get('uis.color_green_number', 'facefusion.processors.modules.background_remover'),
|
label = translator.get('uis.fill_color_green_number', 'facefusion.processors.modules.background_remover'),
|
||||||
value = background_remover_color[1],
|
value = background_remover_fill_color[1],
|
||||||
minimum = background_remover_choices.background_remover_color_range[0],
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
maximum = background_remover_choices.background_remover_color_range[-1],
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
)
|
)
|
||||||
with gradio.Row():
|
with gradio.Row():
|
||||||
BACKGROUND_REMOVER_COLOR_BLUE_NUMBER = gradio.Number(
|
BACKGROUND_REMOVER_FILL_COLOR_BLUE_NUMBER = gradio.Number(
|
||||||
label = translator.get('uis.color_blue_number', 'facefusion.processors.modules.background_remover'),
|
label = translator.get('uis.fill_color_blue_number', 'facefusion.processors.modules.background_remover'),
|
||||||
value = background_remover_color[2],
|
value = background_remover_fill_color[2],
|
||||||
minimum = background_remover_choices.background_remover_color_range[0],
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
maximum = background_remover_choices.background_remover_color_range[-1],
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
)
|
)
|
||||||
BACKGROUND_REMOVER_COLOR_ALPHA_NUMBER = gradio.Number(
|
BACKGROUND_REMOVER_FILL_COLOR_ALPHA_NUMBER = gradio.Number(
|
||||||
label = translator.get('uis.color_alpha_number', 'facefusion.processors.modules.background_remover'),
|
label = translator.get('uis.fill_color_alpha_number', 'facefusion.processors.modules.background_remover'),
|
||||||
value = background_remover_color[3],
|
value = background_remover_fill_color[3],
|
||||||
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
|
)
|
||||||
|
with gradio.Group(visible = has_background_remover) as BACKGROUND_REMOVER_DESPILL_COLOR_WRAPPER:
|
||||||
|
with gradio.Row():
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_RED_NUMBER = gradio.Number(
|
||||||
|
label = translator.get('uis.despill_color_red_number', 'facefusion.processors.modules.background_remover'),
|
||||||
|
value = background_remover_despill_color[0],
|
||||||
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
|
)
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_GREEN_NUMBER = gradio.Number(
|
||||||
|
label = translator.get('uis.despill_color_green_number', 'facefusion.processors.modules.background_remover'),
|
||||||
|
value = background_remover_despill_color[1],
|
||||||
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
|
)
|
||||||
|
with gradio.Row():
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_BLUE_NUMBER = gradio.Number(
|
||||||
|
label = translator.get('uis.despill_color_blue_number', 'facefusion.processors.modules.background_remover'),
|
||||||
|
value = background_remover_despill_color[2],
|
||||||
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
|
)
|
||||||
|
BACKGROUND_REMOVER_DESPILL_COLOR_ALPHA_NUMBER = gradio.Number(
|
||||||
|
label = translator.get('uis.despill_color_alpha_number', 'facefusion.processors.modules.background_remover'),
|
||||||
|
value = background_remover_despill_color[3],
|
||||||
minimum = background_remover_choices.background_remover_color_range[0],
|
minimum = background_remover_choices.background_remover_color_range[0],
|
||||||
maximum = background_remover_choices.background_remover_color_range[-1],
|
maximum = background_remover_choices.background_remover_color_range[-1],
|
||||||
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
step = calculate_int_step(background_remover_choices.background_remover_color_range)
|
||||||
)
|
)
|
||||||
register_ui_component('background_remover_model_dropdown', BACKGROUND_REMOVER_MODEL_DROPDOWN)
|
register_ui_component('background_remover_model_dropdown', BACKGROUND_REMOVER_MODEL_DROPDOWN)
|
||||||
register_ui_component('background_remover_color_red_number', BACKGROUND_REMOVER_COLOR_RED_NUMBER)
|
register_ui_component('background_remover_fill_color_red_number', BACKGROUND_REMOVER_FILL_COLOR_RED_NUMBER)
|
||||||
register_ui_component('background_remover_color_green_number', BACKGROUND_REMOVER_COLOR_GREEN_NUMBER)
|
register_ui_component('background_remover_fill_color_green_number', BACKGROUND_REMOVER_FILL_COLOR_GREEN_NUMBER)
|
||||||
register_ui_component('background_remover_color_blue_number', BACKGROUND_REMOVER_COLOR_BLUE_NUMBER)
|
register_ui_component('background_remover_fill_color_blue_number', BACKGROUND_REMOVER_FILL_COLOR_BLUE_NUMBER)
|
||||||
register_ui_component('background_remover_color_alpha_number', BACKGROUND_REMOVER_COLOR_ALPHA_NUMBER)
|
register_ui_component('background_remover_fill_color_alpha_number', BACKGROUND_REMOVER_FILL_COLOR_ALPHA_NUMBER)
|
||||||
|
register_ui_component('background_remover_despill_color_red_number', BACKGROUND_REMOVER_DESPILL_COLOR_RED_NUMBER)
|
||||||
|
register_ui_component('background_remover_despill_color_green_number', BACKGROUND_REMOVER_DESPILL_COLOR_GREEN_NUMBER)
|
||||||
|
register_ui_component('background_remover_despill_color_blue_number', BACKGROUND_REMOVER_DESPILL_COLOR_BLUE_NUMBER)
|
||||||
|
register_ui_component('background_remover_despill_color_alpha_number', BACKGROUND_REMOVER_DESPILL_COLOR_ALPHA_NUMBER)
|
||||||
|
|
||||||
|
|
||||||
def listen() -> None:
|
def listen() -> None:
|
||||||
BACKGROUND_REMOVER_MODEL_DROPDOWN.change(update_background_remover_model, inputs = BACKGROUND_REMOVER_MODEL_DROPDOWN, outputs = BACKGROUND_REMOVER_MODEL_DROPDOWN)
|
BACKGROUND_REMOVER_MODEL_DROPDOWN.change(update_background_remover_model, inputs = BACKGROUND_REMOVER_MODEL_DROPDOWN, outputs = BACKGROUND_REMOVER_MODEL_DROPDOWN)
|
||||||
background_remover_color_inputs = [ BACKGROUND_REMOVER_COLOR_RED_NUMBER, BACKGROUND_REMOVER_COLOR_GREEN_NUMBER, BACKGROUND_REMOVER_COLOR_BLUE_NUMBER, BACKGROUND_REMOVER_COLOR_ALPHA_NUMBER ]
|
background_remover_fill_color_inputs = [ BACKGROUND_REMOVER_FILL_COLOR_RED_NUMBER, BACKGROUND_REMOVER_FILL_COLOR_GREEN_NUMBER, BACKGROUND_REMOVER_FILL_COLOR_BLUE_NUMBER, BACKGROUND_REMOVER_FILL_COLOR_ALPHA_NUMBER ]
|
||||||
|
background_remover_despill_color_inputs = [ BACKGROUND_REMOVER_DESPILL_COLOR_RED_NUMBER, BACKGROUND_REMOVER_DESPILL_COLOR_GREEN_NUMBER, BACKGROUND_REMOVER_DESPILL_COLOR_BLUE_NUMBER, BACKGROUND_REMOVER_DESPILL_COLOR_ALPHA_NUMBER ]
|
||||||
|
|
||||||
for background_remover_color_input in background_remover_color_inputs:
|
for background_remover_fill_color_input in background_remover_fill_color_inputs:
|
||||||
background_remover_color_input.change(update_background_remover_color, inputs = background_remover_color_inputs)
|
background_remover_fill_color_input.change(update_background_remover_fill_color, inputs = background_remover_fill_color_inputs)
|
||||||
|
|
||||||
|
for background_remover_despill_color_input in background_remover_despill_color_inputs:
|
||||||
|
background_remover_despill_color_input.change(update_background_remover_despill_color, inputs = background_remover_despill_color_inputs)
|
||||||
|
|
||||||
processors_checkbox_group = get_ui_component('processors_checkbox_group')
|
processors_checkbox_group = get_ui_component('processors_checkbox_group')
|
||||||
if processors_checkbox_group:
|
if processors_checkbox_group:
|
||||||
processors_checkbox_group.change(remote_update, inputs = processors_checkbox_group, outputs = [BACKGROUND_REMOVER_MODEL_DROPDOWN, BACKGROUND_REMOVER_COLOR_WRAPPER])
|
processors_checkbox_group.change(remote_update, inputs = processors_checkbox_group, outputs = [ BACKGROUND_REMOVER_MODEL_DROPDOWN, BACKGROUND_REMOVER_FILL_COLOR_WRAPPER, BACKGROUND_REMOVER_DESPILL_COLOR_WRAPPER ])
|
||||||
|
|
||||||
|
|
||||||
def remote_update(processors : List[str]) -> Tuple[gradio.Dropdown, gradio.Group]:
|
def remote_update(processors : List[str]) -> Tuple[gradio.Dropdown, gradio.Group, gradio.Group]:
|
||||||
has_background_remover = 'background_remover' in processors
|
has_background_remover = 'background_remover' in processors
|
||||||
return gradio.Dropdown(visible = has_background_remover), gradio.Group(visible = has_background_remover)
|
return gradio.Dropdown(visible = has_background_remover), gradio.Group(visible = has_background_remover), gradio.Group(visible = has_background_remover)
|
||||||
|
|
||||||
|
|
||||||
def update_background_remover_model(background_remover_model : BackgroundRemoverModel) -> gradio.Dropdown:
|
def update_background_remover_model(background_remover_model : BackgroundRemoverModel) -> gradio.Dropdown:
|
||||||
@@ -99,9 +149,17 @@ def update_background_remover_model(background_remover_model : BackgroundRemover
|
|||||||
return gradio.Dropdown()
|
return gradio.Dropdown()
|
||||||
|
|
||||||
|
|
||||||
def update_background_remover_color(red : int, green : int, blue : int, alpha : int) -> None:
|
def update_background_remover_fill_color(red : int, green : int, blue : int, alpha : int) -> None:
|
||||||
red = sanitize_int_range(red, background_remover_choices.background_remover_color_range)
|
red = sanitize_int_range(red, background_remover_choices.background_remover_color_range)
|
||||||
green = sanitize_int_range(green, background_remover_choices.background_remover_color_range)
|
green = sanitize_int_range(green, background_remover_choices.background_remover_color_range)
|
||||||
blue = sanitize_int_range(blue, background_remover_choices.background_remover_color_range)
|
blue = sanitize_int_range(blue, background_remover_choices.background_remover_color_range)
|
||||||
alpha = sanitize_int_range(alpha, background_remover_choices.background_remover_color_range)
|
alpha = sanitize_int_range(alpha, background_remover_choices.background_remover_color_range)
|
||||||
state_manager.set_item('background_remover_color', (red, green, blue, alpha))
|
state_manager.set_item('background_remover_fill_color', (red, green, blue, alpha))
|
||||||
|
|
||||||
|
|
||||||
|
def update_background_remover_despill_color(red : int, green : int, blue : int, alpha : int) -> None:
|
||||||
|
red = sanitize_int_range(red, background_remover_choices.background_remover_color_range)
|
||||||
|
green = sanitize_int_range(green, background_remover_choices.background_remover_color_range)
|
||||||
|
blue = sanitize_int_range(blue, background_remover_choices.background_remover_color_range)
|
||||||
|
alpha = sanitize_int_range(alpha, background_remover_choices.background_remover_color_range)
|
||||||
|
state_manager.set_item('background_remover_despill_color', (red, green, blue, alpha))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Generator, List, Optional
|
from typing import Any, Iterator, List, Optional
|
||||||
|
|
||||||
import gradio
|
import gradio
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ def listen() -> None:
|
|||||||
BENCHMARK_START_BUTTON.click(start, outputs = BENCHMARK_BENCHMARKS_DATAFRAME)
|
BENCHMARK_START_BUTTON.click(start, outputs = BENCHMARK_BENCHMARKS_DATAFRAME)
|
||||||
|
|
||||||
|
|
||||||
def start() -> Generator[List[Any], None, None]:
|
def start() -> Iterator[List[Any]]:
|
||||||
state_manager.sync_state()
|
state_manager.sync_state()
|
||||||
|
|
||||||
for benchmark in benchmarker.run():
|
for benchmark in benchmarker.run():
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ def listen() -> None:
|
|||||||
'target_video'
|
'target_video'
|
||||||
]):
|
]):
|
||||||
for method in [ 'change', 'clear' ]:
|
for method in [ 'change', 'clear' ]:
|
||||||
getattr(ui_component, method)(remote_update, outputs = [OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_IMAGE_SCALE_SLIDER, OUTPUT_AUDIO_ENCODER_DROPDOWN, OUTPUT_AUDIO_QUALITY_SLIDER, OUTPUT_AUDIO_VOLUME_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_PRESET_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER, OUTPUT_VIDEO_SCALE_SLIDER, OUTPUT_VIDEO_FPS_SLIDER])
|
getattr(ui_component, method)(remote_update, outputs = [ OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_IMAGE_SCALE_SLIDER, OUTPUT_AUDIO_ENCODER_DROPDOWN, OUTPUT_AUDIO_QUALITY_SLIDER, OUTPUT_AUDIO_VOLUME_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_PRESET_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER, OUTPUT_VIDEO_SCALE_SLIDER, OUTPUT_VIDEO_FPS_SLIDER ])
|
||||||
|
|
||||||
|
|
||||||
def remote_update() -> Tuple[gradio.Slider, gradio.Slider, gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Dropdown, gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Slider]:
|
def remote_update() -> Tuple[gradio.Slider, gradio.Slider, gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Dropdown, gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Slider]:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from facefusion.types import AudioFrame, Face, Mask, VisionFrame
|
|||||||
from facefusion.uis import choices as uis_choices
|
from facefusion.uis import choices as uis_choices
|
||||||
from facefusion.uis.core import get_ui_component, get_ui_components, register_ui_component
|
from facefusion.uis.core import get_ui_component, get_ui_components, register_ui_component
|
||||||
from facefusion.uis.types import ComponentOptions, PreviewMode
|
from facefusion.uis.types import ComponentOptions, PreviewMode
|
||||||
from facefusion.vision import conditional_merge_vision_mask, detect_frame_orientation, extract_vision_mask, fit_cover_frame, obscure_frame, read_static_image, read_static_images, read_video_frame, restrict_frame, unpack_resolution
|
from facefusion.vision import detect_frame_orientation, extract_vision_mask, fit_cover_frame, merge_vision_mask, obscure_frame, read_static_image, read_static_images, read_video_frame, restrict_frame, unpack_resolution
|
||||||
|
|
||||||
PREVIEW_IMAGE : Optional[gradio.Image] = None
|
PREVIEW_IMAGE : Optional[gradio.Image] = None
|
||||||
|
|
||||||
@@ -90,10 +90,14 @@ def listen() -> None:
|
|||||||
|
|
||||||
for ui_component in get_ui_components(
|
for ui_component in get_ui_components(
|
||||||
[
|
[
|
||||||
'background_remover_color_red_number',
|
'background_remover_fill_color_red_number',
|
||||||
'background_remover_color_green_number',
|
'background_remover_fill_color_green_number',
|
||||||
'background_remover_color_blue_number',
|
'background_remover_fill_color_blue_number',
|
||||||
'background_remover_color_alpha_number',
|
'background_remover_fill_color_alpha_number',
|
||||||
|
'background_remover_despill_color_red_number',
|
||||||
|
'background_remover_despill_color_green_number',
|
||||||
|
'background_remover_despill_color_blue_number',
|
||||||
|
'background_remover_despill_color_alpha_number',
|
||||||
'face_debugger_items_checkbox_group',
|
'face_debugger_items_checkbox_group',
|
||||||
'frame_colorizer_size_dropdown',
|
'frame_colorizer_size_dropdown',
|
||||||
'face_mask_types_checkbox_group',
|
'face_mask_types_checkbox_group',
|
||||||
@@ -197,7 +201,7 @@ def update_preview_image(preview_mode : PreviewMode, preview_resolution : str, f
|
|||||||
reference_vision_frame = read_static_image(state_manager.get_item('target_path'))
|
reference_vision_frame = read_static_image(state_manager.get_item('target_path'))
|
||||||
target_vision_frame = read_static_image(state_manager.get_item('target_path'), 'rgba')
|
target_vision_frame = read_static_image(state_manager.get_item('target_path'), 'rgba')
|
||||||
target_vision_mask = extract_vision_mask(target_vision_frame)
|
target_vision_mask = extract_vision_mask(target_vision_frame)
|
||||||
target_vision_frame = conditional_merge_vision_mask(target_vision_frame, target_vision_mask)
|
target_vision_frame = merge_vision_mask(target_vision_frame, target_vision_mask)
|
||||||
preview_vision_frame = process_preview_frame(reference_vision_frame, source_vision_frames, source_audio_frame, source_voice_frame, target_vision_frame, preview_mode, preview_resolution)
|
preview_vision_frame = process_preview_frame(reference_vision_frame, source_vision_frames, source_audio_frame, source_voice_frame, target_vision_frame, preview_mode, preview_resolution)
|
||||||
preview_vision_frame = cv2.cvtColor(preview_vision_frame, cv2.COLOR_BGRA2RGBA)
|
preview_vision_frame = cv2.cvtColor(preview_vision_frame, cv2.COLOR_BGRA2RGBA)
|
||||||
return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ])
|
return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ])
|
||||||
@@ -206,7 +210,7 @@ def update_preview_image(preview_mode : PreviewMode, preview_resolution : str, f
|
|||||||
reference_vision_frame = read_video_frame(state_manager.get_item('target_path'), state_manager.get_item('reference_frame_number'))
|
reference_vision_frame = read_video_frame(state_manager.get_item('target_path'), state_manager.get_item('reference_frame_number'))
|
||||||
temp_vision_frame = read_video_frame(state_manager.get_item('target_path'), frame_number)
|
temp_vision_frame = read_video_frame(state_manager.get_item('target_path'), frame_number)
|
||||||
temp_vision_mask = extract_vision_mask(temp_vision_frame)
|
temp_vision_mask = extract_vision_mask(temp_vision_frame)
|
||||||
temp_vision_frame = conditional_merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
temp_vision_frame = merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
||||||
preview_vision_frame = process_preview_frame(reference_vision_frame, source_vision_frames, source_audio_frame, source_voice_frame, temp_vision_frame, preview_mode, preview_resolution)
|
preview_vision_frame = process_preview_frame(reference_vision_frame, source_vision_frames, source_audio_frame, source_voice_frame, temp_vision_frame, preview_mode, preview_resolution)
|
||||||
preview_vision_frame = cv2.cvtColor(preview_vision_frame, cv2.COLOR_BGRA2RGBA)
|
preview_vision_frame = cv2.cvtColor(preview_vision_frame, cv2.COLOR_BGRA2RGBA)
|
||||||
return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ])
|
return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ])
|
||||||
@@ -296,7 +300,7 @@ def extract_crop_frame(vision_frame : VisionFrame, face : Face) -> Optional[Visi
|
|||||||
|
|
||||||
|
|
||||||
def prepare_output_frame(target_vision_frame : VisionFrame, temp_vision_frame : VisionFrame, temp_vision_mask : Mask) -> VisionFrame:
|
def prepare_output_frame(target_vision_frame : VisionFrame, temp_vision_frame : VisionFrame, temp_vision_mask : Mask) -> VisionFrame:
|
||||||
temp_vision_mask = temp_vision_mask.clip(state_manager.get_item('background_remover_color')[-1], 255)
|
temp_vision_mask = temp_vision_mask.clip(state_manager.get_item('background_remover_fill_color')[-1], 255)
|
||||||
temp_vision_frame = conditional_merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
temp_vision_frame = merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
||||||
temp_vision_frame = cv2.resize(temp_vision_frame, target_vision_frame.shape[1::-1])
|
temp_vision_frame = cv2.resize(temp_vision_frame, target_vision_frame.shape[1::-1])
|
||||||
return temp_vision_frame
|
return temp_vision_frame
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Generator, List, Optional, Tuple
|
from typing import Iterator, List, Optional, Tuple
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import gradio
|
import gradio
|
||||||
@@ -10,7 +10,7 @@ from facefusion.streamer import multi_process_capture, open_stream
|
|||||||
from facefusion.types import Fps, VisionFrame, WebcamMode
|
from facefusion.types import Fps, VisionFrame, WebcamMode
|
||||||
from facefusion.uis.core import get_ui_component
|
from facefusion.uis.core import get_ui_component
|
||||||
from facefusion.uis.types import File
|
from facefusion.uis.types import File
|
||||||
from facefusion.vision import unpack_resolution
|
from facefusion.vision import fit_cover_frame, unpack_resolution
|
||||||
|
|
||||||
SOURCE_FILE : Optional[gradio.File] = None
|
SOURCE_FILE : Optional[gradio.File] = None
|
||||||
WEBCAM_IMAGE : Optional[gradio.Image] = None
|
WEBCAM_IMAGE : Optional[gradio.Image] = None
|
||||||
@@ -82,7 +82,7 @@ def pre_stop() -> Tuple[gradio.File, gradio.Image, gradio.Button, gradio.Button]
|
|||||||
return gradio.File(visible = True), gradio.Image(visible = False), gradio.Button(visible = True), gradio.Button(visible = False)
|
return gradio.File(visible = True), gradio.Image(visible = False), gradio.Button(visible = True), gradio.Button(visible = False)
|
||||||
|
|
||||||
|
|
||||||
def start(webcam_device_id : int, webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Generator[VisionFrame, None, None]:
|
def start(webcam_device_id : int, webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Iterator[VisionFrame]:
|
||||||
state_manager.init_item('face_selector_mode', 'one')
|
state_manager.init_item('face_selector_mode', 'one')
|
||||||
state_manager.sync_state()
|
state_manager.sync_state()
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ def start(webcam_device_id : int, webcam_mode : WebcamMode, webcam_resolution :
|
|||||||
stream = None
|
stream = None
|
||||||
|
|
||||||
if webcam_mode in [ 'udp', 'v4l2' ]:
|
if webcam_mode in [ 'udp', 'v4l2' ]:
|
||||||
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) # type:ignore[arg-type]
|
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) #type:ignore[arg-type]
|
||||||
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
|
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
|
||||||
|
|
||||||
if camera_capture and camera_capture.isOpened():
|
if camera_capture and camera_capture.isOpened():
|
||||||
@@ -98,14 +98,15 @@ def start(webcam_device_id : int, webcam_mode : WebcamMode, webcam_resolution :
|
|||||||
camera_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, webcam_height)
|
camera_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, webcam_height)
|
||||||
camera_capture.set(cv2.CAP_PROP_FPS, webcam_fps)
|
camera_capture.set(cv2.CAP_PROP_FPS, webcam_fps)
|
||||||
|
|
||||||
for capture_frame in multi_process_capture(camera_capture, webcam_fps):
|
for capture_vision_frame in multi_process_capture(camera_capture, webcam_fps):
|
||||||
capture_frame = cv2.cvtColor(capture_frame, cv2.COLOR_BGR2RGB)
|
capture_vision_frame = cv2.cvtColor(capture_vision_frame, cv2.COLOR_BGR2RGB)
|
||||||
|
capture_vision_frame = fit_cover_frame(capture_vision_frame, (webcam_width, webcam_height))
|
||||||
|
|
||||||
if webcam_mode == 'inline':
|
if webcam_mode == 'inline':
|
||||||
yield capture_frame
|
yield capture_vision_frame
|
||||||
else:
|
if webcam_mode in [ 'udp', 'v4l2' ]:
|
||||||
try:
|
try:
|
||||||
stream.stdin.write(capture_frame.tobytes())
|
stream.stdin.write(capture_vision_frame.tobytes())
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import importlib
|
import importlib
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
@@ -72,6 +73,7 @@ def init() -> None:
|
|||||||
os.environ['GRADIO_ANALYTICS_ENABLED'] = '0'
|
os.environ['GRADIO_ANALYTICS_ENABLED'] = '0'
|
||||||
os.environ['GRADIO_TEMP_DIR'] = os.path.join(state_manager.get_item('temp_path'), 'gradio')
|
os.environ['GRADIO_TEMP_DIR'] = os.path.join(state_manager.get_item('temp_path'), 'gradio')
|
||||||
|
|
||||||
|
logging.getLogger('asyncio').setLevel(logging.CRITICAL)
|
||||||
warnings.filterwarnings('ignore', category = UserWarning, module = 'gradio')
|
warnings.filterwarnings('ignore', category = UserWarning, module = 'gradio')
|
||||||
gradio.processing_utils._check_allowed = uis_overrides.mock
|
gradio.processing_utils._check_allowed = uis_overrides.mock
|
||||||
gradio.processing_utils.convert_video_to_playable_mp4 = uis_overrides.convert_video_to_playable_mp4
|
gradio.processing_utils.convert_video_to_playable_mp4 = uis_overrides.convert_video_to_playable_mp4
|
||||||
|
|||||||
@@ -6,10 +6,14 @@ ComponentName = Literal\
|
|||||||
'age_modifier_direction_slider',
|
'age_modifier_direction_slider',
|
||||||
'age_modifier_model_dropdown',
|
'age_modifier_model_dropdown',
|
||||||
'background_remover_model_dropdown',
|
'background_remover_model_dropdown',
|
||||||
'background_remover_color_red_number',
|
'background_remover_fill_color_red_number',
|
||||||
'background_remover_color_green_number',
|
'background_remover_fill_color_green_number',
|
||||||
'background_remover_color_blue_number',
|
'background_remover_fill_color_blue_number',
|
||||||
'background_remover_color_alpha_number',
|
'background_remover_fill_color_alpha_number',
|
||||||
|
'background_remover_despill_color_red_number',
|
||||||
|
'background_remover_despill_color_green_number',
|
||||||
|
'background_remover_despill_color_blue_number',
|
||||||
|
'background_remover_despill_color_alpha_number',
|
||||||
'deep_swapper_model_dropdown',
|
'deep_swapper_model_dropdown',
|
||||||
'deep_swapper_morph_slider',
|
'deep_swapper_morph_slider',
|
||||||
'expression_restorer_factor_slider',
|
'expression_restorer_factor_slider',
|
||||||
|
|||||||
@@ -355,7 +355,11 @@ def extract_vision_mask(vision_frame : VisionFrame) -> Mask:
|
|||||||
return numpy.full(vision_frame.shape[:2], 255, dtype = numpy.uint8)
|
return numpy.full(vision_frame.shape[:2], 255, dtype = numpy.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_vision_mask(vision_frame : VisionFrame, vision_mask : Mask) -> VisionFrame:
|
||||||
|
return numpy.dstack((vision_frame[:, :, :3], vision_mask))
|
||||||
|
|
||||||
|
|
||||||
def conditional_merge_vision_mask(vision_frame : VisionFrame, vision_mask : Mask) -> VisionFrame:
|
def conditional_merge_vision_mask(vision_frame : VisionFrame, vision_mask : Mask) -> VisionFrame:
|
||||||
if numpy.any(vision_mask < 255):
|
if numpy.any(vision_mask < 255):
|
||||||
return numpy.dstack((vision_frame[:, :, :3], vision_mask))
|
return merge_vision_mask(vision_frame, vision_mask)
|
||||||
return vision_frame
|
return vision_frame
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
|
|||||||
{
|
{
|
||||||
'__metadata__':
|
'__metadata__':
|
||||||
{
|
{
|
||||||
'vendor': 'Unknown',
|
'vendor': 'Anjok07',
|
||||||
'license': 'Non-Commercial',
|
'license': 'MIT',
|
||||||
'year': 2023
|
'year': 2023
|
||||||
},
|
},
|
||||||
'hashes':
|
'hashes':
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ def process(start_time : float) -> ErrorCode:
|
|||||||
setup,
|
setup,
|
||||||
prepare_image,
|
prepare_image,
|
||||||
process_image,
|
process_image,
|
||||||
partial(finalize_image, start_time),
|
partial(finalize_image, start_time)
|
||||||
]
|
]
|
||||||
process_manager.start()
|
process_manager.start()
|
||||||
|
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
error_code = task() # type:ignore[operator]
|
error_code = task() #type:ignore[operator]
|
||||||
|
|
||||||
if error_code > 0:
|
if error_code > 0:
|
||||||
process_manager.end()
|
process_manager.end()
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def process(start_time : float) -> ErrorCode:
|
|||||||
process_manager.start()
|
process_manager.start()
|
||||||
|
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
error_code = task() # type:ignore[operator]
|
error_code = task() #type:ignore[operator]
|
||||||
|
|
||||||
if error_code > 0:
|
if error_code > 0:
|
||||||
process_manager.end()
|
process_manager.end()
|
||||||
@@ -152,18 +152,6 @@ def restore_audio() -> ErrorCode:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def finalize_video(start_time : float) -> ErrorCode:
|
|
||||||
logger.debug(translator.get('clearing_temp'), __name__)
|
|
||||||
clear_temp_directory(state_manager.get_item('target_path'))
|
|
||||||
|
|
||||||
if is_video(state_manager.get_item('output_path')):
|
|
||||||
logger.info(translator.get('processing_video_succeeded').format(seconds = calculate_end_time(start_time)), __name__)
|
|
||||||
else:
|
|
||||||
logger.error(translator.get('processing_video_failed'), __name__)
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def process_temp_frame(temp_frame_path : str, frame_number : int) -> bool:
|
def process_temp_frame(temp_frame_path : str, frame_number : int) -> bool:
|
||||||
reference_vision_frame = read_static_video_frame(state_manager.get_item('target_path'), state_manager.get_item('reference_frame_number'))
|
reference_vision_frame = read_static_video_frame(state_manager.get_item('target_path'), state_manager.get_item('reference_frame_number'))
|
||||||
source_vision_frames = read_static_images(state_manager.get_item('source_paths'))
|
source_vision_frames = read_static_images(state_manager.get_item('source_paths'))
|
||||||
@@ -195,3 +183,15 @@ def process_temp_frame(temp_frame_path : str, frame_number : int) -> bool:
|
|||||||
|
|
||||||
temp_vision_frame = conditional_merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
temp_vision_frame = conditional_merge_vision_mask(temp_vision_frame, temp_vision_mask)
|
||||||
return write_image(temp_frame_path, temp_vision_frame)
|
return write_image(temp_frame_path, temp_vision_frame)
|
||||||
|
|
||||||
|
|
||||||
|
def finalize_video(start_time : float) -> ErrorCode:
|
||||||
|
logger.debug(translator.get('clearing_temp'), __name__)
|
||||||
|
clear_temp_directory(state_manager.get_item('target_path'))
|
||||||
|
|
||||||
|
if is_video(state_manager.get_item('output_path')):
|
||||||
|
logger.info(translator.get('processing_video_succeeded').format(seconds = calculate_end_time(start_time)), __name__)
|
||||||
|
else:
|
||||||
|
logger.error(translator.get('processing_video_failed'), __name__)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|||||||
+6
-7
@@ -1,9 +1,8 @@
|
|||||||
gradio-rangeslider==0.0.8
|
gradio-rangeslider==0.0.8
|
||||||
gradio==5.44.1
|
gradio==5.44.1
|
||||||
numpy==2.3.4
|
numpy==2.2.1
|
||||||
onnx==1.19.1
|
onnx==1.21.0
|
||||||
onnxruntime==1.23.2
|
onnxruntime==1.24.4
|
||||||
opencv-python==4.12.0.88
|
opencv-python==4.13.0.92
|
||||||
psutil==7.1.2
|
tqdm==4.67.3
|
||||||
tqdm==4.67.1
|
scipy==1.17.1
|
||||||
scipy==1.16.3
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def before_all() -> None:
|
|||||||
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
|
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
|
||||||
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
|
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
|
||||||
])
|
])
|
||||||
subprocess.run(['ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg')])
|
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope = 'function', autouse = True)
|
@pytest.fixture(scope = 'function', autouse = True)
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ def test_create_float_range() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_calc_int_step() -> None:
|
def test_calc_int_step() -> None:
|
||||||
assert calculate_int_step([0, 1]) == 1
|
assert calculate_int_step([ 0, 1 ]) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_calc_float_step() -> None:
|
def test_calc_float_step() -> None:
|
||||||
assert calculate_float_step([0.1, 0.2]) == 0.1
|
assert calculate_float_step([ 0.1, 0.2 ]) == 0.1
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
from shutil import which
|
from shutil import which
|
||||||
|
|
||||||
from facefusion import metadata
|
from facefusion import metadata
|
||||||
from facefusion.curl_builder import chain, head, run
|
from facefusion.curl_builder import chain, ping, run, set_timeout
|
||||||
|
|
||||||
|
|
||||||
def test_run() -> None:
|
def test_run() -> None:
|
||||||
user_agent = metadata.get('name') + '/' + metadata.get('version')
|
user_agent = metadata.get('name') + '/' + metadata.get('version')
|
||||||
|
|
||||||
assert run([]) == [ which('curl'), '--user-agent', user_agent, '--insecure', '--location', '--silent' ]
|
assert run([]) == [ which('curl'), '--user-agent', user_agent, '--location', '--silent', '--ssl-no-revoke' ]
|
||||||
|
|
||||||
|
|
||||||
def test_chain() -> None:
|
def test_chain() -> None:
|
||||||
assert chain(head(metadata.get('url'))) == [ '-I', metadata.get('url') ]
|
assert chain(
|
||||||
|
ping(metadata.get('url')),
|
||||||
|
set_timeout(5)
|
||||||
|
) == [ '-I', metadata.get('url'), '--connect-timeout', '5' ]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from facefusion.execution import create_inference_session_providers, get_available_execution_providers, has_execution_provider
|
from facefusion.execution import create_inference_providers, get_available_execution_providers, has_execution_provider
|
||||||
|
|
||||||
|
|
||||||
def test_has_execution_provider() -> None:
|
def test_has_execution_provider() -> None:
|
||||||
@@ -10,15 +10,15 @@ def test_get_available_execution_providers() -> None:
|
|||||||
assert 'cpu' in get_available_execution_providers()
|
assert 'cpu' in get_available_execution_providers()
|
||||||
|
|
||||||
|
|
||||||
def test_create_inference_session_providers() -> None:
|
def test_create_inference_providers() -> None:
|
||||||
inference_session_providers =\
|
inference_providers =\
|
||||||
[
|
[
|
||||||
('CUDAExecutionProvider',
|
('CUDAExecutionProvider',
|
||||||
{
|
{
|
||||||
'device_id': '1',
|
'device_id': 1,
|
||||||
'cudnn_conv_algo_search': 'EXHAUSTIVE'
|
'cudnn_conv_algo_search': 'EXHAUSTIVE'
|
||||||
}),
|
}),
|
||||||
'CPUExecutionProvider'
|
'CPUExecutionProvider'
|
||||||
]
|
]
|
||||||
|
|
||||||
assert create_inference_session_providers('1', [ 'cpu', 'cuda' ]) == inference_session_providers
|
assert create_inference_providers(1, [ 'cpu', 'cuda' ]) == inference_providers
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import pytest
|
|||||||
from facefusion import face_classifier, face_detector, face_landmarker, face_recognizer, state_manager
|
from facefusion import face_classifier, face_detector, face_landmarker, face_recognizer, state_manager
|
||||||
from facefusion.download import conditional_download
|
from facefusion.download import conditional_download
|
||||||
from facefusion.face_analyser import get_many_faces
|
from facefusion.face_analyser import get_many_faces
|
||||||
|
from facefusion.face_store import clear_static_faces
|
||||||
from facefusion.vision import read_static_image
|
from facefusion.vision import read_static_image
|
||||||
from .helper import get_test_example_file, get_test_examples_directory
|
from .helper import get_test_example_file, get_test_examples_directory
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ def before_all() -> None:
|
|||||||
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.8:ih*0.8', get_test_example_file('source-80crop.jpg') ])
|
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.8:ih*0.8', get_test_example_file('source-80crop.jpg') ])
|
||||||
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.7:ih*0.7', get_test_example_file('source-70crop.jpg') ])
|
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.7:ih*0.7', get_test_example_file('source-70crop.jpg') ])
|
||||||
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.6:ih*0.6', get_test_example_file('source-60crop.jpg') ])
|
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.6:ih*0.6', get_test_example_file('source-60crop.jpg') ])
|
||||||
state_manager.init_item('execution_device_ids', [ '0' ])
|
state_manager.init_item('execution_device_ids', [ 0 ])
|
||||||
state_manager.init_item('execution_providers', [ 'cpu' ])
|
state_manager.init_item('execution_providers', [ 'cpu' ])
|
||||||
state_manager.init_item('download_providers', [ 'github' ])
|
state_manager.init_item('download_providers', [ 'github' ])
|
||||||
state_manager.init_item('face_detector_angles', [ 0 ])
|
state_manager.init_item('face_detector_angles', [ 0 ])
|
||||||
@@ -37,6 +38,7 @@ def before_each() -> None:
|
|||||||
face_detector.clear_inference_pool()
|
face_detector.clear_inference_pool()
|
||||||
face_landmarker.clear_inference_pool()
|
face_landmarker.clear_inference_pool()
|
||||||
face_recognizer.clear_inference_pool()
|
face_recognizer.clear_inference_pool()
|
||||||
|
clear_static_faces()
|
||||||
|
|
||||||
|
|
||||||
def test_get_one_face_with_retinaface() -> None:
|
def test_get_one_face_with_retinaface() -> None:
|
||||||
@@ -62,7 +64,7 @@ def test_get_one_face_with_retinaface() -> None:
|
|||||||
|
|
||||||
def test_get_one_face_with_scrfd() -> None:
|
def test_get_one_face_with_scrfd() -> None:
|
||||||
state_manager.init_item('face_detector_model', 'scrfd')
|
state_manager.init_item('face_detector_model', 'scrfd')
|
||||||
state_manager.init_item('face_detector_size', '640x640')
|
state_manager.init_item('face_detector_size', '320x320')
|
||||||
state_manager.init_item('face_detector_margin', (0, 0, 0, 0))
|
state_manager.init_item('face_detector_margin', (0, 0, 0, 0))
|
||||||
face_detector.pre_check()
|
face_detector.pre_check()
|
||||||
|
|
||||||
@@ -82,7 +84,7 @@ def test_get_one_face_with_scrfd() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_get_one_face_with_yoloface() -> None:
|
def test_get_one_face_with_yoloface() -> None:
|
||||||
state_manager.init_item('face_detector_model', 'yoloface')
|
state_manager.init_item('face_detector_model', 'yolo_face')
|
||||||
state_manager.init_item('face_detector_size', '640x640')
|
state_manager.init_item('face_detector_size', '640x640')
|
||||||
state_manager.init_item('face_detector_margin', (0, 0, 0, 0))
|
state_manager.init_item('face_detector_margin', (0, 0, 0, 0))
|
||||||
face_detector.pre_check()
|
face_detector.pre_check()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from facefusion.inference_manager import INFERENCE_POOL_SET, get_inference_pool
|
|||||||
|
|
||||||
@pytest.fixture(scope = 'module', autouse = True)
|
@pytest.fixture(scope = 'module', autouse = True)
|
||||||
def before_all() -> None:
|
def before_all() -> None:
|
||||||
state_manager.init_item('execution_device_ids', [ '0' ])
|
state_manager.init_item('execution_device_ids', [ 0 ])
|
||||||
state_manager.init_item('execution_providers', [ 'cpu' ])
|
state_manager.init_item('execution_providers', [ 'cpu' ])
|
||||||
state_manager.init_item('download_providers', [ 'github' ])
|
state_manager.init_item('download_providers', [ 'github' ])
|
||||||
content_analyser.pre_check()
|
content_analyser.pre_check()
|
||||||
|
|||||||
+5
-2
@@ -1,10 +1,12 @@
|
|||||||
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from facefusion.json import read_json, write_json
|
from facefusion.json import read_json, write_json
|
||||||
|
|
||||||
|
|
||||||
def test_read_json() -> None:
|
def test_read_json() -> None:
|
||||||
_, json_path = tempfile.mkstemp(suffix = '.json')
|
file_descriptor, json_path = tempfile.mkstemp(suffix = '.json')
|
||||||
|
os.close(file_descriptor)
|
||||||
|
|
||||||
assert not read_json(json_path)
|
assert not read_json(json_path)
|
||||||
|
|
||||||
@@ -14,6 +16,7 @@ def test_read_json() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_write_json() -> None:
|
def test_write_json() -> None:
|
||||||
_, json_path = tempfile.mkstemp(suffix = '.json')
|
file_descriptor, json_path = tempfile.mkstemp(suffix = '.json')
|
||||||
|
os.close(file_descriptor)
|
||||||
|
|
||||||
assert write_json(json_path, {})
|
assert write_json(json_path, {})
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
import pytest
|
from facefusion.program_helper import find_argument_group, validate_actions, validate_args
|
||||||
|
|
||||||
from facefusion.program_helper import find_argument_group, validate_actions
|
|
||||||
|
|
||||||
|
|
||||||
def test_find_argument_group() -> None:
|
def test_find_argument_group() -> None:
|
||||||
@@ -12,12 +10,26 @@ def test_find_argument_group() -> None:
|
|||||||
|
|
||||||
assert find_argument_group(program, 'test-1')
|
assert find_argument_group(program, 'test-1')
|
||||||
assert find_argument_group(program, 'test-2')
|
assert find_argument_group(program, 'test-2')
|
||||||
assert find_argument_group(program, 'invalid') is None
|
assert find_argument_group(program, 'test-3') is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
|
||||||
def test_validate_args() -> None:
|
def test_validate_args() -> None:
|
||||||
pass
|
program = ArgumentParser()
|
||||||
|
program.add_argument('--test-1', default = 'test_1', choices = [ 'test_1', 'test_2' ])
|
||||||
|
|
||||||
|
assert validate_args(program) is True
|
||||||
|
|
||||||
|
subparsers = program.add_subparsers()
|
||||||
|
sub_program = subparsers.add_parser('sub-command')
|
||||||
|
sub_program.add_argument('--test-2', default = 'test_2', choices = [ 'test_1', 'test_2' ])
|
||||||
|
|
||||||
|
assert validate_args(program) is True
|
||||||
|
|
||||||
|
for action in sub_program._actions:
|
||||||
|
if action.dest == 'test_2':
|
||||||
|
action.default = 'test_3'
|
||||||
|
|
||||||
|
assert validate_args(program) is False
|
||||||
|
|
||||||
|
|
||||||
def test_validate_actions() -> None:
|
def test_validate_actions() -> None:
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ from facefusion.sanitizer import sanitize_int_range
|
|||||||
|
|
||||||
def test_sanitize_int_range() -> None:
|
def test_sanitize_int_range() -> None:
|
||||||
assert sanitize_int_range(0, [ 0, 1, 2 ]) == 0
|
assert sanitize_int_range(0, [ 0, 1, 2 ]) == 0
|
||||||
assert sanitize_int_range(2, [0, 1, 2]) == 2
|
assert sanitize_int_range(2, [ 0, 1, 2 ]) == 2
|
||||||
assert sanitize_int_range(-1, [ 0, 1 ]) == 0
|
assert sanitize_int_range(-1, [ 0, 1 ]) == 0
|
||||||
assert sanitize_int_range(3, [ 0, 1 ]) == 0
|
assert sanitize_int_range(3, [ 0, 1 ]) == 0
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
from facefusion import translator
|
from facefusion import translator
|
||||||
from facefusion.locals import LOCALS
|
from facefusion.locales import LOCALES
|
||||||
|
|
||||||
|
|
||||||
def test_load() -> None:
|
def test_load() -> None:
|
||||||
translator.load(LOCALS, __name__)
|
translator.load(LOCALES, __name__)
|
||||||
|
|
||||||
assert __name__ in translator.LOCAL_POOL_SET
|
assert __name__ in translator.LOCALE_POOL_SET
|
||||||
|
|
||||||
|
|
||||||
def test_get() -> None:
|
def test_get() -> None:
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from facefusion.common_helper import is_linux
|
||||||
from facefusion.download import conditional_download
|
from facefusion.download import conditional_download
|
||||||
from facefusion.vision import calculate_histogram_difference, count_trim_frame_total, count_video_frame_total, detect_image_resolution, detect_video_duration, detect_video_fps, detect_video_resolution, match_frame_color, normalize_resolution, pack_resolution, predict_video_frame_total, read_image, read_video_frame, restrict_image_resolution, restrict_trim_frame, restrict_video_fps, restrict_video_resolution, scale_resolution, unpack_resolution, write_image
|
from facefusion.vision import calculate_histogram_difference, count_trim_frame_total, count_video_frame_total, detect_image_resolution, detect_video_duration, detect_video_fps, detect_video_resolution, match_frame_color, normalize_resolution, pack_resolution, predict_video_frame_total, read_image, read_video_frame, restrict_image_resolution, restrict_trim_frame, restrict_video_fps, restrict_video_resolution, scale_resolution, unpack_resolution, write_image
|
||||||
from .helper import get_test_example_file, get_test_examples_directory, get_test_output_file, prepare_test_output_directory
|
from .helper import get_test_example_file, get_test_examples_directory, get_test_output_file, prepare_test_output_directory
|
||||||
@@ -92,11 +94,13 @@ def test_restrict_video_fps() -> None:
|
|||||||
assert restrict_video_fps(get_test_example_file('target-1080p.mp4'), 60.0) == 25.0
|
assert restrict_video_fps(get_test_example_file('target-1080p.mp4'), 60.0) == 25.0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get('CI') and is_linux(), reason = 'h264 codec not present')
|
||||||
def test_detect_video_duration() -> None:
|
def test_detect_video_duration() -> None:
|
||||||
assert detect_video_duration(get_test_example_file('target-240p.mp4')) == 10.8
|
assert detect_video_duration(get_test_example_file('target-240p.mp4')) == 10.8
|
||||||
assert detect_video_duration('invalid') == 0
|
assert detect_video_duration('invalid') == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get('CI') and is_linux(), reason = 'h264 codec not present')
|
||||||
def test_count_trim_frame_total() -> None:
|
def test_count_trim_frame_total() -> None:
|
||||||
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), 0, 200) == 200
|
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), 0, 200) == 200
|
||||||
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), 70, 270) == 200
|
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), 70, 270) == 200
|
||||||
@@ -107,6 +111,7 @@ def test_count_trim_frame_total() -> None:
|
|||||||
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), None, None) == 270
|
assert count_trim_frame_total(get_test_example_file('target-240p.mp4'), None, None) == 270
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get('CI') and is_linux(), reason = 'h264 codec not present')
|
||||||
def test_restrict_trim_frame() -> None:
|
def test_restrict_trim_frame() -> None:
|
||||||
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), 0, 200) == (0, 200)
|
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), 0, 200) == (0, 200)
|
||||||
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), 70, 270) == (70, 270)
|
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), 70, 270) == (70, 270)
|
||||||
@@ -117,6 +122,7 @@ def test_restrict_trim_frame() -> None:
|
|||||||
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), None, None) == (0, 270)
|
assert restrict_trim_frame(get_test_example_file('target-240p.mp4'), None, None) == (0, 270)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(os.environ.get('CI') and is_linux(), reason = 'h264 codec not present')
|
||||||
def test_detect_video_resolution() -> None:
|
def test_detect_video_resolution() -> None:
|
||||||
assert detect_video_resolution(get_test_example_file('target-240p.mp4')) == (426, 226)
|
assert detect_video_resolution(get_test_example_file('target-240p.mp4')) == (426, 226)
|
||||||
assert detect_video_resolution(get_test_example_file('target-240p-90deg.mp4')) == (226, 426)
|
assert detect_video_resolution(get_test_example_file('target-240p-90deg.mp4')) == (226, 426)
|
||||||
|
|||||||
Reference in New Issue
Block a user