reyhane1222 commited on
Commit
96ad7d9
·
verified ·
1 Parent(s): 184663b

Update app.py

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