svjack's picture
Update app.py
3d2f8c8 verified
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)