EngReem85 commited on
Commit
e386977
·
verified ·
1 Parent(s): 8313df0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -33
app.py CHANGED
@@ -7,7 +7,7 @@ import os
7
  import spaces
8
 
9
  # ============================================
10
- # 1. تحميل أو بناء النموذج
11
  # ============================================
12
  model_path = 'mnist_cnn_model.keras'
13
 
@@ -15,14 +15,15 @@ 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)),
22
  layers.Conv2D(64, (3, 3), activation='relu'),
23
  layers.MaxPooling2D((2, 2)),
24
  layers.Flatten(),
25
- layers.Dense(64, activation='relu'),
 
26
  layers.Dense(10, activation='softmax')
27
  ])
28
  model.compile(optimizer='adam',
@@ -31,57 +32,74 @@ else:
31
 
32
  (x_train, y_train), _ = datasets.mnist.load_data()
33
  x_train = x_train.reshape((60000, 28, 28, 1)).astype('float32') / 255
34
- model.fit(x_train, y_train, epochs=3, validation_split=0.1, verbose=1)
35
  model.save(model_path)
36
  print("✅ تم بناء النموذج وتدريبه وحفظه.")
37
 
38
  # ============================================
39
- # 2. تحميل بيانات الاختبار للأمثلة العشوائية
40
  # ============================================
41
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
42
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
43
 
44
  # ============================================
45
- # 3. دالة معالجة الصورة والتنبؤ (ذكية)
46
  # ============================================
47
  @spaces.GPU
48
  def predict_sketch(image):
49
  try:
50
- # 1. تحويل إلى تدرج رمادي
 
 
 
 
51
  if len(image.shape) == 3:
52
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
53
  else:
54
  gray = image
55
 
56
- # 2. تغيير الحجم إلى 28x28
57
  resized = cv2.resize(gray, (28, 28))
58
 
59
- # 3. تطبيع القيم إلى [0,1]
60
- normalized = resized.astype('float32') / 255.0
 
61
 
62
- # 4. **المعالجة الذكية: نحاول كلا الاتجاهين ونأخذ الأفضل**
63
- # MNIST تدربت على خلفية سوداء (0) وأرقام بيضاء (1)
64
- # لكن Sketchpad قد يعطي خلفية بيضاء وأرقام سوداء
 
65
 
66
- # الخيار 1: الصورة كما هي (افتراض أن الخلفية سوداء والرقم أبيض)
67
- img1 = normalized.reshape(1, 28, 28, 1)
68
- pred1 = model.predict(img1, verbose=0)[0]
69
 
70
- # الخيار 2: قلب الألوان (افتراض أن الخلفية بيضاء والرقم أسود)
71
- img2 = (1 - normalized).reshape(1, 28, 28, 1)
72
- pred2 = model.predict(img2, verbose=0)[0]
73
 
74
- # اختيار النتيجة ذات الثقة الأعلى
75
- max_conf1 = np.max(pred1)
76
- max_conf2 = np.max(pred2)
 
77
 
78
- if max_conf1 >= max_conf2:
79
- return {str(i): float(pred1[i]) for i in range(10)}
80
- else:
81
- return {str(i): float(pred2[i]) for i in range(10)}
82
-
 
 
 
 
 
 
 
 
 
 
 
83
  except Exception as e:
84
- return {"خطأ": str(e)}
85
 
86
  # ============================================
87
  # 4. دالة المثال العشوائي
@@ -89,7 +107,9 @@ def predict_sketch(image):
89
  def random_example():
90
  idx = np.random.randint(0, len(test_images))
91
  img = test_images[idx].reshape(28, 28)
92
- img_rgb = np.stack([img] * 3, axis=2)
 
 
93
  return img_rgb, f"الرقم الحقيقي: {test_labels[idx]}"
94
 
95
  # ============================================
@@ -101,19 +121,23 @@ with gr.Blocks(title="MNIST Recognizer") as demo:
101
 
102
  with gr.Row():
103
  with gr.Column(scale=1):
104
- sketch = gr.Sketchpad(label="✏️ ارسم هنا")
 
 
 
 
105
  with gr.Row():
106
  submit_btn = gr.Button("🔮 توقع", variant="primary")
107
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
108
- info = gr.Textbox(label="📌 معلومات", interactive=False)
109
 
110
  with gr.Column(scale=1):
111
  output = gr.Label(num_top_classes=3, label="📊 الاحتمالات")
112
 
113
- submit_btn.click(fn=predict_sketch, inputs=sketch, outputs=output)
114
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
115
 
116
  # ============================================
117
- # 6. تشغيل التطبيق (في النطاق العام لـ ZeroGPU)
118
  # ============================================
119
  demo.launch()
 
7
  import spaces
8
 
9
  # ============================================
10
+ # 1. تحميل النموذج (مع تدريب أفضل إن لزم)
11
  # ============================================
12
  model_path = 'mnist_cnn_model.keras'
13
 
 
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)),
22
  layers.Conv2D(64, (3, 3), activation='relu'),
23
  layers.MaxPooling2D((2, 2)),
24
  layers.Flatten(),
25
+ layers.Dense(128, activation='relu'),
26
+ layers.Dropout(0.5),
27
  layers.Dense(10, activation='softmax')
28
  ])
29
  model.compile(optimizer='adam',
 
32
 
33
  (x_train, y_train), _ = datasets.mnist.load_data()
34
  x_train = x_train.reshape((60000, 28, 28, 1)).astype('float32') / 255
35
+ model.fit(x_train, y_train, epochs=5, validation_split=0.1, verbose=1)
36
  model.save(model_path)
37
  print("✅ تم بناء النموذج وتدريبه وحفظه.")
38
 
39
  # ============================================
40
+ # 2. تحميل بيانات الاختبار
41
  # ============================================
42
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
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:
102
+ return {"خطأ": str(e)}, f"❌ خطأ: {str(e)}"
103
 
104
  # ============================================
105
  # 4. دالة المثال العشوائي
 
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
  # ============================================
 
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="📊 الاحتمالات")
136
 
137
+ submit_btn.click(fn=predict_sketch, inputs=sketch, outputs=[output, info])
138
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
139
 
140
  # ============================================
141
+ # 6. تشغيل التطبيق (في النطاق العام)
142
  # ============================================
143
  demo.launch()