المحتويات
مقدمة عن الرؤية الحاسوبية ثلاثية الأبعاد
مع تطورات الواقع المعزّز والعالم الافتراضي AR / VR، وكذلك تطور السيارات ذاتية القيادة، أصبحت مشكلة الرؤية ثلاثية الأبعاد أكثر أهمية نظراً لما تقدمه من معلومات وفيرة أكثر من الرؤية ثنائية الأبعاد 2D. سنقدم في هذه المقالة نموذجين أساسيين للتعلم العميق من أجل تحليل مشهد ثلاثي الأبعاد، هما فوكسل (VoxNet) وبوينت نت (PointNet).
موجز عن بنية ثلاثي الأبعاد 3D
إن الصورة ثلاثية الأبعاد عبارة عن صورة ثنائية الأبعاد 2D (عرض x ارتفاع) يضاف إليها بُعدًا آخر هو العُمق. هناك نوعان من الأشكال ثلاثية الأبعاد الأكثر استخدامًا، point cloud السحابة النقطية و RGB-D السحابة ذات خصائص أحمر أخضر أزرق عمق.
السحابة ذات خصائص أحمر أخضر أزرق عمق RGB-D
في الصور العادية المبنيّة بمجموعة من البكسلات يمكننا تحديد موقع أي بكسل بواسطة إحداثيات (x, y) ثم يمكننا الحصول على ثلاث خصائص وهي (R,G,B) للّون على التوالي. بينما في الصور من نوع RGB-D، ستكون إحداثيات (x, y) مقابلة لأربع خصائص (R,G,B,Depth)، حيث أن depth هو العمق.
الاختلاف الوحيد بين السحابة النقطية والسحابة ذات خصائص أحمر أخضر أزرق عمق RGB-D, point cloud هو أنه باستخدام السحابة النقطية (point cloud)، تعكس إحداثيات (x, y) القيم الفعلية في العالم الحقيقي بدلاً من قيم الأعداد الصحيحة البسيطة.
السحابة النقطية point cloud
يمكن إنشاء السحابة النقطية من صور السحابة ذات خصائص أحمر أخضر أزرق عمق RGB-D. إذا كان لديك مسح ذات خصائص أحمر أخضر أزرق عمق RGB-D وتعرف أيضًا ببنية مسح الكاميرا، ستتمكن من إنشاء السحابة النقطية من صورة RGB-D، ببساطة عن طريق حساب إحداثيات (x, y) في العالم الحقيقي باستخدام بنية الكاميرا. يطلق عليه مصطلح معايرة الكاميرا. أما الآن فيجب علينا أن نعلم أن صورة ذات خصائص أحمر أخضر أزرق عمق RGB-D عبارة عن صور محاذية للشبكية بينما تكون السحابة النقطية في بنية متفرقة.
الرؤية ثلاثية الأبعاد 3D
كما هو الحال في الرؤية ثنائية البعد، يجب علينا اكتشاف جميع الكائنات الموجودة داخل المسح ثلاثي الأبعاد والتعرف عليها. على عكس الصور ثنائية البعد، السؤال هنا ما هو أفضل تنسيق لبيانات الدخل من أجل استخدام شبكات الطيّ العصبونية CNN.
شبكية فوكسل Voxel Grid
شبكية فوكسل هي الطريقة الأكثر بديهية التي تلائم الكائنات ثلاثية الأبعاد في نمط الخطوط، لجعلها تبدو مثل صورة البكسل، وهنا نسميها فوكسل بدلاً من بكسل. في هذه الحالة، يتم وصف الصور ثلاثية الأبعاد بواسطة إحداثيات (x, y, z)، وستبدو مثل أجزاء لعب الليغو Lego.
فوكسل-نت هي عبارة عن بنية قائمة على التعلم العميق لتصنيف السحابة النقطية باستخدام شبكية الإشغال (occupancy grid)، والتي تعمل جيدًا في مشاكل التصنيف.
على سبيل المثال، إذا قمنا ملاءمة السحابة النقطية الخاصة بنا مع شبكية فوكسل 32x32x32، فيمكننا بناء مصفوفة 32x32x32 مليئة بالأصفار. ثم نقوم بتوسيع نطاق السحابة النقطية لحساب عدد النقاط داخل كل فوكسل صغير.
بعد الحصول على شبكية فوكسل، سنقوم بإجراء عملية الطّي ثلاثية الأبعاد بعد ذلك، والتي تقوم بتحريك المكعب بشكل فعّال فوق صور فوكسل الأساسية.
نحن نوعاً ما نقوم بتحجيم عمليات المسح إلى نفس الأساس. يمكننا أن نتخيل أنه إذا كان لدينا عمليات مسح واسعة النطاق، فسيكون كل كائن مجرد فوكسل واحد ومن شأنه أن يؤدي إلى بعض المشاكل. أيضًا، ليس من السهل تحديد لون RGB لكل فوكسل بسبب عمليات تكبير الصورة upsampling هذه.
بالنسبة لمجموعة البيانات البسيطة (التي تحتوي على عدد مماثل من النقاط، ومقياس مسح مشابه) ، قد تكون شبكية فوكسل-نت طريقة بسيطة وجيدة، ولكن إذا تمت مصادفة مجموعة بيانات معقدة، فقد لا تكون اختيارًا جيدًا.
النقاط Points
يمكن للتوابع المعتمدة على الفوكسل أن تعمل بشكل جيد في مشاكل التصنيف، إلا أنها تضحي بالكثير من المعلومات عند عمليات تكبير الصورة upsampling لذلك، قد نرغب في تدريب شبكتنا لتعطي استجابة أفضل .
المشكلة الأولى هي ترتيب النقاط، نحن نعلم أن السحابة النقطية ثابتة (غير متغيرة) من حيث ترتيب النقاط.
هناك ثلاث استراتيجيات للتعامل مع البوينت نت:
1- رتب النقاط.
2- قم بالإدخال كسلسلة RNN (الشَّبَكَاتُ العُصبُونِيَّةُ الإرجاعِيَّةُ)، عن طريق زيادة التسلسل بجميع أنواع التباديل.
3- استخدم دالة متماثلة لتجميع المعلومات من كل نقطة. نعني بالدالة المتماثلة مثل + أو * وهي دالة ثنائية متماثلة.
في ورقة بوينت نت، يقولون أن الطريقة الأولى تحتوي على عمليات حسابية معقدة والطريقة الثانية ليست قوية بما يكفي. لذلك، يتم استخدام دالة متماثلة تجميع القيمة الكبرى (max pooling) وهي الحد الأقصى للتجميع.
تبدو البنية بأكملها كما هو موضح بالشكل أدناه،
بشكل عام يمكن اعتبار أن استخدام شبكات الطي أكثر مرونة حيث يعتمد على اتصال كامل وطبقات للحد الأقصى للتجميع، لتسهيل الموضوع لنبدأ بالشرح بشكل عملي أكثر عن طريق شيفرة برمجية.
أولاً، سأقدم مثالاً للسحابة النقطية تمثل (x, y, z, r, g, b) لكل صف. وكل صف يمثل نقطة هنا. لنفترض أنه لدينا n نقطة في هذا المثال.
…
-38. 17. 54. 149 148 147
-38. 89. 54. 152 153 152
-79. 99. 32. 151 151 148
…
ملاحظة: إن الدخل الحقيقي لشبكة البوينت نت يستخدم تقييس ألوان RGB وقيم النقاط الاساسية x,y التي تتم محاذاتها إلى وسط المساحة. لكننا لم نفعل ذلك هنا لعدم العبث بالأرقام العائمة (التي تحتوي على فاصلة).
التصنيف في بوينت نت
لعملية الأولى هي القيام بالطي ثنائي الأبعاد، بحجم النواة (1, 6) لتجميع المعلومات ذات الصلة (x, y, z, r, g, b; six in total) من نقطة واحدة. يجب أن يكون الخرج (n, 1, 64) هنا.
net = tf_util.conv2d(input_image, 64, [1,6], padding='VALID', stride=[1,1], scope='conv1')
net = tf_util.conv2d(net, 64, [1,1], padding='VALID', stride=[1,1], scope='conv2')net = tf_util.conv2d(net, 64, [1,1], padding='VALID', stride=[1,1], scope='conv3')net = tf_util.conv2d(net, 128, [1,1], padding='VALID', stride=[1,1], scope='conv4')points_feat1 = tf_util.conv2d(net, 1024, [1,1], padding='VALID', stride=[1,1], scope='conv5')
والآن الخطوات الأكثر أهمية، هي الحد الأقصى للتجميع لتحديد المميزة الأكثر استثنائية لجميع النقاط. هذا هو السبب في أن ترتيب النقاط يبقى ثابتاً. نظرًا لأنه لدينا 1024 مرشحًا في الطبقات السابقة، ستخرج هذه الطبقة 1024 مميزة.
pc_feat1 = tf_util.max_pool2d(points_feat1, [n,1], padding='VALID', scope='maxpool1')
ثم سيتم توصيل جميع المميزات بالكامل بواسطة الطبقات كاملة الاتصال.
pc_feat1 = tf.reshape(pc_feat1, [batch_size, -1])pc_feat1 = tf_util.fully_connected(pc_feat1, 256, bn=True, scope='fc1')pc_feat1 = tf_util.fully_connected(pc_feat1, 128, bn=True, scope='fc2')
ملاحظة: حجم الدُفعة في حالتنا هو 1. بينما يكون دخل شبكة بوينت نت عبارة عن مسح ضوئي للمشهد، والذي سيتم فصله إلى دفعات صغيرة (4096 نقطة في كل دفعة). ستقوم شبكة بوينت نت بالكشف عن المميزات
حتى الآن، يمكنك العودة إلى الرسم البياني أعلاه الشكل (5)، إذا قمت بإضافة طبقة أخرى متصلة بالكامل لإخراج عدد من الفئات labels، هذه هي الطريقة التي تقوم بها بوينت نت بالتصنيف على السحابة النقطية. موجز،
1- لتجميع معلومات كل نقطة.
2- للعثور على الميزة الأكثر استثنائية في كل نقطة.
3- ثم ربط التصنيف بالكامل.
التجزئة الدلالية في بوينت نت
إن جزء التجزئة هو نوع من التطوير المستمر لنموذج التصنيف. ما زلنا نريد أن تكون الشبكة قادرة على تجاهل ترتيب النقاط. لذلك، فإننا نجمع كل مميزات النقطة مع “المميزات العامة”، للسماح لكل نقطة بمعرفة السياق.
pc_feat1_reshape = tf.reshape(pc_feat1, [batch_size, 1, 1, -1])pc_feat1_expand = tf.tile(pc_feat1_reshape, [1, num_point, 1, 1])points_feat1_concat = tf.concat(axis=3, values=[points_feat1, pc_feat1_expand])
ثم سنستخدم مجموعة من جداءات الطي 1×1 لاستخراج المميزات الجديدة للضرب النقطي (point-wise).
net = tf_util.conv2d(points_feat1_concat, 512, [1,1], padding='VALID', stride=[1,1], scope='conv6')net = tf_util.conv2d(net, 256, [1,1], padding='VALID', stride=[1,1], scope='conv7')
ثم نكون قادرين على وضع نقاط تنبؤ. على سبيل المثال، 13 فئة لكل نقطة.
الخاتمة
نظراً لأهمية الرؤية ثلاثة الأبعاد في يومنا هذا، تعلمنا بشكل مختصر بعض الاشكال الأساسية والمهمة الأكثر استخداما وهي السحابة ذات خصائص أحمر أخضر أزرق عمق والسحابة النقطية، إضافة لبعض الخطوات لاستخراج شكل ثلاثي الابعاد باستخدام الشبكات ذات التعلم بعمق.