EngReem85 commited on
Commit
070be86
·
verified ·
1 Parent(s): 4d2d3f7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -50
app.py CHANGED
@@ -5,15 +5,16 @@ import cv2
5
  from tensorflow.keras import datasets, layers, models
6
  import os
7
 
8
- # ==========================================
9
- # 1. تحميل أو بناء النموذج (حل احتياطي)
10
- # ==========================================
11
  model_path = 'mnist_cnn_model.keras'
 
12
  if os.path.exists(model_path):
13
  model = tf.keras.models.load_model(model_path)
14
  print("✅ تم تحميل النموذج المحفوظ.")
15
  else:
16
- print("⚠️ لم نجد النموذج، جارٍ البناء والتدريب (مرة واحدة فقط)...")
17
  model = models.Sequential([
18
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
19
  layers.MaxPooling2D((2, 2)),
@@ -26,91 +27,77 @@ else:
26
  model.compile(optimizer='adam',
27
  loss='sparse_categorical_crossentropy',
28
  metrics=['accuracy'])
 
29
  (train_images, train_labels), _ = datasets.mnist.load_data()
30
  train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
31
  model.fit(train_images, train_labels, epochs=3, validation_split=0.1, verbose=1)
32
  model.save(model_path)
33
- print("✅ تم بناء النموذج وحفظه.")
34
 
35
- # ==========================================
36
- # 2. تحميل بيانات MNIST للأمثلة العشوائية
37
- # ==========================================
38
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
39
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
40
 
41
- # ==========================================
42
- # 3. دالة التنبؤ بالصورة (المرسومة أو المرفوعة)
43
- # ==========================================
44
- def predict_image(image):
 
 
 
45
  try:
46
- # صورة من ImageEditor تأتي بصيغة dict
47
- if isinstance(image, dict):
48
- image = image['composite']
49
-
50
- # تحويل إلى تدرج رمادي
51
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
52
- # تغيير الحجم
53
  resized = cv2.resize(gray, (28, 28))
54
- # قلب الألوان (MNIST تدربت على كتابة بيضاء بخلفية سوداء)
55
  inverted = 255 - resized
56
- # تطبيع
57
  normalized = inverted.astype('float32') / 255.0
58
- # تهيئة للشبكة
59
  reshaped = normalized.reshape(1, 28, 28, 1)
60
 
61
- # التنبؤ
62
  prediction = model.predict(reshaped, verbose=0)[0]
63
  # تحويل إلى قاموس لعرضه في Label
64
  return {str(i): float(prediction[i]) for i in range(10)}
65
  except Exception as e:
66
  return {"خطأ": str(e)}
67
 
68
- # ==========================================
69
  # 4. دالة جلب مثال عشوائي من بيانات الاختبار
70
- # ==========================================
71
  def random_example():
72
  idx = np.random.randint(0, len(test_images))
73
  img = test_images[idx].reshape(28, 28)
74
- # تحويل الصورة إلى 3 قنوات (RGB) لأن ImageEditor يتوقع ذلك
75
  img_rgb = np.stack([img] * 3, axis=2)
76
- # ImageEditor يحتاج إلى هذا الهيكل بالضبط
77
- image_dict = {"composite": img_rgb}
78
  info_text = f"🖼️ رقم العينة: {idx} | الرقم الحقيقي: {test_labels[idx]}"
79
- return image_dict, info_text
80
 
81
- # ==========================================
82
- # 5. بناء الواجهة المتكاملة (Blocks) - بدون theme
83
- # ==========================================
84
- with gr.Blocks(title="MNIST Recognizer") as demo:
85
  gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد")
86
- gr.Markdown("ارسم رقماً في المربع الأسود، أو ارفع صورة، أو جرب أحد الأمثلة العشوائية.")
87
 
88
  with gr.Row():
89
- # العمود الأيسر (المدخلات)
90
  with gr.Column(scale=1):
91
- # مكون الرسم والتحرير (الأفضل والأحدث)
92
- sketch = gr.ImageEditor(
93
- label="✏️ ارسم هنا",
94
- type="numpy",
95
- canvas_size=(280, 280),
96
- brush=gr.Brush(colors=["#FFFFFF"], default_color="#FFFFFF"),
97
- eraser=gr.Eraser(default_size=20)
98
- )
99
  with gr.Row():
100
  submit_btn = gr.Button("🔮 توقع", variant="primary")
101
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
102
- info = gr.Textbox(label="📌 معلومات", interactive=False, value="ارسم أو اختر مثالاً.")
103
 
104
- # العمود الأيمن (المخرجات)
105
  with gr.Column(scale=1):
106
  output = gr.Label(num_top_classes=3, label="📊 أعلى 3 احتمالات")
107
 
108
  # ربط الأزرار بالدوال
109
- submit_btn.click(fn=predict_image, inputs=sketch, outputs=output)
110
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
111
 
112
- # ==========================================
113
- # 6. 🔥 التشغيل لـ Hugging Face Spaces
114
- # ==========================================
115
- # لا تستخدم demo.launch() هنا! Spaces يدير التشغيل بنفسه.
116
- # فقط اجعل المتغير 'demo' هو الواجهة النهائية.
 
5
  from tensorflow.keras import datasets, layers, models
6
  import os
7
 
8
+ # ============================================================
9
+ # 1. تحميل أو بناء النموذج (حل احتياطي في حال عدم وجود الملف)
10
+ # ============================================================
11
  model_path = 'mnist_cnn_model.keras'
12
+
13
  if os.path.exists(model_path):
14
  model = tf.keras.models.load_model(model_path)
15
  print("✅ تم تحميل النموذج المحفوظ.")
16
  else:
17
+ print("⚠️ لم يتم العثور على النموذج، جارٍ البناء والتدريب...")
18
  model = models.Sequential([
19
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
20
  layers.MaxPooling2D((2, 2)),
 
27
  model.compile(optimizer='adam',
28
  loss='sparse_categorical_crossentropy',
29
  metrics=['accuracy'])
30
+
31
  (train_images, train_labels), _ = datasets.mnist.load_data()
32
  train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
33
  model.fit(train_images, train_labels, epochs=3, validation_split=0.1, verbose=1)
34
  model.save(model_path)
35
+ print("✅ تم بناء النموذج وتدريبه وحفظه.")
36
 
37
+ # ============================================================
38
+ # 2. تحميل بيانات MNIST للاستخدام في الأمثلة العشوائية
39
+ # ============================================================
40
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
41
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
42
 
43
+ # ============================================================
44
+ # 3. دالة التنبؤ بالصورة المرسومة
45
+ # ============================================================
46
+ def predict_sketch(image):
47
+ """
48
+ تستقبل الصورة من Sketchpad، تعالجها، وتعيد الاحتمالات لكل فئة.
49
+ """
50
  try:
51
+ # الصورة قادمة بصيغة (height, width, 3) من نوع numpy array
 
 
 
 
52
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
 
53
  resized = cv2.resize(gray, (28, 28))
54
+ # قلب الألوان لأن MNIST تدربت على خلفية سوداء وكتابة بيضاء
55
  inverted = 255 - resized
 
56
  normalized = inverted.astype('float32') / 255.0
 
57
  reshaped = normalized.reshape(1, 28, 28, 1)
58
 
 
59
  prediction = model.predict(reshaped, verbose=0)[0]
60
  # تحويل إلى قاموس لعرضه في Label
61
  return {str(i): float(prediction[i]) for i in range(10)}
62
  except Exception as e:
63
  return {"خطأ": str(e)}
64
 
65
+ # ============================================================
66
  # 4. دالة جلب مثال عشوائي من بيانات الاختبار
67
+ # ============================================================
68
  def random_example():
69
  idx = np.random.randint(0, len(test_images))
70
  img = test_images[idx].reshape(28, 28)
71
+ # تحويل الصورة إلى 3 قنوات (RGB) لأن Sketchpad يتوقع ذلك
72
  img_rgb = np.stack([img] * 3, axis=2)
 
 
73
  info_text = f"🖼️ رقم العينة: {idx} | الرقم الحقيقي: {test_labels[idx]}"
74
+ return img_rgb, info_text
75
 
76
+ # ============================================================
77
+ # 5. بناء واجهة Gradio باستخدام Blocks + Sketchpad
78
+ # ============================================================
79
+ with gr.Blocks(title="MNIST Digit Recognizer") as demo:
80
  gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد")
81
+ gr.Markdown("ارسم رقماً (0-9) في المربع، أو اضغط على زر **'مثال عشوائي'** لتجربة النموذج.")
82
 
83
  with gr.Row():
84
+ # العمود الأيسر: لوحة الرسم والأزرار
85
  with gr.Column(scale=1):
86
+ sketch = gr.Sketchpad(label="✏️ ارسم هنا")
 
 
 
 
 
 
 
87
  with gr.Row():
88
  submit_btn = gr.Button("🔮 توقع", variant="primary")
89
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
90
+ info = gr.Textbox(label="📌 معلومات", interactive=False, value="ارسم أو اختر مثالاً عشوائياً.")
91
 
92
+ # العمود الأيمن: عرض النتائج
93
  with gr.Column(scale=1):
94
  output = gr.Label(num_top_classes=3, label="📊 أعلى 3 احتمالات")
95
 
96
  # ربط الأزرار بالدوال
97
+ submit_btn.click(fn=predict_sketch, inputs=sketch, outputs=output)
98
  random_btn.click(fn=random_example, inputs=[], outputs=[sketch, info])
99
 
100
+ # ============================================================
101
+ # 6. 🔥 هذا هو المتغير الذي سيستخدمه Hugging Face Spaces
102
+ demo.launch()
103
+ # ============================================================