Java opencv3d计算姿态_我怎样才能估计与3d到2d点对应的相机姿态(使用opencv)

你好,我的目标是开发头部跟踪功能,用于飞机(模拟器)驾驶舱,以便提供AR支持民用飞行员降落并在恶劣的视觉条件下飞行。我怎样才能估计与3d到2d点对应的相机姿态(使用opencv)

我的方法是检测其中我知道3D坐标的特征点(在黑暗模拟器LED中),并计算估计的(头戴式相机)姿态[R | t](旋转和平移相连)。

我有问题是估计姿态似乎总是错的,我的3D点(这也是我用来估计姿势)的投影不与2D图像点重叠(或不可见)。

我的问题是:

我怎么能估计相机姿态与一组给定的2D到3D的点对应的。

为什么它不起作用我怎么尝试它,哪里可能是错误的来源?

为了得到在真实生活环境中工作的理论解决方案,测量(3D和2D点以及相机矩阵)必须有多精确?

理论上这种方法对于共面点(x,y轴是否改变)有效吗?

我使用的硬件是爱普生BT-200。

在飞机中,我定义了一个固定的坐标系,我期望我的程序能够进行相对平移和旋转。程序检测(独特)LED的图像坐标并将它们与其对应的3D坐标进行匹配。用我使用open-cv示例android代码(https://github.com/Itseez/opencv/tree/master/samples/android/camera-calibration)获得的相机矩阵,我尝试使用solvePnP估计姿态。

我的相机矩阵和失真稍有变化。以下是我从程序中收到的一些值。我确信我打印出来的圆形图案的圆距与源代码中记载的相同(以米为单位测量)。

下面是一些例子以及我如何创建它的OpenCV Mat。

// protected final double[] DISTORTION_MATRIX_VALUES = new double[]{

// /*This matrix should have 5 values*/

// 0.04569467373955304,

// 0.1402980385369059,

// 0,

// 0,

// -0.2982135315849994

// };

// protected final double[] DISTORTION_MATRIX_VALUES = new double[]{

// /*This matrix should have 5 values*/

// 0.08245931646421553,

// -0.9893762277047577,

// 0,

// 0,

// 3.23553287438898

// };

// protected final double[] DISTORTION_MATRIX_VALUES = new double[]{

// /*This matrix should have 5 values*/

// 0.07444480392067945,

// -0.7817175834131075,

// 0,

// 0,

// 2.65433773093283

// };

protected final double[] DISTORTION_MATRIX_VALUES = new double[]{

/*This matrix should have 5 values*/

0.08909941096327206,

-0.9537960457721699,

0,

0,

3.449728790843752

};

protected final double[][] CAMERA_MATRIX_VALUES = new double[][]{

/*This matrix should have 3x3 values*/

// {748.6595405553738, 0, 319.5},

// {0, 748.6595405553738, 239.5},

// {0, 0, 1}

// {698.1744297982436, 0, 320},

// {0, 698.1744297982436, 240},

// {0, 0, 1}

// {707.1226937511951, 0, 319.5},

// {0, 707.1226937511951, 239.5},

// {0, 0, 1}

{702.1458656346429, 0, 319.5},

{0, 702.1458656346429, 239.5},

{0, 0, 1}

};

private void initDestortionMatrix(){

distortionMatrix = new MatOfDouble();

distortionMatrix.fromArray(DISTORTION_MATRIX_VALUES);

}

private void initCameraMatrix(){

cameraMatrix = new Mat(new Size(3,3), CvType.CV_64F);

for(int i=0;i

cameraMatrix.put(i, 0, CAMERA_MATRIX_VALUES[i]);

}

}

为了估计相机姿势我使用solvePnP(和solvePnPRansac)在几个位置(1,2,3,4)描述。 solvePnP的结果I用作投影的输入(Calib3d.projectPoints)。 concatinated结果的倒数[R | t]我用作估计的姿势。

因为我在生产环境中的成绩太差,我创建了一个测试环境。在这种环境下,我放置了相机(这是因为它的3D形状(它是一个玻璃杯)在桌子边缘稍微向下旋转,这个边缘我用作世界坐标系的纵坐标。我搜索了open-cv坐标系如何定位并找到不同的答案(一个在stackoverflow上,另一个在官方的youtube上讨论opencv)。无论如何,我测试了如果我通过在图像上投影3D点(在该坐标系中描述)获得坐标系,并检查给定的世界形状是否保持恒定。

所以我用z向前走,y向下,x向右走。

为了更接近我的解决方案,我估计了我的测试环境中的姿势。平移矢量输出和欧拉角度输出指的是[R | t]的倒数。因为我使用open-cv坐标系统以对数(我假设指的是飞机坐标系)方程式计算它,所以euler天使可能无法正确显示(它们可能会交换或错误,如果我们考虑顺序)。 (计算发生在我将附上的Pose类中)。但无论如何,即使翻译矢量(相反)出现是错误的(在我的简单测试中)。

在与该图像一个测试我有一个辊(这可能是间距飞机坐标)的30°和50 厘米平移向上。这个出现更合理。所以我假设因为我的观点是共面的,我可能会得到不明确的结果。所以我意识到另一个测试的Z轴改变了一点。但是通过这个测试,即使投影失败了。

对于solvePnP,我尝试了所有不同的求解算法标志和ransac algorithm的不同参数。

也许你能以某种方式帮助我找到我的错误,或向我展示一条解决我最初问题的好路径。我将附上我的调试源码以及许多println语句和调试图像。 此代码包含我的测量点。

感谢您的帮助提前。

1.png

编辑2015年3月22日: 最后,我有能够发现我犯的错误。

我在for循环修改的垫目标,因为OpenCV的作品很多 与呼叫参考,而我不够细心这里。所以用于再投影的tvec和rvec是不正确的。

我在测试环境中的一个要点(在图像 坐标中)由于轴方向的混淆而被标记为错误。

所以我的方法一般是正确的。我在测试数据集中至少没有收到有效的重新投影。不幸的是,OpenCV PnP算法:“ITERATIVE,P3P,EPNP”返回了各种结果,即使使用非常不准确但接近的内部猜测,结果也只是有时是正确的。 P3P algorithm应该提供3种解决方案,但OpenCV只提供一种解决方案。 EPNP应该返回良好的结果,但与EPNP OpenCV返回最差的结果,从我的人的obersation评估。

现在的问题是,如何过滤不准确的值或确保OpenCV函数返回有效的值。 (也许我会修改本机代码以接收3种PnP解决方案)。

的compressed images here(37MB),做节目我目前的结果(迭代的PnP-解算器),以零旋转和75厘米向上的内在猜测。打印输出的x轴向前,y轴向左和z向下,以及相对应的滚动,俯仰和偏航角。

+0

我现在发现,根据y坐标,我的图像点的顺序是错误的。 (我在图像坐标中有一个向上的y轴)。我的价值观变得更接近但仍然不够好。 –

2015-03-17 13:42:42

+1

我现在发现论文和EPNP可用于共面点: P3P:http://www.mmrc.iss.ac.cn/~xgao/paper/ieee.pdf EPNP:http:// cvlabwww .epfl.ch /〜lepetit/papers/lepetit_ijcv08.pdf –

2015-03-17 16:21:23

+0

我将校准示例中的平方尺寸参数从米改为了厘米,但收到了几乎相等的矩阵! –

2015-03-17 17:05:40

你可能感兴趣的:(Java,opencv3d计算姿态)