Search code examples
javaandroidaugmented-realityarcore

How to superimpose 2d image in ARCore?


How to superimpose 2d image in ARCore after image gets recognized in Android Studio?

Any help will be appreciated.


Solution

  • According to the developer docs,

    Augmented Images in ARCore let you build AR apps that can respond to 2D images, such as posters or product packaging, in the user’s environment. You provide a set of reference images, and ARCore tracking tells you where those images are physically located in an AR session, once they are detected in the camera view.

    Here's what you should have in MainActivity.java class:

    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();
        }
    }
    

    Hope this helps.