EngReem85 commited on
Commit
dd7ac53
·
verified ·
1 Parent(s): 24a7bb6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -114
app.py CHANGED
@@ -11,8 +11,6 @@ import gdown
11
  import os
12
  import albumentations as A
13
  import segmentation_models_pytorch as smp
14
- from rembg import remove
15
- import mediapipe as mp
16
 
17
  # تعريفات عالمية
18
  classifier = None
@@ -21,10 +19,6 @@ class_names = ["Abnormal(Ulcer)", "Normal(Healthy skin)"]
21
  IMG_SIZE = 224
22
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
23
 
24
- # تهيئة MediaPipe للكشف عن القدم
25
- mp_pose = mp.solutions.pose
26
- mp_drawing = mp.solutions.drawing_utils
27
-
28
  class FUSegNet(nn.Module):
29
  """FUSegNet نموذج مخصص لمطابقة هيكل"""
30
  def __init__(self, encoder_name='efficientnet-b7', classes=1, activation='sigmoid'):
@@ -46,6 +40,7 @@ def check_and_download(url, path, min_size_mb=50):
46
  print(f"📥 تحميل النموذج من Google Drive: {url}")
47
  try:
48
  gdown.download(url, path, quiet=False, fuzzy=True)
 
49
  except Exception as e:
50
  print(f"❌ خطأ في التحميل: {e}")
51
 
@@ -99,62 +94,54 @@ def initialize_models():
99
  print(f"❌ خطأ في تحميل نموذج التجزئة: {e}")
100
  segmenter = None
101
 
102
- def remove_background(img: Image.Image):
103
- """إزالة خلفية الصورة للتركيز على القدم"""
104
  try:
105
- # استخدام rembg لإزالة الخلفية
106
  img_np = np.array(img)
107
- img_no_bg = remove(img_np)
108
- return Image.fromarray(img_no_bg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  except Exception as e:
110
  print(f"⚠️ فشل إزالة الخلفية: {e}")
111
  return img
112
 
113
  def detect_foot_region(img: Image.Image):
114
- """الكشف عن منطقة القدم باستخدام MediaPipe"""
115
  try:
116
  img_np = np.array(img)
 
117
 
118
- with mp_pose.Pose(static_image_mode=True, min_detection_confidence=0.5) as pose:
119
- results = pose.process(cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR))
120
-
121
- if results.pose_landmarks:
122
- # الحصول على معالم القدمين (المراجع 29-32 للقدم اليسرى و 30-31 للقدم اليمنى)
123
- landmarks = results.pose_landmarks.landmark
124
-
125
- h, w, _ = img_np.shape
126
- foot_points = []
127
-
128
- # القدم اليسرى
129
- left_foot_indices = [27, 29, 31]
130
- for idx in left_foot_indices:
131
- if landmarks[idx].visibility > 0.5:
132
- foot_points.append([int(landmarks[idx].x * w), int(landmarks[idx].y * h)])
133
-
134
- # القدم اليمنى
135
- right_foot_indices = [28, 30, 32]
136
- for idx in right_foot_indices:
137
- if landmarks[idx].visibility > 0.5:
138
- foot_points.append([int(landmarks[idx].x * w), int(landmarks[idx].y * h)])
139
-
140
- if foot_points:
141
- foot_points = np.array(foot_points)
142
- x_min, y_min = foot_points.min(axis=0)
143
- x_max, y_max = foot_points.max(axis=0)
144
-
145
- # توسيع منطقة الاهتمام قليلاً
146
- padding = 50
147
- x_min = max(0, x_min - padding)
148
- y_min = max(0, y_min - padding)
149
- x_max = min(w, x_max + padding)
150
- y_max = min(h, y_max + padding)
151
-
152
- return img_np[y_min:y_max, x_min:x_max]
153
-
154
- return img_np
155
  except Exception as e:
156
  print(f"⚠️ فشل الكشف عن القدم: {e}")
157
- return np.array(img)
158
 
159
  def preprocess_for_classification(img: Image.Image):
160
  """معالجة الصورة للتصنيف"""
@@ -169,11 +156,10 @@ def classify_image(img: Image.Image):
169
  print("🔄 معالجة الصورة وإزالة الخلفية...")
170
 
171
  # 1. إزالة الخلفية
172
- img_no_bg = remove_background(img)
173
 
174
  # 2. الكشف عن منطقة القدم
175
- foot_region = detect_foot_region(img_no_bg)
176
- foot_img = Image.fromarray(foot_region)
177
 
178
  if classifier is None:
179
  # التصنيف الافتراضي باستخدام تحليل الألوان
@@ -233,9 +219,9 @@ def segment_ulcer(img: Image.Image):
233
  output = segmenter(img_tensor)
234
  pred = output.squeeze().cpu().numpy()
235
 
236
- # إيجاد أفضل عتبة
237
- best_threshold = 0.3
238
- mask_bin = (pred >= best_threshold).astype(np.uint8)
239
  mask_resized = cv2.resize(mask_bin, (img.width, img.height))
240
 
241
  ulcer_pixels = np.sum(mask_resized)
@@ -299,17 +285,16 @@ def check_early_symptoms(img: Image.Image):
299
  symptoms.append("احمرار خفيف في الجلد")
300
 
301
  # 2. جفاف الجلد
302
- lab = cv2.cvtColor(img_np, cv2.COLOR_RGB2LAB)
303
- l_channel = lab[:,:,0]
304
- dry_skin_ratio = np.sum(l_channel > 200) / l_channel.size
305
  if dry_skin_ratio > 0.1:
306
  symptoms.append("جفاف في الجلد")
307
 
308
- # 3. تورم محتمل
309
- edges = cv2.Canny(cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY), 50, 150)
310
  edge_density = np.sum(edges > 0) / edges.size
311
  if edge_density > 0.05:
312
- symptoms.append("تورم محتمل")
313
 
314
  return symptoms
315
 
@@ -317,6 +302,10 @@ def apply_ulcer_mask(img: Image.Image, mask):
317
  """تطبيق قناع القرحة على الصورة"""
318
  img_np = np.array(img)
319
 
 
 
 
 
320
  # إنشاء قناع ملون
321
  colored_mask = np.zeros_like(img_np)
322
  colored_mask[mask == 1] = [255, 0, 0] # أحمر
@@ -333,29 +322,35 @@ def apply_ulcer_mask(img: Image.Image, mask):
333
 
334
  return Image.fromarray(result)
335
 
336
- def generate_report(classification, ulcer_percentage, risk_level, risk_score, symptoms, has_ulcer):
337
- """توليد تقرير مفصل"""
 
338
  report = {
339
  "التصنيف": classification,
340
  "نسبة_القرحة": f"{ulcer_percentage:.2f}%",
341
- "مستوى_الخطورة": risk_level,
342
- "درجة_الخطورة": risk_score,
343
- "التوصيات": []
344
  }
345
 
346
  if not has_ulcer:
 
347
  if symptoms:
348
- report["الأعراض_المبكرة"] = symptoms
349
- report["التوصيات"].append("مراجعة طبية للكشف عن الأعراض المبكرة")
350
- report["التوصيات"].append("العناية اليومية بالقدمين")
 
351
  else:
352
- report["الحالة"] = "سليمة"
353
- report["التوصيات"].append("استمرار في العناية بالقدمين")
354
- report["التوصيات"].append("فحص دوري للقدمين")
355
  else:
356
- report["التوصيات"].append("مراجعة عاجلة مع طبيب مختص")
357
- report["التوصيات"].append("العناية المركزة بالمنطقة المصابة")
358
- report["التوصيات"].append("تجنب الضغط على المنطقة المصابة")
 
 
 
 
359
 
360
  return report
361
 
@@ -365,10 +360,11 @@ def analyze_single_image(img: Image.Image):
365
  return None, {"خطأ": "لم يتم رفع صورة"}
366
 
367
  try:
368
- print("\n" + "="*50)
369
  print("🚀 بدء تحليل الصورة...")
370
 
371
  # 1. التصنيف مع إزالة الخلفية
 
372
  classification, processed_img = classify_image(img)
373
  has_ulcer = classification == "Abnormal(Ulcer)"
374
 
@@ -381,6 +377,7 @@ def analyze_single_image(img: Image.Image):
381
  print("✅ لا توجد قرحة - الكشف عن الأعراض المبكرة...")
382
  early_symptoms = check_early_symptoms(processed_img)
383
  final_img = processed_img
 
384
  else:
385
  print("⚠️ اكتشاف قرحة - المتابعة للتجزئة...")
386
  # 3. تجزئة القرحة
@@ -391,16 +388,21 @@ def analyze_single_image(img: Image.Image):
391
 
392
  # 4. تطبيق القناع
393
  final_img = apply_ulcer_mask(processed_img, ulcer_mask)
 
394
 
395
  # 5. حساب مستوى الخطر
396
  risk_level, risk_score, risk_emoji = calculate_risk_level(ulcer_percentage)
397
 
398
- # 6. توليد التقرير
399
- report = generate_report(
400
  classification, ulcer_percentage, risk_level, risk_score,
401
  early_symptoms, has_ulcer
402
  )
403
 
 
 
 
 
404
  print(f"📊 النتائج النهائية:")
405
  print(f" - التصنيف: {classification}")
406
  print(f" - نسبة القرحة: {ulcer_percentage:.2f}%")
@@ -412,31 +414,18 @@ def analyze_single_image(img: Image.Image):
412
 
413
  except Exception as e:
414
  print(f"❌ خطأ في تحليل الصورة: {e}")
415
- return img, {"خطأ": f"فشل في التحليل: {str(e)}"}
416
-
417
- def analyze_images(img1, img2):
418
- """تحليل صورتين"""
419
- results = []
420
- reports = {}
421
-
422
- for idx, img in enumerate([img1, img2]):
423
- image_key = f"صورة_{idx+1}"
424
-
425
- if img is None:
426
- results.append(None)
427
- reports[image_key] = {"حالة": "لم يتم رفع صورة"}
428
- else:
429
- analyzed_img, report = analyze_single_image(img)
430
- results.append(analyzed_img)
431
- reports[image_key] = report
432
-
433
- return results, reports
434
 
435
  # تهيئة النماذج
436
  print("🚀 جاري تهيئة النماذج...")
437
  initialize_models()
438
 
439
- # واجهة Gradio
440
  with gr.Blocks(title="نظام تحليل قرحة القدم السكري", theme=gr.themes.Soft()) as demo:
441
  gr.Markdown("""
442
  # 🦶 نظام الذكاء الاصطناعي لتحليل قرحة القدم السكري
@@ -447,25 +436,32 @@ with gr.Blocks(title="نظام تحليل قرحة القدم السكري", the
447
  3. **إذا لا توجد قرحة**: الكشف عن أعراض مبكرة
448
  4. **إذا توجد قرحة**: تحديد منطقة القرحة بدقة
449
  5. **تقييم مستوى الخطورة** وتوليد التقرير
 
 
450
  """)
451
 
452
  with gr.Row():
453
- with gr.Column():
454
- gr.Markdown("### 📤 رفع الصور")
455
- with gr.Row():
456
- img1 = gr.Image(type="pil", label="الصورة الأولى", height=250)
457
- img2 = gr.Image(type="pil", label="الصورة الثانية", height=250)
458
-
459
  analyze_btn = gr.Button("🔍 بدء التحليل", variant="primary", size="lg")
 
 
 
 
 
 
 
 
460
 
461
- with gr.Column():
462
- gr.Markdown("### 📊 النتائج")
463
- gallery = gr.Gallery(label="الصور المحللة", columns=2, height="auto")
464
- json_output = gr.JSON(label="التقارير الطبية")
465
 
466
  gr.Markdown("""
467
  ---
468
- **🎯 تفسير النتائج:**
469
  - **🟢 No Risk**: لا توجد قرحة ولا أعراض مبكرة
470
  - **🟡 Low Risk**: أعراض مبكرة أو قرحة صغيرة (<1%)
471
  - **🟠 Medium Risk**: قرحة متوسطة (1-5%)
@@ -475,11 +471,12 @@ with gr.Blocks(title="نظام تحليل قرحة القدم السكري", the
475
  """)
476
 
477
  analyze_btn.click(
478
- fn=analyze_images,
479
- inputs=[img1, img2],
480
- outputs=[gallery, json_output]
481
  )
482
 
483
  if __name__ == "__main__":
484
  print("🌐 بدء تشغيل السيرفر...")
485
- demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
 
 
11
  import os
12
  import albumentations as A
13
  import segmentation_models_pytorch as smp
 
 
14
 
15
  # تعريفات عالمية
16
  classifier = None
 
19
  IMG_SIZE = 224
20
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
21
 
 
 
 
 
22
  class FUSegNet(nn.Module):
23
  """FUSegNet نموذج مخصص لمطابقة هيكل"""
24
  def __init__(self, encoder_name='efficientnet-b7', classes=1, activation='sigmoid'):
 
40
  print(f"📥 تحميل النموذج من Google Drive: {url}")
41
  try:
42
  gdown.download(url, path, quiet=False, fuzzy=True)
43
+ print(f"✅ تم تحميل: {os.path.basename(path)}")
44
  except Exception as e:
45
  print(f"❌ خطأ في التحميل: {e}")
46
 
 
94
  print(f"❌ خطأ في تحميل نموذج التجزئة: {e}")
95
  segmenter = None
96
 
97
+ def remove_background_simple(img: Image.Image):
98
+ """إزالة خلفية الصورة بطريقة مبسطة باستخدام OpenCV"""
99
  try:
 
100
  img_np = np.array(img)
101
+
102
+ # تحويل إلى HSV للكشف عن لون البشرة
103
+ hsv = cv2.cvtColor(img_np, cv2.COLOR_RGB2HSV)
104
+
105
+ # نطاق لون البشرة في HSV
106
+ lower_skin = np.array([0, 20, 70], dtype=np.uint8)
107
+ upper_skin = np.array([20, 255, 255], dtype=np.uint8)
108
+
109
+ # قناع البشرة
110
+ skin_mask = cv2.inRange(hsv, lower_skin, upper_skin)
111
+
112
+ # تنظيف القناع
113
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
114
+ skin_mask = cv2.morphologyEx(skin_mask, cv2.MORPH_OPEN, kernel)
115
+ skin_mask = cv2.morphologyEx(skin_mask, cv2.MORPH_CLOSE, kernel)
116
+ skin_mask = cv2.dilate(skin_mask, kernel, iterations=1)
117
+
118
+ # تطبيق القناع على الصورة
119
+ result = cv2.bitwise_and(img_np, img_np, mask=skin_mask)
120
+
121
+ # إذا كانت الصورة سوداء بالكامل، نعيد الصورة الأصلية
122
+ if np.sum(result) == 0:
123
+ return img
124
+
125
+ return Image.fromarray(result)
126
  except Exception as e:
127
  print(f"⚠️ فشل إزالة الخلفية: {e}")
128
  return img
129
 
130
  def detect_foot_region(img: Image.Image):
131
+ """الكشف عن منطقة القدم"""
132
  try:
133
  img_np = np.array(img)
134
+ h, w = img_np.shape[:2]
135
 
136
+ # طريقة مبسطة للكشف عن المنطقة السفلية (القدم)
137
+ # نفترض أن القدم في الجزء السفلي من الصورة
138
+ foot_height = h // 2 # النصف السفلي من الصورة
139
+ foot_region = img_np[h - foot_height:, :]
140
+
141
+ return Image.fromarray(foot_region)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  except Exception as e:
143
  print(f"⚠️ فشل الكشف عن القدم: {e}")
144
+ return img
145
 
146
  def preprocess_for_classification(img: Image.Image):
147
  """معالجة الصورة للتصنيف"""
 
156
  print("🔄 معالجة الصورة وإزالة الخلفية...")
157
 
158
  # 1. إزالة الخلفية
159
+ img_no_bg = remove_background_simple(img)
160
 
161
  # 2. الكشف عن منطقة القدم
162
+ foot_img = detect_foot_region(img_no_bg)
 
163
 
164
  if classifier is None:
165
  # التصنيف الافتراضي باستخدام تحليل الألوان
 
219
  output = segmenter(img_tensor)
220
  pred = output.squeeze().cpu().numpy()
221
 
222
+ # استخدام عتبة ثابتة
223
+ threshold = 0.3
224
+ mask_bin = (pred >= threshold).astype(np.uint8)
225
  mask_resized = cv2.resize(mask_bin, (img.width, img.height))
226
 
227
  ulcer_pixels = np.sum(mask_resized)
 
285
  symptoms.append("احمرار خفيف في الجلد")
286
 
287
  # 2. جفاف الجلد
288
+ gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
289
+ dry_skin_ratio = np.sum(gray > 200) / gray.size
 
290
  if dry_skin_ratio > 0.1:
291
  symptoms.append("جفاف في الجلد")
292
 
293
+ # 3. تشققات محتملة
294
+ edges = cv2.Canny(gray, 50, 150)
295
  edge_density = np.sum(edges > 0) / edges.size
296
  if edge_density > 0.05:
297
+ symptoms.append("تشققات محتملة في الجلد")
298
 
299
  return symptoms
300
 
 
302
  """تطبيق قناع القرحة على الصورة"""
303
  img_np = np.array(img)
304
 
305
+ ulcer_pixels = np.sum(mask == 1)
306
+ if ulcer_pixels == 0:
307
+ return img
308
+
309
  # إنشاء قناع ملون
310
  colored_mask = np.zeros_like(img_np)
311
  colored_mask[mask == 1] = [255, 0, 0] # أحمر
 
322
 
323
  return Image.fromarray(result)
324
 
325
+ def generate_detailed_report(classification, ulcer_percentage, risk_level, risk_score, symptoms, has_ulcer):
326
+ """توليد تقرير مفصل بالعربية"""
327
+
328
  report = {
329
  "التصنيف": classification,
330
  "نسبة_القرحة": f"{ulcer_percentage:.2f}%",
331
+ "مستوى_الخطورة": f"{risk_level} {risk_score}/5",
332
+ "التوصيات_الطبية": []
 
333
  }
334
 
335
  if not has_ulcer:
336
+ report["الحالة"] = "سليمة"
337
  if symptoms:
338
+ report["الاعراض_المبكرة"] = symptoms
339
+ report["التوصيات_الطبية"].append("🔸 مراجعة طبية للكشف عن الأعراض المبكرة")
340
+ report["التوصيات_الطبية"].append("🔸 العناية اليومية بالقدمين وترطيبها")
341
+ report["التوصيات_الطبية"].append("🔸 فحص دوري للقدمين")
342
  else:
343
+ report["الاعراض_المبكرة"] = "لا توجد أعراض مبكرة"
344
+ report["التوصيات_الطبية"].append("استمرار في العناية الروتينية بالقدمين")
345
+ report["التوصيات_الطبية"].append("✅ الحفاظ على نظافة القدمين وجفافهما")
346
  else:
347
+ report["الحالة"] = "توجد قرحة"
348
+ report["التوصيات_الطبية"].append("🚨 مراجعة عاجلة مع طبيب مختص")
349
+ report["التوصيات_الطبية"].append("🔴 تجنب الضغط على المنطقة المصابة")
350
+ report["التوصيات_الطبية"].append("💊 العناية المركزة بالمنطقة وتنظيفها يومياً")
351
+
352
+ if risk_level == "High Risk":
353
+ report["التوصيات_الطبية"].append("⚠️ قد تحتاج إلى تدخل طبي عاجل")
354
 
355
  return report
356
 
 
360
  return None, {"خطأ": "لم يتم رفع صورة"}
361
 
362
  try:
363
+ print("\n" + "="*60)
364
  print("🚀 بدء تحليل الصورة...")
365
 
366
  # 1. التصنيف مع إزالة الخلفية
367
+ print("📝 الخطوة 1: التصنيف وإزالة الخلفية...")
368
  classification, processed_img = classify_image(img)
369
  has_ulcer = classification == "Abnormal(Ulcer)"
370
 
 
377
  print("✅ لا توجد قرحة - الكشف عن الأعراض المبكرة...")
378
  early_symptoms = check_early_symptoms(processed_img)
379
  final_img = processed_img
380
+ analysis_note = "تم تحليل الصورة ولم يتم اكتشاف قرحة"
381
  else:
382
  print("⚠️ اكتشاف قرحة - المتابعة للتجزئة...")
383
  # 3. تجزئة القرحة
 
388
 
389
  # 4. تطبيق القناع
390
  final_img = apply_ulcer_mask(processed_img, ulcer_mask)
391
+ analysis_note = f"تم اكتشاف قرحة بنسبة {ulcer_percentage:.2f}%"
392
 
393
  # 5. حساب مستوى الخطر
394
  risk_level, risk_score, risk_emoji = calculate_risk_level(ulcer_percentage)
395
 
396
+ # 6. توليد التقرير المفصل
397
+ report = generate_detailed_report(
398
  classification, ulcer_percentage, risk_level, risk_score,
399
  early_symptoms, has_ulcer
400
  )
401
 
402
+ # إضافة ملخص النتائج
403
+ report["ملخص_التحليل"] = analysis_note
404
+ report["رمز_الخطورة"] = risk_emoji
405
+
406
  print(f"📊 النتائج النهائية:")
407
  print(f" - التصنيف: {classification}")
408
  print(f" - نسبة القرحة: {ulcer_percentage:.2f}%")
 
414
 
415
  except Exception as e:
416
  print(f"❌ خطأ في تحليل الصورة: {e}")
417
+ error_report = {
418
+ "خطأ": "فشل في تحليل الصورة",
419
+ "التفاصيل": str(e),
420
+ "التوصيات": ["يرجى تحميل صورة أخرى", "تأكد من وضوح الصورة"]
421
+ }
422
+ return img, error_report
 
 
 
 
 
 
 
 
 
 
 
 
 
423
 
424
  # تهيئة النماذج
425
  print("🚀 جاري تهيئة النماذج...")
426
  initialize_models()
427
 
428
+ # واجهة Gradio المبسطة
429
  with gr.Blocks(title="نظام تحليل قرحة القدم السكري", theme=gr.themes.Soft()) as demo:
430
  gr.Markdown("""
431
  # 🦶 نظام الذكاء الاصطناعي لتحليل قرحة القدم السكري
 
436
  3. **إذا لا توجد قرحة**: الكشف عن أعراض مبكرة
437
  4. **إذا توجد قرحة**: تحديد منطقة القرحة بدقة
438
  5. **تقييم مستوى الخطورة** وتوليد التقرير
439
+
440
+ **🔍 ارفع صورة واحدة للتحليل**
441
  """)
442
 
443
  with gr.Row():
444
+ with gr.Column(scale=1):
445
+ gr.Markdown("### 📤 رفع الصورة")
446
+ image_input = gr.Image(type="pil", label="صورة القدم", height=300)
 
 
 
447
  analyze_btn = gr.Button("🔍 بدء التحليل", variant="primary", size="lg")
448
+
449
+ gr.Markdown("""
450
+ **💡 نصائح للصورة:**
451
+ - صورة واضحة للقدم
452
+ - إضاءة جيدة
453
+ - خلفية بسيطة إن أمكن
454
+ - القدم مرئية بوضوح
455
+ """)
456
 
457
+ with gr.Column(scale=1):
458
+ gr.Markdown("### 📊 نتائج التحليل")
459
+ image_output = gr.Image(label="الصورة المحللة", height=300)
460
+ json_output = gr.JSON(label="التقرير الطبي", show_label=True)
461
 
462
  gr.Markdown("""
463
  ---
464
+ **🎯 تفسير مستويات الخطورة:**
465
  - **🟢 No Risk**: لا توجد قرحة ولا أعراض مبكرة
466
  - **🟡 Low Risk**: أعراض مبكرة أو قرحة صغيرة (<1%)
467
  - **🟠 Medium Risk**: قرحة متوسطة (1-5%)
 
471
  """)
472
 
473
  analyze_btn.click(
474
+ fn=analyze_single_image,
475
+ inputs=[image_input],
476
+ outputs=[image_output, json_output]
477
  )
478
 
479
  if __name__ == "__main__":
480
  print("🌐 بدء تشغيل السيرفر...")
481
+ print(" النظام جاهز لتحليل صورة واحدة")
482
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=True)