EngReem85 commited on
Commit
546adda
·
verified ·
1 Parent(s): c8e0182

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -39
app.py CHANGED
@@ -1,47 +1,174 @@
 
1
  import gradio as gr
2
  import numpy as np
3
  import tensorflow as tf
4
- import cv2
5
- from tensorflow.keras import datasets, layers, models
6
 
7
- # تحميل النموذج (إذا لم تجده، ابنه)
8
  try:
9
- model = tf.keras.models.load_model('mnist_cnn_model.keras')
10
- print("✅ تم تحميل النموذج")
11
- except:
12
- print("⚠️ بناء نموذج جديد...")
13
- model = models.Sequential([
14
- layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
15
- layers.MaxPooling2D((2, 2)),
16
- layers.Conv2D(64, (3, 3), activation='relu'),
17
- layers.MaxPooling2D((2, 2)),
18
- layers.Flatten(),
19
- layers.Dense(64, activation='relu'),
20
- layers.Dense(10, activation='softmax')
21
- ])
22
- model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
23
- (x_train, y_train), _ = datasets.mnist.load_data()
24
- x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255
25
- model.fit(x_train, y_train, epochs=3, validation_split=0.1, verbose=1)
26
- model.save('mnist_cnn_model.keras')
27
-
28
- # دالة التنبؤ
29
- def predict(image):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  try:
 
 
 
 
 
 
 
31
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
32
- img = cv2.resize(gray, (28, 28))
33
- img = (255 - img).astype('float32') / 255.0
34
- img = img.reshape(1, 28, 28, 1)
35
- pred = model.predict(img, verbose=0)[0]
36
- return {str(i): float(pred[i]) for i in range(10)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  except Exception as e:
38
- return {"error": str(e)}
39
-
40
- # 🔥 تعريف demo (يجب أن يكون في المستوى العام)
41
- demo = gr.Interface(
42
- fn=predict,
43
- inputs=gr.Sketchpad(label="ارسم هنا"),
44
- outputs=gr.Label(num_top_classes=3),
45
- title="MNIST Recognizer",
46
- description="ارسم رقماً بالماوس"
47
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
  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__":
174
+ demo.launch()