EngReem85 commited on
Commit
e3cbe08
·
verified ·
1 Parent(s): 569f15b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -24
app.py CHANGED
@@ -5,13 +5,15 @@ import cv2
5
  from tensorflow.keras import datasets, layers, models
6
  import os
7
 
8
- # 1. تحميل أو بناء النموذج
 
 
9
  model_path = 'mnist_cnn_model.keras'
10
  if os.path.exists(model_path):
11
  model = tf.keras.models.load_model(model_path)
12
  print("✅ تم تحميل النموذج المحفوظ.")
13
  else:
14
- print("⚠️ بناء النموذج وتدريبه...")
15
  model = models.Sequential([
16
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
17
  layers.MaxPooling2D((2, 2)),
@@ -28,36 +30,87 @@ else:
28
  train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
29
  model.fit(train_images, train_labels, epochs=3, validation_split=0.1, verbose=1)
30
  model.save(model_path)
31
- print("✅ تم حفظ النموذج.")
32
 
33
- # 2. دالة التنبؤ
 
 
 
 
 
 
 
 
34
  def predict_image(image):
35
  try:
36
- # إذا كانت الصورة قادمة من ImageEditor كـ dict
37
  if isinstance(image, dict):
38
  image = image['composite']
 
 
39
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
 
40
  resized = cv2.resize(gray, (28, 28))
 
41
  inverted = 255 - resized
 
42
  normalized = inverted.astype('float32') / 255.0
 
43
  reshaped = normalized.reshape(1, 28, 28, 1)
44
- pred = model.predict(reshaped, verbose=0)[0]
45
- return {str(i): float(pred[i]) for i in range(10)}
 
 
 
46
  except Exception as e:
47
- return {"error": str(e)}
48
-
49
- # 3. إنشاء الواجهة باستخدام gr.Interface (الأكثر استقراراً)
50
- demo = gr.Interface(
51
- fn=predict_image,
52
- inputs=gr.ImageEditor(
53
- label="ارسم أو ارفع صورة",
54
- type="numpy",
55
- canvas_size=(280, 280)
56
- ),
57
- outputs=gr.Label(num_top_classes=3, label="الاحتمالات"),
58
- title="🧠 التعرف على الأرقام المكتوبة بخط اليد",
59
- description="ارسم رقماً (0-9) في المربع، أو ارفع صورة، واضغط Submit."
60
- )
61
-
62
- # 4. التشغيل (بدون أي معاملات إضافية)
63
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)),
 
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)
83
+ # ==========================================
84
+ with gr.Blocks(title="MNIST Recognizer", theme=gr.themes.Soft()) 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' هو الواجهة النهائية.