如何在emgu CV中进行相机校准后访问旋转和平移向量? [英] How do I access the rotation and translation vectors after camera calibration in emgu CV?

查看:2256
本文介绍了如何在emgu CV中进行相机校准后访问旋转和平移向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相机校准的目标是找到内在和外在参数:


  1. 内在的是那些描述相机本身(焦点
    长度,失真等)我得到的值,没有问题。

  2. 外部参数基本上是相机的位置。当我尝试访问那些我获得 AccessViolationException

执行此类校准是


  1. 拍摄已知角点的校准目标图片

  2. 图像中的角点

  3. 从3D和2D点之间的对应中找到将一个变换到另一个的矩阵

  4. 和外部参数。

调用校准函数如下所示:

  Mat [] rotationVectors = new Mat [1]; 
Mat [] translVectors = new Mat [1];

double error = CvInvoke.CalibrateCamera(realCorners,
detectedCorners,
calibrationImages [0] .Image.Size,
cameraMatrix,
distortionCoefficients,
0,
new MCvTermCriteria(30,0.1),
out rotationVectors,
out translationVectors);

Console.WriteLine(rotationVectors [0] .Size); // AccessViolationException




  • 我在这里只使用一个图片,当使用更多的图像时,同样的问题(30)不同的校准图像将产生不同的结果翻译 - / rotationVector

  • 检测点并将其绘制到原始图像中,得到reasonabel结果。

  • 可以访问 cameraMatrix distortionCoefficients ,并包含值。 (我试图只发布代码的相关部分)

  • 我使用emgu版本3.0.0.2157



为什么在 rotationVectors 上获得 AccessViolationException c



我放置了一个断点,发现内部 Data 属性 null 。查看VS调试程序的屏幕截图:



< img src =https://i.stack.imgur.com/e6Tvf.pngalt =enter image description here>



这解释为什么我不能访问它。

解决方案 div>

这是因为EmguCV中的错误。您正在呼叫

  public static double CalibrateCamera(
MCvPoint3D32f [] [] objectPoints,
PointF [] [] imagePoints,
SizeSize,
IInputOutputArray cameraMatrix,
IInputOutputArray distortionCoeffs,
CvEnum.CalibType calibrationType,
MCvTermCriteria termCriteria,
out Mat [] rotationVectors ,
out Mat [] translationVectors)

p>

  public static double CalibrateCamera(
IInputArray objectPoints,
IInputArray imagePoints,
Size imageSize,
IInputOutputArray cameraMatrix,
IInputOutputArray distortionCoeffs,
IOutputArray rotationVectors,
IOutputArray translationVectors,
CvEnum.CalibType flags,
MCvTermCriteria termCriteria)

IOutputArray rotationVectors 应复制到 Mat [] rotationVectors 。翻译中的同样的事情。问题出在循环。



  for(int i = 0; i< ; imageCount; i ++)
{
rotationVectors [i] = new Mat();
使用(Mat matR = rotationVectors [i])// < - bug
matR.CopyTo(rotationVectors [i]);
translationVectors [i] = new Mat();
using(Mat matT = translationVectors [i])//< - bug
matT.CopyTo(translationVectors [i]);
}

,应该有

  for(int i = 0; i  {
rotationVectors [i] = new Mat
using(Mat matR = rVecs [i])
matR.CopyTo(rotationVectors [i]);
translationVectors [i] = new Mat();
using(Mat matT = tVecs [i])
matT.CopyTo(translationVectors [i]);
}



最后,要获取旋转和翻译值,您可以使用 DataPointer

  var rotation = new Matrix< float>(rotationVectors [0] rotationVectors [0] .Cols,rotationVectors [0] .DataPointer); 


The goal of a camera calibration is to find the intrinsic and extrinsic parameters:

  1. The intrinsic ones are those that describe the camera itself (focal length, distortion, etc.) I get values for those, no problem.
  2. The extrinsic parameters are basically the position of the camera. When I try to access those I get an AccessViolationException.

One way to perform such calibration is to

  1. take an image of a calibration target with known corners
  2. find those corners in the image
  3. from the correspondence between 3D and 2D points, find the matrix that transforms one into the other
  4. that matrix consists of the intrinsic and extrinsic parameters.

The call to the calibration function looks like this:

Mat[] rotationVectors = new Mat[1];
Mat[] translationVectors = new Mat[1];

double error = CvInvoke.CalibrateCamera(realCorners,
                                        detectedCorners,
                                        calibrationImages[0].Image.Size,
                                        cameraMatrix,
                                        distortionCoefficients,
                                        0,
                                        new MCvTermCriteria(30, 0.1),
                                        out rotationVectors,
                                        out translationVectors);

Console.WriteLine(rotationVectors[0].Size); // AccessViolationException

  • I only use one image here, but I have the same problem when using more images (30) Different calibration images would yield different results for translation-/rotationVector anyway, which makes me doubt that using only 1 image is a problem.
  • The detection of points works and drawing them into the original image gives reasonabel results.
  • Both cameraMatrix and distortionCoefficients can be accessed and contain values. (I tried to only post the relevant parts of the code)
  • I use emgu version 3.0.0.2157

Why do I get an AccessViolationException on the rotationVectors and translationVectors?

I placed a breakpoint and found that the internal Data property is null. See screenshot of VS debugger:

That explains why I cannot access it. But why is it null in the first place?

解决方案

It is because of bug in EmguCV. You are calling

public static double CalibrateCamera(
   MCvPoint3D32f[][] objectPoints,
   PointF[][] imagePoints,
   Size imageSize,
   IInputOutputArray cameraMatrix,
   IInputOutputArray distortionCoeffs,
   CvEnum.CalibType calibrationType,
   MCvTermCriteria termCriteria,
   out Mat[] rotationVectors,
   out Mat[] translationVectors)

inside this method there is a call to

public static double CalibrateCamera(
   IInputArray objectPoints,
   IInputArray imagePoints,
   Size imageSize,
   IInputOutputArray cameraMatrix,
   IInputOutputArray distortionCoeffs,
   IOutputArray rotationVectors,
   IOutputArray translationVectors,
   CvEnum.CalibType flags,
   MCvTermCriteria termCriteria)

IOutputArray rotationVectors should be copied to Mat[] rotationVectors. The same thing in case of translationVectors. The problem is in this loop.

There is

for (int i = 0; i < imageCount; i++)
{
   rotationVectors[i] = new Mat();
   using (Mat matR = rotationVectors[i]) // <- bug
      matR.CopyTo(rotationVectors[i]);
   translationVectors[i] = new Mat();
   using (Mat matT = translationVectors[i]) // <- bug
      matT.CopyTo(translationVectors[i]);                
}

and there should be

for (int i = 0; i < imageCount; i++)
{
   rotationVectors[i] = new Mat();
   using (Mat matR = rVecs[i]) 
      matR.CopyTo(rotationVectors[i]);
   translationVectors[i] = new Mat();
   using (Mat matT = tVecs[i]) 
      matT.CopyTo(translationVectors[i]);                
}

Finally to get rotation and translation values you can copy data using DataPointer

var rotation = new Matrix<float>(rotationVectors[0].Rows, rotationVectors[0].Cols, rotationVectors[0].DataPointer);

这篇关于如何在emgu CV中进行相机校准后访问旋转和平移向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆