-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Cv2.StereoCalibrate with IEnumerable<InputArray> throws OpenCVException (vector of vectors type mismatch) due to pointer marshaling #1842
Description
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.