turns-00044.parquet:9365
952238cd2dc4279b23e50f83
turn 1/1o1-mini-2024-09-12EnglishUnited States1895 words
degenerate_repetitionAbsentFinal dense release
USER
make a gui script that adds based on dfm folder all the dfms to this file and is it possible to get res of model from the model itself if so then use that for the res and there should be a entry per dfm links can stay the same and in gui let me select the py file and also the dfm folder and make all dfms point to the dfm folder here is script from argparse import ArgumentParser
from typing import List, Tuple
import cv2
import numpy
import facefusion.jobs.job_manager
import facefusion.jobs.job_store
import facefusion.processors.core as processors
from facefusion import config, content_analyser, face_classifier, face_detector, face_landmarker, face_masker, face_recognizer, inference_manager, logger, process_manager, state_manager, wording
from facefusion.download import conditional_download_hashes, conditional_download_sources
from facefusion.face_analyser import get_many_faces, get_one_face
from facefusion.face_helper import paste_back, warp_face_by_face_landmark_5
from facefusion.face_masker import create_occlusion_mask, create_static_box_mask
from facefusion.face_selector import find_similar_faces, sort_and_filter_faces
from facefusion.face_store import get_reference_faces
from facefusion.filesystem import in_directory, is_image, is_video, resolve_relative_path, same_file_extension
from facefusion.processors import choices as processors_choices
from facefusion.processors.typing import DeepSwapperInputs
from facefusion.program_helper import find_argument_group
from facefusion.thread_helper import thread_semaphore
from facefusion.typing import ApplyStateItem, Args, Face, InferencePool, Mask, ModelOptions, ModelSet, ProcessMode, QueuePayload, UpdateProgress, VisionFrame
from facefusion.vision import adaptive_match_frame_color, read_image, read_static_image, write_image
MODEL_SET : ModelSet =\
{
'jackie_chan':
{
'hashes':
{
'deep_swapper':
{
'url': 'https://huggingface.co/bluefoxcreation/DFM/resolve/main/Jackie_Chan.hash',
'path': resolve_relative_path('../.assets/models/Jackie_Chan.hash')
}
},
'sources':
{
'deep_swapper':
{
'url': 'https://github.com/iperov/DeepFaceLive/releases/download/JACKIE_CHAN/Jackie_Chan.dfm',
'path': resolve_relative_path('../.assets/models/Jackie_Chan.dfm')
}
},
'template': 'arcface_128_v2',
'size': (224, 224)
}
}
def get_inference_pool() -> InferencePool:
model_sources = get_model_options().get('sources')
model_context = __name__ + '.' + state_manager.get_item('deep_swapper_model')
return inference_manager.get_inference_pool(model_context, model_sources)
def clear_inference_pool() -> None:
model_context = __name__ + '.' + state_manager.get_item('deep_swapper_model')
inference_manager.clear_inference_pool(model_context)
def get_model_options() -> ModelOptions:
deep_swapper_model = state_manager.get_item('deep_swapper_model')
return MODEL_SET.get(deep_swapper_model)
def register_args(program : ArgumentParser) -> None:
group_processors = find_argument_group(program, 'processors')
if group_processors:
group_processors.add_argument('--deep-swapper-model', help = wording.get('help.deep_swapper_model'), default = config.get_str_value('processors.deep_swapper_model', 'jackie_chan'), choices = processors_choices.deep_swapper_models)
facefusion.jobs.job_store.register_step_keys([ 'deep_swapper_model' ])
def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
apply_state_item('deep_swapper_model', args.get('deep_swapper_model'))
def pre_check() -> bool:
download_directory_path = resolve_relative_path('../.assets/models')
model_hashes = get_model_options().get('hashes')
model_sources = get_model_options().get('sources')
return conditional_download_hashes(download_directory_path, model_hashes) and conditional_download_sources(download_directory_path, model_sources)
def pre_process(mode : ProcessMode) -> bool:
if mode in [ 'output', 'preview' ] and not is_image(state_manager.get_item('target_path')) and not is_video(state_manager.get_item('target_path')):
logger.error(wording.get('choose_image_or_video_target') + wording.get('exclamation_mark'), __name__)
return False
if mode == 'output' and not in_directory(state_manager.get_item('output_path')):
logger.error(wording.get('specify_image_or_video_output') + wording.get('exclamation_mark'), __name__)
return False
if mode == 'output' and not same_file_extension([ state_manager.get_item('target_path'), state_manager.get_item('output_path') ]):
logger.error(wording.get('match_target_and_output_extension') + wording.get('exclamation_mark'), __name__)
return False
return True
def post_process() -> None:
read_static_image.cache_clear()
if state_manager.get_item('video_memory_strategy') in [ 'strict', 'moderate' ]:
clear_inference_pool()
if state_manager.get_item('video_memory_strategy') == 'strict':
content_analyser.clear_inference_pool()
face_classifier.clear_inference_pool()
face_detector.clear_inference_pool()
face_landmarker.clear_inference_pool()
face_masker.clear_inference_pool()
face_recognizer.clear_inference_pool()
def swap_face(target_face : Face, temp_vision_frame : VisionFrame) -> VisionFrame:
model_template = get_model_options().get('template')
model_size = get_model_options().get('size')
crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, target_face.landmark_set.get('5/68'), model_template, model_size)
crop_vision_frame_raw = crop_vision_frame.copy()
box_mask = create_static_box_mask(crop_vision_frame.shape[:2][::-1], state_manager.get_item('face_mask_blur'), state_manager.get_item('face_mask_padding'))
crop_masks =\
[
box_mask
]
if 'occlusion' in state_manager.get_item('face_mask_types'):
occlusion_mask = create_occlusion_mask(crop_vision_frame)
crop_masks.append(occlusion_mask)
crop_vision_frame = prepare_crop_frame(crop_vision_frame)
crop_vision_frame, crop_source_mask, crop_target_mask = forward(crop_vision_frame)
crop_vision_frame = normalize_crop_frame(crop_vision_frame)
crop_vision_frame = adaptive_match_frame_color(crop_vision_frame_raw, crop_vision_frame)
crop_source_mask = feather_crop_mask(crop_source_mask)
crop_target_mask = feather_crop_mask(crop_target_mask)
crop_combine_mask = numpy.maximum.reduce([ crop_source_mask, crop_target_mask ])
crop_masks.append(crop_combine_mask)
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
def forward(crop_vision_frame : VisionFrame) -> Tuple[VisionFrame, Mask, Mask]:
deep_swapper = get_inference_pool().get('deep_swapper')
deep_swapper_inputs = {}
for deep_swapper_input in deep_swapper.get_inputs():
if deep_swapper_input.name == 'in_face:0':
deep_swapper_inputs[deep_swapper_input.name] = crop_vision_frame
if deep_swapper_input.name == 'morph_value:0':
morph_value = numpy.array([ 1 ]).astype(numpy.float32)
deep_swapper_inputs[deep_swapper_input.name] = morph_value
with thread_semaphore():
crop_target_mask, crop_vision_frame, crop_source_mask = deep_swapper.run(None, deep_swapper_inputs)
return crop_vision_frame[0], crop_source_mask[0], crop_target_mask[0]
def prepare_crop_frame(crop_vision_frame : VisionFrame) -> VisionFrame:
crop_vision_frame = cv2.addWeighted(crop_vision_frame, 1.5, cv2.GaussianBlur(crop_vision_frame, (0, 0), 2), -0.5, 0)
crop_vision_frame = crop_vision_frame / 255.0
crop_vision_frame = numpy.expand_dims(crop_vision_frame, axis = 0).astype(numpy.float32)
return crop_vision_frame
def normalize_crop_frame(crop_vision_frame : VisionFrame) -> VisionFrame:
crop_vision_frame = (crop_vision_frame * 255.0).clip(0, 255)
crop_vision_frame = crop_vision_frame.astype(numpy.uint8)
return crop_vision_frame
def feather_crop_mask(crop_source_mask : Mask) -> Mask:
model_size = get_model_options().get('size')
crop_mask = crop_source_mask.reshape(model_size).clip(0, 1)
crop_mask = cv2.erode(crop_mask, numpy.ones((5, 5), numpy.uint8), iterations = 1)
crop_mask = cv2.GaussianBlur(crop_mask, (7, 7), 0)
return crop_mask
def get_reference_frame(source_face : Face, target_face : Face, temp_vision_frame : VisionFrame) -> VisionFrame:
return swap_face(target_face, temp_vision_frame)
def process_frame(inputs : DeepSwapperInputs) -> VisionFrame:
reference_faces = inputs.get('reference_faces')
target_vision_frame = inputs.get('target_vision_frame')
many_faces = sort_and_filter_faces(get_many_faces([ target_vision_frame ]))
if state_manager.get_item('face_selector_mode') == 'many':
if many_faces:
for target_face in many_faces:
target_vision_frame = swap_face(target_face, target_vision_frame)
if state_manager.get_item('face_selector_mode') == 'one':
target_face = get_one_face(many_faces)
if target_face:
target_vision_frame = swap_face(target_face, target_vision_frame)
if state_manager.get_item('face_selector_mode') == 'reference':
similar_faces = find_similar_faces(many_faces, reference_faces, state_manager.get_item('reference_face_distance'))
if similar_faces:
for similar_face in similar_faces:
target_vision_frame = swap_face(similar_face, target_vision_frame)
return target_vision_frame
def process_frames(source_path : List[str], queue_payloads : List[QueuePayload], update_progress : UpdateProgress) -> None:
reference_faces = get_reference_faces() if 'reference' in state_manager.get_item('face_selector_mode') else None
for queue_payload in process_manager.manage(queue_payloads):
target_vision_path = queue_payload['frame_path']
target_vision_frame = read_image(target_vision_path)
output_vision_frame = process_frame(
{
'reference_faces': reference_faces,
'target_vision_frame': target_vision_frame
})
write_image(target_vision_path, output_vision_frame)
update_progress(1)
def process_image(source_path : str, target_path : str, output_path : str) -> None:
reference_faces = get_reference_faces() if 'reference' in state_manager.get_item('face_selector_mode') else None
target_vision_frame = read_static_image(target_path)
output_vision_frame = process_frame(
{
'reference_faces': reference_faces,
'target_vision_frame': target_vision_frame
})
write_image(output_path, output_vision_frame)
def process_video(source_paths : List[str], temp_frame_paths : List[str]) -> None:
processors.multi_process_frames(None, temp_frame_paths, process_frames)
ASSISTANT
Certainly! Below is a Python script that creates a graphical user interface (GUI) using `tkinter`. This GUI allows you to:
1. **Select a Python script** (like the one you provided).
2. **Select a folder containing `.dfm` files**.
3. **Automatically parse each `.dfm` file** to extract necessary information (like model name and resolution).
4. **Update the `MODEL_SET` dictionary** in the selected Python script with entries for each `.dfm` file found in the selected folder.
### Key Features:
- **File Selection**: Users can select the target Python script and the `.dfm` folder through file dialogs.
- **Automatic Parsing**: The script attempts to extract the resolution (`size`) from each `.dfm` file. If it cannot, it defaults to `(224, 224)`.
- **Model Entry Generation**: For each `.dfm` file, the script generates a corresponding entry in the `MODEL_SET` dictionary with appropriate URLs and paths.
- **Backup Creation**: Before modifying the original script, a backup is created to prevent data loss.
- **Error Handling**: The script includes basic error handling to notify users of issues during the process.
### Assumptions:
- The `.dfm` files are named in a consistent manner (e.g., `Jackie_Chan.dfm`) to extract model names.
- The URL patterns for hashes and sources follow a consistent format based on the model name.
- You have the necessary read/write permissions for the selected Python script and folders.
### Required Libraries:
- `tkinter`: For creating the GUI.
- `tkinter.filedialog`: For file and folder selection dialogs.
- `re`: For regex operations to parse information from `.dfm` files.
- `json`: For handling JSON data if needed (optional based on your implementation).
- `os`: For file path operations.
### The GUI Script:
```python
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import os
import re
import shutil
def extract_model_info(dfm_path):
"""
Extract model information from a .dfm file.
Modify this function based on how resolution or other info can be extracted from the .dfm file.
For demonstration, we'll assume .dfm files are named as ModelName_resWIDTHxHEIGHT.dfm
Example: Jackie_Chan_res224x224.dfm
"""
filename = os.path.basename(dfm_path)
match = re.match(r"(.+?)_res(\d+)x(\d+)\.dfm", filename)
if match:
model_name = match.group(1)
width = int(match.group(2))
height = int(match.group(3))
size = (width, height)
else:
# Default values if pattern does not match
model_name = os.path.splitext(filename)[0]
size = (224, 224)
return model_name, size
def update_model_set(script_path, dfm_folder):
try:
with open(script_path, 'r') as file:
content = file.read()
# Backup the original script
backup_path = script_path + ".backup"
shutil.copy(script_path, backup_path)
# Find the existing MODEL_SET dictionary
model_set_match = re.search(r"MODEL_SET\s*:\s*ModelSet\s*=\s*({.*?})", content, re.DOTALL)
if not model_set_match:
messagebox.showerror("Error", "MODEL_SET dictionary not found in the selected script.")
return
model_set_str = model_set_match.group(1)
# Prepare to insert new models
new_models = []
for filename in os.listdir(dfm_folder):
if filename.endswith('.dfm'):
dfm_path = os.path.join(dfm_folder, filename)
model_name, size = extract_model_info(dfm_path)
# Construct URLs based on the model name
hash_url = f'https://huggingface.co/bluefoxcreation/DFM/resolve/main/{model_name}.hash'
dfm_url = f'https://github.com/iperov/DeepFaceLive/releases/download/{model_name}/{filename}'
# Construct paths relative to the script's directory
script_dir = os.path.dirname(script_path)
relative_hash_path = os.path.relpath(os.path.join(dfm_folder, f"{model_name}.hash"), script_dir)
relative_dfm_path = os.path.relpath(dfm_path, script_dir)
model_entry = f"""
'{model_name.lower()}': {{
'hashes': {{
'deep_swapper': {{
'url': '{hash_url}',
'path': resolve_relative_path('{relative_hash_path}')
}}
}},
'sources': {{
'deep_swapper': {{
'url': '{dfm_url}',
'path': resolve_relative_path('{relative_dfm_path}')
}}
}},
'template': 'arcface_128_v2',
'size': {size}
}}"""
new_models.append(model_entry)
# Combine all new models
new_models_str = ",".join(new_models)
# Insert new models before the closing brace of MODEL_SET
updated_model_set_str = model_set_str.rstrip('}').rstrip() + "," + new_models_str + "\n}"
# Replace the old MODEL_SET with the updated one
updated_content = content.replace(model_set_str, updated_model_set_str)
with open(script_path, 'w') as file:
file.write(updated_content)
messagebox.showinfo("Success", f"MODEL_SET updated successfully!\nBackup created at {backup_path}")
except Exception as e:
messagebox.showerror("Error", f"An error occurred: {str(e)}")
def browse_script():
file_path = filedialog.askopenfilename(
title="Select Python Script",
filetypes=[("Python Files", "*.py")]
)
if file_path:
script_entry.delete(0, tk.END)
script_entry.insert(0, file_path)
def browse_folder():
folder_path = filedialog.askdirectory(
title="Select DFM Folder"
)
if folder_path:
folder_entry.delete(0, tk.END)
folder_entry.insert(0, folder_path)
def execute_update():
script_path = script_entry.get()
dfm_folder = folder_entry.get()
if not os.path.isfile(script_path):
messagebox.showerror("Error", "Please select a valid Python script.")
return
if not os.path.isdir(dfm_folder):
messagebox.showerror("Error", "Please select a valid DFM folder.")
return
update_model_set(script_path, dfm_folder)
# Create the main window
root = tk.Tk()
root.title("MODEL_SET Updater")
root.geometry("600x200")
root.resizable(False, False)
# Create and place the widgets
frame = ttk.Frame(root, padding="20 20 20 20")
frame.pack(fill=tk.BOTH, expand=True)
# Python Script Selection
script_label = ttk.Label(frame, text="Select Python Script:")
script_label.grid(column=0, row=0, sticky=tk.W, pady=5)
script_entry = ttk.Entry(frame, width=50)
script_entry.grid(column=1, row=0, pady=5)
script_button = ttk.Button(frame, text="Browse", command=browse_script)
script_button.grid(column=2, row=0, padx=5, pady=5)
# DFM Folder Selection
folder_label = ttk.Label(frame, text="Select DFM Folder:")
folder_label.grid(column=0, row=1, sticky=tk.W, pady=5)
folder_entry = ttk.Entry(frame, width=50)
folder_entry.grid(column=1, row=1, pady=5)
folder_button = ttk.Button(frame, text="Browse", command=browse_folder)
folder_button.grid(column=2, row=1, padx=5, pady=5)
# Update Button
update_button = ttk.Button(frame, text="Update MODEL_SET", command=execute_update)
update_button.grid(column=1, row=2, pady=20)
# Add padding to all children
for child in frame.winfo_children():
child.grid_configure(padx=5, pady=5)
# Start the GUI event loop
root.mainloop()
```
### How to Use the GUI:
1. **Run the Script**:
- Save the above script to a file, e.g., `model_set_updater.py`.
- Ensure you have Python installed on your system.
- Run the script using the command:
```
python model_set_updater.py
```
2. **Select the Python Script**:
- Click the "Browse" button next to "Select Python Script".
- Navigate to and select the Python script you provided (the one containing the `MODEL_SET` dictionary).
3. **Select the DFM Folder**:
- Click the "Browse" button next to "Select DFM Folder".
- Navigate to and select the folder containing your `.dfm` files.
4. **Update `MODEL_SET`**:
- After selecting both the script and folder, click the "Update MODEL_SET" button.
- The script will parse each `.dfm` file, extract the model name and resolution, and update the `MODEL_SET` dictionary in the selected Python script.
- A backup of the original script will be created with a `.backup` extension (e.g., `your_script.py.backup`).
5. **Completion**:
- Upon successful completion, a message box will notify you.
- If any errors occur, they will be displayed in a message box for troubleshooting.
### Notes and Customizations:
- **Model Info Extraction**:
- The `extract_model_info` function uses a regex pattern to extract model names and resolutions from `.dfm` filenames.
- Modify this function if your `.dfm` files follow a different naming convention or if resolution info is stored differently.
- **URL Patterns**:
- The script constructs URLs based on assumed patterns. Adjust the `hash_url` and `dfm_url` constructions if your URLs follow a different format.
- **Path Handling**:
- The script calculates relative paths based on the location of the selected Python script. Ensure that this relative path calculation aligns with your project's directory structure.
- **Error Handling**:
- The script includes basic error handling. Depending on your needs, you might want to enhance it to handle more specific cases.
- **Backup Safety**:
- Always ensure that the backup creation logic (`shutil.copy`) correctly points to the desired backup location. Test with non-critical scripts first to ensure it behaves as expected.
By using this GUI, you can efficiently manage and update the `MODEL_SET` in your Python scripts based on the `.dfm` files in a specified folder, enhancing scalability and reducing manual errors.