1. Übersicht
ARCore ist eine Plattform zum Erstellen von Augmented Reality-Apps für Android. Mit Augmented Images können Sie AR-Apps erstellen, die vorab registrierte 2D-Bilder in der realen Welt erkennen und virtuelle Inhalte darauf verankern können.
In diesem Codelab erfahren Sie, wie Sie eine vorhandene ARCore-Beispiel-App so ändern, dass sie Augmented Images enthält, die sich bewegen oder an einem festen Ort platziert sind.
Aufgaben
In diesem Codelab bauen Sie auf einer vorhandenen ARCore-Beispiel-App auf. Am Ende des Codelabs kann Ihre App Folgendes:
- Ein Bildziel erkennen und ein virtuelles Labyrinth daran anbringen
- Das sich bewegende Ziel verfolgen, solange es sich im Sichtfeld der Kamera befindet

Erstellen Sie zum ersten Mal eine ARCore-App?
Möchten Sie in diesem Codelab Beispielcode schreiben oder diese Seiten nur lesen?
Lerninhalte
- Augmented Images in ARCore in Java verwenden
- Einschätzen, ob ein Bild von ARCore erkannt werden kann
- Virtuelle Inhalte an ein Bild anhängen und ihre Bewegung verfolgen
Vorbereitung
Für dieses Codelab benötigen Sie bestimmte Hardware und Software.
Hardwareanforderungen
- Ein von ARCore unterstütztes Gerät, das über ein USB-Kabel mit Ihrem Entwicklungscomputer verbunden ist
Softwareanforderungen
- ARCore APK 1.9.0 oder höher. Diese APK wird normalerweise automatisch über den Play Store auf dem Gerät installiert.
- Ein Entwicklungssystem mit Android Studio (Version 3.1 oder höher)
- Internetzugriff, da Sie während der Entwicklung Bibliotheken herunterladen müssen
Jetzt, da Sie alles vorbereitet haben, können wir loslegen.
2. Entwicklungsumgebung einrichten
SDK herunterladen
Zuerst laden wir das aktuelle ARCore Android SDK von GitHub herunter. Entpacken Sie die Datei am gewünschten Speicherort. Für dieses Codelab ist die früheste SDK-Version 1.18.1. Der Ordner wird als arcore-android-sdk-x.xx.x bezeichnet. Der genaue Wert ist die Version des SDK, das Sie verwenden.
Starten Sie Android Studio und klicken Sie auf Open an existing Android Studio project (Vorhandenes Android Studio-Projekt öffnen).

Rufen Sie diesen entzippten Ordner auf:
arcore-android-sdk-x.xx.x/samples/augmented_image_java
Klicken Sie auf Öffnen.
Warten Sie, bis Android Studio das Projekt synchronisiert hat. Wenn in Ihrer Android Studio-Installation die erforderlichen Komponenten fehlen, schlägt die Ausführung möglicherweise mit der Meldung Install missing platform and sync project fehl. Folgen Sie der Anleitung, um das Problem zu beheben.
Beispiel-App ausführen
Nachdem Sie jetzt ein funktionierendes ARCore-App-Projekt haben, können Sie es testen.
Verbinden Sie Ihr ARCore-Gerät mit dem Entwicklungscomputer und verwenden Sie das Menü Run > Run „app“, um die Debug-Version auf dem Gerät auszuführen. Wählen Sie im Dialogfeld, in dem Sie aufgefordert werden, das Gerät auszuwählen, auf dem die Ausführung erfolgen soll, das verbundene Gerät aus und klicken Sie auf OK.


In diesem Beispielprojekt wird targetSdkVersion 28 verwendet. Wenn Sie einen Build-Fehler wie Failed to find Build Tools revision 28.0.3 haben, folgen Sie der Anleitung in Android Studio, um die erforderliche Version der Android Build Tools herunterzuladen und zu installieren.
Wenn alles erfolgreich ist, wird die Beispiel-App auf dem Gerät gestartet und Sie werden aufgefordert, die Berechtigung zu erteilen, mit Augmented Image Fotos und Videos aufzunehmen. Tippen Sie auf ZULASSEN, um die Berechtigung zu erteilen.
Mit einem Beispielbild testen
Nachdem Sie Ihre Entwicklungsumgebung eingerichtet haben, können Sie die App testen, indem Sie ihr ein Bild zur Verfügung stellen.
Klicken Sie in Android Studio im Fenster Project auf app > assets und doppelklicken Sie auf die Datei default.jpg, um sie zu öffnen.

Richten Sie die Kamera Ihres Geräts auf das Bild der Erde auf dem Bildschirm und folgen Sie der Anleitung, um das gescannte Bild in das Fadenkreuz einzupassen.
Über dem Bild wird ein Bildrahmen eingeblendet, wie hier:

Als Nächstes nehmen wir kleine Verbesserungen an der Beispiel-App vor.
3. Ein Labyrinthmodell auf dem 2D-Bild anzeigen
Sie können Augmented Images verwenden, indem Sie ein 3D‑Modell darüber einblenden.
3D-Modell herunterladen
In diesem Codelab verwenden wir das Bild „Circle Maze – Green“ von Evol, das unter der Lizenz CC-BY 3.0 veröffentlicht wurde. Ich habe eine Kopie dieses 3D-Modells im GitHub-Repository dieses Codelabs gespeichert. Hier finden Sie es.
So laden Sie das Modell herunter und fügen es in Android Studio ein:
- Rufen Sie das GitHub-Repository dieses Codelabs, das Verzeichnis „third_party“ auf.
- Klicken Sie auf GreenMaze_obj.zip und dann auf die Schaltfläche Herunterladen.
Dadurch wird eine Datei mit dem Namen GreenMaze_obj.zip heruntergeladen.
- Erstellen Sie in Android Studio das Verzeichnis
green-mazeunter app > assets > models. - Entpacken Sie
GreenMaze_obj.zipund kopieren Sie den Inhalt an diesen Speicherort:arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze - Rufen Sie in Android Studio app > assets > models > green-maze auf.
In diesem Ordner sollten sich zwei Dateien befinden: GreenMaze.obj und GreenMaze.mtl.

Labyrinthmodell rendern
So wird das GreenMaze.obj-3D-Modell über dem vorhandenen 2D-Bild angezeigt:
Fügen Sie in AugmentedImageRenderer.java eine Mitgliedsvariable namens mazeRenderer hinzu, um das Labyrinthmodell zu rendern. Da das Labyrinth an das Bild angehängt werden soll, ist es sinnvoll, mazeRenderer in die Klasse AugmentedImageRenderer einzufügen.
AugmentedImageRenderer.java
// Add a member variable to hold the maze model.
private final ObjectRenderer mazeRenderer = new ObjectRenderer();
Laden Sie in der Funktion createOnGlThread() die GreenMaze.obj. Verwenden Sie der Einfachheit halber dieselbe Frame-Textur wie die Textur.
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);
}
Ersetzen Sie die Definition der draw()-Funktion durch Folgendes. Dadurch wird die Größe des Labyrinths an die Größe des erkannten Bildes angepasst und auf dem Bildschirm gerendert.
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);
}
Das Labyrinth sollte jetzt über dem default.jpg-Bild der Erde angezeigt werden.
Hinweis:Da Sie keine vollständige Kontrolle über dieses 3D-Beispielmodell haben, werden im obigen Code einige „magische“ Zahlen verwendet. Die Abmessungen des Labyrinthmodells sind 492,65 × 120 × 492,65, mit dem Mittelpunkt bei (251,3, 60, -129,0). Die Wertebereiche der X-, Y- und Z-Koordinaten der Eckpunkte sind [5,02, 497,67], [0, 120] bzw. [–375,17, 117,25]. Daher muss der Maßstab des Labyrinthmodells image_size / 492.65 sein. Der mazeModelLocalOffset wird eingeführt, weil das 3D-Modell des Labyrinths nicht um den Ursprung (0, 0, 0) zentriert ist.
Die Wand des Labyrinths ist noch etwas zu hoch, um auf das Bild zu passen. Erstellen Sie eine Hilfsfunktion updateModelMatrix(), mit der X, Y und Z ungleichmäßig skaliert werden können, um die Höhe des Labyrinths um 0,1 zu skalieren. Behalten Sie die vorhandene updateModelMatrix(float[] modelMatrix, float scaleFactor) bei und fügen Sie die Funktionsüberladung updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) als neue Funktion hinzu.
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);
}
Führen Sie den Code aus. Das Labyrinth sollte jetzt perfekt über dem Bild liegen.

4. Andy ins Labyrinth einfügen
Nachdem Sie ein Labyrinth erstellt haben, fügen Sie eine Figur hinzu, die sich darin bewegen kann. Verwenden Sie die Datei andy.obj, die im ARCore Android SDK enthalten ist. Behalten Sie die Textur des Bildrahmens bei, da sie sich von der Textur des grünen Labyrinths unterscheidet, das über dem Bild gerendert wird.
Fügen Sie in AugmentedImageRenderer.java einen privaten ObjectRenderer hinzu, um Andy zu rendern.
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
Initialisieren Sie als Nächstes andyRenderer am Ende von 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);
}
Rendere Andy am Ende der Funktion draw() auf dem Labyrinth.
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);
}
Führen Sie den Code aus. Sie sollten Andy oben auf dem Labyrinth sehen.

Zielbildqualität festlegen
ARCore verwendet visuelle Merkmale, um Bilder zu erkennen. Aufgrund von Qualitätsunterschieden können nicht alle Bilder leicht erkannt werden.
arcoreimg ist ein Befehlszeilentool, mit dem Sie festlegen können, wie gut ein Bild von ARCore erkannt wird. Es wird eine Zahl zwischen 0 und 100 ausgegeben, wobei 100 am einfachsten zu erkennen ist.
. Hier ein Beispiel:
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
maze.jpg hat einen Wert von 100 und wird daher von ARCore leicht erkannt.
5. Optional: Andy im Labyrinth bewegen
Schließlich können Sie noch Code hinzufügen, damit sich Andy im Labyrinth bewegt. Verwenden Sie beispielsweise die Open-Source-Physik-Engine jBullet für die Physiksimulation. Sie können diesen Teil überspringen.
Laden Sie PhysicsController.java herunter und fügen Sie es Ihrem Projekt im Verzeichnis
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
Fügen Sie in Android Studio GreenMaze.obj dem Verzeichnis project assets hinzu, damit es zur Laufzeit geladen werden kann. Kopieren Sie GreenMaze.obj aus app > assets > models > green-maze in app > assets.
Fügen Sie der Datei build.gradle der App die folgenden Abhängigkeiten hinzu.
app/build.gradle
// jbullet library
implementation 'cz.advel.jbullet:jbullet:20101010-1'
Definieren Sie eine Variable andyPose, um die Position der aktuellen Pose von Andy zu speichern.
AugmentedImageRenderer.java
// Create a new pose for the Andy
private Pose andyPose = Pose.IDENTITY;
Ändern Sie AugmentedImageRenderer.java, damit Andy mit der neuen Variablen andyPose gerendert wird.
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);
}
Eine neue Hilfsfunktion, updateAndyPose(), wurde hinzugefügt, um Updates zur Andy-Pose zu erhalten.
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
Erstellen Sie in AugmentedImageActivity.java ein PhysicsController-Objekt, das die JBullet-Physik-Engine verwendet, um alle physikbezogenen Funktionen zu verwalten.
AugmentedImageActivity.java
import com.google.ar.core.Pose;
// Declare the PhysicsController object
private PhysicsController physicsController;
In der Physics-Engine verwenden wir eine starre Kugel, um Andy darzustellen, und aktualisieren seine Pose anhand der Pose der Kugel. Rufen Sie PhysicsController auf, um die Physik zu aktualisieren, sobald die App ein Bild erkennt. Wenn Sie den Ball wie in der realen Welt bewegen möchten, wenden Sie die Schwerkraft an, um den Ball im Labyrinth zu bewegen.
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;
Führen Sie die App aus. Andy sollte sich jetzt realistisch bewegen, wenn Sie das Bild neigen.
Im folgenden Beispiel wird ein anderes Smartphone verwendet, um das Bild anzuzeigen. Sie können aber auch ein Tablet, das Cover eines gedruckten Buchs oder einfach ein auf einem flachen Objekt angebrachtes Blatt Papier verwenden.

Geschafft! Viel Spaß dabei, Andy durch das Labyrinth zu lotsen. Tipp: Wenn Sie das Zielbild auf den Kopf drehen, finden Sie den Ausgang leichter.
6. Glückwunsch
Herzlichen Glückwunsch! Sie haben dieses Codelab abgeschlossen und damit Folgendes erreicht:
- Sie haben ein ARCore-Beispiel für AugmentedImage Java erstellt und ausgeführt.
- Das Beispiel wurde aktualisiert, um ein Labyrinthmodell im richtigen Maßstab auf dem Bild darzustellen.
- Die Pose des Bildes wurde für etwas Lustiges genutzt.
Wenn Sie sich den vollständigen Code ansehen möchten, können Sie ihn hier herunterladen.