File size: 5,336 Bytes
d64bbca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6938c7
3d2f8c8
d64bbca
b6938c7
3d2f8c8
d64bbca
 
 
 
b6938c7
 
3d2f8c8
b6938c7
d64bbca
 
b6938c7
d64bbca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6938c7
d64bbca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6938c7
d64bbca
 
 
 
 
 
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
import gradio as gr
import numpy as np
import imageio
from PIL import Image
import os

# 定义颜色列表,每个颜色对应一个 mask
colors = [
    '#000000',  # 背景色
    '#2692F3',  # 蓝色
    '#F89E12',  # 橙色
    '#16C232',  # 绿色
    '#F92F6C',  # 粉色
    '#AC6AEB',  # 紫色
]

# 将颜色转换为 RGB 值
palette = np.array([
    tuple(int(s[i + 1:i + 3], 16) for i in (0, 2, 4))
    for s in colors[1:]  # 跳过背景色
])  # (N, 3)

# 计算颜色距离
def color_distance(c1, c2):
    return np.sqrt(np.sum((c1 - c2) ** 2, axis=-1))

# 处理用户绘制的图像,生成 mask
def process_image(img):
    # 保存用户上传的图像(包含绘制的掩码)
    imageio.imwrite("output_image.png", img["composite"])

    # 提取用户绘制的图层
    user_input = np.asarray(img["layers"][0])  # (H, W, 4)
    height, width, _ = user_input.shape

    # 提取 alpha 通道作为前景 mask
    alpha_channel = user_input[..., 3]  # (H, W)
    foreground_mask = alpha_channel > 0  # 用户绘制的区域

    # 提取 RGB 通道
    user_input_rgb = user_input[..., :3]  # (H, W, 3)

    # 使用颜色距离生成 mask
    masks = []
    for i, color in enumerate(palette):
        distance = color_distance(user_input_rgb, color)
        mask = (distance < 100)  # 调整颜色偏差阈值
        mask = mask * foreground_mask  # 只保留用户绘制的区域
        masks.append(mask)

    # 生成合并后的 mask(使用对应颜色的 RGB 值)
    merged_mask = np.zeros((height, width, 4), dtype=np.uint8)  # RGBA 图像
    merged_mask[..., 3] = 255  # 设置背景为完全不透明(黑色背景)
    for i, mask in enumerate(masks):
        merged_mask[mask, :3] = palette[i]  # 使用对应颜色填充 RGB 通道
        merged_mask[mask, 3] = 255  # 设置前景为完全不透明

    # 将 mask 转换为 PIL 图像(使用对应颜色的 RGB 值)
    mask_images = []
    for i, mask in enumerate(masks):
        mask_array = np.zeros((height, width, 4), dtype=np.uint8)  # RGBA 图像
        mask_array[mask, :3] = palette[i]  # 使用对应颜色填充 RGB 通道
        mask_array[mask, 3] = 255  # 设置前景为完全不透明
        mask_image = Image.fromarray(mask_array, mode='RGBA')
        mask_images.append(mask_image)

    merged_mask_image = Image.fromarray(merged_mask, mode='RGBA')

    # 保存 mask 到本地
    output_dir = "output_masks"
    os.makedirs(output_dir, exist_ok=True)
    for i, mask_image in enumerate(mask_images):
        mask_image.save(f"{output_dir}/mask_{i + 1}.png")
    merged_mask_image.save(f"{output_dir}/merged_mask.png")

    print(f"Masks saved to {output_dir}")
    return img["background"], *mask_images, merged_mask_image

# Gradio 界面
with gr.Blocks() as demo:
    # 添加 HTML 标题和介绍
    gr.Markdown("""
    # 🎨 **Multi-Color Mask Generator**
    Welcome to the **Multi-Color Mask Generator**! This tool allows you to upload an image, draw masks using different colors, and generate corresponding mask images. Each mask is saved as an RGBA image, and a merged mask is also created for your convenience.
    """)

    with gr.Row():
        # 左侧:用户上传图像并绘制掩码
        with gr.Column():
            gr.Markdown("### 🖌️ **Draw Your Mask**")
            img = gr.ImageEditor(
                image_mode='RGBA',
                sources=['upload'],  # 允许用户上传图像
                transforms=[],       # 禁用变换功能
                brush=gr.Brush(
                    colors=colors[1:],  # 设置画笔颜色
                    color_mode="fixed",
                ),
                type='pil',
                label="Draw Mask",
                height=800,  # 设置较高的纵向高度
                width=600,   # 设置宽度
            )
        # 右侧:显示处理后的图像
        with gr.Column():
            gr.Markdown("### 🖼️ **Generated Masks**")
            img1 = gr.Image(label="Background Image", show_label=True)  # 显示背景图像
            img2 = gr.Image(label="Mask 1 (Blue)", show_label=True)     # 显示蓝色掩码
            img3 = gr.Image(label="Mask 2 (Orange)", show_label=True)   # 显示橙色掩码
            img4 = gr.Image(label="Mask 3 (Green)", show_label=True)    # 显示绿色掩码
            img5 = gr.Image(label="Mask 4 (Pink)", show_label=True)     # 显示粉色掩码
            img6 = gr.Image(label="Mask 5 (Purple)", show_label=True)   # 显示紫色掩码
            img7 = gr.Image(label="Merged Mask", show_label=True)       # 显示合并后的掩码

    # 按钮:触发图像处理
    btn = gr.Button("Generate Masks")
    btn.click(process_image, img, [img1, img2, img3, img4, img5, img6, img7])

    # 添加 HTML 结尾
    gr.Markdown("""
    ## 📝 **How to Use**
    1. Upload an image using the **Draw Mask** section.
    2. Use the brush tool to draw masks with different colors.
    3. Click the **Generate Masks** button to create and save the masks.
    4. View the generated masks on the right side.
    ## 📂 **Output**
    - Each mask is saved as an RGBA image in the `output_masks` directory.
    - A merged mask is also generated for your convenience.
    ## 🚀 **Enjoy!**
    """)

# 启动应用
demo.launch(debug=True, share=True)