reyhane1222 commited on
Commit
8ae9faf
·
verified ·
1 Parent(s): 5be1df3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +251 -98
app.py CHANGED
@@ -1,88 +1,150 @@
1
  # -*- coding: utf-8 -*-
 
 
 
 
2
  import gradio as gr
3
  from collections import Counter
4
  from transformers import AutoImageProcessor, AutoModelForImageClassification
5
  from PIL import Image
6
- import torch, math, pandas as pd
 
7
 
8
  # ==============================
9
- # 📦 بارگذاری مدل (یکبار کش میشه)
10
  # ==============================
11
- model_id = "prithivMLmods/Minc-Materials-23"
12
- processor = AutoImageProcessor.from_pretrained(model_id)
13
- model = AutoModelForImageClassification.from_pretrained(model_id)
 
 
 
 
 
14
 
15
  # ==============================
16
  # 📊 پارامترهای مصالح
17
  # ==============================
18
  material_params = {
19
- "brick": {"alpha":0.3,"eps":0.9,"I":1600},
20
- "stone": {"alpha":0.25,"eps":0.92,"I":2000},
21
- "polishedstone":{"alpha":0.2,"eps":0.9,"I":2100},
22
- "concrete":{"alpha":0.35,"eps":0.9,"I":1800},
23
- "metal":{"alpha":0.5,"eps":0.2,"I":4000},
24
- "glass":{"alpha":0.1,"eps":0.85,"I":1500},
25
- "wood":{"alpha":0.35,"eps":0.9,"I":800},
26
- "tile":{"alpha":0.4,"eps":0.9,"I":1200},
27
- "ceramic":{"alpha":0.45,"eps":0.92,"I":1300},
28
- "painted":{"alpha":0.3,"eps":0.9,"I":1000},
29
- "plastic":{"alpha":0.1,"eps":0.95,"I":800},
30
- "paper":{"alpha":0.6,"eps":0.95,"I":500},
31
- "mirror":{"alpha":0.7,"eps":0.1,"I":2000},
32
- "foliage":{"alpha":0.25,"eps":0.98,"I":900},
33
- "water":{"alpha":0.06,"eps":0.98,"I":4200},
34
-
35
  }
36
 
37
- # دسته‌ها و جایگزین‌ها (خلاصه)
38
- replacement_text = {
39
- "facade": {"brick":"آجر روشن یا نمای سرامیکی روشن","stone":"سنگ روشن یا نمای گچی بازتابی"},
40
- "glazing": {"glass":"شیشه دوجداره Low-E","mirror":"شیشه مات یا بازتاب متعادل"},
41
- "metallic": {"metal":"آلومینیوم رنگ روشن"},
42
- "coverings": {"plastic":"چوب روشن یا سنگ سبک"},
43
- "wood_elements": {"wood":"چوب روشن با پوشش بازتابی"},
44
- "vegetation": {"foliage":None},
45
- "water_bodies": {"water":None},
46
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
- material_categories = {
50
- "facade":["brick","stone","polishedstone","concrete","tile","ceramic","painted"],
51
- "glazing":["glass","mirror"],
52
- "metallic":["metal"],
53
- "coverings":["plastic","paper","fabric"],
54
- "wood_elements":["wood"],
55
- "vegetation":["foliage"],
56
- "water_bodies":["water"],
57
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  }
59
 
60
  # ==============================
61
- # محاسبات
62
  # ==============================
63
- def ET_proxy(T,RH):
64
- es = 0.6108*math.exp((17.27*T)/(T+237.3))
65
- return es*(1-RH/100)
66
 
67
- def calc_deltaT(material,T_air,RH,u,S):
68
- if material not in material_params: return 0.0
69
- p = material_params[material]
70
- alpha,eps,I = p["alpha"],p["eps"],p["I"]
71
- A,B,C,D = 1.0,0.4,0.8,0.015
72
- h_c = 5.8+4.1*u
73
- if material=="foliage":
74
- C_m = A*(1-alpha)-D*ET_proxy(T_air,RH)
 
 
 
 
 
75
  else:
76
- C_m = A*(1-alpha)+B*(1-eps)+(C/math.sqrt(max(I,1)))
77
- gamma = S/max(h_c,1e-6)
78
- return gamma*C_m/1000.0
79
- # بهبود تابع برش تصویر - افزایش همپوشانی برای پوشش بهتر
80
- def get_patches(image, size=224, stride=100): # کاهش stride از 200 به 100
 
81
  patches = []
82
  w, h = image.size
83
 
84
- # افزودن مقیاس‌های مختلف
85
- for scale in [1.0, 0.75, 0.5]:
86
  scaled_w, scaled_h = int(w * scale), int(h * scale)
87
  if min(scaled_w, scaled_h) < size:
88
  continue
@@ -97,52 +159,143 @@ def get_patches(image, size=224, stride=100): # کاهش stride از 200 به 1
97
  patches.append(patch)
98
 
99
  return patches
 
100
  # ==============================
101
- # تابع اصلی
102
  # ==============================
103
- def analyze(img,T_air,RH=40,u=2,S=700):
104
- img=img.convert("RGB")
105
- patches=get_patches(img)
106
-
107
- all_predictions=[]
108
- for patch in patches:
109
- inputs=processor(images=patch,return_tensors="pt")
110
- with torch.no_grad():
111
- outputs=model(**inputs)
112
- probs=torch.nn.functional.softmax(outputs.logits,dim=-1)
113
- label=model.config.id2label[torch.argmax(probs[0]).item()]
114
- all_predictions.append(label)
115
-
116
- counter=Counter(all_predictions)
117
- total_patches=len(patches)
118
- materials_found={m for m,c in counter.items() if c>=3 and m in material_params}
119
-
120
- results=[]
121
- for m in materials_found:
122
- share=counter[m]/total_patches
123
- dT=calc_deltaT(m,T_air,RH,u,S)
124
- results.append(f"{m} | سهم={share*100:.1f}% | ΔT={dT:+.3f}°C")
125
-
126
- if not results: return "⛔ هیچ مصالح معتبری شناسایی نشد."
127
-
128
- scene_deltaT=sum((counter[m]/total_patches)*calc_deltaT(m,T_air,RH,u,S) for m in materials_found)
129
- summary=f"📌 ΔT میانگین وزنی: {scene_deltaT:+.2f} °C\n📌 دمای مؤثر سطح: {T_air+scene_deltaT:.2f} °C"
130
- return "\n".join(results+["",summary])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  # ==============================
133
- # رابط کاربری Gradio
134
  # ==============================
135
  demo = gr.Interface(
136
- fn=analyze,
137
  inputs=[
138
- gr.Image(type="pil",label="📷 تصویر را بارگذاری کنید"),
139
- gr.Number(label="🌡️ دمای هوا (°C)",value=32),
140
- gr.Number(label="💧 رطوبت نسبی (%)",value=40),
141
- gr.Number(label="💨 سرعت باد (m/s)",value=2),
142
- gr.Number(label="☀️ تابش خورشیدی (W/m²)",value=700)
143
  ],
144
- outputs=gr.Textbox(label="نتایج تحلیل")
 
 
 
 
145
  )
146
 
147
- if __name__=="__main__":
148
- demo.launch()
 
1
  # -*- coding: utf-8 -*-
2
+ """
3
+ کد کامل تحلیل مصالح ساختمانی با Gradio Interface
4
+ """
5
+
6
  import gradio as gr
7
  from collections import Counter
8
  from transformers import AutoImageProcessor, AutoModelForImageClassification
9
  from PIL import Image
10
+ import torch
11
+ import math
12
 
13
  # ==============================
14
+ # 📦 بارگذاری مدل
15
  # ==============================
16
+ @torch.no_grad()
17
+ def load_model():
18
+ model_id = "prithivMLmods/Minc-Materials-23"
19
+ processor = AutoImageProcessor.from_pretrained(model_id)
20
+ model = AutoModelForImageClassification.from_pretrained(model_id)
21
+ return processor, model
22
+
23
+ processor, model = load_model()
24
 
25
  # ==============================
26
  # 📊 پارامترهای مصالح
27
  # ==============================
28
  material_params = {
29
+ "brick": {"alpha": 0.3, "eps": 0.9, "I": 1600, "name": "آجر"},
30
+ "stone": {"alpha": 0.25, "eps": 0.92, "I": 2000, "name": "سنگ"},
31
+ "polishedstone": {"alpha": 0.2, "eps": 0.9, "I": 2100, "name": "سنگ صیقلی"},
32
+ "concrete": {"alpha": 0.35, "eps": 0.9, "I": 1800, "name": "بتن"},
33
+ "metal": {"alpha": 0.5, "eps": 0.2, "I": 4000, "name": "فلز"},
34
+ "glass": {"alpha": 0.1, "eps": 0.85, "I": 1500, "name": "شیشه"},
35
+ "wood": {"alpha": 0.35, "eps": 0.9, "I": 800, "name": "چوب"},
36
+ "tile": {"alpha": 0.4, "eps": 0.9, "I": 1200, "name": "کاشی"},
37
+ "ceramic": {"alpha": 0.45, "eps": 0.92, "I": 1300, "name": "سرامیک"},
38
+ "painted": {"alpha": 0.3, "eps": 0.9, "I": 1000, "name": "سطح رنگ‌شده"},
39
+ "plastic": {"alpha": 0.1, "eps": 0.95, "I": 800, "name": "پلاستیک"},
40
+ "paper": {"alpha": 0.6, "eps": 0.95, "I": 500, "name": "کاغذ"},
41
+ "mirror": {"alpha": 0.7, "eps": 0.1, "I": 2000, "name": "آینه"},
42
+ "foliage": {"alpha": 0.25, "eps": 0.98, "I": 900, "name": "گیاهان"},
43
+ "water": {"alpha": 0.06, "eps": 0.98, "I": 4200, "name": "آب"},
44
+ "sky": {"alpha": 1.0, "eps": 1.0, "I": 0, "name": "آسمان"},
45
  }
46
 
47
+ material_categories = {
48
+ "facade": {
49
+ "members": ["brick", "stone", "polishedstone", "concrete", "tile", "ceramic", "painted"],
50
+ "candidates": ["brick", "stone", "polishedstone", "concrete", "tile", "ceramic", "painted"]
51
+ },
52
+ "glazing": {
53
+ "members": ["glass", "mirror"],
54
+ "candidates": ["glass", "mirror"]
55
+ },
56
+ "metallic": {
57
+ "members": ["metal"],
58
+ "candidates": ["metal"]
59
+ },
60
+ "coverings": {
61
+ "members": ["plastic", "paper"],
62
+ "candidates": ["plastic", "paper"]
63
+ },
64
+ "wood_elements": {
65
+ "members": ["wood"],
66
+ "candidates": ["wood"]
67
+ },
68
+ "vegetation": {
69
+ "members": ["foliage"],
70
+ "candidates": ["foliage"]
71
+ },
72
+ "water_bodies": {
73
+ "members": ["water"],
74
+ "candidates": ["water"]
75
+ },
76
+ "background": {
77
+ "members": ["sky"],
78
+ "candidates": ["sky"]
79
+ }
80
  }
81
 
82
+ replacement_text = {
83
+ "facade": {
84
+ "brick": "آجر روشن یا نمای سرامیکی/تایل روشن با پوشش بازتابی",
85
+ "stone": "سنگ روشن یا سنگ با پوشش بازتابی",
86
+ "polishedstone": "سنگ مات روشن یا سرامیک نما روشن",
87
+ "concrete": "بتن روشن با پوشش بازتابی یا موزاییک نما روشن",
88
+ "tile": "کاشی/سرامیک روشن یا متخلخل",
89
+ "ceramic": "سرامیک روشن با نمای بازتابی",
90
+ "painted": "رنگ بازتابی (cool paint) یا پوشش نانو بازتابی"
91
+ },
92
+ "glazing": {
93
+ "glass": "شیشه دو جداره با پوشش Low-E یا شیشه بازتابی کنترل‌شده",
94
+ "mirror": "شیشه مات یا شیشه Low-E با فریم عایق"
95
+ },
96
+ "metallic": {
97
+ "metal": "آلومینیوم رنگ روشن یا پوشش پودری با بازتاب بالا"
98
+ },
99
+ "coverings": {
100
+ "plastic": "سنگ سبک یا چوب روکش‌دار روشن",
101
+ "paper": "جایگزینی طراحی یا مواد پایدارتر"
102
+ },
103
+ "wood_elements": {
104
+ "wood": "چوب رنگ روشن یا چوب با روکش بازتابی/محافظ"
105
+ },
106
+ "vegetation": {
107
+ "foliage": "حفظ و گسترش پوشش گیاهی طبیعی"
108
+ },
109
+ "water_bodies": {
110
+ "water": "حفظ منابع آبی به عنوان عنصر خنک‌کننده"
111
+ },
112
+ "background": {
113
+ "sky": "عنصر طبیعی بدون نیاز به تغییر"
114
+ }
115
  }
116
 
117
  # ==============================
118
+ # 🔧 توابع کمکی
119
  # ==============================
120
+ def ET_proxy(T, RH):
121
+ es = 0.6108 * math.exp((17.27 * T) / (T + 237.3))
122
+ return es * (1 - RH / 100.0)
123
 
124
+ def calc_deltaT(material, T_air, RH, u, S):
125
+ if material not in material_params:
126
+ return 0.0
127
+
128
+ alpha = material_params[material]["alpha"]
129
+ eps = material_params[material]["eps"]
130
+ I = material_params[material]["I"]
131
+
132
+ A, B, C, D = 1.0, 0.4, 0.8, 0.015
133
+ h_c = 5.8 + 4.1 * u
134
+
135
+ if material == "foliage":
136
+ C_m = A * (1 - alpha) - D * ET_proxy(T_air, RH)
137
  else:
138
+ C_m = A * (1 - alpha) + B * (1 - eps) + (C / math.sqrt(max(I, 1)))
139
+
140
+ gamma = S / max(h_c, 1e-6)
141
+ return gamma * C_m / 1000.0
142
+
143
+ def get_patches(image, size=224, stride=100):
144
  patches = []
145
  w, h = image.size
146
 
147
+ for scale in [1.0, 0.75]:
 
148
  scaled_w, scaled_h = int(w * scale), int(h * scale)
149
  if min(scaled_w, scaled_h) < size:
150
  continue
 
159
  patches.append(patch)
160
 
161
  return patches
162
+
163
  # ==============================
164
+ # 🎯 تابع اصلی تحلیل
165
  # ==============================
166
+ def analyze_image(img, T_air, RH, u, S):
167
+ try:
168
+ img = img.convert("RGB")
169
+ patches = get_patches(img)
170
+
171
+ if len(patches) == 0:
172
+ return "⛔ تصویر نامعتبر است یا کوچک است."
173
+
174
+ # پیش‌بینی با اعتم��د بیشتر
175
+ all_predictions = []
176
+ confidence_threshold = 0.7 # افزایش آستانه اطمینان
177
+
178
+ for patch in patches:
179
+ inputs = processor(images=patch, return_tensors="pt")
180
+
181
+ with torch.no_grad():
182
+ outputs = model(**inputs)
183
+ probs = torch.nn.functional.softmax(outputs.logits, dim=-1)
184
+ confidence, pred = torch.max(probs, dim=-1)
185
+
186
+ if confidence.item() > confidence_threshold:
187
+ label = model.config.id2label[pred.item()]
188
+ all_predictions.append(label)
189
+
190
+ if not all_predictions:
191
+ return "⛔ هیچ مصالح معتبری با اطمینان کافی شناسایی نشد."
192
+
193
+ counter = Counter(all_predictions)
194
+ total_patches = len(all_predictions)
195
+
196
+ # فیلتر مواد با فراوانی کافی
197
+ materials_found = {}
198
+ ignore_classes = ["food", "skin", "other", "wallpaper", "carpet", "fabric"]
199
+
200
+ for m, count in counter.items():
201
+ if (m in material_params and
202
+ m not in ignore_classes and
203
+ count >= max(3, total_patches * 0.1)):
204
+ materials_found[m] = count
205
+
206
+ if not materials_found:
207
+ return "⛔ هیچ مصالح معتبری شناسایی نشد."
208
+
209
+ # محاسبه اطلاعات مواد
210
+ material_info = {}
211
+ for m, count in materials_found.items():
212
+ share = count / total_patches
213
+ dT = calc_deltaT(m, T_air, RH, u, S)
214
+ material_info[m] = {"count": count, "share": share, "deltaT": dT}
215
+
216
+ # محاسبه توصیه‌ها
217
+ IMPROVEMENT_THRESHOLD = 0.02
218
+ SHARE_IMPORTANCE_THRESHOLD = 0.03
219
+
220
+ candidate_delta_cache = {}
221
+ for cat, info in material_categories.items():
222
+ for candidate in info["candidates"]:
223
+ if candidate not in candidate_delta_cache:
224
+ candidate_delta_cache[candidate] = calc_deltaT(candidate, T_air, RH, u, S)
225
+
226
+ results = []
227
+ for m, info in material_info.items():
228
+ # پیدا کردن دسته
229
+ found_category = None
230
+ for cat, cinfo in material_categories.items():
231
+ if m in cinfo["members"]:
232
+ found_category = cat
233
+ break
234
+
235
+ if found_category is None:
236
+ results.append(f"{material_params[m]['name']} | سهم={info['share']*100:.1f}% | ΔT={info['deltaT']:+.2f}°C | دسته‌بندی نشده")
237
+ continue
238
+
239
+ # پیدا کردن بهترین جایگزین
240
+ candidates = material_categories[found_category]["candidates"]
241
+ cand_list = []
242
+ for c in candidates:
243
+ dTc = candidate_delta_cache.get(c, calc_deltaT(c, T_air, RH, u, S))
244
+ cand_list.append((c, dTc))
245
+
246
+ cand_list.sort(key=lambda x: x[1])
247
+ current_dT = info["deltaT"]
248
+ best_candidate, best_dT = cand_list[0]
249
+ improvement = current_dT - best_dT
250
+
251
+ if improvement >= IMPROVEMENT_THRESHOLD and best_candidate != m:
252
+ importance = "بالا" if info["share"] >= SHARE_IMPORTANCE_THRESHOLD else "اختیاری"
253
+ suggestion = replacement_text.get(found_category, {}).get(best_candidate, "جایگزین بهینه")
254
+
255
+ results.append(
256
+ f"{material_params[m]['name']} | سهم={info['share']*100:.1f}% | ΔT={current_dT:+.2f}°C | "
257
+ f"جایگزین: {material_params[best_candidate]['name']} (ΔT={best_dT:+.2f}°C) | "
258
+ f"بهبود: {improvement:.2f}°C | اهمیت: {importance} | پیشنهاد: {suggestion}"
259
+ )
260
+ else:
261
+ results.append(
262
+ f"{material_params[m]['name']} | سهم={info['share']*100:.1f}% | ΔT={current_dT:+.2f}°C | بهینه است"
263
+ )
264
+
265
+ # محاسبه میانگین وزنی
266
+ scene_deltaT = sum(info["share"] * info["deltaT"] for info in material_info.values())
267
+
268
+ summary = (
269
+ f"\n📊 خلاصه نتایج:\n"
270
+ f"• ΔT میانگین وزنی: {scene_deltaT:+.2f}°C\n"
271
+ f"• دمای مؤثر سطح: {T_air + scene_deltaT:.2f}°C\n"
272
+ f"• تعداد پچ‌های تحلیل شده: {total_patches}\n"
273
+ f"• مصالح شناسایی شده: {', '.join([material_params[m]['name'] for m in materials_found.keys()])}"
274
+ )
275
+
276
+ return "\n".join(results) + summary
277
+
278
+ except Exception as e:
279
+ return f"خطا در پردازش: {str(e)}"
280
 
281
  # ==============================
282
+ # 🎨 رابط کاربری Gradio
283
  # ==============================
284
  demo = gr.Interface(
285
+ fn=analyze_image,
286
  inputs=[
287
+ gr.Image(type="pil", label="📷 تصویر نمای ساختمان"),
288
+ gr.Slider(minimum=-10, maximum=50, value=32, step=1, label="🌡️ دمای هوا (°C)"),
289
+ gr.Slider(minimum=0, maximum=100, value=40, step=5, label="💧 رطوبت نسبی (%)"),
290
+ gr.Slider(minimum=0, maximum=10, value=2, step=0.5, label="💨 سرعت باد (m/s)"),
291
+ gr.Slider(minimum=0, maximum=1500, value=700, step=50, label="☀️ تابش خورشیدی (W/m²)")
292
  ],
293
+ outputs=gr.Textbox(label="نتایج تحلیل", lines=20),
294
+ title="🏗️ تحلیل هوشمند مصالح ساختمانی",
295
+ description="""این سامانه با استفاده از هوش مصنوعی، مصالح ساختمانی را شناسایی کرده و
296
+ با تحلیل حرارتی، بهینه‌ترین گزینه‌ها را برای بهبود عملکرد حرارتی پیشنهاد می‌دهد.""",
297
+ allow_flagging="never"
298
  )
299
 
300
+ if __name__ == "__main__":
301
+ demo.launch(share=True, server_name="0.0.0.0", server_port=7860)