אתם יכולים להשתמש בפיד המצלמה ש-ARCore מתעד בצינור עיבוד נתונים של למידת מכונה כדי ליצור חוויה חכמה של מציאות רבודה. הדוגמה של ARCore ML Kit מדגימה איך להשתמש ב-ML Kit וב-Google Cloud Vision API לזיהוי אובייקטים בעולם האמיתי. הדוגמה משתמשת במודל של למידת מכונה כדי לסווג אובייקטים בתצוגת המצלמה, ומצרפת תווית לאובייקט בסצנה הווירטואלית.
הדוגמה של ARCore ML Kit כתובה ב-Kotlin. היא זמינה גם כאפליקציה לדוגמה ml_kotlin מתוך המאגר ARCore SDK ב-GitHub.
שימוש בתמונת המעבד (CPU) של ARCore
כברירת מחדל, ב-ARCore מתועדים שתי קבוצות לפחות של זרמי תמונות:
- זרם תמונה של המעבד (CPU) המשמש לזיהוי תכונות ולעיבוד תמונה. כברירת מחדל, הרזולוציה של המעבד (CPU) היא VGA (640x480). אם צריך, אפשר להגדיר את ARCore להשתמש בשידור תמונות נוסף ברזולוציה גבוהה יותר.
- זרם של טקסטורות GPU, שמכיל מרקם ברזולוציה גבוהה, בדרך כלל ברזולוציה של 1080p. מצב זה משמש בדרך כלל כתצוגה מקדימה של המצלמה שפונה למשתמש.
מאוחסנים במרקם OpenGL שצוין על ידי
Session.setCameraTextureName()
. - כל סטרימינג נוסף שצוין על ידי
SharedCamera.setAppSurfaces()
.
שיקולים לקביעת גודל התמונה במעבד (CPU)
אין עלות נוספת לשימוש בשידור ברירת המחדל של המעבד (CPU) בגודל VGA, כי מערכת ARCore משתמשת בשידור הזה כדי להבין את העולם. בקשה של שידור ברזולוציה אחרת עשויה להיות יקרה, כי יהיה צורך לצלם שידור נוסף. חשוב לזכור שרזולוציה גבוהה יותר עשויה להפוך ליקרה במהירות עבור המודל שלך: הכפלת הרוחב והגובה של התמונה מכפילה את כמות הפיקסלים בתמונה.
כדאי להפחית את רמת הביצועים של התמונה, אם המודל עדיין יכול להניב ביצועים טובים בתמונה ברזולוציה נמוכה יותר.
הגדרת שידור תמונה נוסף של המעבד (CPU) ברזולוציה גבוהה
הביצועים של מודל למידת המכונה עשויים להיות תלויים ברזולוציה של התמונה המשמשת כקלט. אפשר לשנות את הרזולוציה של השידורים האלה על ידי שינוי הרזולוציה של CameraConfig
הנוכחית באמצעות Session.setCameraConfig()
, בחירת הגדרה חוקית מ-Session.getSupportedCameraConfigs()
.
Java
CameraConfigFilter cameraConfigFilter = new CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK); List<CameraConfig> supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter); // Select an acceptable configuration from supportedCameraConfigs. CameraConfig cameraConfig = selectCameraConfig(supportedCameraConfigs); session.setCameraConfig(cameraConfig);
Kotlin
val cameraConfigFilter = CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK) val supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter) // Select an acceptable configuration from supportedCameraConfigs. val cameraConfig = selectCameraConfig(supportedCameraConfigs) session.setCameraConfig(cameraConfig)
אחזור התמונה של המעבד (CPU)
מאחזרים את התמונה של המעבד (CPU) באמצעות Frame.acquireCameraImage()
.
אין להשליך את התמונות האלה מיד לאחר שאין בהן צורך.
Java
Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); // Process `cameraImage` using your ML inference model. } catch (NotYetAvailableException e) { // NotYetAvailableException is an exception that can be expected when the camera is not ready // yet. The image may become available on a next frame. } catch (RuntimeException e) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e); } finally { if (cameraImage != null) { cameraImage.close(); } }
Kotlin
// NotYetAvailableException is an exception that can be expected when the camera is not ready yet. // Map it to `null` instead, but continue to propagate other errors. fun Frame.tryAcquireCameraImage() = try { acquireCameraImage() } catch (e: NotYetAvailableException) { null } catch (e: RuntimeException) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e) } // The `use` block ensures the camera image is disposed of after use. frame.tryAcquireCameraImage()?.use { image -> // Process `image` using your ML inference model. }
עיבוד התמונה של המעבד (CPU)
כדי לעבד את התמונה של המעבד (CPU), אפשר להשתמש במספר ספריות של למידת מכונה.
- ML Kit: ML Kit מספק ממשק API של זיהוי אובייקטים ומעקב במכשיר.
הוא כולל מסווג גס שמובנה ב-API, והוא יכול גם להשתמש במודלים של סיווג בהתאמה אישית כדי לכסות דומיין צר יותר של אובייקטים.
באמצעות
InputImage.fromMediaImage
ניתן להמיר את התמונה של המעבד (CPU) ל-InputImage
. - למידת מכונה ב-Firebase: פלטפורמת Firebase מספקת ממשקי API ללמידת מכונה שפועלים בענן או במכשיר. עיינו במסמכי התיעוד של Firebase בנושא תוויות מאובטח של תמונות ב-Cloud Vision באמצעות Firebase Auth ו-פונקציות ב-Android.
הצגת תוצאות בסצנת ה-AR
במקרים רבים, מודלים לזיהוי תמונות מקבלים פלט של אובייקטים על ידי ציון נקודת מרכז או פוליגון תוחם שמייצג את האובייקט שזוהה.
אפשר לחבר עוגן לאובייקט שזוהה באמצעות נקודת המרכז או המרכז של התיבה התוחמת שמתקבלת מהמודל. באמצעות Frame.hitTest()
ניתן להעריך את תנוחת העצם בסצנה הווירטואלית.
המירו IMAGE_PIXELS
קואורדינטות ל-VIEW
קואורדינטות:
Java
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. float[] cpuCoordinates = new float[] {mlResult.getX(), mlResult.getY()}; float[] viewCoordinates = new float[2]; frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates); // `viewCoordinates` now contains coordinates suitable for hit testing.
Kotlin
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. val cpuCoordinates = floatArrayOf(mlResult.x, mlResult.y) val viewCoordinates = FloatArray(2) frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates ) // `viewCoordinates` now contains coordinates suitable for hit testing.
משתמשים בקואורדינטות VIEW
הבאות כדי לבצע בדיקת היט וליצור עוגן מהתוצאה:
Java
List<HitResult> hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]); HitResult depthPointResult = null; for (HitResult hit : hits) { if (hit.getTrackable() instanceof DepthPoint) { depthPointResult = hit; break; } } if (depthPointResult != null) { Anchor anchor = depthPointResult.getTrackable().createAnchor(depthPointResult.getHitPose()); // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Kotlin
val hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]) val depthPointResult = hits.filter { it.trackable is DepthPoint }.firstOrNull() if (depthPointResult != null) { val anchor = depthPointResult.trackable.createAnchor(depthPointResult.hitPose) // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
שיקולי ביצועים
כדי לחסוך בכוח העיבוד ולצרוך פחות אנרגיה, כדאי לפעול לפי ההמלצות הבאות:
- אין להריץ את מודל ה-ML בכל מסגרת נכנסת. במקום זאת, כדאי להפעיל את זיהוי האובייקטים בקצב פריימים נמוך.
- חשבו על מודל ההסקה של למידת מכונה (ML) אונליין כדי להפחית את המורכבות החישובית.