معاينة مختبر آمنة
Object Detection
هذي معاينة منقّحة للقراءة فقط؛ ما فيه أي شيء يشتغل داخل الصفحة.
قراءة فقط
معاينة الدفتر
Object Detection
> **ملاحظة بيئة التشغيل المدمجة:** هالمعاينة تستخدم عيّنة صغيرة وثابتة وآمنة من ناحية الحقوق عشان تكون النتايج قابلة للتكرار. النتايج بالحجم الكامل تحتاج مجموعة البيانات أو النموذج الموثّق بالدرس داخل بيئة خارجية معتمدة.
## اكتشاف الأجسام
هالدفتر جزء من منهج الذكاء الاصطناعي للمبتدئين.
> **وصف الشكل:** خوارزميات معالجة الصور
## طريقة أولية لاكتشاف الأجسام
* نقسّم الصورة إلى مربعات.
* نشغّل شبكة عصبية التفافية (Convolutional Neural Network, CNN) لتصنيف كل مربع.
* نختار المربعات اللي يتجاوز تنشيطها العتبة المحددة.
import cv2
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
import osخلونا نقرأ صورة تجريبية ونضيف حولها حشوًا يخلي أبعادها مربعة:
# Generated image fixture replaces the excluded third-party photograph.
yy, xx = np.mgrid[:512, :512]
img = np.stack((
(xx + 60) % 256,
(yy * 2 + 20) % 256,
((xx + yy) // 2 + 90) % 256,
), axis=-1).astype(np.uint8)
img[150:370, 180:340, :] = np.array([185, 120, 75], dtype=np.uint8)
plt.imshow(img)بنستخدم شبكة VGG-16 من نوع CNN ومدرّبة مسبقًا:
vgg = keras.applications.vgg16.VGG16(weights=None)خلونا نعرّف دالة تتنبأ باحتمال وجود قطوة في الصورة. تحتوي ImageNet على عدة فئات للقطط، وفهارسها من 281 إلى 294؛ لذلك بنجمع احتمالات هالفئات عشان نحصل على الاحتمال الإجمالي لفئة «قطوة»:
def predict(img):
im = cv2.resize(img,(224,224))
im = keras.applications.vgg16.preprocess_input(im)
pr = vgg.predict(np.expand_dims(im,axis=0))[0]
return np.sum(pr[281:294]) # we know that VGG classes for cats are from 281 to 294
predict(img)الدالة الجاية تبني خريطة حرارية للاحتمالات بعد ما تقسّم الصورة إلى مربعات $n\times n$:
def predict_map(img,n):
dx = img.shape[0] // n
res = np.zeros((n,n),dtype=np.float32)
for i in range(n):
for j in range(n):
im = img[dx*i:dx*(i+1),dx*j:dx*(j+1)]
r = predict(im)
res[i,j] = r
return res
fig,ax = plt.subplots(1,2,figsize=(15,5))
ax[1].imshow(img)
ax[0].imshow(predict_map(img,10))## اكتشاف أجسام بسيطة
إذا بغينا نحدد الصندوق المحيط بدقة أعلى، نحتاج **نموذج الانحدار (Regression Model)** يتنبأ بإحداثياته. بنبدأ بمثال بسيط: مستطيلات سوداء داخل صور بحجم 32x32، ونبي النموذج يكتشفها. الفكرة وبعض الشفرة مأخوذة من [هالتدوينة](https://towardsdatascience.com/object-detection-with-neural-networks-a4e2c46b4491).
الدالة الجاية تولّد لنا مجموعة صور تجريبية:
def generate_images(num_imgs, img_size=8, min_object_size = 1, max_object_size = 4):
bboxes = np.zeros((num_imgs, 4))
imgs = np.zeros((num_imgs, img_size, img_size)) # set background to 0
for i_img in range(num_imgs):
w, h = np.random.randint(min_object_size, max_object_size, size=2)
x = np.random.randint(0, img_size - w)
y = np.random.randint(0, img_size - h)
imgs[i_img, x:x+w, y:y+h] = 1. # set rectangle to 1
bboxes[i_img] = [x, y, w, h]
return imgs, bboxes
imgs, bboxes = generate_images(2_000)
print(f"Images shape = {imgs.shape}")
print(f"BBoxes shape = {bboxes.shape}")عشان نخلي مخرجات الشبكة ضمن النطاق [0;1]، بنقسم `bboxes` على حجم الصورة:
bb = bboxes/8.0
bb[0]في مثالنا البسيط بنستخدم شبكة عصبية كثيفة. أما بالتطبيقات الواقعية، فالأجسام تكون أعقد، وغالبًا تكون **الشبكات العصبية الالتفافية (CNNs)** أنسب لهالمهمة. بنستخدم محسّن الانحدار المتدرج العشوائي (Stochastic Gradient Descent) ومتوسط مربع الخطأ (Mean Squared Error, MSE) مقياسًا؛ لأن مهمتنا **انحدار**.
model = keras.Sequential([
keras.layers.Flatten(input_shape=(8,8)),
keras.layers.Dense(200, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(4)
])
model.compile('sgd','mse')
model.summary()الحين ندرّب الشبكة. وبنطبّع بيانات الإدخال بعد، بطرح المتوسط والقسمة على الانحراف المعياري، عشان نحصل على أداء أفضل شوي.
imgs_norm = (imgs-np.mean(imgs))/np.std(imgs)
model.fit(imgs_norm,bb,epochs=3)قيمة الخسارة تبدو زينة نسبيًا؛ خلونا نشوف وش تعني بمقياس أوضح مثل mAP. أول شيء، بنعرّف مقياس التقاطع على الاتحاد (Intersection over Union, IoU) بين صندوقين محيطين:
def IOU(bbox1, bbox2):
'''Calculate overlap between two bounding boxes [x, y, w, h] as the area of intersection over the area of unity'''
x1, y1, w1, h1 = bbox1[0], bbox1[1], bbox1[2], bbox1[3]
x2, y2, w2, h2 = bbox2[0], bbox2[1], bbox2[2], bbox2[3]
w_I = min(x1 + w1, x2 + w2) - max(x1, x2)
h_I = min(y1 + h1, y2 + h2) - max(y1, y2)
if w_I <= 0 or h_I <= 0: # no overlap
return 0.
I = w_I * h_I
U = w1 * h1 + w2 * h2 - I
return I / Uالحين بنولّد 500 صورة اختبار، ونعرض أول 5 صور عشان نشوف دقة النتائج بصريًا. وبنطبع قيمة IoU لكل صورة بعد.
import matplotlib
test_imgs, test_bboxes = generate_images(500)
bb_res = model.predict((test_imgs-np.mean(imgs))/np.std(imgs))*8
plt.figure(figsize=(15,5))
for i in range(5):
print(f"pred={bb_res[i]},act={test_bboxes[i]}, IOU={IOU(bb_res[i],test_bboxes[i])}")
plt.subplot(1,5,i+1)
plt.imshow(test_imgs[i])
plt.gca().add_patch(matplotlib.patches.Rectangle((bb_res[i,1],bb_res[i,0]),bb_res[i,3],bb_res[i,2],ec='r'))
#plt.annotate('IOU: {:.2f}'.format(IOU(bb_res[i],test_bboxes[i])),(bb_res[i,1],bb_res[i,0]+bb_res[i,3]),color='y')ولحساب متوسط IoU على كل الحالات، نمر على عينات الاختبار كلها، ونحسب IoU لكل عينة، ثم نأخذ المتوسط:
np.array([IOU(a,b) for a,b in zip(test_bboxes,bb_res)]).mean()## اكتشاف الأجسام في التطبيقات الواقعية
خوارزميات اكتشاف الأجسام الواقعية أعقد من مثالنا بكثير. إذا تبغون تدخلون بتفاصيل تطبيق RetinaNet، تابعوا [دليل Keras لاكتشاف الأجسام باستخدام RetinaNet](https://keras.io/examples/vision/retinanet/). وإذا كان هدفكم تدرّبون نموذج اكتشاف أجسام مباشرة، تقدرون تستخدمون [مكتبة Keras RetinaNet](https://github.com/fizyr/keras-retinanet).
حذفنا المخرجات وعدّادات التشغيل والودجات والمحتوى النشط وقت الاستيراد. شغّل الدفاتر بس في بيئة خارجية تثق فيها.
سجّل تطبيقك
التسجيل اختياري، يفيدك تتذكر وش طبّقت، ولا يمنع إكمال الدورة.