Spaces:
Running
Running
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) |