-
Notifications
You must be signed in to change notification settings - Fork 7.5k
BOUNTY: Mouth Mask Feature #740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reviewer's Guide by SourceryThis PR implements a mouth mask feature for face swapping that preserves the original mouth area of the target face. The implementation includes mask creation, color correction, and visualization capabilities. The changes primarily affect the face swapper module and add new UI controls. Class diagram for the updated face swapper moduleclassDiagram
class FaceSwapper {
+get_face_swapper() : Any
+swap_face(source_face: Face, target_face: Face, temp_frame: Frame) : Frame
+process_frame(source_face: Face, temp_frame: Frame) : Frame
+process_frame_v2(temp_frame: Frame, temp_frame_path: str) : Frame
+process_frames(source_path: str, temp_frame_paths: List[str], progress: Any) : None
+process_image(source_path: str, target_path: str, output_path: str) : None
+process_video(source_path: str, temp_frame_paths: List[str]) : None
+create_lower_mouth_mask(face: Face, frame: Frame) : (np.ndarray, np.ndarray, tuple, np.ndarray)
+draw_mouth_mask_visualization(frame: Frame, face: Face, mouth_mask_data: tuple) : Frame
+apply_mouth_area(frame: np.ndarray, mouth_cutout: np.ndarray, mouth_box: tuple, face_mask: np.ndarray, mouth_polygon: np.ndarray) : np.ndarray
+create_face_mask(face: Face, frame: Frame) : np.ndarray
+apply_color_transfer(source, target)
}
class UI {
+create_root(start: Callable[[], None], destroy: Callable[[], None]) : ctk.CTk
}
class Globals {
+mouth_mask: bool
+show_mouth_mask_box: bool
+mask_feather_ratio: int
+mask_down_size: float
+mask_size: int
}
FaceSwapper --> UI : uses
FaceSwapper --> Globals : uses
UI --> Globals : uses
note for FaceSwapper "New methods for mouth mask feature added"
note for UI "New UI controls for mouth mask feature added"
note for Globals "New global variables for mouth mask feature added"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @KRSHH - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟡 General issues: 2 issues found
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
final_blend = blended * face_mask_3channel + roi * (1 - face_mask_3channel) | ||
|
||
frame[min_y:max_y, min_x:max_x] = final_blend.astype(np.uint8) | ||
except Exception as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Use more specific exception handling to avoid masking critical errors
Catching all exceptions silently could hide serious issues. Consider catching specific exceptions (e.g., ValueError, cv2.error) and logging the error details for debugging.
|
||
face_top = np.min([right_side_face[0, 1], left_side_face[-1, 1]]) | ||
forehead_height = face_top - eyebrow_top | ||
extended_forehead_height = int(forehead_height * 5.0) # Extend by 50% |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider making magic numbers configurable parameters
The forehead extension factor (5.0) and face width padding (5%) should be configurable parameters since they may need adjustment for different face shapes and sizes.
FOREHEAD_EXTENSION_FACTOR = 5.0
extended_forehead_height = int(forehead_height * FOREHEAD_EXTENSION_FACTOR)
model_path = resolve_relative_path("../models/inswapper_128_fp16.onnx") | ||
FACE_SWAPPER = insightface.model_zoo.get_model( | ||
model_path, providers=modules.globals.execution_providers | ||
) | ||
return FACE_SWAPPER | ||
|
||
|
||
def swap_face(source_face: Face, target_face: Face, temp_frame: Frame) -> Frame: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider separating the face swapping code into dedicated classes and modules for mask generation, visualization, and core swapping logic
The face swapping code mixes multiple concerns that should be separated. Consider:
- Extract mouth masking into a dedicated class:
class MouthMaskGenerator:
def __init__(self, expansion_factor=1.0, feather_ratio=10):
self.expansion_factor = expansion_factor
self.feather_ratio = feather_ratio
def generate_mask(self, face: Face, frame: Frame) -> dict:
# Current create_lower_mouth_mask logic goes here
return {
'mask': mask,
'cutout': mouth_cutout,
'bounds': (min_x, min_y, max_x, max_y),
'polygon': lower_lip_polygon
}
- Move visualization to a separate debug module:
# debug_visualizer.py
def visualize_mouth_mask(frame: Frame, mask_data: dict) -> Frame:
# Current visualization code goes here
return annotated_frame
- Simplify swap_face to focus on high-level flow:
def swap_face(source_face: Face, target_face: Face, frame: Frame) -> Frame:
face_swapper = get_face_swapper()
result = face_swapper.get(frame, target_face, source_face, paste_back=True)
if modules.globals.mouth_mask:
mask_gen = MouthMaskGenerator()
mask_data = mask_gen.generate_mask(target_face, frame)
result = apply_mouth_area(result, **mask_data)
if modules.globals.show_mouth_mask_box:
result = debug.visualize_mouth_mask(result, mask_data)
return result
This separates concerns while preserving functionality, making the code more maintainable and easier to test.
Directly commited to main last time (now reverted)... my mistake |
Describes better.
BOUNTY: Mouth Mask Feature
Summary by Sourcery
Implement a mouth mask feature in the face swapping module to enhance realism by separately handling the mouth area. Update the UI to include switches for enabling the mouth mask and visualizing the mouth mask box, giving users more control over the feature.
New Features:
Enhancements: