
في هذا الدليل ، سوف تتعلم كيفية إضافة نماذج ثلاثية الأبعاد إلى العالم الحقيقي. تتيح لك مكتبة ARCore من Google إضافة نماذج ثلاثية الأبعاد كاملة لصورة ثنائية الأبعاد (صورة أو فيديو).
تحتاج إلى تزويد النظام بنوع من الصور المرجعية ، والتي سيبحث عنها ARCore في العالم الحقيقي من أجل إضافة نموذج ثلاثي الأبعاد للصورة على أساسه. يستخدم الواقع المعزز بالفعل على نطاق واسع ، على سبيل المثال ، في الكتب والصحف والمجلات ، إلخ.
قبل الغوص في هذا البرنامج التعليمي ، يجب أن تتعرف على المادتين السابقتين حول هذا الموضوع والتي ستقدم لك مصطلحات AR الأساسية:
ما هي صور الواقع المعزز؟
وفقًا للوثائق الخاصة بالمطورين ، تتيح لك صور الواقع المعزز في ARCore إنشاء تطبيقات الواقع المعزز التي يمكنها "تحريك" صور ثنائية الأبعاد ، مثل الملصقات أو عبوة المنتج.
يمكنك تحميل بعض الصور المرجعية إلى ARCore ، ثم يُعلمك باكتشافها أثناء جلسة AR ، على سبيل المثال ، عند تصوير مقطع فيديو. وتستخدم هذه المعلومات لوضع النموذج الثلاثي الأبعاد على صورة ثنائية الأبعاد.
قيود استخدام صور الواقع المعزز
فيما يلي بعض القيود التي قد تواجهها عند استخدام صور الواقع المعزز:
- لا يمكن لـ ARCore معالجة سوى 20 صورة مرجعية في وقت واحد.
- يجب أن تكون الطائرة المادية في العالم الحقيقي مسطحة ، ويجب أن تكون مساحتها أكبر من 15 سم × 15 سم.
- يتعذر على ARCore تتبع الصور والكائنات المتحركة.
اختيار الصورة المرجعية الصحيحة
فيما يلي بعض النصائح لاختيار صورة مرجعية جيدة لـ ARCore:
- تدعم صور الواقع المعزز تنسيقات PNG و JPEG و JPG.
- لا يهم ما إذا كانت الصورة ملونة أو سوداء وبيضاء ، الشيء الرئيسي هو أن تكون في تناقض عالٍ.
- يجب أن تكون دقة الصورة 300 × 300 بكسل على الأقل.
- استخدام صور عالية الدقة لا يعني تحسين الأداء.
- يجب تجنب الصور ذات الأنماط المتكررة (مثل الأنماط أو نقاط البولكا).
- استخدم أداة arcoreimg لتقييم مدى جودة صورتك. ينصح بتقييم 75 نقطة على الأقل.
كيفية استخدام أداة arcoreimg:
- قم بتنزيل ARCore SDK لنظام Android من هذا الرابط .
- بفك محتويات الملف إلى أي مكان.
- في المجلد المستخرج ، انتقل إلى أدوات> arcoreimg> windows (حتى إذا كان لديك Linux أو macOS).
- افتح موجه الأوامر في هذا الدليل.
- وأدخل هذا الأمر:
arcoreimg.exe eval-img --input_image_path=dog.png
استبدل dog.png بالمسار الكامل لصورتك .
الشروع في العمل مع تطبيق الواقع المعزز
الآن بعد أن تعرفت على ARCore واخترت صورة جيدة بمعدل 75+ ، فقد حان الوقت لبدء كتابة رمز التطبيق.
إنشاء جزء
سننشئ جزءًا ونضيفه إلى نشاطنا. إنشاء فئة تسمى CustomArFragment
من ArFragment
. هنا هو رمز CustomArFragment
:
package com.ayusch.augmentedimages; import android.util.Log; import com.google.ar.core.Config; import com.google.ar.core.Session; import com.google.ar.sceneform.ux.ArFragment; public class CustomArFragment extends ArFragment { @Override protected Config getSessionConfiguration(Session session) { getPlaneDiscoveryController().setInstructionView(null); Config config = new Config(session); config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE); session.configure(config); getArSceneView().setupSession(session); return config; } }
بادئ ذي بدء ، أطفأنا اكتشاف الطائرة. من خلال القيام بذلك ، نقوم بإزالة أيقونة اليد من الشاشة التي تظهر فور تهيئة الجزء وإخبار المستخدم بالحاجة إلى نقل هاتفه الذكي للعثور على الطائرة. لم نعد نحتاج إلى ذلك ، لأننا لم نعثر على طائرات عشوائية ، بل صورة ملموسة.
ثم حددنا وضع التحديث LATEST_CAMERA_IMAGE
. يضمن ذلك إعلامنا بتحديثات الصور عند تحديث إطار الكاميرا.
إعداد قاعدة بيانات الصور
أضف الصورة المرجعية المحددة (التي تريد البحث عنها في العالم المادي) إلى مجلد الأصول (قم بإنشائها إذا لم تكن موجودة بالفعل). الآن يمكننا إضافة الصور إلى قاعدة البيانات الخاصة بنا.
سنقوم بإنشاء قاعدة البيانات هذه بمجرد إنشاء الجزء. في سجلات نعرض نتيجة هذه العملية:
if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) { Log.d("SetupAugImgDb", "Success"); } else { Log.e("SetupAugImgDb","Faliure setting up db"); }
إليك ما CustomArFragment
عليه CustomArFragment
:
package com.ayusch.augmentedimages; import android.util.Log; import com.google.ar.core.Config; import com.google.ar.core.Session; import com.google.ar.sceneform.ux.ArFragment; public class CustomArFragment extends ArFragment { @Override protected Config getSessionConfiguration(Session session) { getPlaneDiscoveryController().setInstructionView(null); Config config = new Config(session); config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE); session.configure(config); getArSceneView().setupSession(session); if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) { Log.d("SetupAugImgDb", "Success"); } else { Log.e("SetupAugImgDb","Faliure setting up db"); } return config; } }
قريبا سوف نضيف طريقة MainActivity
إلى MainActivity
. الآن ، دعونا نضيف CustomArFragment
إلى CustomArFragment
:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <fragment android:id="@+id/sceneform_fragment" android:name="com.ayusch.augmentedimages.CustomArFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.constraint.ConstraintLayout>
إضافة صورة إلى قاعدة البيانات
سنقوم الآن بإعداد قاعدة بيانات الصور الخاصة بنا ، والعثور على الصورة المرجعية في العالم الحقيقي وإضافة نموذج ثلاثي الأبعاد إلى الصورة.
لنبدأ بإنشاء قاعدة البيانات الخاصة بنا. إنشاء أسلوب setupAugmentedImagesDb
عام في فئة MainActivity
:
public boolean setupAugmentedImagesDb(Config config, Session session) { AugmentedImageDatabase augmentedImageDatabase; Bitmap bitmap = loadAugmentedImage(); if (bitmap == null) { return false; } augmentedImageDatabase = new AugmentedImageDatabase(session); augmentedImageDatabase.addImage("tiger", bitmap); config.setAugmentedImageDatabase(augmentedImageDatabase); return true; } private Bitmap loadAugmentedImage() { try (InputStream is = getAssets().open("blanket.jpeg")) { return BitmapFactory.decodeStream(is); } catch (IOException e) { Log.e("ImageLoad", "IO Exception", e); } return null; }
لقد أنشأنا أيضًا طريقة loadAugmentedImage
صورة من مجلد مورد وإرجاع صورة نقطية.
في setupAugmentedImagesDb
نقوم أولاً بتهيئة قاعدة البيانات الخاصة بنا للجلسة الحالية ، ثم نضيف الصورة إلى قاعدة البيانات هذه. نحن اسمه لدينا صورة النمر . ثم نقوم بتثبيت قاعدة البيانات هذه في التهيئة ونعود صوابًا ، مشيرًا إلى أنه تمت إضافة الصورة بنجاح.
في العالم الحقيقي الكشف عن صورة مرجعية
الآن سنبدأ في اكتشاف صورنا المرجعية في العالم الحقيقي. للقيام بذلك ، سننشئ مستمعًا سيتم استدعاؤه في كل مرة يتم فيها تحديث إطار الفيديو ، وسيتم تحليل هذا الإطار لوجود صورة مرجعية هناك.
أضف هذا السطر إلى طريقة onCreate()
في MainActivity
:
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
الآن قم بإضافة طريقة MainActivity
إلى MainActivity
:
@RequiresApi(api = Build.VERSION_CODES.N) private void onUpdateFrame(FrameTime frameTime) { Frame frame = arFragment.getArSceneView().getArFrame(); Collection<AugmentedImage> augmentedImages = frame.getUpdatedTrackables(AugmentedImage.class); for (AugmentedImage augmentedImage : augmentedImages) { if (augmentedImage.getTrackingState() == TrackingState.TRACKING) { if (augmentedImage.getName().equals("tiger") && shouldAddModel) { placeObject(arFragment, augmentedImage.createAnchor(augmentedImage.getCenterPose()), Uri.parse("Mesh_BengalTiger.sfb")); shouldAddModel = false; } } } }
في السطر الأول نحصل على الإطار نفسه. يمكن تخيل الإطار كقطة شاشة عادية من مقطع فيديو. إذا كنت على دراية بكيفية عمل الفيديو ، فأنت تعلم أنه مجرد مجموعة من الصور تتغير بعضها البعض بسرعة كبيرة ، مما يعطي انطباعًا بوجود شيء ما يتحرك. نحن فقط نأخذ واحدة من هذه الصور.
بعد تلقينا الإطار ، نقوم بتحليله لوجود صورتنا المرجعية عليه. نحن نأخذ قائمة بجميع العناصر التي تتبعها ARCore باستخدام frame.getUpdatedTrackables
. ثم نكررها ونفحص ما إذا كانت صورة النمر موجودة في الإطار.
إذا تم العثور على تطابق ، فنحن ببساطة نأخذ ونضع النموذج ثلاثي الأبعاد أعلى الصورة المكتشفة.
ملاحظة shouldAddModel
استخدام علامة shouldAddModel
بحيث نضيف النموذج الثلاثي الأبعاد مرة واحدة فقط.
وضع نموذج ثلاثي الأبعاد على صورة مرجعية
الآن وقد وجدنا صورتنا المرجعية في العالم الحقيقي ، يمكننا إضافة نموذج ثلاثي الأبعاد فوقه. أضف addNodeToScene
و addNodeToScene
:
placeObject
: يتم استخدام هذه الطريقة لإنشاء كائن تم تقديمه باستخدام Uri
. بمجرد اكتمال التقديم ، يتم تمرير الكائن إلى أسلوب addNodeToScene
، حيث يتم إرفاق الكائن بالعقدة ، ويتم وضع هذه العقدة في المشهد.addNodeToScene
: addNodeToScene
هذه الطريقة عقدة من المرساة الناتجة ، تنشئ عقدة أخرى ينضم إليها الكائن المرئي ، ثم تضيف هذه العقدة إلى عقدة المرساة وتضعها على المسرح.
هذا ما يبدو عليه MainActivity
:
package com.ayusch.augmentedimages; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.support.annotation.RequiresApi; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.google.ar.core.Anchor; import com.google.ar.core.AugmentedImage; import com.google.ar.core.AugmentedImageDatabase; import com.google.ar.core.Config; import com.google.ar.core.Frame; import com.google.ar.core.Session; import com.google.ar.core.TrackingState; import com.google.ar.sceneform.AnchorNode; import com.google.ar.sceneform.FrameTime; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.rendering.Renderable; import com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode; import java.io.IOException; import java.io.InputStream; import java.util.Collection; public class MainActivity extends AppCompatActivity { ArFragment arFragment; boolean shouldAddModel = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.sceneform_fragment); arFragment.getPlaneDiscoveryController().hide(); arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame); } @RequiresApi(api = Build.VERSION_CODES.N) private void placeObject(ArFragment arFragment, Anchor anchor, Uri uri) { ModelRenderable.builder() .setSource(arFragment.getContext(), uri) .build() .thenAccept(modelRenderable -> addNodeToScene(arFragment, anchor, modelRenderable)) .exceptionally(throwable -> { Toast.makeText(arFragment.getContext(), "Error:" + throwable.getMessage(), Toast.LENGTH_LONG).show(); return null; } ); } @RequiresApi(api = Build.VERSION_CODES.N) private void onUpdateFrame(FrameTime frameTime) { Frame frame = arFragment.getArSceneView().getArFrame(); Collection<AugmentedImage> augmentedImages = frame.getUpdatedTrackables(AugmentedImage.class); for (AugmentedImage augmentedImage : augmentedImages) { if (augmentedImage.getTrackingState() == TrackingState.TRACKING) { if (augmentedImage.getName().equals("tiger") && shouldAddModel) { placeObject(arFragment, augmentedImage.createAnchor(augmentedImage.getCenterPose()), Uri.parse("Mesh_BengalTiger.sfb")); shouldAddModel = false; } } } } public boolean setupAugmentedImagesDb(Config config, Session session) { AugmentedImageDatabase augmentedImageDatabase; Bitmap bitmap = loadAugmentedImage(); if (bitmap == null) { return false; } augmentedImageDatabase = new AugmentedImageDatabase(session); augmentedImageDatabase.addImage("tiger", bitmap); config.setAugmentedImageDatabase(augmentedImageDatabase); return true; } private Bitmap loadAugmentedImage() { try (InputStream is = getAssets().open("blanket.jpeg")) { return BitmapFactory.decodeStream(is); } catch (IOException e) { Log.e("ImageLoad", "IO Exception", e); } return null; } private void addNodeToScene(ArFragment arFragment, Anchor anchor, Renderable renderable) { AnchorNode anchorNode = new AnchorNode(anchor); TransformableNode node = new TransformableNode(arFragment.getTransformationSystem()); node.setRenderable(renderable); node.setParent(anchorNode); arFragment.getArSceneView().getScene().addChild(anchorNode); node.select(); } }
الآن قم بتشغيل التطبيق الخاص بك. يجب أن تشاهد الشاشة كما هو موضح أدناه. حرك الهاتف أعلى قليلاً من الكائن المرجعي. وبمجرد اكتشاف ARCore للصورة المرجعية في العالم الحقيقي ، فإنه يضيف نموذج 3D الخاص بك إليها.

اقرأ أيضًا: إنشاء تطبيق ARCore الأول