Added Multi Face

Added ability to upload multiple source face files and have it apply them all to each diffused image
This commit is contained in:
jiveabillion 2023-11-27 17:13:21 -05:00
parent de84e022ee
commit 0f7f73d47f
2 changed files with 141 additions and 38 deletions

View File

@ -1,5 +1,6 @@
import os, glob import os, glob
import gradio as gr import gradio as gr
import tempfile
from PIL import Image from PIL import Image
try: try:
import torch.cuda as cuda import torch.cuda as cuda
@ -8,7 +9,7 @@ except:
EP_is_visible = False EP_is_visible = False
from typing import List from typing import List
from PIL import Image
import modules.scripts as scripts import modules.scripts as scripts
from modules.upscaler import Upscaler, UpscalerData from modules.upscaler import Upscaler, UpscalerData
from modules import scripts, shared, images, scripts_postprocessing from modules import scripts, shared, images, scripts_postprocessing
@ -65,10 +66,11 @@ class FaceSwapScript(scripts.Script):
with gr.Tab("Main"): with gr.Tab("Main"):
with gr.Column(): with gr.Column():
img = gr.Image(type="pil") img = gr.Image(type="pil")
face_files = gr.File(label="Multiple Source Face Files",file_count="multiple",file_types=["image"],info="Upload multiple face files and each file will be processed in post processing")
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}") enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
save_original = gr.Checkbox(False, label="Save Original", info="Save the original image(s) made before swapping; If you use \"img2img\" - this option will affect with \"Swap in generated\" only") save_original = gr.Checkbox(False, label="Save Original", info="Save the original image(s) made before swapping; If you use \"img2img\" - this option will affect with \"Swap in generated\" only")
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.") mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
gr.Markdown("<br>") gr.Markdown("<br>")
gr.Markdown("Source Image (above):") gr.Markdown("Source Image (above):")
with gr.Row(): with gr.Row():
@ -143,13 +145,16 @@ class FaceSwapScript(scripts.Script):
) )
with gr.Tab("Masking"): with gr.Tab("Masking"):
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.") save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
mask_areas = gr.CheckboxGroup( mask_areas = gr.CheckboxGroup(
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
) )
mask_blur = gr.Slider(label="Mask blur ", minimum=0, maximum=64, step=1, value=MaskOption.DEFAULT_MASK_BLUR,info="The number of pixels from the outer edge of the mask to blur.")
face_size = gr.Radio( face_size = gr.Radio(
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512." label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
) )
mask_blur = gr.Slider(label="Mask blur", minimum=0, maximum=64, step=1, value=12,info="The number of pixels from the outer edge of the mask to blur.")
mask_vignette_fallback_threshold = gr.Slider( mask_vignette_fallback_threshold = gr.Slider(
minimum=0.1, minimum=0.1,
maximum=1.0, maximum=1.0,
@ -158,7 +163,6 @@ class FaceSwapScript(scripts.Script):
label="Vignette fallback threshold", label="Vignette fallback threshold",
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size." info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
) )
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
with gr.Tab("Settings"): with gr.Tab("Settings"):
models = get_models() models = get_models()
with gr.Row(visible=EP_is_visible): with gr.Row(visible=EP_is_visible):
@ -239,7 +243,7 @@ class FaceSwapScript(scripts.Script):
use_minimal_area, use_minimal_area,
face_size, face_size,
mask_vignette_fallback_threshold, mask_vignette_fallback_threshold,
face_files
] ]
@ -304,22 +308,23 @@ class FaceSwapScript(scripts.Script):
target_hash_check, target_hash_check,
device, device,
mask_face, mask_face,
save_face_mask, save_face_mask:bool,
mask_areas, mask_areas,
mask_blur, mask_blur:int,
mask_use_minimal_area, mask_use_minimal_area,
mask_face_size, mask_face_size,
mask_vignette_fallback_threshold, mask_vignette_fallback_threshold,
face_files
): ):
self.enable = enable self.enable = enable
if self.enable: if self.enable:
reset_messaged() reset_messaged()
if check_process_halt(): if check_process_halt():
return return
global MODELS_PATH global MODELS_PATH
self.source = img self.source = img
self.face_restorer_name = face_restorer_name self.face_restorer_name = face_restorer_name
self.upscaler_scale = upscaler_scale self.upscaler_scale = upscaler_scale
@ -345,6 +350,7 @@ class FaceSwapScript(scripts.Script):
self.mask_face_size = mask_face_size self.mask_face_size = mask_face_size
self.mask_vignette_fallback_threshold = mask_vignette_fallback_threshold self.mask_vignette_fallback_threshold = mask_vignette_fallback_threshold
self.mask_use_minimal_area = mask_use_minimal_area self.mask_use_minimal_area = mask_use_minimal_area
self.face_files = face_files
if self.gender_source is None or self.gender_source == "No": if self.gender_source is None or self.gender_source == "No":
self.gender_source = 0 self.gender_source = 0
if self.gender_target is None or self.gender_target == "No": if self.gender_target is None or self.gender_target == "No":
@ -367,9 +373,9 @@ class FaceSwapScript(scripts.Script):
self.target_hash_check = False self.target_hash_check = False
set_Device(self.device) set_Device(self.device)
logger.status(f"Self: {self}") apply_logging_patch(console_logging_level)
if self.source is not None: if self.source is not None:
apply_logging_patch(console_logging_level)
if isinstance(p, StableDiffusionProcessingImg2Img) and self.swap_in_source: if isinstance(p, StableDiffusionProcessingImg2Img) and self.swap_in_source:
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index) logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
@ -401,7 +407,7 @@ class FaceSwapScript(scripts.Script):
if shared.state.interrupted or shared.state.skipped: if shared.state.interrupted or shared.state.skipped:
return return
else: elif self.face_files is None or len(self.face_files) == 0:
logger.error("Please provide a source face") logger.error("Please provide a source face")
def postprocess(self, p: StableDiffusionProcessing, processed: Processed, *args): def postprocess(self, p: StableDiffusionProcessing, processed: Processed, *args):
@ -410,14 +416,15 @@ class FaceSwapScript(scripts.Script):
reset_messaged() reset_messaged()
if check_process_halt(): if check_process_halt():
return return
postprocess_run: bool = True
orig_images : List[Image.Image] = processed.images[processed.index_of_first_image:]
orig_infotexts : List[str] = processed.infotexts[processed.index_of_first_image:]
result_images:List[Image.Image] = []
if self.save_original: if self.save_original:
postprocess_run: bool = True
orig_images : List[Image.Image] = processed.images[processed.index_of_first_image:]
orig_infotexts : List[str] = processed.infotexts[processed.index_of_first_image:]
result_images: List = processed.images result_images: List = processed.images
# result_info: List = processed.infotexts # result_info: List = processed.infotexts
@ -469,7 +476,48 @@ class FaceSwapScript(scripts.Script):
# fullfn = split_fullfn[0] + ".txt" # fullfn = split_fullfn[0] + ".txt"
# with open(fullfn, 'w', encoding="utf8") as f: # with open(fullfn, 'w', encoding="utf8") as f:
# f.writelines(output) # f.writelines(output)
if self.face_files is not None and len(self.face_files) > 0:
for i,(img,info) in enumerate(zip(orig_images, orig_infotexts)):
for j,f_img in enumerate(self.face_files):
if check_process_halt():
postprocess_run = False
break
if len(self.face_files) > 1:
logger.status("Swap in face file #%s", j+1)
result, output, swapped, masked_faces = swap_face(
Image.open(os.path.abspath(f_img.name)),
img,
source_faces_index=self.source_faces_index,
faces_index=self.faces_index,
model=self.model,
enhancement_options=self.enhancement_options,
gender_source=self.gender_source,
gender_target=self.gender_target,
source_hash_check=self.source_hash_check,
target_hash_check=self.target_hash_check,
device=self.device,
mask_face=self.mask_face,
mask_options=self.mask_options
)
if result is not None and swapped > 0:
result_images.append(result)
suffix = f"-swapped-ff-{j+1}"
try:
img_path = save_image(result, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
except:
logger.error("Cannot save a result image - please, check SD WebUI Settings (Saving and Paths)")
if self.mask_face and self.save_face_mask and masked_faces is not None:
result_images.append(masked_faces)
suffix = f"-mask-ff-{j+1}"
try:
img_path = save_image(masked_faces, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
except:
logger.error("Cannot save a Masked Face image - please, check SD WebUI Settings (Saving and Paths)")
elif result is None:
logger.error("Cannot create a result image")
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run: if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
grid = make_grid(result_images) grid = make_grid(result_images)
result_images.insert(0, grid) result_images.insert(0, grid)
@ -480,13 +528,62 @@ class FaceSwapScript(scripts.Script):
processed.images = result_images processed.images = result_images
# processed.infotexts = result_info # processed.infotexts = result_info
elif self.face_files is not None and len(self.face_files) > 0:
for i,(img,info) in enumerate(zip(orig_images, orig_infotexts)):
for j,f_img in enumerate(self.face_files):
if check_process_halt():
postprocess_run = False
break
if len(self.face_files) > 1:
logger.status("Swap in face file #%s", j+1)
result, output, swapped, masked_faces = swap_face(
Image.open(os.path.abspath(f_img.name)),
img,
source_faces_index=self.source_faces_index,
faces_index=self.faces_index,
model=self.model,
enhancement_options=self.enhancement_options,
gender_source=self.gender_source,
gender_target=self.gender_target,
source_hash_check=self.source_hash_check,
target_hash_check=self.target_hash_check,
device=self.device,
mask_face=self.mask_face,
mask_options=self.mask_options
)
if result is not None and swapped > 0:
result_images.append(result)
suffix = f"-swapped-ff-{j+1}"
try:
img_path = save_image(result, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
except:
logger.error("Cannot save a result image - please, check SD WebUI Settings (Saving and Paths)")
if self.mask_face and self.save_face_mask and masked_faces is not None:
result_images.append(masked_faces)
suffix = f"-mask-ff-{j+1}"
try:
img_path = save_image(masked_faces, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
except:
logger.error("Cannot save a Masked Face image - please, check SD WebUI Settings (Saving and Paths)")
elif result is None:
logger.error("Cannot create a result image")
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
grid = make_grid(result_images)
result_images.insert(0, grid)
try:
save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], shared.opts.grid_format, info=info, short_filename=not shared.opts.grid_extended_filename, p=p, grid=True)
except:
logger.error("Cannot save a grid - please, check SD WebUI Settings (Saving and Paths)")
processed.images = result_images
def postprocess_batch(self, p, *args, **kwargs): def postprocess_batch(self, p, *args, **kwargs):
if self.enable and not self.save_original: if self.enable and not self.save_original:
images = kwargs["images"] images = kwargs["images"]
def postprocess_image(self, p, script_pp: scripts.PostprocessImageArgs, *args): def postprocess_image(self, p, script_pp: scripts.PostprocessImageArgs, *args):
if self.enable and self.swap_in_generated and not self.save_original: if self.enable and self.swap_in_generated and not ( self.save_original or ( self.face_files is not None and len(self.face_files) > 0)):
current_job_number = shared.state.job_no + 1 current_job_number = shared.state.job_no + 1
job_count = shared.state.job_count job_count = shared.state.job_count
@ -498,7 +595,7 @@ class FaceSwapScript(scripts.Script):
if self.source is not None: if self.source is not None:
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index) logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
image: Image.Image = script_pp.image image: Image.Image = script_pp.image
result, output, swapped = swap_face( result, output, swapped, masked_faces = swap_face(
self.source, self.source,
image, image,
source_faces_index=self.source_faces_index, source_faces_index=self.source_faces_index,
@ -510,7 +607,8 @@ class FaceSwapScript(scripts.Script):
source_hash_check=self.source_hash_check, source_hash_check=self.source_hash_check,
target_hash_check=self.target_hash_check, target_hash_check=self.target_hash_check,
device=self.device, device=self.device,
mask_face=self.mask_face mask_face=self.mask_face,
mask_options=self.mask_options
) )
try: try:
pp = scripts_postprocessing.PostprocessedImage(result) pp = scripts_postprocessing.PostprocessedImage(result)
@ -525,7 +623,7 @@ class FaceSwapScript(scripts.Script):
# f.writelines(output) # f.writelines(output)
except: except:
logger.error("Cannot create a result image") logger.error("Cannot create a result image")
class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing): class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
name = 'ReActor' name = 'ReActor'
@ -536,9 +634,9 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
with gr.Tab("Main"): with gr.Tab("Main"):
with gr.Column(): with gr.Column():
img = gr.Image(type="pil") img = gr.Image(type="pil")
face_files = gr.File(file_count="multiple",file_types=["image"],info="Upload multiple face files and each file will be processed in post processing")
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}") enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.") mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
gr.Markdown("Source Image (above):") gr.Markdown("Source Image (above):")
with gr.Row(): with gr.Row():
source_faces_index = gr.Textbox( source_faces_index = gr.Textbox(
@ -599,13 +697,16 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
) )
with gr.Tab("Masking"): with gr.Tab("Masking"):
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.") save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
mask_areas = gr.CheckboxGroup( mask_areas = gr.CheckboxGroup(
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
) )
mask_blur = gr.Slider(label="Mask blur ", minimum=0, maximum=64, step=1, value=MaskOption.DEFAULT_MASK_BLUR,info="The number of pixels from the outer edge of the mask to blur.")
face_size = gr.Radio( face_size = gr.Radio(
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512." label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
) )
mask_blur = gr.Slider(label="Mask blur", minimum=0, maximum=64, step=1, value=12,info="The number of pixels from the outer edge of the mask to blur.")
mask_vignette_fallback_threshold = gr.Slider( mask_vignette_fallback_threshold = gr.Slider(
minimum=0.1, minimum=0.1,
maximum=1.0, maximum=1.0,
@ -614,7 +715,6 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
label="Vignette fallback threshold", label="Vignette fallback threshold",
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size." info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
) )
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
with gr.Tab("Settings"): with gr.Tab("Settings"):
models = get_models() models = get_models()
@ -654,7 +754,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
label="Console Log Level", label="Console Log Level",
type="index", type="index",
) )
args = { args = {
'img': img, 'img': img,
'enable': enable, 'enable': enable,
@ -679,6 +779,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
'mask_vignette_fallback_threshold':mask_vignette_fallback_threshold, 'mask_vignette_fallback_threshold':mask_vignette_fallback_threshold,
'face_size':face_size, 'face_size':face_size,
'use_minimal_area':use_minimal_area, 'use_minimal_area':use_minimal_area,
'face_files':face_files
} }
return args return args
@ -713,9 +814,9 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
mask_areas = self.mask_areas, mask_areas = self.mask_areas,
save_face_mask = self.save_face_mask, save_face_mask = self.save_face_mask,
mask_blur = self.mask_blur, mask_blur = self.mask_blur,
face_size = self.mask_face_size, face_size = self.face_size,
vignette_fallback_threshold = self.mask_vignette_fallback_threshold, vignette_fallback_threshold = self.mask_vignette_fallback_threshold,
use_minimal_area = self.mask_use_minimal_area, use_minimal_area = self.use_minimal_area,
) )
def process(self, pp: scripts_postprocessing.PostprocessedImage, **args): def process(self, pp: scripts_postprocessing.PostprocessedImage, **args):
if args['enable']: if args['enable']:
@ -723,6 +824,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
if check_process_halt(): if check_process_halt():
return return
global MODELS_PATH global MODELS_PATH
self.source = args['img'] self.source = args['img']
self.face_restorer_name = args['face_restorer_name'] self.face_restorer_name = args['face_restorer_name']
self.upscaler_scale = args['upscaler_scale'] self.upscaler_scale = args['upscaler_scale']
@ -743,6 +845,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
self.mask_vignette_fallback_threshold= args['mask_vignette_fallback_threshold'] self.mask_vignette_fallback_threshold= args['mask_vignette_fallback_threshold']
self.face_size= args['face_size'] self.face_size= args['face_size']
self.use_minimal_area= args['use_minimal_area'] self.use_minimal_area= args['use_minimal_area']
self.face_files = args['face_files']
if self.gender_source is None or self.gender_source == "No": if self.gender_source is None or self.gender_source == "No":
self.gender_source = 0 self.gender_source = 0
if self.gender_target is None or self.gender_target == "No": if self.gender_target is None or self.gender_target == "No":
@ -764,12 +867,12 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
reset_messaged() reset_messaged()
set_Device(self.device) set_Device(self.device)
apply_logging_patch(self.console_logging_level)
if self.source is not None: if self.source is not None:
apply_logging_patch(self.console_logging_level)
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index) logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
image: Image.Image = pp.image image: Image.Image = pp.image
result, output, swapped = swap_face( result, output, swapped,masked_faces = swap_face(
self.source, self.source,
image, image,
source_faces_index=self.source_faces_index, source_faces_index=self.source_faces_index,

View File

@ -43,10 +43,10 @@ else:
PROVIDERS = ["CPUExecutionProvider"] PROVIDERS = ["CPUExecutionProvider"]
class MaskOption: class MaskOption:
DEFAULT_FACE_AREAS = ["Face"] DEFAULT_FACE_AREAS = ["Face"]
DEFAULT_FACE_SIZE = 512 DEFAULT_FACE_SIZE:int = 512
DEFAULT_VIGNETTE_THRESHOLD = 0.1 DEFAULT_VIGNETTE_THRESHOLD:float = 0.1
DEFAULT_MASK_BLUR = 12, DEFAULT_MASK_BLUR:int = 12,
DEFAULT_USE_MINIMAL_AREA = True DEFAULT_USE_MINIMAL_AREA:bool = True
@dataclass @dataclass
class EnhancementOptions: class EnhancementOptions:
@ -63,7 +63,7 @@ class EnhancementOptions:
class MaskOptions: class MaskOptions:
mask_areas:List[str] mask_areas:List[str]
save_face_mask: bool = False save_face_mask: bool = False
mask_blur:int = 12 mask_blur:int = 12
face_size:int = 512 face_size:int = 512
vignette_fallback_threshold:float =0.10 vignette_fallback_threshold:float =0.10
use_minimal_area:bool = True use_minimal_area:bool = True
@ -336,7 +336,7 @@ def swap_face(
): ):
global SOURCE_FACES, SOURCE_IMAGE_HASH, TARGET_FACES, TARGET_IMAGE_HASH, PROVIDERS global SOURCE_FACES, SOURCE_IMAGE_HASH, TARGET_FACES, TARGET_IMAGE_HASH, PROVIDERS
result_image = target_img result_image = target_img
masked_faces = None
PROVIDERS = ["CUDAExecutionProvider"] if device == "CUDA" else ["CPUExecutionProvider"] PROVIDERS = ["CUDAExecutionProvider"] if device == "CUDA" else ["CPUExecutionProvider"]
if check_process_halt(): if check_process_halt():