Spaces:
Build error
Build error
陶泓 commited on
Commit ·
b3bf84a
1
Parent(s): 16456bb
完善交互
Browse files
app.py
CHANGED
|
@@ -3,10 +3,10 @@ import torch
|
|
| 3 |
import numpy as np
|
| 4 |
from PIL import Image
|
| 5 |
import requests
|
| 6 |
-
import matplotlib.pyplot as plt
|
| 7 |
from io import BytesIO
|
| 8 |
from transformers import AutoProcessor, CLIPSegForImageSegmentation
|
| 9 |
from scipy.ndimage import label, find_objects
|
|
|
|
| 10 |
|
| 11 |
# Streamlit 应用标题
|
| 12 |
st.title("使用图像分割模型分割证件照")
|
|
@@ -21,72 +21,88 @@ texts = [text.strip() for text in texts_input.split(',')]
|
|
| 21 |
# 选择面积阈值
|
| 22 |
area_threshold = st.slider("忽略小区域的面积阈值", 0, 10000, 5000)
|
| 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 |
-
if area < area_threshold:
|
| 67 |
-
continue
|
| 68 |
-
|
| 69 |
-
# 创建一个矩形掩码
|
| 70 |
-
single_object_mask = np.zeros_like(mask_resized)
|
| 71 |
-
single_object_mask[object_slice] = 1
|
| 72 |
|
| 73 |
-
#
|
| 74 |
-
|
| 75 |
-
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
cols = np.any(non_black_area, axis=0)
|
| 82 |
-
rmin, rmax = np.where(rows)[0][[0, -1]]
|
| 83 |
-
cmin, cmax = np.where(cols)[0][[0, -1]]
|
| 84 |
|
| 85 |
-
#
|
| 86 |
-
|
|
|
|
| 87 |
|
| 88 |
-
#
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
|
|
|
| 3 |
import numpy as np
|
| 4 |
from PIL import Image
|
| 5 |
import requests
|
|
|
|
| 6 |
from io import BytesIO
|
| 7 |
from transformers import AutoProcessor, CLIPSegForImageSegmentation
|
| 8 |
from scipy.ndimage import label, find_objects
|
| 9 |
+
import time
|
| 10 |
|
| 11 |
# Streamlit 应用标题
|
| 12 |
st.title("使用图像分割模型分割证件照")
|
|
|
|
| 21 |
# 选择面积阈值
|
| 22 |
area_threshold = st.slider("忽略小区域的面积阈值", 0, 10000, 5000)
|
| 23 |
|
| 24 |
+
# 添加 GPU/CPU 选择按钮
|
| 25 |
+
device_option = st.radio("选择设备", ("GPU", "CPU"))
|
| 26 |
+
|
| 27 |
+
# 提交按钮
|
| 28 |
+
if st.button('提交'):
|
| 29 |
+
# 在按钮点击后确定设备
|
| 30 |
+
device = torch.device('cuda' if device_option == 'GPU' and torch.cuda.is_available() else 'cpu')
|
| 31 |
+
|
| 32 |
+
start_time = time.time() # 开始计时
|
| 33 |
+
|
| 34 |
+
# 加载模型和处理器到选定设备
|
| 35 |
+
processor = AutoProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
|
| 36 |
+
model = CLIPSegForImageSegmentation.from_pretrained("CIDAS/clipseg-rd64-refined").to(device)
|
| 37 |
+
|
| 38 |
+
# 下载并处理图像
|
| 39 |
+
response = requests.get(url)
|
| 40 |
+
image = Image.open(BytesIO(response.content))
|
| 41 |
+
|
| 42 |
+
# 显示原始图像
|
| 43 |
+
st.image(image, caption="原图", use_column_width=True)
|
| 44 |
+
|
| 45 |
+
# 处理图像和文本
|
| 46 |
+
inputs = processor(text=texts, images=[image] * len(texts), padding=True, return_tensors="pt").to(device)
|
| 47 |
+
outputs = model(**inputs)
|
| 48 |
+
|
| 49 |
+
# 将 logits 转换为概率值并生成掩码
|
| 50 |
+
probabilities = torch.sigmoid(outputs.logits)
|
| 51 |
+
masks = probabilities > 0.5
|
| 52 |
+
masks = masks.detach().cpu().numpy() # 将数据移回 CPU 以进行后续处理
|
| 53 |
+
|
| 54 |
+
# 获取原始图像的 NumPy 数组
|
| 55 |
+
image_np = np.array(image)
|
| 56 |
+
|
| 57 |
+
# 全局计数器初始化
|
| 58 |
+
global_counter = 1
|
| 59 |
+
|
| 60 |
+
# 对每个物体生成分割图像
|
| 61 |
+
for i, mask in enumerate(masks):
|
| 62 |
+
# 将掩码调整为与原始图像相同的尺寸
|
| 63 |
+
mask_resized = Image.fromarray(mask).resize((image_np.shape[1], image_np.shape[0]), resample=Image.LANCZOS)
|
| 64 |
+
mask_resized = np.array(mask_resized) > 0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
+
# 标记连通区域
|
| 67 |
+
labeled_mask, num_features = label(mask_resized)
|
| 68 |
+
object_slices = find_objects(labeled_mask)
|
| 69 |
|
| 70 |
+
for j in range(1, num_features + 1):
|
| 71 |
+
# 获取当前连通区域的边界框
|
| 72 |
+
object_slice = object_slices[j-1]
|
| 73 |
+
area = (object_slice[0].stop - object_slice[0].start) * (object_slice[1].stop - object_slice[1].start)
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
+
# 忽略面积小于阈值的区域
|
| 76 |
+
if area < area_threshold:
|
| 77 |
+
continue
|
| 78 |
|
| 79 |
+
# 创建一个矩形掩码
|
| 80 |
+
single_object_mask = np.zeros_like(mask_resized)
|
| 81 |
+
single_object_mask[object_slice] = 1
|
| 82 |
+
|
| 83 |
+
# 仅保留原始图像中与当前矩形掩码匹配的区域
|
| 84 |
+
single_segmented_image = np.zeros_like(image_np)
|
| 85 |
+
single_segmented_image[single_object_mask.astype(bool)] = image_np[single_object_mask.astype(bool)]
|
| 86 |
+
|
| 87 |
+
# 去除黑色背景(即裁剪图像到非黑色区域)
|
| 88 |
+
non_black_area = np.any(single_segmented_image > 0, axis=-1)
|
| 89 |
+
if non_black_area.any():
|
| 90 |
+
rows = np.any(non_black_area, axis=1)
|
| 91 |
+
cols = np.any(non_black_area, axis=0)
|
| 92 |
+
rmin, rmax = np.where(rows)[0][[0, -1]]
|
| 93 |
+
cmin, cmax = np.where(cols)[0][[0, -1]]
|
| 94 |
+
|
| 95 |
+
# 裁剪图像
|
| 96 |
+
cropped_image = single_segmented_image[rmin:rmax+1, cmin:cmax+1]
|
| 97 |
+
|
| 98 |
+
# 显示裁剪后的图像
|
| 99 |
+
st.image(cropped_image, caption=f"{texts[i]} - 图 {global_counter}", use_column_width=True)
|
| 100 |
+
|
| 101 |
+
# 增加全局计数器
|
| 102 |
+
global_counter += 1
|
| 103 |
+
|
| 104 |
+
end_time = time.time() # 结束计时
|
| 105 |
+
elapsed_time = end_time - start_time # 计算运行时间
|
| 106 |
|
| 107 |
+
# 显示程序运行时间
|
| 108 |
+
st.write(f"程序运行时间: {elapsed_time:.2f} 秒")
|