File size: 6,469 Bytes
78d359b
 
 
 
 
 
 
 
 
 
933c40c
78d359b
 
 
933c40c
 
78d359b
933c40c
 
78d359b
 
 
933c40c
 
78d359b
933c40c
78d359b
 
933c40c
78d359b
 
 
 
 
 
 
 
933c40c
78d359b
 
 
 
 
 
 
933c40c
78d359b
 
933c40c
78d359b
 
933c40c
78d359b
 
933c40c
78d359b
933c40c
78d359b
933c40c
78d359b
933c40c
 
78d359b
 
 
 
 
 
 
 
 
 
933c40c
 
78d359b
933c40c
78d359b
933c40c
78d359b
933c40c
78d359b
 
933c40c
78d359b
 
933c40c
78d359b
 
933c40c
78d359b
 
 
933c40c
78d359b
 
 
933c40c
78d359b
 
933c40c
78d359b
 
 
 
 
 
 
 
933c40c
78d359b
933c40c
78d359b
933c40c
 
78d359b
 
 
933c40c
78d359b
 
 
 
 
 
 
 
 
933c40c
 
78d359b
 
 
 
 
 
 
 
933c40c
78d359b
 
 
 
 
933c40c
78d359b
933c40c
78d359b
 
933c40c
78d359b
 
 
 
 
933c40c
78d359b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
933c40c
78d359b
 
 
 
 
 
 
 
 
 
 
 
 
 
63d8dec
 
adf5040
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
import gradio as gr
from gradio_image_prompter import ImagePrompter
import torch
import numpy as np
from sam2.sam2_image_predictor import SAM2ImagePredictor
from PIL import Image
from uuid import uuid4
import os
from huggingface_hub import upload_folder
import shutil

MODEL = "facebook/sam2-hiera-large"
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
PREDICTOR = SAM2ImagePredictor.from_pretrained(MODEL, device=DEVICE)


GLOBALS = {}


IMAGE = None
MASKS = None
INDEX = None


def prompter(prompts):

    image = np.array(prompts["image"])  # Convert the image to a numpy array
    points = prompts["points"]  # Get the points from prompts

    # Perform inference with multimask_output=True
    with torch.inference_mode():
        PREDICTOR.set_image(image)
        input_point = [[point[0], point[1]] for point in points]
        input_label = [1] * len(points)  # Assuming all points are foreground
        masks, _, _ = PREDICTOR.predict(
            point_coords=input_point, point_labels=input_label, multimask_output=True
        )

    # Prepare individual images with separate overlays
    overlay_images = []
    for i, mask in enumerate(masks):
        print(f"Predicted Mask {i+1}:", mask.shape)
        red_mask = np.zeros_like(image)
        red_mask[:, :, 0] = mask.astype(np.uint8) * 255  # Apply the red channel
        red_mask = Image.fromarray(red_mask)

        # Convert the original image to a PIL image
        original_image = Image.fromarray(image)

        # Blend the original image with the red mask
        blended_image = Image.blend(original_image, red_mask, alpha=0.5)

        # Add the blended image to the list
        overlay_images.append(blended_image)

    global IMAGE, MASKS

    IMAGE, MASKS = image, masks

    return overlay_images[0], overlay_images[1], overlay_images[2], masks


def select_mask(
    selected_mask_index,
    mask1,
    mask2,
    mask3,
):
    masks = [mask1, mask2, mask3]
    global INDEX
    INDEX = selected_mask_index
    return masks[selected_mask_index]


def save_selected_mask(image, mask, output_dir="output"):

    output_dir = os.path.join(os.getcwd(), output_dir)

    os.makedirs(output_dir, exist_ok=True)

    # Generate a unique UUID for the folder name
    folder_id = str(uuid4())

    # Create a path for the new folder
    folder_path = os.path.join(output_dir, folder_id)

    # Ensure the folder is created
    os.makedirs(folder_path, exist_ok=True)

    # Define the paths for saving the image and mask
    image_path = os.path.join(folder_path, "image.npy")
    mask_path = os.path.join(folder_path, "mask.npy")

    # Save the image and mask to the respective paths
    with open(image_path, "wb") as f:
        np.save(f, IMAGE)

    with open(mask_path, "wb") as f:
        np.save(f, MASKS[INDEX])

        # Upload the folder to the Hugging Face Hub
    upload_folder(
        folder_path=output_dir,
        # path_in_repo=path_in_repo,
        repo_id="amaye15/object-segmentation",
        repo_type="dataset",
        # ignore_patterns="**/logs/*.txt",  # Adjust this if needed
    )

    shutil.rmtree(folder_path)

    return f"Image and mask saved to {folder_path}."


def save_dataset_name(key, dataset_name):
    global GLOBALS
    GLOBALS[key] = dataset_name

    iframe_code = f"""
    <iframe
      src="https://huggingface.co/datasets/{dataset_name}/embed/viewer/default/train"
      frameborder="0"
      width="100%"
      height="560px"
    ></iframe>
    """
    return f"Huggingface Dataset: {dataset_name}", iframe_code


# Define the Gradio Blocks app
with gr.Blocks() as demo:
    with gr.Tab("Setup"):
        with gr.Row():
            with gr.Column():
                source = gr.Textbox(label="Source Dataset")
                source_display = gr.Markdown()
                iframe_display = gr.HTML()

                source.change(
                    save_dataset_name,
                    inputs=(gr.State("source_dataset"), source),
                    outputs=(source_display, iframe_display),
                )

            with gr.Column():

                destination = gr.Textbox(label="Destination Dataset")
                destination_display = gr.Markdown()

                destination.change(
                    save_dataset_name,
                    inputs=(gr.State("destination_dataset"), destination),
                    outputs=destination_display,
                )

    with gr.Tab("Object Mask - Point Prompt"):
        gr.Markdown("# Image Point Collector with Multiple Separate Mask Overlays")
        gr.Markdown(
            "Upload an image, click on it, and get each predicted mask overlaid separately in red on individual images."
        )

        with gr.Row():
            with gr.Column():
                # Input: ImagePrompter
                image_input = ImagePrompter(show_label=False)
                submit_button = gr.Button("Submit")
        with gr.Row():
            with gr.Column():
                # Outputs: Up to 3 overlay images
                image_output_1 = gr.Image(show_label=False)
            with gr.Column():
                image_output_2 = gr.Image(show_label=False)
            with gr.Column():
                image_output_3 = gr.Image(show_label=False)

        # Dropdown for selecting the correct mask
        with gr.Row():
            mask_selector = gr.Radio(
                label="Select the correct mask",
                choices=["Mask 1", "Mask 2", "Mask 3"],
                type="index",
            )
            # selected_mask_output = gr.Image(show_label=False)

        save_button = gr.Button("Save Selected Mask and Image")
        save_message = gr.Textbox(visible=False)

        # Define the action triggered by the submit button
        submit_button.click(
            fn=prompter,
            inputs=image_input,
            outputs=[image_output_1, image_output_2, image_output_3, gr.State()],
        )

        # Define the action triggered by mask selection
        mask_selector.change(
            fn=select_mask,
            inputs=[mask_selector, image_output_1, image_output_2, image_output_3],
            outputs=gr.State(),
        )

        # Define the action triggered by the save button
        save_button.click(
            fn=save_selected_mask,
            inputs=[gr.State(), gr.State()],
            outputs=save_message,
            show_progress=True,
        )

# Launch the Gradio app
demo.launch()