EngReem85 commited on
Commit
16c0125
·
verified ·
1 Parent(s): e386977

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -37
app.py CHANGED
@@ -15,7 +15,7 @@ if os.path.exists(model_path):
15
  model = tf.keras.models.load_model(model_path)
16
  print("✅ تم تحميل النموذج المحفوظ.")
17
  else:
18
- print("⚠️ بناء نموذج جديد مع تدريب أطول...")
19
  model = models.Sequential([
20
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
21
  layers.MaxPooling2D((2, 2)),
@@ -43,59 +43,58 @@ else:
43
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
44
 
45
  # ============================================
46
- # 3. دالة معالجة الصورة والتنبؤ (مع تصحيح)
47
  # ============================================
48
  @spaces.GPU
49
  def predict_sketch(image):
50
  try:
51
- # --- 3.1 التأكد من شكل الصورة ---
52
  if isinstance(image, dict):
53
  image = image['composite']
54
 
55
- # إذا كانت الصورة (280, 280, 3) أو (280, 280)
56
  if len(image.shape) == 3:
57
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
58
  else:
59
  gray = image
60
 
61
- # --- 3.2 تغيير الحجم إلى 28x28 ---
62
  resized = cv2.resize(gray, (28, 28))
63
 
64
- # --- 3.3 اكتشاف اتجاه الألوان تلقائياً ---
65
- # حساب متوسط السطوع
66
  mean_val = np.mean(resized)
67
-
68
- # إذا كان المتوسط > 127 (أي الخلفية فاتحة والكتابة غامقة) → نقلب الألوان
69
- # لأن MNIST تريد خلفية سوداء (0) وكتابة بيضاء (1)
70
  if mean_val > 127:
 
71
  resized = 255 - resized
 
 
 
72
 
73
- # --- 3.4 تطبيق عتبة (Threshold) لتحسين الرسم ---
74
  _, thresh = cv2.threshold(resized, 128, 255, cv2.THRESH_BINARY)
75
 
76
- # --- 3.5 تطبيع إلى [0,1] وإعادة التشكيل ---
77
  normalized = thresh.astype('float32') / 255.0
78
  reshaped = normalized.reshape(1, 28, 28, 1)
79
 
80
- # --- 3.6 التنبؤ ---
81
  pred = model.predict(reshaped, verbose=0)[0]
82
- predicted_class = np.argmax(pred)
83
- confidence = np.max(pred)
84
 
85
- # --- 3.7 معلومات التصحيح (تعرض في مربع المعلومات) ---
86
- debug_info = f"""
87
- 📊 معلومات المعالجة:
88
- - متوسط السطوع الأصلي: {mean_val:.1f}
89
- - تم {'قلب الألوان' if mean_val > 127 else 'الإبقاء على الألوان'}
90
- - الفئة المتوقعة: {predicted_class}
91
- - نسبة الثقة: {confidence:.2%}
92
- - أعلى 3 احتمالات:
93
- """
94
  top3_idx = np.argsort(pred)[-3:][::-1]
95
- for i, idx in enumerate(top3_idx):
96
- debug_info += f"\n {i+1}. {idx}: {pred[idx]:.2%}"
97
-
98
- # إرجاع الاحتمالات والمعلومات
 
 
 
 
 
 
 
99
  return {str(i): float(pred[i]) for i in range(10)}, debug_info
100
 
101
  except Exception as e:
@@ -107,13 +106,13 @@ def predict_sketch(image):
107
  def random_example():
108
  idx = np.random.randint(0, len(test_images))
109
  img = test_images[idx].reshape(28, 28)
110
- # تكبير الصورة لتظهر بشكل واضح في Sketchpad
111
  img_large = cv2.resize(img, (280, 280))
112
  img_rgb = np.stack([img_large] * 3, axis=2)
113
  return img_rgb, f"الرقم الحقيقي: {test_labels[idx]}"
114
 
115
  # ============================================
116
- # 5. بناء واجهة Gradio
117
  # ============================================
118
  with gr.Blocks(title="MNIST Recognizer") as demo:
119
  gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد")
@@ -121,15 +120,12 @@ with gr.Blocks(title="MNIST Recognizer") as demo:
121
 
122
  with gr.Row():
123
  with gr.Column(scale=1):
124
- sketch = gr.Sketchpad(
125
- label="✏️ ارسم هنا",
126
- brush_radius=12, # تحكم في سمك الفرشاة
127
- brush_color="#FFFFFF" # لون الفرشاة (أبيض على خلفية سوداء)
128
- )
129
  with gr.Row():
130
  submit_btn = gr.Button("🔮 توقع", variant="primary")
131
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
132
- info = gr.Textbox(label="📌 معلومات التصحيح", interactive=False, lines=8)
133
 
134
  with gr.Column(scale=1):
135
  output = gr.Label(num_top_classes=3, label="📊 الاحتمالات")
@@ -138,6 +134,6 @@ with gr.Blocks(title="MNIST Recognizer") as demo:
138
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
139
 
140
  # ============================================
141
- # 6. تشغيل التطبيق (في النطاق العام)
142
  # ============================================
143
  demo.launch()
 
15
  model = tf.keras.models.load_model(model_path)
16
  print("✅ تم تحميل النموذج المحفوظ.")
17
  else:
18
+ print("⚠️ بناء نموذج جديد...")
19
  model = models.Sequential([
20
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
21
  layers.MaxPooling2D((2, 2)),
 
43
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
44
 
45
  # ============================================
46
+ # 3. دالة التنبؤ (ذكية وتظهر معلومات التصحيح)
47
  # ============================================
48
  @spaces.GPU
49
  def predict_sketch(image):
50
  try:
51
+ # 3.1 التأكد من أن الصورة بصيغة numpy
52
  if isinstance(image, dict):
53
  image = image['composite']
54
 
55
+ # 3.2 تحويل إلى تدرج رمادي
56
  if len(image.shape) == 3:
57
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
58
  else:
59
  gray = image
60
 
61
+ # 3.3 تغيير الحجم إلى 28x28
62
  resized = cv2.resize(gray, (28, 28))
63
 
64
+ # 3.4 اكتشاف اتجاه الألوان تلقائياً
 
65
  mean_val = np.mean(resized)
 
 
 
66
  if mean_val > 127:
67
+ # الخلفية فاتحة، نقلب الألوان
68
  resized = 255 - resized
69
+ flip_status = "تم قلب الألوان (خلفية فاتحة → خلفية سوداء)"
70
+ else:
71
+ flip_status = "الإبقاء على الألوان (خلفية سوداء بالفعل)"
72
 
73
+ # 3.5 تطبيق عتبة لتحسين الرسم
74
  _, thresh = cv2.threshold(resized, 128, 255, cv2.THRESH_BINARY)
75
 
76
+ # 3.6 تطبيع وإعادة تشكيل
77
  normalized = thresh.astype('float32') / 255.0
78
  reshaped = normalized.reshape(1, 28, 28, 1)
79
 
80
+ # 3.7 التنبؤ
81
  pred = model.predict(reshaped, verbose=0)[0]
82
+ predicted_class = int(np.argmax(pred))
83
+ confidence = float(np.max(pred))
84
 
85
+ # 3.8 بناء معلومات التصحيح
 
 
 
 
 
 
 
 
86
  top3_idx = np.argsort(pred)[-3:][::-1]
87
+ top3_str = "\n".join([f" {i+1}. {idx}: {pred[idx]:.2%}" for i, idx in enumerate(top3_idx)])
88
+ debug_info = f"""
89
+ 📊 معلومات المعالجة:
90
+ - متوسط السطوع الأصلي: {mean_val:.1f}
91
+ - {flip_status}
92
+ - الفئة المتوقعة: {predicted_class}
93
+ - نسبة الثقة: {confidence:.2%}
94
+ - أعلى 3 احتمالات:
95
+ {top3_str}
96
+ """
97
+ # 3.9 إرجاع الاحتمالات ومعلومات التصحيح
98
  return {str(i): float(pred[i]) for i in range(10)}, debug_info
99
 
100
  except Exception as e:
 
106
  def random_example():
107
  idx = np.random.randint(0, len(test_images))
108
  img = test_images[idx].reshape(28, 28)
109
+ # تكبير الصورة لـ Sketchpad
110
  img_large = cv2.resize(img, (280, 280))
111
  img_rgb = np.stack([img_large] * 3, axis=2)
112
  return img_rgb, f"الرقم الحقيقي: {test_labels[idx]}"
113
 
114
  # ============================================
115
+ # 5. بناء واجهة Gradio (بدون وسائط غير مدعومة)
116
  # ============================================
117
  with gr.Blocks(title="MNIST Recognizer") as demo:
118
  gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد")
 
120
 
121
  with gr.Row():
122
  with gr.Column(scale=1):
123
+ # 🔥 حذف brush_radius و brush_color نهائياً
124
+ sketch = gr.Sketchpad(label="✏️ ارسم هنا")
 
 
 
125
  with gr.Row():
126
  submit_btn = gr.Button("🔮 توقع", variant="primary")
127
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
128
+ info = gr.Textbox(label="📌 معلومات التصحيح", interactive=False, lines=10)
129
 
130
  with gr.Column(scale=1):
131
  output = gr.Label(num_top_classes=3, label="📊 الاحتمالات")
 
134
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
135
 
136
  # ============================================
137
+ # 6. تشغيل التطبيق (في النطاق العام لـ ZeroGPU)
138
  # ============================================
139
  demo.launch()