liusida / ComfyUI-AutoCropFaces

Use RetinaFace to detect and automatically crop faces
MIT License
54 stars 10 forks source link

Add support for multiple face paste #13

Open yuvraj108c opened 1 month ago

yuvraj108c commented 1 month ago

https://github.com/liusida/ComfyUI-AutoCropFaces/blob/b2139db9a8ffb4707832106a58f519bbd04e6118/__init__.py#L169

yuvraj108c commented 1 month ago

Made one using LLM's. Feel free to use it as appropriate

class StitchCroppedFaces:
    def __init__(self):
        pass

    @classmethod
    def INPUT_TYPES(s):
        return {
            "required": {
                "base_image": ("IMAGE",),
                "cropped_faces": ("IMAGE",),
                "crop_data": ("CROP_DATA",),
            },
        }

    RETURN_TYPES = ("IMAGE",)
    FUNCTION = "stitch_faces"
    CATEGORY = "Faces"

    def stitch_faces(self, base_image, cropped_faces, crop_data):
        base_image_copy = base_image.clone()
        B,H,W,C = base_image_copy.shape

        # Ensure cropped_faces is a batch
        if len(cropped_faces.shape) == 3:
            cropped_faces = cropped_faces.unsqueeze(0)

        # Check if crop_data is None or empty (no faces detected)
        if crop_data is None or len(crop_data) == 0:
            print("No faces detected. Returning original image.")
            return (base_image_copy,)

        # Handle single face case
        if isinstance(crop_data, tuple):
            crop_data = [crop_data]
            cropped_faces = cropped_faces.unsqueeze(0) if len(cropped_faces.shape) == 3 else cropped_faces

        # Iterate through each cropped face and its corresponding crop data
        for face, crop_info in zip(cropped_faces, crop_data):
            # Unpack crop_info
            if isinstance(crop_info, tuple) and len(crop_info) == 2:
                (face_h, face_w), (x, y, x2, y2) = crop_info
            else:
                print(f"Unexpected crop_data format: {crop_info}. Skipping this face.")
                continue

            # Calculate width and height
            w, h = x2 - x, y2 - y

            # Resize the face to match the crop dimensions
            resized_face = F.interpolate(face.permute(2, 0, 1).unsqueeze(0), size=(h, w), mode='bilinear', align_corners=False)
            resized_face = resized_face.squeeze(0).permute(1, 2, 0)

            # Calculate the paste coordinates
            x_end = min(x2, W)
            y_end = min(y2, H)

            # Paste the resized face onto the stitched image
            base_image_copy[0, y:y_end, x:x_end] = resized_face[:y_end-y, :x_end-x]

        return (base_image_copy,)
Mubumbutu commented 2 weeks ago

Could you write one sentence... what? where? how? Why? I don't understand anything, and I would like to be able to use multiface.