ARCore setLocalPosition и оценка ArucoPoseSingleMarkers на Android с Opencv - PullRequest
0 голосов
/ 13 января 2020

Я хочу использовать маркер Aruco для определения местоположения Якоря объекта в Arcore в Android, поскольку обнаружение плоскости Arcore примерно неустойчиво.

Однако я не знаю, как преобразовать позиция маркера Aruco, обнаруженная opencv на основе результатов эстимейла оценки PoseSingleMarkers ().

Не могли бы вы мне ответить, чтобы исправить код в [Как выполнить следующий код] или дать некоторую информацию о преобразовании из от Aruco до ARCore?

- Настройка разработки:

Модуль Opencv:

Добавлено ниже строки в сборке. gradle (Модуль)

реализация 'com.quickbirdstud ios: opencv: 3.4.4-contrib'

Исходный код формы:

Пример проекта hellosceneform в Sceneform SDK 1.14.0

Результат:

После выполнения следующего кода 3D-модель Andy может быть показана и перемещена маркером Aruco. Но Энди не находится в маркере Аруко.

enter image description here

Youtube:

https://www.youtube.com/watch?v=WAW6JgH52UA

Github:

https://github.com/qaplqq/hellosceneformaruco

- Код:

Befor OnCreate Event:
private Node node=new Node();
private CameraBridgeViewBase javaCameraView;
Mat cameraMatrix =  new Mat(3,3,CvType.CV_32FC1);
MatOfDouble distorsionMatrix= new MatOfDouble();

BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            super.onManagerConnected(status);
            switch (status) {
                case BaseLoaderCallback.SUCCESS: {
                    javaCameraView.enableView();
                    break;
                }
                default: {
                    super.onManagerConnected(status);
                    break;
                }
            }
        }
    };

    static {
        if (OpenCVLoader.initDebug()) {
            Log.i(TAG, "opencv loaded");
        } else {
            Log.i(TAG, "opencv not loaded");
        }
    }

In OnCreate Event:

// disable plane detect
      arFragment.getPlaneDiscoveryController().hide();
      arFragment.getPlaneDiscoveryController().setInstructionView(null);
      arFragment.getArSceneView().getPlaneRenderer().setEnabled(false);

        cameraMatrix.put(0,0, 469.7718, 0, 259.0107,
                0, 469.5324, 251.2255,
                0, 0, 1.0000);

        double[] distArray =  { -0.1007,
                0.2118,
                0,
                0,
                -0.6476};
        distorsionMatrix.fromArray(distArray);


 ModelRenderable.builder()
        .setSource(this, R.raw.andy)
        .build()
        .thenAccept(renderable -> {
            andyRenderable = renderable;

            Scene sce = arFragment.getArSceneView().getScene();

            if(andyRenderable!= null){
                node.setParent(sce);
                node.setLocalPosition(new Vector3(0f, -2f, -7f));
                node.setLocalScale(new Vector3(3f, 3f, 3f));

                node.setRenderable(andyRenderable);

                sce.addChild(node);

            }
        })
        .exceptionally(
            throwable -> {
              Toast toast =
                  Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
              toast.setGravity(Gravity.CENTER, 0, 0);
              toast.show();
              return null;
            });

 arFragment.getArSceneView().getScene().addOnUpdateListener(frameTime -> {
            arFragment.onUpdate(frameTime);
            onUpdate();
        });
// end of  OnCreate Event

private void onUpdate() {

        Frame frame = arFragment.getArSceneView().getArFrame();
        if (frame == null) {
            return;
        }

        try (Image image = frame.acquireCameraImage()) {
            if (image.getFormat() != ImageFormat.YUV_420_888) {
                throw new IllegalArgumentException(
                        "Expected image in YUV_420_888 format, got format " + image.getFormat());
            }

            Mat mat1 = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC1);

            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            mat1.put(0, 0, bytes);



  Dictionary dictionary =  Aruco.getPredefinedDictionary(Aruco.DICT_4X4_50);
            Mat ids = new Mat();

            List<Mat> corners = new ArrayList<>();

            Aruco.detectMarkers(mat1, dictionary, corners, ids);

            if (corners.size()>0) {

                Mat rvecs = new Mat();
                Mat tvecs = new Mat();

                Aruco.estimatePoseSingleMarkers(corners, 100f, cameraMatrix, distorsionMatrix, rvecs, tvecs);

                double[] mvalr1 = rvecs.row(0).get(0, 0);
                double[] mvalt1 = tvecs.row(0).get(0, 0);

                String strl1 = String.format("%.1f",mvalt1[0]) + "," + String.format("%.1f",mvalt1[1]) ;

                float x1 = (float) mvalt1[0];
                float y1 = (float) mvalt1[1];
                float z1 = (float) mvalt1[2];

                Log.d(TAG, "Aruco: "+strl1 +":"+x1+","+y1+","+z1 );

               // How to How to transform positions to x1, y1, z1 in  arcore's coordination?

                node.setLocalPosition(new Vector3(x1/10, y1/10, -7f));

// I fix z in -7f, since it is an easy way to find Andy in testing 

...