How to place a 3d object over a QR code after scanning thee QR code in ar scenefrom

42 Views Asked by At

I have been trying to scan a QR code for a project. The Project is simple we have a QR code with some unique data in it like its location (eg:- 1st exit, front entrence1, etc) when a person scans the QR code an object is placed over the QR code for localization, and based on the QR code data, and many objects checkpoints are placed automatically relative to the object over the QR code through which the app shows the route kind of an ar indoor navigation system but the problem I'm facing is that I don't know how to use the latest version of arcore which uses openGL so I used the last latest sceneform which is way easy and there are tutorials on it but the problem is I don't have any idea how to scan the QR code using sceneform and then place an anchor over the QR code and then place an anchor over it so that I can place the object.

Is there any better way for localization because I'm using Firebase to store the relative location? is there any better way so then even if the camera loses vision for some time the points should automatically come to their original position.

I'm using this version of sceneform my Gorisse thomas:- implementation "com.gorisse.thomas.sceneform:sceneform:1.23.0"

and also I want the code in Java and not in Kotlin

I have also tried Google's MLKit but it also seems to not work I tried every method and also tried AI like chatGPT and Black Box but none of them could provide me a working code even after some modifications it still didn't work

This is the Java code I tried till now and I also tried many modifications but it doesn't seem to work

import static androidx.constraintlayout.helper.widget.MotionEffect.TAG;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.Image;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.ar.core.Anchor;
import com.google.ar.core.ArImage;
import com.google.ar.core.HitResult;
import com.google.ar.core.Plane;
import com.google.ar.core.exceptions.NotYetAvailableException;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.ArSceneView;
import com.google.ar.sceneform.math.Vector3;
import com.google.ar.sceneform.rendering.Color;
import com.google.ar.sceneform.rendering.MaterialFactory;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.rendering.ShapeFactory;
import com.google.ar.sceneform.ux.BaseArFragment;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.ar.core.Camera;
import com.google.ar.core.Frame;
import com.google.ar.core.TrackingState;
import com.google.ar.sceneform.ux.ArFragment;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    private ArFragment arFragment;
    BarcodeScanner barcodeScanner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize the AR Fragment
        arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);

        arFragment.setOnTapArPlaneListener(new BaseArFragment.OnTapArPlaneListener() {
            @Override
            public void onTapPlane(HitResult hitResult, Plane plane, MotionEvent motionEvent) {
                planeCube(hitResult.createAnchor());
            }
        });
    }

    private void planeCube(Anchor anchor) {
        MaterialFactory
                .makeOpaqueWithColor(this, new Color(android.graphics.Color.BLUE))
                .thenAccept(material -> {
                    ModelRenderable modelRenderable = ShapeFactory.makeCube(new Vector3(0.1f,0.1f,0.1f), new Vector3(0f,0.1f,0),material);

                    try {
                        planeModel(modelRenderable, anchor);
                    } catch (NotYetAvailableException e) {
                        e.printStackTrace();
                    }
                });
    }

    private void planeModel(ModelRenderable modelRenderable, Anchor anchor) throws NotYetAvailableException {
        AnchorNode anchorNode = new AnchorNode(anchor);
        anchorNode.setRenderable(modelRenderable);
        //arFragment.getArSceneView().getScene().addChild(anchorNode);
        Image camera = Objects.requireNonNull(arFragment.getArSceneView().getArFrame()).acquireCameraImage();
        InputImage inputImage = InputImage.fromMediaImage(camera, /* image rotation */ 0);
        //Bitmap bit = convertFrameToBitmap(camera);
        processImage(inputImage);
    }

    private Bitmap convertFrameToBitmap(Image image) {
        if (image != null) {
            int width = image.getWidth();
            int height = image.getHeight();
            Log.d(TAG, "convertFrameToBitmap: ");

            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            bitmap.copyPixelsFromBuffer(buffer);

            image.close(); // Close the ArImage to release resources
            return bitmap;
        }
        return null;
    }

    private void processImage(InputImage image) {
        Log.d(TAG, "processImage: "+image);
        // Detect QR codes in the image.
        barcodeScanner.process(image)
                .addOnSuccessListener(barcodes -> {
                    for (Barcode barcode : barcodes) {
                        // Retrieve and process detected QR codes.
                        String qrCodeData = barcode.getRawValue();
                        Log.d("QRCode", "QR Code detected: " + qrCodeData);

                        // Place your AR object or show a toast message here.
                    }
                })
                .addOnFailureListener(e -> Log.e("QRCode", "Error detecting QR code: " + e.getMessage()));
    }

}

This is my XML code:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/arFragment"
        android:name="com.google.ar.sceneform.ux.ArFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Can anyone provide me with some ideas or code to make this work? and checkpoints are placed based on the position of the QR code

Please anyone help me out your work will be greatly appreciated! Have a Good day

Thank you

0

There are 0 best solutions below