Kuidas luua laiendatud piltide rakendust ARCore'iga

See artikkel postitati algselt siia.

Selles õpetuses saate teada, kuidas 3D-mudeleid reaalsesse maailma paigutada, määrates ankru tavalise tasapinna asemel konkreetseks stseeniks. Google'i ARCore võimaldab teil laiendada 2D-pilte, mida ARCore tunneb ära, et seejärel asetada 3D-mudelid nende kohale.

Pakute mõned võrdluspildid ja ARCore'i jälgimine määrab, kus need pildid keskkonnas füüsiliselt asuvad. Liitpilte kasutatakse juba laialdaselt, näiteks raamatutes, ajalehtedes, ajakirjades jne.

Kuid enne selle õppematerjali süvenemist peate selle eeltingimusena tutvuma järgmiste artiklitega:

  • Mis on Google'i ARCore?
  • Liitreaalsuse rakenduse loomine ARCore abil.

Kui olete nende kahega lõpetanud, saate põhiteadmised mõningatest ARCore ja Sceneform'i terminoloogiatest, näiteks Stseen, Ankur, Sõlm, TransformeeritavNood jne.

Mis on liitpildid?

Arendajate dokumentide kohaselt võimaldab ARCore'i laiendatud pilt teil luua AR-i rakendusi, mis saavad kasutaja keskkonnas reageerida 2D-piltidele, näiteks plakatitele või tootepakenditele. Esitate võrdluspiltide komplekti ja ARCore'i jälgimine annab teile teada, kus need pildid AR-seansil füüsiliselt asuvad, kui need kaameravaates tuvastatakse.

Põhimõtteliselt saate laiendatud piltide abil muuta lihtsa 2D-pildi liitpildiks, mida teie rakendus tunneb ära ja mida saab seejärel kasutada 3D-mudeli paigutamiseks selle kohale.

Kui võiksite kasutada laiendatud pilte

Siin on mõned piirangud, mida võiksite kaaluda enne laiendatud piltide kasutamist:

  • Teie juhtum ei tohi hõlmata rohkem kui 20 pildi korraga skannimist (kuna ARCore suudab jälgida ainult kuni 20 pilti korraga).
  • Füüsilise vastaspoole suurus reaalmaailmas peab olema suurem kui 15cm X 15cm ja tasane.
  • Te ei soovi liikuvaid objekte jälgida. ARCore ei saa liikuvaid pilte jälgida, ehkki see võib hakata jälitama, kui pilt peatub.
  • ARCore kasutab võrdluspildil funktsioonipunkte ja võib salvestada funktsioonipunktide teavet kuni 1000 pildi jaoks.

Hea võrdluspildi valimine

Siin on mõned näpunäited hea võrdluspildi valimiseks, et parandada ARCore'i tuvastatavust:

  • Liitpildid toetavad PNG-, JPEG- ja JPG-vorminguid.
  • Avastamine põhineb kõrge kontrastsusega punktidel ja seega tuvastatakse nii värvilised kui ka mustvalged pildid, sõltumata sellest, kas kasutatakse värvilist või mustvalget võrdluspilti.
  • Kujutise eraldusvõime peab olema vähemalt 300 X 300 pikslit.
  • Suure eraldusvõimega piltide kasutamine ei tähenda paremat jõudlust.
  • Vältida tuleb korduvate omadustega pilte, nagu mustrid ja täpid.
  • Kasutage arcoreimgi tööriista, et hinnata, kui hea teie võrdluspilt on. Soovitatav on vähemalt 75 punkti.

Kuidas kasutada arcoreimgi tööriista:

  • Laadige ARCore SDK for Android alla sellelt lingilt:
  • Ekstraktige ZIP-faili ZIP-sisu ükskõik kuhu, kuhu soovite.
  • Liikuge ekstraheeritud kausta ja minge tööriistadele -> arcoreimg -> windows (linux / macos, mida te kasutate)
  • Selles kohas avage käsuviip.
  • Sisestage see käsk:
arcoreimg.exe eval-img --input_image_path = dog.png

Asendage dog.png oma pildi täieliku rajaga.

Laiendatud piltide rakendusega alustamine

Nüüd, kui olete tutvunud ARCore ja Sceneformiga ning olete valinud hea võrdluspildi skooriga 75+, on aeg hakata rakendust kodeerima !!

Loo kohandatud fragment

Loome kohandatud fragmendi, mida oma tegevusele lisada. Vajame kohandatud fragmenti, kuna muudame vaikimisi kasutatava fragmendi mõnda omadust.

Looge klass nimega CustomArFragment ja laiendage seda ArFragmentist. Siin on CustomArFragment'i kood:

pakett 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;
avaliku klassi CustomArFragment laiendab ArFragmentit {
    @Ülesõit
    kaitstud Config getSessionConfiguration (seansi seanss) {
        getPlaneDiscoveryController (). setInstructionView (null);
        Config config = uus Config (seanss);
        config.setUpdateMode (Config.UpdateMode.LATEST_CAMERA_IMAGE);
        session.configure (config);
        getArSceneView (). setupSession (sessioon);
        tagasta konfiguratsioon;
    }
}

Esiteks seadsime lennuki avastamise juhise nulliks. Seda tehes lülitame välja käeikooni, mis ilmub vahetult pärast fragmendi lähtestamist, mis juhendab kasutajat oma telefoni liikuma. Me ei vaja seda enam, kuna me ei tuvasta juhuslikke lennukeid, vaid konkreetset pilti.

Järgmisena seadsime seansi värskendusrežiimi LATEST_CAMERA_IMAGE. See tagab, et teie värskenduskuulajale helistatakse alati, kui kaamera raami värskendatakse. See konfigureerib värskendusmeetodi käitumist.

Laiendatud piltide andmebaasi seadistamine

Lisage oma varade kausta valitud viitepilt (mida soovite füüsilises maailmas tuvastada). Kui teie varade kausta pole, looge see. Nüüd lisame oma andmebaasi laiendatud kujutised, mis siis reaalses maailmas tuvastatakse.

Seadistame selle andmebaasi kohe, kui fragment (stseen) on loodud. Seejärel kontrollime selle kõne õnnestumist ja ebaõnnestumist ning määrame vastavalt logi. Lisage oma kohandatud fragmendile järgmine kood:

if (((((MainActivity) getActivity ()). setupAugmentedImagesDb (config, session))) {
    Logi.d ("SetupAugImgDb", "Edu");
} veel {
    Log.e ("SetupAugImgDb", "Faliure setup db");
}

CustomArFragment näeks välja selline:

pakett 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;
avaliku klassi CustomArFragment laiendab ArFragmentit {
    @Ülesõit
    kaitstud Config getSessionConfiguration (seansi seanss) {
        getPlaneDiscoveryController (). setInstructionView (null);
        Config config = uus Config (seanss);
        config.setUpdateMode (Config.UpdateMode.LATEST_CAMERA_IMAGE);
        session.configure (config);
        getArSceneView (). setupSession (sessioon);
        if (((((MainActivity) getActivity ()). setupAugmentedImagesDb (config, session))) {
            Logi.d ("SetupAugImgDb", "Edu");
        } veel {
            Log.e ("SetupAugImgDb", "Faliure setup db");
        }
        tagasta konfiguratsioon;
    }
}

Peagi loome MainActivity-s meetodi setupAugmentedImagesDb. Lisage nüüd loodud CustomArFragment ja lisage see meie tegevus_main.xml, siin on teie tegevuse_main.xml kood:


    

Pange tähele, et määrasime selle fragmendi nime meie CustomArFragment'ile. See on vajalik tagamaks, et lisatud fragment on meie kohandatud fragment. See tagab, et lubade käitlemise ja seansi initsialiseerimise eest hoolitsetakse.

Kujutise lisamine laiendatud piltide andmebaasi

Siin seame üles oma piltide andmebaasi. Leidke võrdluspilt reaalses maailmas ja lisage vastavalt sellele 3D-mudel.

Alustame meie andmebaasi seadistamisega. Loo klassis MainActivity.java avaliku funktsiooni setupAugmentedImagesDb:

avalik boolean setupAugmentedImagesDb (konfigureerimine, seansi seanss) {
    AugmentedImageDatabase laiendatudImageDatabase;
    Bitmap bitmap = loadAugmentedImage ();
    if (bitmap == null) {
        tagastama vale;
    }
    augmentedImageDatabase = uus AugmentedImageDatabase (seanss);
    augmentedImageDatabase.addImage ("tiiger", bitmap);
    config.setAugmentedImageDatabase (augmentedImageDatabase);
    tagasi tõsi;
}
privaatne bitmap-laadimineAugmentedImage () {
proovige (InputStream on = getAssets (). avatud ("blanket.jpeg")) {
        tagastama BitmapFactory.decodeStream (on);
    } saagi (IOException e) {
        Log.e ("ImageLoad", "IO erand", e);
    }
    tagasi null;
}

Meil on ka loadAugmentedImage meetod, mis laadib pildi varade kaustast ja tagastab bitmap.

Seadistuses setupAugmentedImagesDb lähtestame kõigepealt selle seansi jaoks oma andmebaasi ja seejärel lisame sellesse andmebaasi pildi. Nimetame oma pilti “tiigriks”. Seejärel seadsime andmebaasi selle seansi konfiguratsiooni jaoks ja naastes true, mis näitab, et pilt on edukalt lisatud.

Võrdluspiltide tuvastamine reaalses maailmas

Nüüd hakkame tuvastama oma võrdluspilte reaalses maailmas. Selleks lisame oma stseeni kuulaja, kellele helistatakse iga kord, kui kaadrit luuakse, ja seda kaadrit analüüsitakse, et leida meie võrdluspilt.

Lisage see rida saidi MainActivity.java onCreate-meetodil:

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

Nüüd lisage MainActivity-le meetod onUpdateFrame:

@RequiresApi (api = Ehitamine.VERSION_CODES.N)
private void onUpdateFrame (FrameTime frameTime) {
    Raami raam = arFragment.getArSceneView (). GetArFrame ();
    Kogumik  augmentedImages = frame.getUpdatedTrackables (AugmentedImage.class);
    jaoks (AugmentedImage augmentedImage: augmentedImages) {
        if (augmentedImage.getTrackingState () == TrackingState.TRACKING) {
            if (augmentedImage.getName (). equals ("tiiger") && shouldAddModel) {
                placeObject (arFragment, augmentedImage.createAnchor (augmentedImage.getCenterPose ()), Uri.parse ("Mesh_BengalTiger.sfb"));
                shouldAddModel = vale;
            }
        }
    }
}

Esimeses reas saame kaadri sündmuskohalt. Raami saab kujutleda pildi keskel video keskel. Kui olete kursis, kuidas video töötab, võiksite teada, et tegemist on fotodega, mis seisavad üksteise järel tõesti kiiresti, jättes mulje filmilõigust. Kaevandame ühe neist piltidest.

Kui raam on olemas, analüüsime oma võrdluspilti. Koondame nimekirja kõigist üksustest, mida ARCore on jälginud, kasutades frame.getUpdatedTrackables. See on kõigi tuvastatud piltide kogum. Seejärel lükkame kollektsiooni ümber ja kontrollime, kas kaadris on meie pilt “tiiger”.

Kui leiame vaste, liigume edasi ja asetame tuvastatud pildi kohal 3D-mudeli.

Märkus. Olen lisanud, peaksAddModel tagama, et lisame mudeli ainult üks kord.

3D-mudeli asetamine referentspildi kohale

Nüüd, kui oleme oma pildi reaalses maailmas avastanud, võime hakata 3D-mudeleid selle peale lisama. Kopeerime oma eelmisest projektist placeObject ja addNodeToScene meetodid ning lisame need siia.

Ehkki olen juba varem selgitanud, mida need meetodid rida-realt võimaldavad, on siin ülevaade:

  • PlaceObject: Seda meetodit kasutatakse pakutavast Uri-st renderduse ehitamiseks. Kui renderdus on üles ehitatud, antakse see edasi meetodile addNodeToScene, kus renderdus kinnitatakse sõlme ja see sõlm paigutatakse sündmuskohale.
  • AddNodeToScene: See meetod loob vastuvõetud ankrust AnchorNode, loob uue sõlme, millele renderdus kinnitatakse, seejärel lisab selle sõlme AnchorNode ja lisab AnchorNode stseeni.

Siin on meie viimane MainActivity.java klass:

pakett com.ayusch.augmentedimages;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.RequiresApi;
impordi 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;
impordi com.google.ar.core.AugmentedImageDatabase;
import com.google.ar.core.Config;
import com.google.ar.core.Frame;
import com.google.ar.core.Session;
impordi com.google.ar.core.TrackingState;
impordi com.google.ar.sceneform.AnchorNode;
impordi 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.Kogumine;
avaliku klassi MainActivity laiendab AppCompatActivity {
    ArFragment arFragment;
    boolean shouldAddModel = true;
    @Ülesõit
    kaitstud tühine onCreate (Bundle savedInstanceState) {
        super.onCreate (SaveInstanceState);
        setContentView (R.layout.activity_main);
        arFragment = (CustomArFragment) getSupportFragmentManager () .fragmentById (R.id.sceneform_fragment);
        arFragment.getPlaneDiscoveryController (). hide ();
        arFragment.getArSceneView (). getScene (). addOnUpdateListener (see :: onUpdateFrame);
    }
    @RequiresApi (api = Ehitamine.VERSION_CODES.N)
    privaatne tühine kohtObjekt (ArFragment arFragment, Ankru ankur, Uri uri) {
        ModelRenderable.builder ()
                .setSource (arFragment.getContext (), uri)
                .build ()
                .thenAccept (modelRenderable -> addNodeToScene (arFragment, ankur, modelRenderable))
                .erandlikult (visatav -> {
                            Toast.makeText (arFragment.getContext (), "Error:" + throvable.getMessage (), Toast.LENGTH_LONG) .show ();
                            tagasi null;
                        }
                );
    }
    @RequiresApi (api = Ehitamine.VERSION_CODES.N)
    private void onUpdateFrame (FrameTime frameTime) {
        Raami raam = arFragment.getArSceneView (). GetArFrame ();
        Kogumik  augmentedImages = frame.getUpdatedTrackables (AugmentedImage.class);
        jaoks (AugmentedImage augmentedImage: augmentedImages) {
            if (augmentedImage.getTrackingState () == TrackingState.TRACKING) {
                if (augmentedImage.getName (). equals ("tiiger") && shouldAddModel) {
                    placeObject (arFragment, augmentedImage.createAnchor (augmentedImage.getCenterPose ()), Uri.parse ("Mesh_BengalTiger.sfb"));
                    shouldAddModel = vale;
                }
            }
        }
    }
    avalik boolean setupAugmentedImagesDb (konfigureerimine, seansi seanss) {
        AugmentedImageDatabase laiendatudImageDatabase;
        Bitmap bitmap = loadAugmentedImage ();
        if (bitmap == null) {
            tagastama vale;
        }
        augmentedImageDatabase = uus AugmentedImageDatabase (seanss);
        augmentedImageDatabase.addImage ("tiiger", bitmap);
        config.setAugmentedImageDatabase (augmentedImageDatabase);
        tagasi tõsi;
    }
    privaatne bitmap-laadimineAugmentedImage () {
        proovige (InputStream on = getAssets (). avatud ("blanket.jpeg")) {
            tagastama BitmapFactory.decodeStream (on);
        } saagi (IOException e) {
            Log.e ("ImageLoad", "IO erand", e);
        }
        tagasi null;
    }
    private void addNodeToScene (ArFragment arFragment, Ankru ankur, Renderdatav renderdatav) {
        AnchorNode anchorNode = uus AnchorNode (ankur);
        TransformableNode sõlm = uus TransformableNode (arFragment.getTransformationSystem ());
        node.setRenderable (rendering);
        node.setParent (anchorNode);
        arFragment.getArSceneView (). getScene (). addChild (anchorNode);
        sõlm.select ();
    }
}

Nüüd käivitage oma rakendus. Peaksite nägema ekraani, nagu allpool näidatud. Liikuge oma telefoni kohal natuke üle referentsobjekti. ARCore tuvastab funktsioonipunktid ja niipea, kui ta tuvastab võrdluspildi reaalses maailmas, lisab ta sellele teie 3D-mudeli.

[pealdise id = ”manus_1000” align = ”aligncenter” width = ”1280”]

Kasutasin viitena oma tekki

Sellega oleme loonud oma esimese laiendatud piltide rakenduse, kasutades Google'i ARCore ja Sceneform SDK !!

Kui soovite olla kursis kõigi uusimate artiklitega, tellige nädala uudiskiri, sisestades oma e-posti aadressi lehe paremas ülanurgas olevasse vormi.

Nagu see, mida sa lugesid? Ärge unustage jagada seda postitust Facebookis, Whatsappis ja LinkedInis.

Võite mind jälgida LinkedInis, Quoras, Twitteris ja Instagramis, kus vastan mobiiliarendusega seotud küsimustele, eriti Androidi ja Flutteri kohta.