Skip to content
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

How do I create a mask but not optimize it? #636

Closed
zdoek001 opened this issue Jun 10, 2024 · 10 comments
Closed

How do I create a mask but not optimize it? #636

zdoek001 opened this issue Jun 10, 2024 · 10 comments
Labels
question Further information is requested Stale

Comments

@zdoek001
Copy link

How to create a black and white mask of a face

@dosubot dosubot bot added the question Further information is requested label Jun 10, 2024
Copy link

dosubot bot commented Jun 10, 2024

Hey @zdoek001! I'm a bot here to help you out with any bugs, questions, or contributions you have. Let's tackle this issue together while we wait for a human maintainer.

To create a black and white mask of a face without optimizing it, you can use the mediapipe_face_mesh function. This function processes an image to detect face landmarks and creates a mask where the face area is white and the rest is black.

Here is the relevant code:

def mediapipe_face_mesh(
    image: Image.Image, confidence: float = 0.3
) -> PredictOutput[int]:
    import mediapipe as mp

    mp_face_mesh = mp.solutions.face_mesh
    draw_util = mp.solutions.drawing_utils
    drawing_styles = mp.solutions.drawing_styles

    w, h = image.size

    with mp_face_mesh.FaceMesh(
        static_image_mode=True, max_num_faces=20, min_detection_confidence=confidence
    ) as face_mesh:
        arr = np.array(image)
        pred = face_mesh.process(arr)

        if pred.multi_face_landmarks is None:
            return PredictOutput()

        preview = arr.copy()
        masks = []

        for landmarks in pred.multi_face_landmarks:
            draw_util.draw_landmarks(
                image=preview,
                landmark_list=landmarks,
                connections=mp_face_mesh.FACEMESH_TESSELATION,
                landmark_drawing_spec=None,
                connection_drawing_spec=drawing_styles.get_default_face_mesh_tesselation_style(),
            )

            points = np.array(
                [[land.x * w, land.y * h] for land in landmarks.landmark], dtype=int
            )
            outline = cv2.convexHull(points).reshape(-1).tolist()

            mask = Image.new("L", image.size, "black")
            draw = ImageDraw.Draw(mask)
            draw.polygon(outline, fill="white")
            masks.append(mask)

        bboxes = create_bbox_from_mask(masks, image.size)
        preview = Image.fromarray(preview)
        return PredictOutput(bboxes=bboxes, masks=masks, preview=preview)

Additionally, you can use the mask_preprocess function from the adetailer library to preprocess the mask. Here is an example:

from PIL import Image
from adetailer.mask import mask_preprocess

# Preprocess the mask
processed_masks = mask_preprocess(masks, kernel=0, x_offset=0, y_offset=0, merge_invert='NONE')

This function will generate a black and white mask of the face detected in the image, and you can further manipulate the mask using additional utility functions if required [1][2].

To continue talking to Dosu, mention @dosu.

@zdoek001
Copy link
Author

mediapipe_face_mesh

@dosu
Is there an API?

Copy link

dosubot bot commented Jun 10, 2024

Yes, there is an API available for the mediapipe_face_mesh function. This function processes an image to detect face landmarks and creates a mask where the face area is white and the rest is black.

Here is the relevant code:

def mediapipe_face_mesh(
    image: Image.Image, confidence: float = 0.3
) -> PredictOutput[int]:
    import mediapipe as mp

    mp_face_mesh = mp.solutions.face_mesh
    draw_util = mp.solutions.drawing_utils
    drawing_styles = mp.solutions.drawing_styles

    w, h = image.size

    with mp_face_mesh.FaceMesh(
        static_image_mode=True, max_num_faces=20, min_detection_confidence=confidence
    ) as face_mesh:
        arr = np.array(image)
        pred = face_mesh.process(arr)

        if pred.multi_face_landmarks is None:
            return PredictOutput()

        preview = arr.copy()
        masks = []

        for landmarks in pred.multi_face_landmarks:
            draw_util.draw_landmarks(
                image=preview,
                landmark_list=landmarks,
                connections=mp_face_mesh.FACEMESH_TESSELATION,
                landmark_drawing_spec=None,
                connection_drawing_spec=drawing_styles.get_default_face_mesh_tesselation_style(),
            )

            points = np.array(
                [[land.x * w, land.y * h] for land in landmarks.landmark], dtype=int
            )
            outline = cv2.convexHull(points).reshape(-1).tolist()

            mask = Image.new("L", image.size, "black")
            draw = ImageDraw.Draw(mask)
            draw.polygon(outline, fill="white")
            masks.append(mask)

        bboxes = create_bbox_from_mask(masks, image.size)
        preview = Image.fromarray(preview)
        return PredictOutput(bboxes=bboxes, masks=masks, preview=preview)

This function is part of the adetailer repository and can be used to generate face masks from images [1].

To continue talking to Dosu, mention @dosu.

@Bing-su
Copy link
Owner

Bing-su commented Jun 11, 2024

What are you trying to get the mask image for?

@zdoek001
Copy link
Author

zdoek001 commented Jun 11, 2024

What are you trying to get the mask image for?

Once I have the mask image, I will put it in the mask of the img2img. When it is generated, the facial area is excluded so that it can be processed later in other developments
Is there any way to obtain this mask? Via API。@Bing-su

@Bing-su
Copy link
Owner

Bing-su commented Jun 13, 2024

Can't you just draw the mask image directly in img2img inpaint? I don't see the need for a mask.

@zdoek001
Copy link
Author

Can't you just draw the mask image directly in img2img inpaint? I don't see the need for a mask.

If I'm using the Web UI, that can be drawn, but I'm using the Web UI API for the request, as a step in the program, so the implementation of the mask generation needs to be automated

@Bing-su
Copy link
Owner

Bing-su commented Jun 13, 2024

chrome_xJgSkCvP8z
The WebUI has this feature so you can get inpaint masks, but it's probably not possible with the API.

@Bing-su
Copy link
Owner

Bing-su commented Jun 13, 2024

chrome_HGcWbZJwmv
On Saving images/grids

@github-actions github-actions bot added the Stale label Jul 1, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jul 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested Stale
Projects
None yet
Development

No branches or pull requests

2 participants