ما هي الصورة فعلياً؟
الصورة ليست مجرد شكل جميل، بل هي مجموعة من البكسلات الصغيرة جدًا.
كل بكسل يمثل نقطة واحدة في الصورة، وله قيمة تُظهر شدة الضوء أو اللون في هذا الموضع.
إذا كانت الصورة سوداء وبيضاء، فكل بكسل غالباً يأخذ قيمة بين 0 و 255.
مثال مبسط لمصفوفة 3x3 من قيم البكسلات
ما هو RGB؟
Red
القناة الحمراء
Green
القناة الخضراء
Blue
القناة الزرقاء
لماذا نحتاج المعالجة الأولية للصور؟
تغيير الحجم
نضبط صورة لمقاييس ثابتة في الشبكات العصبية.
التحويل إلى grayscale
نقل الصورة إلى درجات الرمادي لتبسيط المعالجة.
إزالة الضوضاء
نقلل التشويش أو الضجيج الناتج عن التصوير.
التطبيع
نحوّل القيم إلى نطاق مناسب مثل 0 إلى 1.
خطوات شائعة في المعالجة الأولية
- • قراءة الصورة من الملف أو الكاميرا.
- • تحويل الصورة إلى RGB أو grayscale حسب الحاجة.
- • تغيير الحجم إلى أبعاد ثابتة مثل 224x224.
- • تطبيع القيم إلى النطاق [0, 1] أو [-1, 1].
- • تطبيق فلترة أو إزالة الضوضاء أو تحسين التباين.
- • تجهيز البيانات لكي تكون جاهزة للـ CNN أو النموذج.
كيف تبدو الصورة في Python؟
from PIL import Image
img = Image.open("cat.jpg").convert("RGB")
print(img.size)
print(img.getpixel((0, 0)))
gray = img.convert("L")
resized = img.resize((224, 224))
print(resized.size)
مثال عملي: استخراج قيمة بكسل
import numpy as np
from PIL import Image
img = Image.open("sample.png").convert("RGB")
arr = np.array(img)
print(arr.shape) # (height, width, 3)
print(arr[0, 0]) # [R, G, B]
print(arr[0, 0, 0]) # قيمة Red
عندما تكون الصورة في Python، فإنها غالباً تُخزن كـ array ثلاثي الأبعاد.
أبعاد المصفوفة تكون عادةً مثل: (الارتفاع, العرض, 3) عندما تكون الصورة RGB.
الرقم 3 يمثل القنوات: الأحمر، الأخضر، والأزرق.
أمثلة عملية على المعالجة الأولية
إعادة القياس
تغيير حجم الصورة إلى 128x128 أو 224x224 لتناسب النموذج.
إزالة الضوضاء
تخفيف التشويش للتحسين في التعرف أو التصنيف.
التطبيع
ضبط القيم لتصبح مناسبة للتدريب مثل تقسيمها على 255.
كود كامل: قراءة، تحويل، وتطبيع الصورة
import numpy as np
from PIL import Image
img = Image.open("example.jpg").convert("RGB")
img = img.resize((224, 224))
arr = np.array(img) / 255.0
print(arr.shape)
print(arr.min(), arr.max())
print(arr[0, 0])
كيف يعمل Convolution في الشبكات الالتفافية؟
ما معنى Feature Extraction؟
حافة
الكشف عن حدود الأشكال.
خطوط
اكتشاف الخطوط المستقيمة والمنحنية.
أنماط
ملاحظة التفاصيل المهمة داخل الصورة.
ما هو Downsampling أو Pooling؟
هل CNN تعمل كأنها عيون ذكية؟
تقرأ الصورة
تكتشف الحواف
تجميع الأنماط
تتخذ القرار
أين يتم تدريب CNN؟ على MNIST من Keras
مجموعة MNIST تحتوي على أرقام مكتوبة بخط اليد من 0 إلى 9، وكل صورة 28×28 بكسل.
توفر Keras مجموعة بيانات جاهزة باسم mnist.
أنت لا تحتاج إلى تنزيلها يدوياً، بل يمكن تحميلها مباشرة باستخدام TensorFlow/Keras.
كل صورة تُخزن على شكل مصفوفة 28×28، وكل مثال له تسمية رقمية من 0 إلى 9.
الكود: تدريب CNN على MNIST من Keras
import tensorflow as tf
from tensorflow.keras import layers, models
# تحميل بيانات MNIST من Keras
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# إعادة الشكل إلى (عدد الصور, 28, 28, 1)
x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0
# تحويل التصنيفات إلى one-hot
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)
# بناء نموذج CNN
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5, batch_size=64, validation_data=(x_test, y_test))
loss, acc = model.evaluate(x_test, y_test)
print('Test accuracy:', acc)
كيف يقرأ النموذج الرقم؟
يعرض الصورة الرقمية المرسومة بيد الإنسان.
يلاحظ الحواف والأنماط داخل الصورة.
يقلل الحجم ويحفظ أهم المعلومات.
يقرر: هذا الرقم هو 7 أو 3 أو 9.
ماذا يحدث داخل CNN بعد اكتشاف الحواف؟
تكتشف الحواف والخطوط الأولية.
تخفف الحجم وتبقي أهم التفاصيل فقط.
تقرر أخيراً ما هو الرقم أو الكائن.
ما هي Flatten و Dense؟
layers.Flatten()
layers.Dense(128, activation='relu')
layers.Dense(10, activation='softmax')
Flatten: يحول الصورة من شكل مصفوفة إلى صف واحد من الأرقام، لكي يمكنها الدخول إلى طبقة معيارية.
Dense: هي طبقات عصبية عادية تتعلم العلاقات بين الميزات لاكتشاف النتيجة النهائية.
لماذا نستخدم ReLU؟
ReLU يعني:
إذا كان الرقم سالبًا، يصبح 0.
إذا كان الرقم موجبًا، يبقى كما هو.
def relu(x):
if x < 0:
return 0
return x
print(relu(-3)) # 0
print(relu(5)) # 5
كيف يتم التدريب فعلياً؟
تبدأ الشبكة بتخمينات عشوائية.
تُقارن النتيجة مع الإجابة الصحيحة.
تُصحح الأوزان لتقليل الخطأ.
تكرر هذه العملية ملايين المرات.
لماذا CNN أفضل من الشبكات العادية على الصور؟
الشبكات العادية تتعامل مع كل بكسل بشكل منفصل، وتسهل عليها أن تنسى العلاقات بين البكسلات القريبة.
CNN تحافظ على المواقع النسبية للبكسلات، لذلك تعرف أن بعض الخطوط تتجمع لتكوّن زاوية، أو أن بعض الأجزاء تشكل رقمًا أو كائنًا.
ملخص صغير جدًا
• الصورة تتكون من بكسلات.
• CNN يمرر فلترًا صغيرًا فوق الصورة لاكتشاف الحواف والأنماط.
• Pooling يقلل الحجم ويبقي أهم المعلومات.
• Flatten يحول الصور إلى أرقام قابلة للفهم.
• Dense يقرر النتيجة النهائية.
• MNIST من Keras يعطي صور أرقام مكتوبة بخط اليد لتدريب النموذج.
Streamlit: ارفع صورة أو ارسم رقمًا ثم استخدم النموذج المصدّر
import streamlit as st
import numpy as np
from PIL import Image, ImageOps
import tensorflow as tf
st.title("MNIST Digit Predictor")
model = tf.keras.models.load_model("mnist_cnn_model.h5")
uploaded_file = st.file_uploader("Upload an image", type=["png", "jpg", "jpeg"])
if uploaded_file is not None:
image = Image.open(uploaded_file).convert("L")
image = ImageOps.invert(image)
image = image.resize((28, 28))
arr = np.array(image).astype("float32") / 255.0
arr = arr.reshape(1, 28, 28, 1)
pred = model.predict(arr)
digit = int(np.argmax(pred))
confidence = float(np.max(pred))
st.image(image, caption="Uploaded image", width=180)
st.success(f"Predicted digit: {digit} | Confidence: {confidence:.2%}")
هذا الكود يسمح للمستخدم برفع صورة رقم مكتوب بخط اليد، أو رسم رقم داخل تطبيق Streamlit، ثم استخدام النموذج المصدّر لمعرفة النتيجة.
تستخدم الصورة كصورة رمادية 28×28، ثم تُعاد تجهيزها حتى تكون مناسبة لإدخالها إلى الشبكة CNN.
نسخة Streamlit مع لوحة رسم
import streamlit as st
import numpy as np
from PIL import Image
import tensorflow as tf
from streamlit_drawable_canvas import st_canvas
st.title("Draw a Digit and Predict")
model = tf.keras.models.load_model("mnist_cnn_model.h5")
canvas_result = st_canvas(
fill_color="black",
stroke_width=12,
background_color="black",
width=280,
height=280,
drawing_mode="freedraw",
key="canvas",
)
if canvas_result.image_data is not None:
img = Image.fromarray(canvas_result.image_data.astype("uint8")).convert("L")
img = img.resize((28, 28))
arr = np.array(img).astype("float32") / 255.0
arr = arr.reshape(1, 28, 28, 1)
pred = model.predict(arr)
digit = int(np.argmax(pred))
prob = float(np.max(pred))
st.success(f"Predicted digit: {digit} | Probability: {prob:.2%}")