陶泓 commited on
Commit
b3bf84a
·
1 Parent(s): 16456bb

完善交互

Browse files
Files changed (1) hide show
  1. app.py +81 -65
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
- processor = AutoProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
26
- model = CLIPSegForImageSegmentation.from_pretrained("CIDAS/clipseg-rd64-refined")
27
-
28
- # 下载并处理图像
29
- response = requests.get(url)
30
- image = Image.open(BytesIO(response.content))
31
-
32
- # 显示原始图像
33
- st.image(image, caption="原图", use_column_width=True)
34
-
35
- # 处理图像和文本
36
- inputs = processor(text=texts, images=[image] * len(texts), padding=True, return_tensors="pt")
37
- outputs = model(**inputs)
38
-
39
- # 将 logits 转换为概率值并生成掩码
40
- probabilities = torch.sigmoid(outputs.logits)
41
- masks = probabilities > 0.5
42
- masks = masks.detach().cpu().numpy()
43
-
44
- # 获取原始图像的 NumPy 数组
45
- image_np = np.array(image)
46
-
47
- # 全局计数器初始化
48
- global_counter = 1
49
-
50
- # 对每个物体生成分割图像
51
- for i, mask in enumerate(masks):
52
- # 将掩码调整为与原始图像相同的尺寸
53
- mask_resized = Image.fromarray(mask).resize((image_np.shape[1], image_np.shape[0]), resample=Image.LANCZOS)
54
- mask_resized = np.array(mask_resized) > 0.5
55
-
56
- # 标记连通区域
57
- labeled_mask, num_features = label(mask_resized)
58
- object_slices = find_objects(labeled_mask)
59
-
60
- for j in range(1, num_features + 1):
61
- # 获取当前连通区域的边界框
62
- object_slice = object_slices[j-1]
63
- area = (object_slice[0].stop - object_slice[0].start) * (object_slice[1].stop - object_slice[1].start)
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
- single_segmented_image = np.zeros_like(image_np)
75
- single_segmented_image[single_object_mask.astype(bool)] = image_np[single_object_mask.astype(bool)]
76
 
77
- # 去除黑色背景(即裁剪图像到非黑色区域)
78
- non_black_area = np.any(single_segmented_image > 0, axis=-1)
79
- if non_black_area.any():
80
- rows = np.any(non_black_area, axis=1)
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
- cropped_image = single_segmented_image[rmin:rmax+1, cmin:cmax+1]
 
87
 
88
- # 显示裁剪后的图像
89
- st.image(cropped_image, caption=f"{texts[i]} - 图 {global_counter}", use_column_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
- # 增加全局计数器
92
- global_counter += 1
 
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} 秒")