EngReem85 commited on
Commit
c00508c
·
verified ·
1 Parent(s): c4cda42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -142
app.py CHANGED
@@ -3,171 +3,92 @@ import gradio as gr
3
  import numpy as np
4
  import tensorflow as tf
5
  from scipy import ndimage
6
- from tensorflow.keras import layers, models
7
 
8
- # 1. بناء نموذج CNN أكثر متانة وقوة
9
- try:
10
- model = tf.keras.models.load_model("mnist_advanced_model.keras")
11
- print("✅ تم تحميل النموذج المتقدم")
12
- except Exception:
13
- print("⚠️ بناء وتدريب نموذج متقدم جديد...")
14
- model = models.Sequential(
15
- [
16
- layers.Conv2D(
17
- 32, (3, 3), activation="relu", input_shape=(28, 28, 1)
18
- ),
19
- layers.BatchNormalization(),
20
- layers.Conv2D(32, (3, 3), activation="relu"),
21
- layers.MaxPooling2D((2, 2)),
22
- layers.Dropout(0.25),
23
- layers.Conv2D(64, (3, 3), activation="relu"),
24
- layers.BatchNormalization(),
25
- layers.MaxPooling2D((2, 2)),
26
- layers.Dropout(0.25),
27
- layers.Flatten(),
28
- layers.Dense(128, activation="relu"),
29
- layers.Dropout(0.5),
30
- layers.Dense(10, activation="softmax"),
31
- ]
32
- )
33
-
34
- model.compile(
35
- optimizer="adam",
36
- loss="sparse_categorical_crossentropy",
37
- metrics=["accuracy"],
38
- )
39
-
40
- (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
41
- x_train = x_train.reshape(-1, 28, 28, 1).astype("float32") / 255.0
42
 
43
- # Data Augmentation لزيادة مرونة النموذج
44
- datagen = tf.keras.preprocessing.image.ImageDataGenerator(
45
- rotation_range=10, zoom_range=0.1, width_shift_range=0.1, height_shift_range=0.1
46
- )
47
-
48
- model.fit(
49
- datagen.flow(x_train, y_train, batch_size=64),
50
- epochs=5,
51
- validation_split=0.1,
52
- )
53
- model.save("mnist_advanced_model.keras")
54
 
55
 
56
- # 2. دالة تمركز الصورة بناءً على مركز الكتلة (طريقة MNIST الأصلية)
57
  def center_image(img):
58
  cy, cx = ndimage.center_of_mass(img)
59
  rows, cols = img.shape
60
  shiftx = np.round(cols / 2.0 - cx)
61
  shifty = np.round(rows / 2.0 - cy)
62
  M = np.float32([[1, 0, shiftx], [0, 1, shifty]])
63
- centered = cv2.warpAffine(img, M, (cols, rows))
64
- return centered
65
-
66
-
67
- # 3. دالة المعالجة والتنبؤ مع دعم خيارات Gradio
68
- def predict(image, apply_centering, thickness_level):
69
- try:
70
- if isinstance(image, dict):
71
- image = image.get("composite", image.get("background"))
72
-
73
- if image is None:
74
- return None, {"error": "لم يتم الرسم"}
75
-
76
- # تحويل إلى خريطة رمادية
77
- gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
78
-
79
- # عكس الألوان (بحيث يكون الرقم أبيض والخلفية سوداء)
80
- _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
81
-
82
- # تطبيق سمك الخط إذا طُلِب
83
- if thickness_level > 0:
84
- kernel = np.ones(
85
- (thickness_level, thickness_level), np.uint8
86
- )
87
- thresh = cv2.dilate(thresh, kernel, iterations=1)
88
-
89
- # قص المنطقة النشطة (Bounding Box) وتكبيرها
90
- coords = cv2.findNonZero(thresh)
91
- if coords is not None:
92
- x, y, w, h = cv2.boundingRect(coords)
93
- cropped = thresh[y : y + h, x : x + w]
94
-
95
- # المحافظة على نسبة العرض إلى الارتفاع عند التحجيم
96
- if w > h:
97
- new_w = 20
98
- new_h = int(h * (20 / w))
99
- else:
100
- new_h = 20
101
- new_w = int(w * (20 / h))
102
-
103
- resized = cv2.resize(
104
- cropped, (new_w, new_h), interpolation=cv2.INTER_AREA
105
- )
106
- padded = np.pad(
107
- resized,
108
- (
109
- ((28 - new_h) // 2, 28 - (new_h + (28 - new_h) // 2)),
110
- ((28 - new_w) // 2, 28 - (new_w + (28 - new_w) // 2)),
111
- ),
112
- "constant",
113
- )
114
- else:
115
- padded = cv2.resize(thresh, (28, 28))
116
 
117
- # تطبيق تمركز الكتلة
118
- if apply_centering:
119
- final_img = center_image(padded)
120
- else:
121
- final_img = padded
122
 
123
- # المعايرة للتغذية في النموذج
124
- input_data = (final_img.astype("float32") / 255.0).reshape(
125
- 1, 28, 28, 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  )
127
- pred = model.predict(input_data, verbose=0)[0]
 
128
 
129
- # إعادة الصورة المعالجة ليعاينها المستخدم، بالإضافة للنتائج
130
- results = {str(i): float(pred[i]) for i in range(10)}
131
- return final_img, results
132
 
133
- except Exception as e:
134
- return None, {"error": str(e)}
 
135
 
 
136
 
137
- # 4. بناء واجهة Gradio باستخدام Blocks للتخصيص الكامل
138
- with gr.Blocks(title="MNIST Advanced Recognizer") as demo:
139
- gr.Markdown("# 🧠 التعرف الذكي على الأرقام (MNIST)")
140
- gr.Markdown(
141
- "ارسم رقماً وقم بتعديل خيارات المعالجة لمعاينة كيف يرى النموذج الصورة."
142
- )
143
 
 
 
 
 
144
  with gr.Row():
145
- with gr.Column(scale=1):
146
- input_pad = gr.Sketchpad(label="لوحة الرسم")
147
- with gr.Accordion("خيارات معالجة الصورة", open=True):
148
- chk_center = gr.Checkbox(
149
- value=True, label="تمركز الصورة (Center of Mass)"
150
- )
151
- sld_thickness = gr.Slider(
152
- minimum=0,
153
- maximum=3,
154
- step=1,
155
- value=1,
156
- label="زيادة سمك الخط (Dilation)",
157
- )
158
-
159
  btn_predict = gr.Button("تنبؤ", variant="primary")
160
-
161
- with gr.Column(scale=1):
162
- out_label = gr.Label(num_top_classes=3, label="أعلى التوقعات")
163
- out_processed_img = gr.Image(
164
- label="الصورة بعد المعالجة (28x28)", image_mode="L"
165
- )
166
 
167
  btn_predict.click(
168
  fn=predict,
169
- inputs=[input_pad, chk_center, sld_thickness],
170
- outputs=[out_processed_img, out_label],
171
  )
172
 
173
  if __name__ == "__main__":
 
3
  import numpy as np
4
  import tensorflow as tf
5
  from scipy import ndimage
 
6
 
7
+ # 1. تحميل النموذج المحفوظ مباشرة
8
+ MODEL_PATH = "mnist_advanced_model.keras"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ try:
11
+ model = tf.keras.models.load_model(MODEL_PATH)
12
+ print("✅ تم تحميل النموذج بنجاح")
13
+ except Exception as e:
14
+ print(f"❌ خطأ: لم يتم العثور على ملف النموذج '{MODEL_PATH}'. التأكد من وجود الملف بجانب app.py")
 
 
 
 
 
 
15
 
16
 
17
+ # 2. دالة تمركز الصورة
18
  def center_image(img):
19
  cy, cx = ndimage.center_of_mass(img)
20
  rows, cols = img.shape
21
  shiftx = np.round(cols / 2.0 - cx)
22
  shifty = np.round(rows / 2.0 - cy)
23
  M = np.float32([[1, 0, shiftx], [0, 1, shifty]])
24
+ return cv2.warpAffine(img, M, (cols, rows))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
 
 
 
 
 
26
 
27
+ # 3. دالة التنبؤ
28
+ def predict(image):
29
+ if image is None:
30
+ return None, {"error": "لم يت�� الرسم"}
31
+
32
+ # استخراج الصورة إذا كانت الواجهة تُرجع قاموساً (Gradio 4+)
33
+ if isinstance(image, dict):
34
+ image = image.get("composite", image.get("background"))
35
+
36
+ # تحويل الصورة إلى رمادي وعكس الألوان (أبيض على أسود)
37
+ gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
38
+ _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
39
+
40
+ # اقتصاص الجزء المرسوم وتغيير حجمه
41
+ coords = cv2.findNonZero(thresh)
42
+ if coords is not None:
43
+ x, y, w, h = cv2.boundingRect(coords)
44
+ cropped = thresh[y : y + h, x : x + w]
45
+
46
+ # الحفاظ على أبعاد الرسمة عند التحجيم لـ 20x20
47
+ if w > h:
48
+ new_w, new_h = 20, int(h * (20 / w))
49
+ else:
50
+ new_h, new_w = 20, int(w * (20 / h))
51
+
52
+ resized = cv2.resize(cropped, (new_w, new_h), interpolation=cv2.INTER_AREA)
53
+
54
+ # إضافة إطار (Padding) لتصبح الصورة 28x28
55
+ pad_vert = (28 - new_h) // 2
56
+ pad_horiz = (28 - new_w) // 2
57
+ padded = np.pad(
58
+ resized,
59
+ ((pad_vert, 28 - new_h - pad_vert), (pad_horiz, 28 - new_w - pad_horiz)),
60
+ "constant",
61
  )
62
+ else:
63
+ padded = cv2.resize(thresh, (28, 28))
64
 
65
+ # تمركز كتلة الرسمة
66
+ final_img = center_image(padded)
 
67
 
68
+ # تجهيز الصورة والتنبؤ
69
+ input_data = (final_img.astype("float32") / 255.0).reshape(1, 28, 28, 1)
70
+ pred = model.predict(input_data, verbose=0)[0]
71
 
72
+ return final_img, {str(i): float(pred[i]) for i in range(10)}
73
 
 
 
 
 
 
 
74
 
75
+ # 4. واجهة Gradio
76
+ with gr.Blocks(title="MNIST Predictor") as demo:
77
+ gr.Markdown("# 🧠 التنبؤ بالأرقام المرسومة")
78
+
79
  with gr.Row():
80
+ with gr.Column():
81
+ input_pad = gr.Sketchpad(label="ارسم رقماً هنا")
 
 
 
 
 
 
 
 
 
 
 
 
82
  btn_predict = gr.Button("تنبؤ", variant="primary")
83
+
84
+ with gr.Column():
85
+ out_label = gr.Label(num_top_classes=3, label="النتيجة")
86
+ out_img = gr.Image(label="الصورة المعالجة (28x28)", image_mode="L")
 
 
87
 
88
  btn_predict.click(
89
  fn=predict,
90
+ inputs=[input_pad],
91
+ outputs=[out_img, out_label],
92
  )
93
 
94
  if __name__ == "__main__":