Skip to content

Cv2.StereoCalibrate with IEnumerable<InputArray> throws OpenCVException (vector of vectors type mismatch) due to pointer marshaling #1842

@crested-ezios

Description

@crested-ezios

Summary of the issue

When calling Cv2.StereoCalibrate using the overload that accepts IEnumerable<InputArray> for objectPoints and imagePoints, it throws an OpenCVException (objectPoints should contain vector of vectors of points of type Point3f).

This occurs because passing a collection of InputArray created from C# arrays (e.g., List<Point3f[]>.Select(x => InputArray.Create(x))) fails to correctly marshal into the std::vector<std::vector<cv::Point3f>> structure expected by the underlying C++ calib3d_stereoCalibrate_InputArray wrapper function.

Note for other developers: A perfect workaround exists. If you use the other overload that accepts double[,] and double[] for the camera matrices and distortion coefficients, the compiler will route the call to calib3d_stereoCalibrate_array, which marshals the flattened memory correctly and runs without issues.

Environment

  • OpenCvSharp Version: 4.13.0.20260308
  • OS: Microsoft Windows [ver. 10.0.22631.6199]
  • Visual Studio: Microsoft Visual Studio Enterprise 2022 (x64) ver. 17.14.27

Example code:

// 1. Prepare dummy data
var patternSize = new Size(9, 6);
int ptsPerImg = patternSize.Width * patternSize.Height;
var objPoints = new List<Point3f[]> { new Point3f[ptsPerImg] };
var imgPoints1 = new List<Point2f[]> { new Point2f[ptsPerImg] };
var imgPoints2 = new List<Point2f[]> { new Point2f[ptsPerImg] };

// 2. Convert to IEnumerable<InputArray>
var opInputs = objPoints.Select(pts => InputArray.Create(pts)).ToArray();
var ip1Inputs = imgPoints1.Select(pts => InputArray.Create(pts)).ToArray();
var ip2Inputs = imgPoints2.Select(pts => InputArray.Create(pts)).ToArray();

// 3. Initialize matrices using cv.Mat
Mat cameraMatrix1 = new Mat(3, 3, MatType.CV_64F);
Mat distCoeffs1 = new Mat(5, 1, MatType.CV_64F);
Mat cameraMatrix2 = new Mat(3, 3, MatType.CV_64F);
Mat distCoeffs2 = new Mat(5, 1, MatType.CV_64F);
Mat R = new Mat(), T = new Mat(), E = new Mat(), F = new Mat();

// 4. This call throws the OpenCVException
double rms = Cv2.StereoCalibrate(
    opInputs, ip1Inputs, ip2Inputs,
    cameraMatrix1, distCoeffs1,
    cameraMatrix2, distCoeffs2,
    new Size(640, 480),
    R, T, E, F,
    CalibrationFlags.FixK3, 
    new TermCriteria(CriteriaTypes.Eps | CriteriaTypes.MaxIter, 100, 1e-5));

Exception Details:

OpenCvSharp.OpenCVException
  HResult=0x80131500
  Message=objectPoints should contain vector of vectors of points of type Point3f
  Source=OpenCvSharp
  StackTrace:
   in OpenCvSharp.Internal.NativeMethods.<>c.<.cctor>b__1701_0(ErrorCode status, String funcName, String errMsg, String fileName, Int32 line, IntPtr userData)
   in OpenCvSharp.Internal.NativeMethods.calib3d_stereoCalibrate_InputArray(IntPtr[] objectPoints, Int32 opSize, IntPtr[] imagePoints1, Int32 ip1Size, IntPtr[] imagePoints2, Int32 ip2Size, IntPtr cameraMatrix1, IntPtr distCoeffs1, IntPtr cameraMatrix2, IntPtr distCoeffs2, Size imageSize, IntPtr R, IntPtr T, IntPtr E, IntPtr F, Int32 flags, TermCriteria criteria, Double& returnValue)
   in OpenCvSharp.Cv2.StereoCalibrate(IEnumerable`1 objectPoints, IEnumerable`1 imagePoints1, IEnumerable`1 imagePoints2, InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, Size imageSize, OutputArray R, OutputArray T, OutputArray E, OutputArray F, CalibrationFlags flags, Nullable`1 criteria)

Expected results

The method should correctly marshal the array of pointers into the required std::vector<std::vector<...>> format, or the library should mark this specific IEnumerable<InputArray> overload as obsolete/unsafe for nested point structures, pointing developers toward the safe calib3d_stereoCalibrate_array overload instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions