1. نظرة عامة
ARCore هي منصة لإنشاء تطبيقات الواقع المعزّز على Android. تتيح لك ميزة الصور المعزّزة إنشاء تطبيقات واقع معزّز يمكنها التعرّف على الصور الثنائية الأبعاد المسجّلة مسبقًا في العالم الحقيقي وتثبيت المحتوى الافتراضي فوقها.
يرشدك هذا الدرس التطبيقي حول الترميز إلى كيفية تعديل نموذج تطبيق حالي من ARCore لدمج "الصور المحسّنة" المتحركة أو المثبّتة في مكانها.
ما ستنشئه
في هذا الدرس التطبيقي حول الترميز، ستعتمد على نموذج تطبيق ARCore حالي. وبحلول نهاية الدرس، سيتمكّن تطبيقك من تنفيذ ما يلي:
- رصد صورة مستهدَفة وإرفاق متاهة افتراضية بالصورة
- تتبُّع الهدف المتحرّك طالما أنّه يظهر في مجال رؤية الكاميرا

هل هذه هي المرة الأولى التي تصنع فيها تطبيق ARCore؟
هل تخطّط لكتابة رمز نموذجي في هذا الدرس العملي أو تريد فقط قراءة هذه الصفحات؟
أهداف الدورة التعليمية
- كيفية استخدام "الصور المعزّزة" في ARCore بلغة Java
- كيفية قياس قدرة الصورة على التعرّف عليها من خلال ARCore
- كيفية إرفاق محتوى افتراضي بصورة وتتبُّع حركتها
المتطلبات الأساسية
ستحتاج إلى أجهزة وبرامج معيّنة لإكمال هذا الدرس التطبيقي حول الترميز.
متطلبات الأجهزة
- جهاز متوافق مع ARCore متصل بجهاز التطوير عبر كابل USB
متطلبات البرامج
- حزمة ARCore APK 1.9.0 أو إصدار أحدث يتم عادةً تثبيت حزمة APK هذه تلقائيًا على الجهاز من خلال متجر Play.
- جهاز تطوير مزوّد بـ استوديو Android (الإصدار 3.1 أو إصدار أحدث)
- الوصول إلى الإنترنت، لأنّك ستحتاج إلى تنزيل المكتبات أثناء التطوير
بعد أن أصبحت كلّ المعلومات جاهزة، لنبدأ.
2. إعداد بيئة التطوير
تنزيل حزمة تطوير البرامج (SDK)
سنبدأ بتنزيل أحدث إصدار من حزمة تطوير البرامج (SDK) لنظام التشغيل Android في ARCore من GitHub. فكّ ضغط الملف في الموقع الجغرافي المفضّل. في هذا الدرس العملي، يكون إصدار حزمة تطوير البرامج (SDK) الأقدم هو 1.18.1. سيُشار إلى المجلد باسم arcore-android-sdk-x.xx.x، وستكون القيمة الدقيقة هي إصدار حزمة تطوير البرامج (SDK) التي تستخدمها.
شغِّل "استوديو Android" وانقر على فتح مشروع حالي في "استوديو Android".

انتقِل إلى هذا المجلد الذي تم فك ضغطه:
arcore-android-sdk-x.xx.x/samples/augmented_image_java
انقر على فتح.
انتظِر إلى أن ينتهي "استوديو Android" من مزامنة المشروع. إذا لم يكن "استوديو Android" يتضمّن المكوّنات المطلوبة، قد يتعذّر تشغيله وتظهر الرسالة Install missing platform and sync project. اتّبِع التعليمات لحلّ المشكلة.
تشغيل نموذج التطبيق
بعد أن أصبح لديك مشروع تطبيق ARCore يعمل، لنختبره.
اربط جهاز ARCore بجهاز التطوير، واستخدِم القائمة تشغيل > تشغيل "التطبيق" لتشغيل إصدار تصحيح الأخطاء على الجهاز. في مربّع الحوار الذي يطلب منك اختيار الجهاز الذي تريد التشغيل منه، اختَر الجهاز المتصل وانقر على حسنًا.


يستخدم نموذج المشروع هذا targetSdkVersion 28. إذا ظهر لك خطأ في الإصدار، مثل Failed to find Build Tools revision 28.0.3، اتّبِع التعليمات الموضّحة في "استوديو Android" لتنزيل إصدار "أدوات إنشاء Android" المطلوب وتثبيته.
إذا سارت الأمور على ما يرام، سيتم تشغيل نموذج التطبيق على الجهاز وسيطلب منك الإذن بالسماح لميزة "الصورة المعزّزة" بالتقاط الصور والفيديوهات. انقر على السماح لمنح الإذن.
الاختبار باستخدام صورة نموذجية
بعد الانتهاء من إعداد بيئة التطوير، يمكنك اختبار التطبيق من خلال تزويده بصورة للنظر إليها.
في "استوديو Android"، انتقِل في نافذة المشروع إلى التطبيق > مواد العرض، ثم انقر مرّتين على الملف default.jpg لفتحه.

وجِّه كاميرا جهازك نحو صورة الكرة الأرضية على الشاشة، واتّبِع التعليمات لمطابقة الصورة التي تريد مسحها ضوئيًا مع الشعيرات المتصالبة.
سيتم عرض إطار صورة فوق الصورة، كما يلي:

بعد ذلك، سنُجري تحسينات بسيطة على التطبيق النموذجي.
3- عرض نموذج متاهة على الصورة الثنائية الأبعاد
يمكنك البدء في استخدام ميزة "الصور المعزّزة" من خلال عرض تصميم ثلاثي الأبعاد فوقها.
تنزيل تصميم ثلاثي الأبعاد
في هذا الدرس التطبيقي حول الترميز، سنستخدم "Circle Maze - Green" من Evol، والمرخّص بموجب CC-BY 3.0. لقد خزّنتُ نسخة من هذا التصميم الثلاثي الأبعاد في مستودع github الخاص بهذا الدرس التطبيقي حول الترميز، ويمكنك العثور عليه هنا.
اتّبِع الخطوات التالية لتنزيل النموذج وتضمينه في "استوديو Android".
- انتقِل إلى مستودع GitHub الخاص بهذا الدرس التطبيقي حول الترميز، وهو دليل third_party.
- انقر على GreenMaze_obj.zip، ثم انقر على زر تنزيل.
سيتم تنزيل ملف باسم GreenMaze_obj.zip.
- في "استوديو Android"، أنشئ الدليل
green-mazeضمن التطبيق > مواد العرض > النماذج. - فك ضغط
GreenMaze_obj.zipونسخ المحتوى إلى هذا الموقع:arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze - في "استوديو Android"، انتقِل إلى app > assets > models > green-maze.
يجب أن يحتوي هذا المجلد على ملفَين: GreenMaze.obj وGreenMaze.mtl.

عرض نموذج المتاهة
اتّبِع الخطوات التالية لعرض GreenMaze.obj التصميم الثلاثي الأبعاد فوق الصورة الثنائية الأبعاد الحالية.
في AugmentedImageRenderer.java، أضِف متغيّرًا للعنصر باسم mazeRenderer لعرض نموذج المتاهة. بما أنّ المتاهة يجب أن تكون مرفقة بالصورة، من المنطقي وضع mazeRenderer داخل فئة AugmentedImageRenderer.
AugmentedImageRenderer.java
// Add a member variable to hold the maze model.
private final ObjectRenderer mazeRenderer = new ObjectRenderer();
في الدالة createOnGlThread()، حمِّل GreenMaze.obj. لتبسيط الأمور، استخدِم نسيج الإطار نفسه المستخدَم في نسيج الصورة.
AugmentedImageRenderer.java
// Replace the definition of the createOnGlThread() function with the
// following code, which loads GreenMaze.obj.
public void createOnGlThread(Context context) throws IOException {
mazeRenderer.createOnGlThread(
context, "models/green-maze/GreenMaze.obj", "models/frame_base.png");
mazeRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
استبدِل تعريف الدالة draw() بالتعريف التالي. يؤدي ذلك إلى ضبط حجم المتاهة ليناسب حجم الصورة التي تم رصدها، وعرضها على الشاشة.
AugmentedImageRenderer.java
// Adjust size of detected image and render it on-screen
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
float[] tintColor =
convertHexToColor(TINT_COLORS_HEX[augmentedImage.getIndex() % TINT_COLORS_HEX.length]);
final float mazeEdgeSize = 492.65f; // Magic number of maze size
final float maxImageEdgeSize = Math.max(augmentedImage.getExtentX(), augmentedImage.getExtentZ()); // Get largest detected image edge size
Pose anchorPose = centerAnchor.getPose();
float mazeScaleFactor = maxImageEdgeSize / mazeEdgeSize; // scale to set Maze to image size
float[] modelMatrix = new float[16];
// OpenGL Matrix operation is in the order: Scale, rotation and Translation
// So the manual adjustment is after scale
// The 251.3f and 129.0f is magic number from the maze obj file
// You mustWe need to do this adjustment because the maze obj file
// is not centered around origin. Normally when you
// work with your own model, you don't have this problem.
Pose mazeModelLocalOffset = Pose.makeTranslation(
-251.3f * mazeScaleFactor,
0.0f,
129.0f * mazeScaleFactor);
anchorPose.compose(mazeModelLocalOffset).toMatrix(modelMatrix, 0);
mazeRenderer.updateModelMatrix(modelMatrix, mazeScaleFactor, mazeScaleFactor/10.0f, mazeScaleFactor); // This line relies on a change in ObjectRenderer.updateModelMatrix later in this codelab.
mazeRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
من المفترض أن تظهر الآن المتاهة فوق default.jpg صورة الأرض.
ملاحظة: بما أنّه ليس لديك تحكّم كامل في هذا التصميم الثلاثي الأبعاد النموذجي، يستخدم الرمز أعلاه بعض الأرقام "السحرية". تبلغ أبعاد نموذج المتاهة 492.65 × 120 × 492.65، ويكون المركز عند (251.3 و60 و129.0-). نطاق قيم الإحداثيات X وY وZ لرؤوسها هو [5.02, 497.67] و[0, 120] و[-375.17, 117.25] على التوالي. وبالتالي، يجب أن يكون مقياس نموذج المتاهة image_size / 492.65. تم تقديم mazeModelLocalOffset لأنّ تصميم المتاهة الثلاثي الأبعاد غير متمركز حول نقطة الأصل (0, 0, 0).
لا يزال جدار المتاهة مرتفعًا بعض الشيء ولا يمكن وضعه فوق الصورة. أنشئ دالة مساعدة updateModelMatrix() يمكنها تغيير حجم X وY وZ بشكل غير متساوٍ لتغيير ارتفاع المتاهة بمقدار 0.1. يُرجى العِلم أنّه عليك الاحتفاظ بالدالة updateModelMatrix(float[] modelMatrix, float scaleFactor) الحالية وإضافة الدالة updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) كدالة جديدة.
common/rendering/ObjectRenderer.java
// Scale X, Y, Z coordinates unevenly
public void updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) {
float[] scaleMatrix = new float[16];
Matrix.setIdentityM(scaleMatrix, 0);
scaleMatrix[0] = scaleFactorX;
scaleMatrix[5] = scaleFactorY;
scaleMatrix[10] = scaleFactorZ;
Matrix.multiplyMM(this.modelMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
}
تشغيل الرمز البرمجي يجب أن تتناسب المتاهة الآن تمامًا مع الصورة أعلاه.

4. إضافة Andy إلى المتاهة
بعد إنشاء المتاهة، أضِف شخصية للتنقّل داخلها. استخدِم ملف andy.obj المُضمَّن في حزمة تطوير البرامج (SDK) لنظام التشغيل Android في ARCore. احتفظ بنسيج إطار الصورة كما هو، لأنّه يبدو مختلفًا عن متاهة اللون الأخضر المعروضة فوق الصورة.
في AugmentedImageRenderer.java، أضِف ObjectRenderer خاصًا لعرض Andy.
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
بعد ذلك، ابدأ andyRenderer في نهاية createOnGlThread().
AugmentedImageRenderer.java
public void createOnGlThread(Context context) throws IOException {
// Initialize andyRenderer
andyRenderer.createOnGlThread(
context, "models/andy.obj", "models/andy.png");
andyRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
أخيرًا، اعرض صورة Andy وهو يقف في أعلى المتاهة في نهاية الدالة draw().
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Render Andy, standing on top of the maze
Pose andyModelLocalOffset = Pose.makeTranslation(
0.0f,
0.1f,
0.0f);
anchorPose.compose(andyModelLocalOffset).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f); // 0.05f is a Magic number to scale
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
تشغيل الرمز البرمجي من المفترض أن يظهر لك Andy واقفًا في أعلى المتاهة.

تحديد جودة الصورة المستهدَفة
تعتمد ARCore على الميزات المرئية للتعرّف على الصور. ونظرًا لاختلاف الجودة، لا يمكن التعرّف على بعض الصور بسهولة.
arcoreimg هي أداة سطر أوامر تتيح لك تحديد مدى سهولة تعرّف ARCore على الصورة. ويعرض رقمًا يتراوح بين 0 و100، حيث يكون الرقم 100 هو الأسهل في التعرّف عليه.
. إليك مثال:
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
تبلغ قيمة maze.jpg 100، لذا يمكن لـ ARCore التعرّف عليها بسهولة.
5- اختياري: تحريك Andy في المتاهة
أخيرًا، يمكنك إضافة بعض الرموز البرمجية لجعل Andy يتحرّك في المتاهة. على سبيل المثال، استخدِم محرّك التأثيرات الحركية مفتوح المصدر jBullet للتعامل مع محاكاة التأثيرات الحركية. لا بأس إذا تخطّيت هذه الخطوة.
نزِّل PhysicsController.java وأضِفه إلى مشروعك في الدليل
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
في "استوديو Android"، أضِف GreenMaze.obj إلى دليل مواد عرض المشروع، حتى يمكن تحميله في وقت التشغيل. انسخ GreenMaze.obj من app > assets > models > green-maze إلى app > assets.
أضِف الاعتماديات التالية إلى ملف build.gradle الخاص بالتطبيق.
app/build.gradle
// jbullet library
implementation 'cz.advel.jbullet:jbullet:20101010-1'
عرِّف المتغيّر andyPose لتخزين موضع وضعية آندي الحالية.
AugmentedImageRenderer.java
// Create a new pose for the Andy
private Pose andyPose = Pose.IDENTITY;
عدِّل AugmentedImageRenderer.java لعرض Andy باستخدام المتغيّر الجديد andyPose.
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Use these code to replace previous code for rendering the Andy object
//
// Adjust the Andy's rendering position
// The Andy's pose is at the maze's vertex's coordinate
Pose andyPoseInImageSpace = Pose.makeTranslation(
andyPose.tx() * mazeScaleFactor,
andyPose.ty() * mazeScaleFactor,
andyPose.tz() * mazeScaleFactor);
anchorPose.compose(andyPoseInImageSpace).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f);
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
أضِف دالة أداة جديدة، updateAndyPose()، لتلقّي تعديلات على وضعية Andy.
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
في AugmentedImageActivity.java، أنشئ عنصر PhysicsController يستخدم محرّك التأثيرات الحركية JBullet لإدارة جميع الدوال ذات الصلة بالتأثيرات الحركية.
AugmentedImageActivity.java
import com.google.ar.core.Pose;
// Declare the PhysicsController object
private PhysicsController physicsController;
في محرك الفيزياء، نستخدم في الواقع كرة صلبة لتمثيل Andy ونعدّل وضعية Andy باستخدام وضعية الكرة. استدعِ الدالة PhysicsController لتعديل الفيزياء كلما تعرّف التطبيق على صورة. لتحريك الكرة كما لو كانت في العالم الحقيقي، طبِّق الجاذبية الأرضية لتحريك الكرة في المتاهة.
AugmentedImageActivity.java
// Update the case clause for TRACKING to call PhysicsController
// whenever the app recognizes an image
private void drawAugmentedImages(
...
case TRACKING:
// Switch to UI Thread to update View
this.runOnUiThread(
new Runnable() {
@Override
public void run() {
fitToScanView.setVisibility(View.GONE);
}
});
// Create a new anchor for newly found images
if (!augmentedImageMap.containsKey(augmentedImage.getIndex())) {
Anchor centerPoseAnchor = augmentedImage.createAnchor(augmentedImage.getCenterPose());
augmentedImageMap.put(
augmentedImage.getIndex(), Pair.create(augmentedImage, centerPoseAnchor));
physicsController = new PhysicsController(this);
} else {
Pose ballPose = physicsController.getBallPose();
augmentedImageRenderer.updateAndyPose(ballPose);
// Use real world gravity, (0, -10, 0), as gravity
// Convert to Physics world coordinate(maze mesh has to be static)
// Use the converted coordinate as a force to move the ball
Pose worldGravityPose = Pose.makeTranslation(0, -10f, 0);
Pose mazeGravityPose = augmentedImage.getCenterPose().inverse().compose(worldGravityPose);
float mazeGravity[] = mazeGravityPose.getTranslation();
physicsController.applyGravityToBall(mazeGravity);
physicsController.updatePhysics();
}
break;
شغِّل التطبيق. من المفترض أن يتحرّك Andy الآن بشكل واقعي عند إمالة الصورة.
يستخدم المثال أدناه هاتفًا آخر لعرض الصورة، ويمكنك استخدام أي شيء يناسبك، مثل جهاز لوحي أو غلاف كتاب ورقي أو مجرد ورقة مطبوعة ملصقة على جسم مسطّح.

هذا كل شيء! استمتِع بمحاولة توجيه آندي عبر المتاهة. ملاحظة: يسهل العثور على المخرج عند قلب صورة الهدف.
6. تهانينا
تهانينا، لقد وصلت إلى نهاية هذا الدرس العملي، وبالتالي:
- أنشأت عيّنة AugmentedImage Java من ARCore وشغّلتها.
- تم تعديل العيّنة لعرض نموذج متاهة على الصورة، بالمقياس المناسب.
- استخدام وضعية الصورة لإنشاء شيء ممتع
إذا أردت الرجوع إلى الرمز الكامل، يمكنك تنزيله هنا.