
In diesem Handbuch erfahren Sie, wie Sie der realen Welt 3D-Modelle hinzufügen. Mit der ARCore-Bibliothek von Google können Sie einem 2D-Bild (Bild oder Video) vollständige 3D-Modelle hinzufügen.
Sie müssen dem System eine Art Referenzbild zur Verfügung stellen, nach dem ARCore in der realen Welt sucht, um dem darauf basierenden Bild ein 3D-Modell hinzuzufügen. Augmented Reality ist beispielsweise in Büchern, Zeitungen, Zeitschriften usw. bereits weit verbreitet.
Bevor Sie in dieses Tutorial eintauchen, sollten Sie sich mit den beiden vorherigen Artikeln zu diesem Thema vertraut machen, in denen Sie die grundlegenden AR-Begriffe kennenlernen:
Was sind Augmented Reality-Bilder?
Laut der Dokumentation für Entwickler können Sie mit Augmented Reality-Bildern in ARCore Augmented Reality-Anwendungen erstellen, mit denen 2D-Bilder wie Poster oder Produktverpackungen „animiert“ werden können.
Sie laden einige Referenzbilder in ARCore hoch und erfahren dann, wie sie während der AR-Sitzung erkannt werden, z. B. beim Aufnehmen eines Videos. Diese Informationen werden verwendet, um das 3D-Modell auf einem 2D-Bild zu positionieren.
Einschränkungen bei der Verwendung von Augmented Reality-Bildern
Im Folgenden sind einige der Einschränkungen aufgeführt, die bei der Verwendung von Augmented-Reality-Bildern auftreten können:
- ARCore kann nur bis zu 20 Referenzbilder gleichzeitig verarbeiten.
- Die physische Ebene in der realen Welt sollte flach sein und eine Fläche von mehr als 15 cm x 15 cm haben.
- ARCore kann keine bewegten Bilder und Objekte verfolgen.
Auswahl des richtigen Referenzbildes
Hier einige Tipps zur Auswahl eines guten Referenzbilds für ARCore:
- Augmented Reality-Bilder unterstützen die Formate PNG, JPEG und JPG.
- Es spielt keine Rolle, ob das Bild farbig oder schwarzweiß ist. Hauptsache, es ist kontrastreich.
- Die Bildauflösung muss mindestens 300 x 300 Pixel betragen.
- Die Verwendung von hochauflösenden Bildern bedeutet keine Leistungsverbesserung.
- Vermeiden Sie Bilder mit sich wiederholenden Mustern (z. B. Muster oder Tupfen).
- Verwenden Sie das Arcoreimg- Tool, um zu bewerten, wie gut Ihr Bild funktioniert. Eine Bewertung von mindestens 75 Punkten wird empfohlen.
So verwenden Sie das Arcoreimg-Tool:
- Laden Sie das ARCore SDK für Android von diesem Link herunter.
- Entpacken Sie den Inhalt der Datei an einen beliebigen Ort.
- Gehen Sie im extrahierten Ordner zu tools> arcoreimg> windows (auch wenn Sie Linux oder macOS haben).
- Öffnen Sie eine Eingabeaufforderung in diesem Verzeichnis.
- Und geben Sie diesen Befehl ein:
arcoreimg.exe eval-img --input_image_path=dog.png
Ersetzen Sie dog.png durch den vollständigen Pfad zu Ihrem Bild.
Erste Schritte mit der Augmented Reality App
Nachdem Sie sich mit ARCore vertraut gemacht und ein gutes Bild mit einer Bewertung von 75+ ausgewählt haben, können Sie mit dem Schreiben des Anwendungscodes beginnen.
Fragmenterstellung
Wir werden ein Fragment erstellen und es unserer Aktivität hinzufügen. Erstellen Sie eine Klasse namens CustomArFragment
und erben Sie sie von ArFragment
. Hier ist der Code für 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; } }
Zunächst schalten wir die Ebenenerkennung aus. Auf diese Weise entfernen wir das Handsymbol vom Bildschirm, das unmittelbar nach der Initialisierung des Fragments angezeigt wird, und informieren den Benutzer über die Notwendigkeit, sein Smartphone zu bewegen, um das Flugzeug zu finden. Wir brauchen das nicht mehr, weil wir keine zufälligen Ebenen finden, sondern ein konkretes Bild.
Dann legen wir den Aktualisierungsmodus für die Sitzung LATEST_CAMERA_IMAGE
. Dies stellt sicher, dass wir über Bildaktualisierungen informiert werden, wenn der Kamerarahmen aktualisiert wird.
Einrichtung der Bilddatenbank
Fügen Sie das ausgewählte Referenzbild (das Sie in der physischen Welt finden möchten) zum Ordner " Assets" hinzu (erstellen Sie es, falls dies noch nicht geschehen ist). Jetzt können wir Bilder zu unserer Datenbank hinzufügen.
Wir werden diese Datenbank erstellen, sobald das Fragment erstellt wurde. In den Protokollen zeigen wir das Ergebnis dieser Operation an:
if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) { Log.d("SetupAugImgDb", "Success"); } else { Log.e("SetupAugImgDb","Faliure setting up db"); }
So CustomArFragment
aus:
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; } }
In setupAugmentedImagesDb
werden wir setupAugmentedImagesDb
Methode MainActivity
. CustomArFragment
wir nun CustomArFragment
zu unserer activity_main.xml
:
<?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>
Hinzufügen eines Bildes zur Datenbank
Jetzt richten wir unsere Bilddatenbank ein, finden das Referenzbild in der realen Welt und fügen dem Bild ein 3D-Modell hinzu.
Beginnen wir mit der Einrichtung unserer Datenbank. Erstellen Sie eine öffentliche setupAugmentedImagesDb
Methode in der MainActivity
Klasse:
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; }
Wir haben auch eine loadAugmentedImage
Methode erstellt, die ein Bild aus einem Ressourcenordner lädt und eine Bitmap zurückgibt.
In setupAugmentedImagesDb
initialisieren wir zuerst unsere Datenbank für die aktuelle Sitzung und fügen dann das Image dieser Datenbank hinzu. Wir haben unseren Bildtiger genannt . Dann installieren wir diese Datenbank in der Konfiguration und geben true
, was darauf hinweist, dass das Image erfolgreich hinzugefügt wurde.
Reale Referenzbilderkennung
Jetzt werden wir beginnen, unsere Referenzbilder in der realen Welt zu entdecken. Zu diesem Zweck erstellen wir einen Listener, der jedes Mal aufgerufen wird, wenn der Videorahmen aktualisiert wird, und dieser Rahmen wird auf das Vorhandensein eines Referenzbilds dort analysiert.
Fügen Sie diese Zeile der onCreate()
-Methode in MainActivity
:
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
onUpdateFrame
nun die onUpdateFrame
Methode zu 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; } } } }
In der ersten Zeile erhalten wir den Rahmen selbst. Ein Frame kann als normaler Screenshot eines Videos vorgestellt werden. Wenn Sie mit der Funktionsweise des Videos vertraut sind, wissen Sie, dass es sich nur um eine Sammlung von Bildern handelt, die sich sehr schnell ändern und den Eindruck erwecken, dass sich etwas bewegt. Wir machen nur eines dieser Bilder.
Nachdem wir den Rahmen erhalten haben, analysieren wir ihn auf das Vorhandensein unseres Referenzbildes. Wir erstellen eine Liste aller von ARCore mithilfe von frame.getUpdatedTrackables verfolgten frame.getUpdatedTrackables
. Dann iterieren wir darüber und prüfen, ob unser Tigerbild im Rahmen vorhanden ist.
Wenn eine Übereinstimmung gefunden wird, nehmen wir einfach das 3D-Modell und platzieren es auf dem erkannten Bild.
Hinweis Das Flag shouldAddModel
verwendet, sodass das 3D-Modell nur einmal shouldAddModel
.
Platzieren eines 3D-Modells über einem Referenzbild
Nachdem wir unser Referenzbild in der realen Welt gefunden haben, können wir ein 3D-Modell hinzufügen. Fügen Sie die addNodeToScene
placeObject
und addNodeToScene
:
placeObject
: Mit dieser Methode wird ein gerendertes Objekt mit einem bestimmten Uri
. Sobald das Rendern abgeschlossen ist, wird das Objekt an die Methode addNodeToScene
, wo das Objekt an den Knoten angehängt und dieser Knoten in der Szene platziert wird.addNodeToScene
: Diese Methode erstellt einen Knoten aus dem resultierenden Anker, erstellt einen weiteren Knoten, mit dem das visualisierte Objekt verbunden wird, fügt diesen Knoten dann dem addNodeToScene
hinzu und platziert ihn auf der Bühne.
So sieht 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(); } }
Führen Sie nun Ihre Anwendung aus. Sie sollten den Bildschirm wie unten gezeigt sehen. Bewegen Sie das Telefon leicht über das Referenzobjekt. Sobald ARCore das Referenzbild in der realen Welt erkennt, fügt es Ihr 3D-Modell hinzu.

Lesen Sie auch: Erstellen Ihrer ersten ARCore-Anwendung