
Dans ce guide, vous apprendrez à ajouter des modÚles 3D au monde réel. La bibliothÚque ARCore de Google vous permet d'ajouter des modÚles 3D complets à une image 2D (photo ou vidéo).
Vous devez fournir au systÚme une sorte d'image de référence qu'ARCore recherchera dans le monde réel afin d'ajouter un modÚle 3D à l'image sur sa base. La réalité augmentée est déjà largement utilisée, par exemple dans les livres, les journaux, les magazines, etc.
Avant de plonger dans ce didacticiel, vous devez vous familiariser avec les deux articles précédents sur ce sujet qui vous présenteront les termes AR de base:
Que sont les images de réalité augmentée?
Selon la documentation destinée aux développeurs , les images de réalité augmentée ARCore vous permettent de créer des applications de réalité augmentée qui peuvent «animer» des images 2D, telles que des affiches ou des emballages de produits.
Vous téléchargez des images de référence sur ARCore, puis il vous informe de leur détection pendant la session AR, par exemple, lors de la prise d'une vidéo. Et ces informations sont utilisées pour positionner le modÚle 3D sur une image 2D.
Limites de l'utilisation d'images de réalité augmentée
Voici quelques-unes des limitations que vous pouvez rencontrer lors de l'utilisation d'images de réalité augmentée:
- ARCore ne peut traiter que jusqu'à 20 images de référence à la fois.
- Le plan physique dans le monde rĂ©el doit ĂȘtre plat et sa surface doit ĂȘtre supĂ©rieure Ă 15 cm x 15 cm.
- ARCore ne peut pas suivre les images et les objets en mouvement.
Choisir la bonne image de référence
Voici quelques conseils pour choisir une bonne image de référence pour ARCore:
- Les images de réalité augmentée prennent en charge les formats PNG, JPEG et JPG.
- Peu importe que l'image soit en couleur ou en noir et blanc, l'essentiel est qu'elle soit en contraste élevé.
- La rĂ©solution de l'image doit ĂȘtre d'au moins 300 x 300 pixels.
- L'utilisation d'images à haute résolution ne signifie pas une amélioration des performances.
- Les images avec des motifs rĂ©pĂ©titifs (tels que des motifs ou des pois) doivent ĂȘtre Ă©vitĂ©es.
- Utilisez l'outil arcoreimg pour évaluer le fonctionnement de votre image. Une note d'au moins 75 points est recommandée.
Comment utiliser l'outil arcoreimg:
- Téléchargez le SDK ARCore pour Android à partir de ce lien .
- Décompressez le contenu du fichier à n'importe quel emplacement.
- Dans le dossier extrait, allez dans tools> arcoreimg> windows (mĂȘme si vous avez Linux ou macOS).
- Ouvrez une invite de commande dans ce répertoire.
- Et entrez cette commande:
arcoreimg.exe eval-img --input_image_path=dog.png
Remplacez dog.png par le chemin d'accĂšs complet Ă votre image.
Premiers pas avec l'application de réalité augmentée
Maintenant que vous vous ĂȘtes familiarisĂ© avec ARCore et avez sĂ©lectionnĂ© une bonne image avec une note de 75+, il est temps de commencer Ă Ă©crire le code d'application.
Création de fragments
Nous allons créer un fragment et l'ajouter à notre activité. Créez une classe appelée CustomArFragment
et CustomArFragment
-la d' ArFragment
. Voici le code de 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; } }
Tout d'abord, nous désactivons la détection des avions. Ce faisant, nous supprimons l'icÎne de la main de l'écran qui apparaßt immédiatement aprÚs l'initialisation du fragment et informe l'utilisateur de la nécessité de déplacer son smartphone pour trouver l'avion. Nous n'en avons plus besoin, car nous ne trouvons pas d'avions aléatoires, mais une image concrÚte.
Ensuite, nous définissons le mode de mise à jour pour la session LATEST_CAMERA_IMAGE
. Cela garantit que nous serons informés des mises à jour de l'image chaque fois que le cadre de la caméra est mis à jour.
Configuration de la base de données d'images
Ajoutez l'image de référence sélectionnée (que vous souhaitez trouver dans le monde physique) dans le dossier des ressources (créez-la si elle ne l'est pas déjà ). Nous pouvons maintenant ajouter des images à notre base de données.
Nous créerons cette base de données dÚs que le fragment sera créé. Dans les journaux, nous affichons le résultat de cette opération:
if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) { Log.d("SetupAugImgDb", "Success"); } else { Log.e("SetupAugImgDb","Faliure setting up db"); }
Voici Ă quoi 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; } }
BientÎt, nous ajouterons la méthode MainActivity
Ă MainActivity
. Ajoutons CustomArFragment
Ă notre 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>
Ajout d'une image à la base de données
Nous allons maintenant configurer notre base de données d'images, trouver l'image de référence dans le monde réel et ajouter un modÚle 3D à l'image.
Commençons par mettre en place notre base de données. Créez une méthode setupAugmentedImagesDb
publique dans la classe 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; }
Nous avons également créé une méthode loadAugmentedImage
qui charge une image Ă partir d'un dossier de ressources et renvoie un bitmap.
Dans setupAugmentedImagesDb
nous initialisons d'abord notre base de données pour la session en cours, puis ajoutons l'image à cette base de données. Nous avons nommé notre image tigre . Ensuite, nous installons cette base de données dans la configuration et retournons true
, indiquant que l'image a été ajoutée avec succÚs.
Détection d'images de référence dans le monde réel
Nous allons maintenant commencer à découvrir nos images de référence dans le monde réel. Pour ce faire, nous allons créer un écouteur qui sera appelé à chaque mise à jour de la trame vidéo, et cette trame sera analysée pour la présence d'une image de référence.
Ajoutez cette ligne à la méthode onCreate()
dans MainActivity
:
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
Ajoutez maintenant la méthode 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; } } } }
Dans la premiĂšre ligne, nous obtenons le cadre lui-mĂȘme. Un cadre peut ĂȘtre imaginĂ© comme une capture d'Ă©cran rĂ©guliĂšre d'une vidĂ©o. Si vous connaissez le fonctionnement de la vidĂ©o, vous savez qu'il ne s'agit que d'une collection d'images qui se changent trĂšs rapidement, donnant l'impression de quelque chose qui bouge. Nous venons de prendre une de ces photos.
AprÚs avoir reçu le cadre, nous l'analysons pour la présence de notre image de référence dessus. Nous prenons une liste de tous les éléments suivis par ARCore à l'aide de frame.getUpdatedTrackables
. Ensuite, nous itérons dessus et vérifions si notre image de tigre est présente dans le cadre.
Si une correspondance est trouvée, nous prenons et plaçons simplement le modÚle 3D au-dessus de l'image détectée.
Remarque L'indicateur shouldAddModel
utilisé pour que nous ajoutions le modÚle 3D une seule fois.
Placer un modÚle 3D sur une image de référence
Maintenant que nous avons trouvé notre image de référence dans le monde réel, nous pouvons ajouter un modÚle 3D dessus. Ajoutez les addNodeToScene
placeObject
et addNodeToScene
:
placeObject
: cette méthode est utilisée pour construire un objet rendu en utilisant un Uri
donné. Une fois le rendu terminé, l'objet est transmis à la méthode addNodeToScene
, oĂč l'objet est attachĂ© au nĆud et ce nĆud est placĂ© sur la scĂšne.addNodeToScene
: cette mĂ©thode crĂ©e un nĆud Ă partir de l'ancre rĂ©sultante, crĂ©e un autre nĆud auquel se joint l'objet visualisĂ©, puis ajoute ce nĆud au nĆud d'ancrage et le place sur la scĂšne.
Voici Ă quoi ressemble 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(); } }
Exécutez maintenant votre application. Vous devriez voir l'écran comme indiqué ci-dessous. Déplacez le téléphone légÚrement au-dessus de l'objet de référence. Et dÚs que ARCore détecte l'image de référence dans le monde réel, il y ajoute votre modÚle 3D.

Lire aussi: Création de votre premiÚre application ARCore