Com es crea una aplicació d'imatges augmentades mitjançant ARCore

Aquest article es va publicar originalment aquí.

En aquest tutorial, aprendreu a col·locar els models 3D al món real configurant l’àncora com una escena específica en lloc d’un pla normal. ARCore de Google us permet ampliar imatges en 2D reconegudes per ARCore i després col·locar-hi models 3D.

Proporcioneu algunes imatges de referència i el seguiment ARCore determina on es troben físicament aquestes imatges a la zona. Les imatges augmentades ja s’utilitzen àmpliament en llibres, diaris, revistes, etc.

Tanmateix, abans d’aprofundir en aquest tutorial, assegureu-vos de llegir els articles següents com a requisit previ per a aquest tutorial:

  • Què és ARCore de Google?
  • Creació d’una aplicació de realitat augmentada amb ARCore.

Un cop hàgiu completat aquests dos passos, tindreu un coneixement bàsic de la terminologia a ARCore i Sceneform, com ara: B. Escena, ancoratge, node, node transformable, etc.

Què són les imatges augmentades?

Segons els documents del desenvolupador, podeu utilitzar Imatges Augmentades a ARCore per crear aplicacions de RA que puguin respondre a imatges en 2D, com ara pòsters o envasos de productes a l’entorn de l’usuari. Proporcionen una sèrie d’imatges de referència i el seguiment ARCore us indica on es troben aquestes imatges en una sessió de RA un cop reconegudes a la vista de la càmera.

Bàsicament, Augmented Images us permet convertir una imatge 2D simple en una imatge augmentada que la vostra aplicació pugui reconèixer i, després, col·locar-hi un model 3D.

Si voleu utilitzar imatges augmentades

A continuació, es detallen algunes limitacions abans d’utilitzar les imatges augmentades:

  • A la vostra aplicació, no es poden escanejar més de 20 imatges alhora (ja que ARCore només pot fer un seguiment de fins a 20 imatges simultàniament).
  • La mida de la contraparte física al món real ha de ser superior a 6 "x 6" i ha de ser plana.
  • No voleu fer un seguiment d'objectes en moviment. ARCore no pot fer un seguiment de les imatges en moviment, tot i que pot començar-ne el seguiment tan aviat com la imatge s'aturi.
  • ARCore utilitza punts de funció a la imatge de referència i pot emmagatzemar informació de punts de funció fins a 1.000 imatges.

Escollir una bona imatge de referència

Aquests són alguns consells per triar una bona imatge de referència per millorar la reconeixement amb ARCore:

  • Les imatges augmentades admeten els formats PNG, JPEG i JPG.
  • La detecció es basa en punts de contrast elevats, de manera que es detecten imatges en color i en blanc i negre independentment de si s’utilitza una imatge de referència en color o en blanc i negre.
  • La resolució de la imatge ha de ser com a mínim de 300 x 300 píxels.
  • L’ús d’imatges en alta resolució no augmenta el rendiment.
  • S'han d'evitar les imatges amb funcions repetitives com ara patrons i lunars.
  • Utilitzeu l'eina arcoreimg per avaluar la qualitat de la vostra imatge de referència. Es recomana una puntuació mínima de 75.

Per utilitzar l'eina arcoreimg:

  • Baixeu l'SDK ARCore per a Android des d'aquest enllaç:
  • Extraieu el contingut zip del fitxer zip en qualsevol moment.
  • Aneu a la carpeta extreta i aneu a eines -> arcoreimg -> windows (linux / macos el que feu servir)
  • Obriu el símbol del sistema en aquest moment.
  • Ara introduïu aquesta ordre:
arcoreimg.exe eval-img --input_image_path = dog.png

Substituïu dog.png pel camí complet cap a la vostra imatge.

Introducció a l'aplicació Augmented Images

Ara que ja us heu familiaritzat amb ARCore i Sceneform i heu triat una bona imatge de referència amb una puntuació superior a 75, és hora de començar a codificar l'aplicació.

Creeu un fragment personalitzat

Crearem un fragment personalitzat per afegir a la nostra activitat. Necessitem un fragment personalitzat, ja que canviarem algunes propietats del fragment estàndard.

Creeu una classe anomenada CustomArFragment i amplieu-la des d'ArFragment. Aquí teniu el codi per a CustomArFragment:

Paquet com.ayusch.augmentedimages;
importa android.util.Log;
importa com.google.ar.core.Config; importació com.google.ar.core.Session; importa com.google.ar.sceneform.ux.ArFragment;
classe pública CustomArFragment amplia ArFragment {
@Override protegit Config getSessionConfiguration (sessió de sessió) {getPlaneDiscoveryController (). setInstructionView (nul); Config config = nova configuració (sessió); config.setUpdateMode (Config.UpdateMode.LATEST_CAMERA_IMAGE); session.configure (config); getArSceneView (). setupSession (sessió);
retorn config; }
}

En primer lloc, establim la declaració de detecció de nivell a zero. D'aquesta manera, desactivem la icona de mà que apareix immediatament després d'inicialitzar el fragment i instruïm l'usuari que mogui el telèfon. Ja no el necessitem, ja que no reconeixem plans aleatoris, sinó una imatge específica.

A continuació, definim el mode d'actualització de la sessió a LATEST_CAMERA_IMAGE. D’aquesta manera, es garanteix que es crida l’oient d’actualitzacions cada vegada que s’actualitza el marc de la càmera. S'utilitza per configurar el comportament del mètode d'actualització.

Configuració de la base de dades d’imatges augmentades

Enganxeu la imatge de referència seleccionada (que voleu reconèixer al món físic) a la carpeta Actius. Si la vostra carpeta Actius no existeix, creeu-ne una. Ara afegirem imatges avançades a la nostra base de dades, que seran reconegudes al món real.

Aquesta base de dades es configura un cop creat el fragment (escena). A continuació, comprovem l’èxit i el fracàs d’aquesta trucada i ajustem el protocol en conseqüència. Afegiu el codi següent al vostre fragment personalitzat:

if (((((MainActivity) getActivity ()). setupAugmentedImagesDb (config, sessió))) {Log.d ("SetupAugImgDb", "Success"); } else {Log.e ("SetupAugImgDb", "Faliure setup db"); }

Així seria el CustomArFragment:

Paquet com.ayusch.augmentedimages;
importa android.util.Log;
importa com.google.ar.core.Config; importació com.google.ar.core.Session; importa com.google.ar.sceneform.ux.ArFragment;
classe pública CustomArFragment amplia ArFragment {
@Override protegit Config getSessionConfiguration (sessió de sessió) {getPlaneDiscoveryController (). setInstructionView (nul); Config config = nova configuració (sessió); config.setUpdateMode (Config.UpdateMode.LATEST_CAMERA_IMAGE); session.configure (config); getArSceneView (). setupSession (sessió);
if (((((MainActivity) getActivity ()). setupAugmentedImagesDb (config, sessió))) {Log.d ("SetupAugImgDb", "Success"); } else {Log.e ("SetupAugImgDb", "Faliure setup db"); }
retorn config; }
}

En breu crearem el mètode setupAugmentedImagesDb a MainActivity. Un cop hàgiu creat el CustomArFragment, afegiu-lo a la nostra activitat_main.xml. Aquí teniu el codi de la vostra activitat_main.xml:


    

Tingueu en compte que estem establint el nom d’aquest fragment a CustomArFragment. Això és necessari per garantir que el fragment afegit sigui el nostre fragment personalitzat. D’aquesta manera es garanteix que es realitzen la manipulació d’autoritzacions i les inicialitzacions de sessió.

Afegir una imatge a la base de dades d’imatges augmentades

Aquí configurem la nostra base de dades d'imatges. Cerqueu la imatge de referència al món real i, a continuació, afegiu un model 3D corresponent.

Comencem configurant la nostra base de dades. Creeu una funció pública setupAugmentedImagesDb a la classe MainActivity.java:

public boolean setupAugmentedImagesDb (configuració de configuració, sessió de sessió) {AugmentedImageDatabase augmentedImageDatabase; Mapa de bits mapa de bits = loadAugmentedImage (); if (mapa de bits == nul) {torna incorrectament; }
augmentedImageDatabase = nova AugmentedImageDatabase (sessió); augmentedImageDatabase.addImage ("Tigre", mapa de bits); config.setAugmentedImageDatabase (augmentedImageDatabase); tornar cert; }
mapa de bits privat loadAugmentedImage () {
try (InputStream is = getAssets (). open ("blanket.jpeg")) {return BitmapFactory.decodeStream (is); } catch (IOException e) {Log.e ("ImageLoad", "IOException", e); }
retorn nul; }

També tenim el mètode loadAugmentedImage que carrega la imatge de la carpeta Actius i retorna un mapa de bits.

A setupAugmentedImagesDb inicialitzem primer la nostra base de dades per a aquesta sessió i després afegim una imatge a aquesta base de dades. Anomenarem la nostra imatge "Tigre". A continuació, establim la base de dades per a aquesta configuració de sessió i retornem true per indicar que la imatge s'ha afegit correctament.

Reconèixer les imatges de referència del món real

Ara començarem a capturar les nostres imatges de referència al món real. Per fer-ho, afegim un oient a la nostra escena que es diu cada vegada que es crea un fotograma i aquest fotograma s’analitza per trobar la nostra imatge de referència.

Afegiu aquesta línia al mètode onCreate de MainActivity.java:

arFragment.getArSceneView (). getScene (). addOnUpdateListener (this :: onUpdateFrame);

Ara afegiu el mètode onUpdateFrame a MainActivity:

@RequiresApi (api = Build.VERSION_CODES.N) private void onUpdateFrame (FrameTime frameTime) {Frame frame = arFragment.getArSceneView (). GetArFrame ();
col · lecció augmentedImages = frame.getUpdatedTrackables (AugmentedImage.class); per a (AugmentedImage augmentedImage: augmentedImages) {if (augmentedImage.getTrackingState () == TrackingState.TRACKING) {if (augmentedImage.getName (). equals ("tigre") && shouldAddModel) {placeObject (arFragment, augmentedImage.createAnage (augmentedImage.createAnage) getCenterPose ()), Uri.parse ("Mesh_BengalTiger.sfb")); shouldAddModel = false; }}}}

A la primera línia obtenim el marc de l’escena. Es pot veure un fotograma com una instantània al centre d’un vídeo. Si coneixeu el funcionament del vídeo, potser sabreu que es tracta d’una sèrie d’imatges fixes que es giren molt ràpidament, donant la impressió d’una pel·lícula. Extraiem una d’aquestes imatges.

Tan bon punt tenim el marc, l’analitzem per obtenir la nostra imatge de referència. Extraiem una llista de tots els elements dels quals ARCore va fer el seguiment amb frame.getUpdatedTrackables. Es tracta d’una col·lecció de totes les imatges reconegudes. A continuació, passem per la col·lecció i comprovem si la nostra imatge "Tigre" es troba al marc.

Quan trobem una coincidència, col·loquem un model 3D sobre la imatge reconeguda.

Nota: He afegit shouldAddModel per assegurar-nos que només afegim el model una vegada.

Col·loqueu un model 3D sobre la imatge de referència

Després de veure la nostra imatge al món real, podem començar a afegir-hi models 3D. Copiem els mètodes placeObject i addNodeToScene del nostre projecte anterior i els afegim aquí.

Tot i que he explicat línia per línia què fan aquests mètodes, aquí teniu una visió general:

  • PlaceObject: aquest mètode crea un renderitzable a partir de la Uri proporcionada. Un cop creat el renderitzable, es passa al mètode addNodeToScene, que afegeix el renderizable a un node i afegeix aquest node a l'escena.
  • AddNodeToScene: aquest mètode crea un AnchorNode a partir de l'ancoratge rebut, crea un altre node al qual s'afegeix la representació, afegeix aquest node a AnchorNode i afegeix l'AnchorNode a l'escena.

Aquí teniu la nostra última classe MainActivity.java:

Paquet com.ayusch.augmentedimages;
importa android.graphics.Bitmap; importar android.graphics.BitmapFactory; Importa android.net.Uri; importa android.os.Build; importa android.support.annotation.RequiresApi; importa android.support.v7.app.AppCompatActivity; importar android.os.Bundle; importa android.util.Log; importa android.widget.Toast;
import com.google.ar.core.Anchor; import com.google.ar.core.AugmentedImage; import com.google.ar.core.AugmentedImageDatabase; importa com.google.ar.core.Config; importa com.google.ar.core.Frame; importa com.google.ar.core.Session; importa com.google.ar.core.TrackingState; import com.google.ar.sceneform.AnchorNode; importa com.google.ar.sceneform.FrameTime; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.rendering.Renderable; importa com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode;
importació java.io.IOException; importa java.io.InputStream; importa java.util.Collection;
classe pública MainActivity amplia AppCompatActivity {ArFragment arFragment; booleà 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)). excepcionalment (throw -> {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 ();
col · lecció augmentedImages = frame.getUpdatedTrackables (AugmentedImage.class); for (AugmentedImage augmentedImage: augmentedImages) {if (augmentedImage.getTrackingState () == TrackingState.TRACKING) {if (augmentedImage.getName (). equals ("tigre") && shouldAddModel) {placeObject (arFragment, augmentedImage.createAnage (augmentedImage.createAnage) getCenterPose ()), Uri.parse ("Mesh_BengalTiger.sfb")); shouldAddModel = false; }}}}
public boolean setupAugmentedImagesDb (configuració de configuració, sessió de sessió) {AugmentedImageDatabase augmentedImageDatabase; Mapa de bits mapa de bits = loadAugmentedImage (); if (mapa de bits == nul) {torna incorrectament; }
augmentedImageDatabase = nova AugmentedImageDatabase (sessió); augmentedImageDatabase.addImage ("Tigre", mapa de bits); config.setAugmentedImageDatabase (augmentedImageDatabase); tornar cert; }
private Bitmap loadAugmentedImage () {try (InputStream is = getAssets (). open ("blanket.jpeg")) {return BitmapFactory.decodeStream (is); } catch (IOException e) {Log.e ("ImageLoad", "IO Exception", e); }
retorn nul; }
private void addNodeToScene (ArFragment arFragment, Anchor anchor, renderizable renderable) {AnchorNode anchorNode = nou AnchorNode (ancoratge); Node TransformableNode = nou TransformableNode (arFragment.getTransformationSystem ()); node.setRenderable (renderable); node.setParent (anchorNode); arFragment.getArSceneView (). getScene (). addChild (anchorNode); node.select (); }
}

Ara executeu l'aplicació. Hauríeu de veure una pantalla com la que es mostra a continuació. Mou una mica sobre l'objecte de referència. ARCore reconeix els punts de les funcions i afegeix el vostre model 3D tan aviat com reconegui la imatge de referència al món real.

[caption id = "attachment_1000" align = "aligncenter" width = "1280"]

Vaig utilitzar la manta com a referència

Ara hem creat la nostra primera aplicació Augmented Images amb ARCore de Google i Sceneform SDK.

Si voleu estar al dia dels darrers articles, subscriviu-vos al butlletí setmanal introduint la vostra adreça de correu electrònic al formulari situat a la part superior dreta d’aquesta pàgina.

T'agrada el que llegeixes? No oblideu compartir aquesta publicació a Facebook, WhatsApp i LinkedIn.

Podeu seguir-me a LinkedIn, Quora, Twitter i Instagram, on responc preguntes sobre el desenvolupament de mòbils, especialment Android i Flutter.