EngReem85 commited on
Commit
da1d009
·
verified ·
1 Parent(s): 59d6247

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -37
app.py CHANGED
@@ -1,20 +1,26 @@
1
  import os
 
 
 
 
 
2
  import cv2
3
  import numpy as np
4
  import tensorflow as tf
5
  import gradio as gr
 
6
  from tensorflow.keras import datasets, layers, models
7
 
8
  # ============================================
9
- # 1. تحميل أو بناء النموذج (على CPU)
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)),
@@ -31,28 +37,23 @@ else:
31
  metrics=['accuracy']
32
  )
33
 
34
- # تحميل بيانات التدريب
35
  (x_train, y_train), _ = datasets.mnist.load_data()
36
  x_train = x_train.reshape((60000, 28, 28, 1)).astype('float32') / 255.0
37
-
38
  model.fit(x_train, y_train, epochs=5, validation_split=0.1, verbose=1)
39
  model.save(model_path)
40
- print("✅ تم حفظ النموذج المكتمل.")
41
 
42
- # ============================================
43
- # 2. تحميل بيانات الاختبار للأمثلة العشوائية
44
- # ============================================
45
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
46
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255.0
47
 
48
  # ============================================
49
- # 3. دالة معالجة واستخراج الصورة
50
  # ============================================
51
  def process_image_for_mnist(image_input):
52
  if image_input is None:
53
  return None, None
54
 
55
- # التعامل مع مدخلات Sketchpad المتنوعة في Gradio
56
  if isinstance(image_input, dict):
57
  image = image_input.get('composite', None)
58
  if image is None:
@@ -65,23 +66,17 @@ def process_image_for_mnist(image_input):
65
  if image is None or not isinstance(image, np.ndarray):
66
  return None, None
67
 
68
- # تحويل RGBA إلى RGB
69
  if len(image.shape) == 3 and image.shape[-1] == 4:
70
  image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
71
 
72
- # تحويل إلى رمادي Gray
73
  if len(image.shape) == 3:
74
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
75
  else:
76
  gray = image.copy()
77
 
78
- # تغيير الحجم إلى 28x28
79
  resized = cv2.resize(gray, (28, 28), interpolation=cv2.INTER_AREA)
80
-
81
- # تطبيق العتبة الثنائية (Otsu Thresholding)
82
  _, binary = cv2.threshold(resized, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
83
 
84
- # عكس الألوان لتصبح الخلفية سوداء (0) والرسم أبيض (255) كبيئة MNIST
85
  if np.sum(binary == 255) > np.sum(binary == 0):
86
  binary = 255 - binary
87
 
@@ -91,8 +86,9 @@ def process_image_for_mnist(image_input):
91
  return normalized, reshaped
92
 
93
  # ============================================
94
- # 4. دالة التنبؤ المباشرة والآمنة
95
  # ============================================
 
96
  def predict_sketch(image):
97
  try:
98
  if image is None:
@@ -101,25 +97,22 @@ def predict_sketch(image):
101
  normalized, reshaped = process_image_for_mnist(image)
102
 
103
  if normalized is None:
104
- return {}, None, "⚠️ لم يتم التعرف على الصورة، يرجى إعادة الرسم."
105
 
106
- # الاستدعاء المباشر للموديل يمنع تعارض الخيوط (Threads) في TensorFlow
107
  preds = model(reshaped, training=False).numpy()[0]
108
  predicted_class = int(np.argmax(preds))
109
  confidence = float(np.max(preds))
110
 
111
- # قاموس الاحتمالات الموجه لـ Gradio Label
112
  probabilities = {str(i): float(preds[i]) for i in range(10)}
113
 
114
- # تحضير صورة العرض المصغرة
115
  display_img = (normalized * 255).astype(np.uint8)
116
  display_img = cv2.resize(display_img, (140, 140), interpolation=cv2.INTER_NEAREST)
117
 
118
- # نصوص معلومات التصحيح
119
  top3_idx = np.argsort(preds)[-3:][::-1]
120
  top3_str = "\n".join([f" {i+1}. الرقم {idx}: {preds[idx]:.2%}" for i, idx in enumerate(top3_idx)])
121
 
122
- debug_info = f"""📊 نتائج التحليل:
123
  - الرقم المتوقع: {predicted_class}
124
  - نسبة الثقة: {confidence:.2%}
125
 
@@ -129,24 +122,23 @@ def predict_sketch(image):
129
  return probabilities, display_img, debug_info
130
 
131
  except Exception as e:
132
- return {}, None, f"❌ حدث خطأ أثناء التوقّع: {str(e)}"
133
 
134
  # ============================================
135
- # 5. دالة اختياري: اختيار مثال عشوائي
136
  # ============================================
137
  def random_example():
138
  idx = np.random.randint(0, len(test_images))
139
  img = test_images[idx].reshape(28, 28)
140
  img_large = cv2.resize(img, (280, 280), interpolation=cv2.INTER_NEAREST)
141
  img_rgb = np.stack([img_large] * 3, axis=2)
142
- return img_rgb, f"🎲 تم جلب رقم عشوائي (الرقم الحقيقي: {test_labels[idx]})"
143
 
144
  # ============================================
145
- # 6. بناء واجهة Gradio
146
  # ============================================
147
- with gr.Blocks(title="MNIST Digit Recognizer") as demo:
148
- gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد (MNIST)")
149
- gr.Markdown("ارسم رقماً من **0 إلى 9** في المربع الأيسر ثم اضغط على زر **توقع**.")
150
 
151
  with gr.Row():
152
  with gr.Column(scale=1):
@@ -154,13 +146,12 @@ with gr.Blocks(title="MNIST Digit Recognizer") as demo:
154
  with gr.Row():
155
  submit_btn = gr.Button("🔮 توقع", variant="primary")
156
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
157
- info = gr.Textbox(label="📌 معلومات التصحيح (Debug Info)", interactive=False, lines=8)
158
 
159
  with gr.Column(scale=1):
160
  output = gr.Label(num_top_classes=3, label="📊 احتمالات التوقع")
161
- processed_img = gr.Image(label="🖼️ الصورة بعد المعالجة (ما يراه النموذج)", image_mode="L")
162
 
163
- # ربط الأحداث
164
  submit_btn.click(
165
  fn=predict_sketch,
166
  inputs=sketch,
@@ -173,7 +164,4 @@ with gr.Blocks(title="MNIST Digit Recognizer") as demo:
173
  outputs=[sketch, info]
174
  )
175
 
176
- # ============================================
177
- # 7. تشغيل التطبيق
178
- # ============================================
179
  demo.launch()
 
1
  import os
2
+
3
+ # ⚠️ إجبار TensorFlow على عدم حجز الـ GPU بالكامل أثناء الـ Startup لمنع تصادم ZeroGPU
4
+ os.environ["TF_FORCE_GPU_ALLOW_GROWTH"] = "true"
5
+ os.environ["CUDA_VISIBLE_DEVICES"] = "0"
6
+
7
  import cv2
8
  import numpy as np
9
  import tensorflow as tf
10
  import gradio as gr
11
+ import spaces # مكتبة ZeroGPU
12
  from tensorflow.keras import datasets, layers, models
13
 
14
  # ============================================
15
+ # 1. تحميل أو بناء النموذج
16
  # ============================================
17
  model_path = 'mnist_cnn_model.keras'
18
 
19
  if os.path.exists(model_path):
20
  model = tf.keras.models.load_model(model_path)
21
+ print("✅ تم تحميل النموذج المحفوظ.")
22
  else:
23
+ print("⚠️ بناء وتدريب النموذج...")
24
  model = models.Sequential([
25
  layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
26
  layers.MaxPooling2D((2, 2)),
 
37
  metrics=['accuracy']
38
  )
39
 
 
40
  (x_train, y_train), _ = datasets.mnist.load_data()
41
  x_train = x_train.reshape((60000, 28, 28, 1)).astype('float32') / 255.0
 
42
  model.fit(x_train, y_train, epochs=5, validation_split=0.1, verbose=1)
43
  model.save(model_path)
44
+ print("✅ تم حفظ النموذج.")
45
 
46
+ # تحميل بيانات الاختبار للأمثلة
 
 
47
  (_, _), (test_images, test_labels) = datasets.mnist.load_data()
48
  test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255.0
49
 
50
  # ============================================
51
+ # 2. دالة معالجة الصورة
52
  # ============================================
53
  def process_image_for_mnist(image_input):
54
  if image_input is None:
55
  return None, None
56
 
 
57
  if isinstance(image_input, dict):
58
  image = image_input.get('composite', None)
59
  if image is None:
 
66
  if image is None or not isinstance(image, np.ndarray):
67
  return None, None
68
 
 
69
  if len(image.shape) == 3 and image.shape[-1] == 4:
70
  image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
71
 
 
72
  if len(image.shape) == 3:
73
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
74
  else:
75
  gray = image.copy()
76
 
 
77
  resized = cv2.resize(gray, (28, 28), interpolation=cv2.INTER_AREA)
 
 
78
  _, binary = cv2.threshold(resized, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
79
 
 
80
  if np.sum(binary == 255) > np.sum(binary == 0):
81
  binary = 255 - binary
82
 
 
86
  return normalized, reshaped
87
 
88
  # ============================================
89
+ # 3. دالة التوقع المحمية بـ ZeroGPU
90
  # ============================================
91
+ @spaces.GPU
92
  def predict_sketch(image):
93
  try:
94
  if image is None:
 
97
  normalized, reshaped = process_image_for_mnist(image)
98
 
99
  if normalized is None:
100
+ return {}, None, "⚠️ تعذر معالجة الصورة المدخلة."
101
 
102
+ # إجراء التوقع باستخدام الـ GPU المخصص ديناميكياً
103
  preds = model(reshaped, training=False).numpy()[0]
104
  predicted_class = int(np.argmax(preds))
105
  confidence = float(np.max(preds))
106
 
 
107
  probabilities = {str(i): float(preds[i]) for i in range(10)}
108
 
 
109
  display_img = (normalized * 255).astype(np.uint8)
110
  display_img = cv2.resize(display_img, (140, 140), interpolation=cv2.INTER_NEAREST)
111
 
 
112
  top3_idx = np.argsort(preds)[-3:][::-1]
113
  top3_str = "\n".join([f" {i+1}. الرقم {idx}: {preds[idx]:.2%}" for i, idx in enumerate(top3_idx)])
114
 
115
+ debug_info = f"""📊 نتائج التوقع (ZeroGPU):
116
  - الرقم المتوقع: {predicted_class}
117
  - نسبة الثقة: {confidence:.2%}
118
 
 
122
  return probabilities, display_img, debug_info
123
 
124
  except Exception as e:
125
+ return {}, None, f"❌ خطأ أثناء التوقّع: {str(e)}"
126
 
127
  # ============================================
128
+ # 4. دالة اختيار مثال عشوائي
129
  # ============================================
130
  def random_example():
131
  idx = np.random.randint(0, len(test_images))
132
  img = test_images[idx].reshape(28, 28)
133
  img_large = cv2.resize(img, (280, 280), interpolation=cv2.INTER_NEAREST)
134
  img_rgb = np.stack([img_large] * 3, axis=2)
135
+ return img_rgb, f"🎲 تم اختيار رقم عشوائي (الرقم الحقيقي: {test_labels[idx]})"
136
 
137
  # ============================================
138
+ # 5. بناء واجهة Gradio
139
  # ============================================
140
+ with gr.Blocks(title="MNIST Recognizer on ZeroGPU") as demo:
141
+ gr.Markdown("# 🧠 التعرف على الأرقام المكتوبة بخط اليد (ZeroGPU)")
 
142
 
143
  with gr.Row():
144
  with gr.Column(scale=1):
 
146
  with gr.Row():
147
  submit_btn = gr.Button("🔮 توقع", variant="primary")
148
  random_btn = gr.Button("🎲 مثال عشوائي", variant="secondary")
149
+ info = gr.Textbox(label="📌 معلومات التصحيح", interactive=False, lines=8)
150
 
151
  with gr.Column(scale=1):
152
  output = gr.Label(num_top_classes=3, label="📊 احتمالات التوقع")
153
+ processed_img = gr.Image(label="🖼️ الصورة بعد المعالجة", image_mode="L")
154
 
 
155
  submit_btn.click(
156
  fn=predict_sketch,
157
  inputs=sketch,
 
164
  outputs=[sketch, info]
165
  )
166
 
 
 
 
167
  demo.launch()