为什么在检测到的 ArUco 标记上不能正确渲染 3D 模型?

问题描述

我和我的队友正在做一个项目,我们使用 OpenCV 检测 ArUco 标记并使用 Rajawali(OpenGL ES 包装库,在 github 上)在检测到的标记上渲染 3D 对象。 我们知道我们的检测是正确的,因为我们使用 drawAxis 方法测试它并且它非常稳定和准确。所以这应该排除校准和检测错误。 这是在我的笔记本电脑上的标记上绘制的轴的外观。这不是视频,但相信我,它在我尝试过的大多数距离/角度配置中都是一致的,所以我认为它非常好。

enter image description here

这除了渲染方法外什么也没有留下,它会产生非常错误的结果。 一旦我们开始尝试在标记上渲染对象:

  1. 方向被扼杀了。模型相对于标记很少正确定向。感觉它几乎没有旋转,只是漂浮在屏幕上。
  2. 翻译也被扼杀了。模型永远不会“粘”在标记上,而是几乎总是随着相机的中心移动(好像它被锁定到相机,而不是标记)。
  3. 模型轻微抖动,不稳定。完全不像轴。即使我拿着相机完全静止。 3 是一个我们可能可以忍受的问题,但 1 和 2 太多了。 这是呈现对象的方法,它是用 Java 编写的,但我认为非 Java 用户也可以使用它。 这是检测标记的方式(rvec 和 tvec 值):
    /**
     * This method takes a gray frame,detects the markers
     * and stores their corners,rvecs,tvecs and ids,* then updates the detectedMarkers list with the new markers detected.
     * @param frameGray
     */
    public void markerDetection(Mat frameGray)
    {
        ids = new Mat();
        corners = new ArrayList<>();
        Aruco.detectMarkers(frameGray,markerDictionary,corners,ids);

        List<MarkerData> newDetectedMarkers = new ArrayList<>();

        if(ids.size().height > 0)
        {
            rvecs = new Mat();
            tvecs = new Mat();
            Aruco.estimatePoseSingleMarkers(corners,markerLength,cameraMatrix,distortionCoef,tvecs);

            for(int i=0; i<ids.size().height; i++)
            {
                double[] rvecArray = new double[]{
                        rvecs.get(i,0)[0],rvecs.get(i,0)[1],0)[2]};
                double[] tvecArray = new double[]{
                        tvecs.get(i,tvecs.get(i,0)[2]};

                MarkerData newMarker = new MarkerData(rvecArray,tvecArray,corners.get(i),(int)ids.get(i,0)[0]);
                newDetectedMarkers.add(newMarker);
            }
        }

        updateDetectedMarkers(newDetectedMarkers);
    }

渲染是这样完成的:

    @Override
    protected void onRender(long elapsedRealtime,double deltaTime) {
        super.onRender(elapsedRealtime,deltaTime);
        getCurrentScene().clearChildren();
        List<MarkerData> markerData = markerDetector.getDetectedMarkers();
        for (MarkerData marker : markerData) {
            try {
                int id = R.raw.monkey;
                LoaderOBJ parser = new LoaderOBJ(mContext.getResources(),mTextureManager,id);
                parser.parse();

                Object3D object = parser.getParsedobject();
                object.setMaterial(defaultMaterial);
                object.setScale(0.3);

                Mat rvec = marker.getRvec(); // 3x1 Mat
                Mat tvec = marker.getTvec(); // 3x1 Mat

                object.setRotation(new Vector3(rvec.get(0,rvec.get(1,rvec.get(2,0)[0]));
                object.setPosition(new Vector3(tvec.get(0,tvec.get(1,tvec.get(2,0)[0]));

                getCurrentScene().addChild(object);
            } catch (ParsingException e) {
                e.printstacktrace();
            }
        }
    }

markerData 是一个 MarkerData 对象列表,其中包含每个检测到的标记rvectveccornersid。 object 是解析后的 3D 对象,在本例中它是 Suzanne 猴子对象。 我们获取与当前标记关联的 rvec 和 tvec,并将它们存储在 rvectvec 中。 我们使用它们来设置旋转和设置对象的位置,剩下的就交给 rajawali 了。 我确信我们在这里和那里都缺少一些线性代数的魔力,但我们在那个领域并不是很精通。我们缺少什么?我们怎样才能做到这一点?帮助将不胜感激。 这是我的猜测,我希望这是一个很好的猜测。无论如何,任何人都可以提供帮助。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)