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

  • 内在的是描述相机本身的(焦点)
    长度,失真等),我可以得到这些值,没问题。
  • 外在参数基本上是相机的位置。当我尝试访问这些代码时,我收到AccessViolationException

  • 执行这种校准的一种方法是
  • 拍摄带有已知角的校准目标的图像
  • 在图像
  • 中找到那些角
    从3D点和2D点之间的对应关系中找到
  • ,找到将一个转换为另一个
  • 的矩阵
  • 表示矩阵由内在和外在参数组成。

  • calibration function的调用如下所示:
    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
    
  • 我在这里只使用一张图像,但是当使用更多图像时,我也会遇到相同的问题(30)无论如何,不​​同的校准图像会为translation-/ rotationVector产生不同的结果,这使我怀疑仅使用一张图像是一个问题。
  • 对点的检测有效并将其绘制到原始图像中可提供合理的结果。
  • cameraMatrixdistortionCoefficients都可以访问并包含值。 (我只尝试发布代码的相关部分)
  • 我使用emgu版本3.0.0.2157

  • 为什么我在AccessViolationExceptionrotationVectors上得到一个translationVectors

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

    c# - 在emgu CV中进行摄像机校准后,如何访问旋转和平移矢量?-LMLPHP

    这就解释了为什么我无法访问它。但是为什么首先是null

    最佳答案

    这是因为EmguCV中的错误。你在打电话

    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)
    

    在此方法中有一个调用
    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。对于translationVectors,也是一样。问题出在this循环中。


    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]);
    }
    

    并且应该有
    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]);
    }
    

    最后,要获得旋转和平移值,您可以使用DataPointer复制数据
    var rotation = new Matrix<float>(rotationVectors[0].Rows, rotationVectors[0].Cols, rotationVectors[0].DataPointer);
    

    关于c# - 在emgu CV中进行摄像机校准后,如何访问旋转和平移矢量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33127581/

    10-13 03:03