Skip to content

Commit 9ea30e6

Browse files
authored
Merge pull request #1860 from shimat/fix_stereocalibrate
Fix Cv2.StereoCalibrate functionality
2 parents bf8f6dd + 7e45d53 commit 9ea30e6

7 files changed

Lines changed: 793 additions & 511 deletions

File tree

src/OpenCvSharp/Cv2/Cv2_calib3d.FishEye.cs

Lines changed: 499 additions & 0 deletions
Large diffs are not rendered by default.

src/OpenCvSharp/Cv2/Cv2_calib3d.cs

Lines changed: 84 additions & 492 deletions
Large diffs are not rendered by default.

src/OpenCvSharp/Internal/PInvoke/NativeMethods/calib3d/NativeMethods_calib3d.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,21 @@ public static extern ExceptionStatus calib3d_stereoCalibrate_InputArray(
202202
int flags, TermCriteria criteria,
203203
out double returnValue);
204204

205+
[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
206+
public static extern ExceptionStatus calib3d_stereoCalibrate_Mat(
207+
IntPtr[] objectPoints, int opSize,
208+
IntPtr[] imagePoints1, int ip1Size,
209+
IntPtr[] imagePoints2, int ip2Size,
210+
IntPtr cameraMatrix1,
211+
IntPtr distCoeffs1,
212+
IntPtr cameraMatrix2,
213+
IntPtr distCoeffs2,
214+
Size imageSize,
215+
IntPtr R, IntPtr T,
216+
IntPtr E, IntPtr F,
217+
int flags, TermCriteria criteria,
218+
out double returnValue);
219+
205220
[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
206221
public static extern unsafe ExceptionStatus calib3d_stereoCalibrate_array(
207222
IntPtr[] objectPoints, int opSize1, int[] opSizes2,

src/OpenCvSharp/Modules/core/Mat/Mat.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,84 @@ public static MatExpr Eye(int rows, int cols, MatType type)
695695
return retVal;
696696
}
697697

698+
/// <summary>
699+
/// Returns a zero array of the specified size and type as <see cref="Mat"/>.
700+
/// Unlike <see cref="Zeros(int,int,MatType)"/>, this method returns a <see cref="Mat"/> directly,
701+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
702+
/// </summary>
703+
/// <param name="rows">Number of rows.</param>
704+
/// <param name="cols">Number of columns.</param>
705+
/// <param name="type">Created matrix type.</param>
706+
/// <returns></returns>
707+
public static Mat ZerosMat(int rows, int cols, MatType type)
708+
{
709+
using var expr = Zeros(rows, cols, type);
710+
return (Mat)expr;
711+
}
712+
713+
/// <summary>
714+
/// Returns a zero array of the specified size and type as <see cref="Mat"/>.
715+
/// Unlike <see cref="Zeros(Size,MatType)"/>, this method returns a <see cref="Mat"/> directly,
716+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
717+
/// </summary>
718+
/// <param name="size">Alternative to the matrix size specification Size(cols, rows).</param>
719+
/// <param name="type">Created matrix type.</param>
720+
/// <returns></returns>
721+
public static Mat ZerosMat(Size size, MatType type)
722+
=> ZerosMat(size.Height, size.Width, type);
723+
724+
/// <summary>
725+
/// Returns an array of all 1's of the specified size and type as <see cref="Mat"/>.
726+
/// Unlike <see cref="Ones(int,int,MatType)"/>, this method returns a <see cref="Mat"/> directly,
727+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
728+
/// </summary>
729+
/// <param name="rows">Number of rows.</param>
730+
/// <param name="cols">Number of columns.</param>
731+
/// <param name="type">Created matrix type.</param>
732+
/// <returns></returns>
733+
public static Mat OnesMat(int rows, int cols, MatType type)
734+
{
735+
using var expr = Ones(rows, cols, type);
736+
return (Mat)expr;
737+
}
738+
739+
/// <summary>
740+
/// Returns an array of all 1's of the specified size and type as <see cref="Mat"/>.
741+
/// Unlike <see cref="Ones(Size,MatType)"/>, this method returns a <see cref="Mat"/> directly,
742+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
743+
/// </summary>
744+
/// <param name="size">Alternative to the matrix size specification Size(cols, rows).</param>
745+
/// <param name="type">Created matrix type.</param>
746+
/// <returns></returns>
747+
public static Mat OnesMat(Size size, MatType type)
748+
=> OnesMat(size.Height, size.Width, type);
749+
750+
/// <summary>
751+
/// Returns an identity matrix of the specified size and type as <see cref="Mat"/>.
752+
/// Unlike <see cref="Eye(int,int,MatType)"/>, this method returns a <see cref="Mat"/> directly,
753+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
754+
/// </summary>
755+
/// <param name="rows">Number of rows.</param>
756+
/// <param name="cols">Number of columns.</param>
757+
/// <param name="type">Created matrix type.</param>
758+
/// <returns></returns>
759+
public static Mat EyeMat(int rows, int cols, MatType type)
760+
{
761+
using var expr = Eye(rows, cols, type);
762+
return (Mat)expr;
763+
}
764+
765+
/// <summary>
766+
/// Returns an identity matrix of the specified size and type as <see cref="Mat"/>.
767+
/// Unlike <see cref="Eye(Size,MatType)"/>, this method returns a <see cref="Mat"/> directly,
768+
/// so a single <c>using</c> statement is sufficient to manage its lifetime.
769+
/// </summary>
770+
/// <param name="size">Alternative to the matrix size specification Size(cols, rows).</param>
771+
/// <param name="type">Created matrix type.</param>
772+
/// <returns></returns>
773+
public static Mat EyeMat(Size size, MatType type)
774+
=> EyeMat(size.Height, size.Width, type);
775+
698776
#region FromArray
699777

700778
/// <summary>

src/OpenCvSharpExtern/calib3d.h

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ CVAPI(ExceptionStatus) calib3d_initCameraMatrix2D_array(
279279
std::vector<std::vector<cv::Point3f> > objectPointsVec(opSize1);
280280
for (auto i = 0; i < opSize1; i++)
281281
objectPointsVec[i] = std::vector<cv::Point3f>(objectPoints[i], objectPoints[i] + opSize2[i]);
282-
std::vector<std::vector<cv::Point3f> > imagePointsVec(ipSize1);
282+
std::vector<std::vector<cv::Point2f> > imagePointsVec(ipSize1);
283283
for (auto i = 0; i < ipSize1; i++)
284-
imagePointsVec[i] = std::vector<cv::Point3f>(imagePoints[i], imagePoints[i] + ipSize2[i]);
284+
imagePointsVec[i] = std::vector<cv::Point2f>(imagePoints[i], imagePoints[i] + ipSize2[i]);
285285

286286
const auto ret = cv::initCameraMatrix2D(objectPointsVec, imagePointsVec, cpp(imageSize), aspectRatio);
287287
*returnValue = new cv::Mat(ret);
@@ -509,9 +509,41 @@ CVAPI(ExceptionStatus) calib3d_stereoCalibrate_InputArray(
509509
double *returnValue)
510510
{
511511
BEGIN_WRAP
512-
std::vector<cv::_InputArray> objectPointsVec(opSize);
513-
std::vector<cv::_InputArray> imagePoints1Vec(ip1Size);
514-
std::vector<cv::_InputArray> imagePoints2Vec(ip2Size);
512+
std::vector<cv::Mat> objectPointsVec(opSize);
513+
std::vector<cv::Mat> imagePoints1Vec(ip1Size);
514+
std::vector<cv::Mat> imagePoints2Vec(ip2Size);
515+
for (auto i = 0; i < opSize; i++)
516+
objectPointsVec[i] = objectPoints[i]->getMat();
517+
for (auto i = 0; i < ip1Size; i++)
518+
imagePoints1Vec[i] = imagePoints1[i]->getMat();
519+
for (auto i = 0; i < ip2Size; i++)
520+
imagePoints2Vec[i] = imagePoints2[i]->getMat();
521+
522+
*returnValue = cv::stereoCalibrate(objectPointsVec, imagePoints1Vec, imagePoints2Vec,
523+
*cameraMatrix1, *distCoeffs1,
524+
*cameraMatrix2, *distCoeffs2,
525+
cpp(imageSize), entity(R), entity(T), entity(E), entity(F), flags, cpp(criteria));
526+
END_WRAP
527+
}
528+
CVAPI(ExceptionStatus) calib3d_stereoCalibrate_Mat(
529+
cv::Mat **objectPoints, int opSize,
530+
cv::Mat **imagePoints1, int ip1Size,
531+
cv::Mat **imagePoints2, int ip2Size,
532+
cv::Mat *cameraMatrix1,
533+
cv::Mat *distCoeffs1,
534+
cv::Mat *cameraMatrix2,
535+
cv::Mat *distCoeffs2,
536+
MyCvSize imageSize,
537+
cv::Mat *R, cv::Mat *T,
538+
cv::Mat *E, cv::Mat *F,
539+
int flags,
540+
MyCvTermCriteria criteria,
541+
double *returnValue)
542+
{
543+
BEGIN_WRAP
544+
std::vector<cv::Mat> objectPointsVec(opSize);
545+
std::vector<cv::Mat> imagePoints1Vec(ip1Size);
546+
std::vector<cv::Mat> imagePoints2Vec(ip2Size);
515547
for (auto i = 0; i < opSize; i++)
516548
objectPointsVec[i] = *objectPoints[i];
517549
for (auto i = 0; i < ip1Size; i++)
@@ -522,7 +554,7 @@ CVAPI(ExceptionStatus) calib3d_stereoCalibrate_InputArray(
522554
*returnValue = cv::stereoCalibrate(objectPointsVec, imagePoints1Vec, imagePoints2Vec,
523555
*cameraMatrix1, *distCoeffs1,
524556
*cameraMatrix2, *distCoeffs2,
525-
cpp(imageSize), entity(R), entity(T), entity(E), entity(F), flags, cpp(criteria));
557+
cpp(imageSize), *R, *T, *E, *F, flags, cpp(criteria));
526558
END_WRAP
527559
}
528560
CVAPI(ExceptionStatus) calib3d_stereoCalibrate_array(
@@ -659,12 +691,12 @@ CVAPI(ExceptionStatus) calib3d_rectify3Collinear_InputArray(
659691
float *returnValue)
660692
{
661693
BEGIN_WRAP
662-
std::vector<cv::_InputArray> imgpt1Vec(imgpt1Size);
663-
std::vector<cv::_InputArray> imgpt3Vec(imgpt3Size);
664-
for (auto i = 0; i < imgpt1Size; i++)
665-
imgpt1Vec[i] = *(imgpt1[i]);
694+
std::vector<cv::Mat> imgpt1Vec(imgpt1Size);
695+
std::vector<cv::Mat> imgpt3Vec(imgpt3Size);
666696
for (auto i = 0; i < imgpt1Size; i++)
667-
imgpt3Vec[i] = *(imgpt3[i]);
697+
imgpt1Vec[i] = imgpt1[i]->getMat();
698+
for (auto i = 0; i < imgpt3Size; i++)
699+
imgpt3Vec[i] = imgpt3[i]->getMat();
668700
cv::Rect _roi1, _roi2;
669701

670702
const auto ret = cv::rectify3Collinear(*cameraMatrix1, *distCoeffs1,

test/OpenCvSharp.Tests/calib3d/Calib3dTest.cs

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void CalibrateCameraByMat()
140140

141141
using var objectPoints = Mat<Point3f>.FromArray(objectPointsArray);
142142
using var imagePoints = Mat<Point2f>.FromArray(imagePointsArray);
143-
using var cameraMatrix = new Mat<double>(Mat.Eye(3, 3, MatType.CV_64FC1));
143+
using var cameraMatrix = Mat.EyeMat(3, 3, MatType.CV_64FC1);
144144
using var distCoeffs = new Mat<double>();
145145
var rms = Cv2.CalibrateCamera([objectPoints], [imagePoints], image.Size(), cameraMatrix,
146146
distCoeffs, out var rotationVectors, out var translationVectors,
@@ -165,7 +165,7 @@ public void FishEyeCalibrate()
165165

166166
using var objectPoints = Mat<Point3f>.FromArray(objectPointsArray);
167167
using var imagePoints = Mat<Point2f>.FromArray(imagePointsArray);
168-
using var cameraMatrix = new Mat<double>(Mat.Eye(3, 3, MatType.CV_64FC1));
168+
using var cameraMatrix = Mat.EyeMat(3, 3, MatType.CV_64FC1);
169169
using var distCoeffs = new Mat<double>();
170170
var rms = Cv2.FishEye.Calibrate([objectPoints], [imagePoints], image.Size(), cameraMatrix,
171171
distCoeffs, out var rotationVectors, out var translationVectors);
@@ -327,8 +327,8 @@ public void SolvePnPTestByMat()
327327

328328
using var objPtsMat = Mat.FromPixelData(objPts.Length, 1, MatType.CV_32FC3, objPts);
329329
using var imgPtsMat = Mat.FromPixelData(imgPts.Length, 1, MatType.CV_32FC2, imgPts);
330-
using var cameraMatrixMat = Mat.Eye(3, 3, MatType.CV_64FC1);
331-
using var distMat = Mat.Zeros(5, 0, MatType.CV_64FC1);
330+
using var cameraMatrixMat = Mat.EyeMat(3, 3, MatType.CV_64FC1);
331+
using var distMat = Mat.ZerosMat(5, 0, MatType.CV_64FC1);
332332
using var rvecMat = new Mat();
333333
using var tvecMat = new Mat();
334334
Cv2.SolvePnP(objPtsMat, imgPtsMat, cameraMatrixMat, distMat, rvecMat, tvecMat);
@@ -496,7 +496,7 @@ public void RecoverPoseWithTriangulatedPoints()
496496

497497
using var points1m = Mat<double>.FromArray(points1);
498498
using var points2m = Mat<double>.FromArray(points2);
499-
using var K = Mat.Eye(3, 3, MatType.CV_64F);
499+
using var K = Mat.EyeMat(3, 3, MatType.CV_64F);
500500
using var inliers = new Mat();
501501
using var E = Cv2.FindEssentialMat(points1m, points2m, K, EssentialMatMethod.LMedS, 0.99, 1.0, inliers);
502502

@@ -575,6 +575,72 @@ public void FindHomographyUsac()
575575
});*/
576576
}
577577

578+
[Fact]
579+
public void StereoCalibrateByInputArray()
580+
{
581+
var patternSize = new Size(10, 7);
582+
583+
using var image = LoadImage("calibration/00.jpg");
584+
Cv2.FindChessboardCorners(image, patternSize, out var cornerPoints);
585+
586+
var objectPointsArray = Create3DChessboardCorners(patternSize, 1.0f).ToArray();
587+
588+
using var opIA = InputArray.Create(objectPointsArray);
589+
using var ip1IA = InputArray.Create(cornerPoints);
590+
using var ip2IA = InputArray.Create(cornerPoints);
591+
592+
using var cameraMatrix1 = Mat.EyeMat(3, 3, MatType.CV_64FC1);
593+
using var distCoeffs1 = new Mat<double>();
594+
using var cameraMatrix2 = Mat.EyeMat(3, 3, MatType.CV_64FC1);
595+
using var distCoeffs2 = new Mat<double>();
596+
using var R = new Mat();
597+
using var T = new Mat();
598+
using var E = new Mat();
599+
using var F = new Mat();
600+
601+
var rms = Cv2.StereoCalibrate(
602+
new[] { opIA }, new[] { ip1IA }, new[] { ip2IA },
603+
cameraMatrix1, distCoeffs1,
604+
cameraMatrix2, distCoeffs2,
605+
image.Size(), R, T, E, F,
606+
CalibrationFlags.UseIntrinsicGuess);
607+
608+
Assert.False(double.IsNaN(rms));
609+
Assert.False(double.IsInfinity(rms));
610+
}
611+
612+
[Fact]
613+
public void StereoCalibrateByMat()
614+
{
615+
var patternSize = new Size(10, 7);
616+
617+
using var image = LoadImage("calibration/00.jpg");
618+
Cv2.FindChessboardCorners(image, patternSize, out var cornerPoints);
619+
620+
var objectPointsArray = Create3DChessboardCorners(patternSize, 1.0f).ToArray();
621+
622+
using var objectPoints = Mat<Point3f>.FromArray(objectPointsArray);
623+
using var imagePoints = Mat<Point2f>.FromArray(cornerPoints);
624+
using var cameraMatrix1 = Mat.EyeMat(3, 3, MatType.CV_64FC1);
625+
using var distCoeffs1 = new Mat();
626+
using var cameraMatrix2 = Mat.EyeMat(3, 3, MatType.CV_64FC1);
627+
using var distCoeffs2 = new Mat();
628+
using var R = new Mat();
629+
using var T = new Mat();
630+
using var E = new Mat();
631+
using var F = new Mat();
632+
633+
var rms = Cv2.StereoCalibrate(
634+
new[] { objectPoints }, new[] { imagePoints }, new[] { imagePoints },
635+
cameraMatrix1, distCoeffs1,
636+
cameraMatrix2, distCoeffs2,
637+
image.Size(), R, T, E, F,
638+
CalibrationFlags.UseIntrinsicGuess);
639+
640+
Assert.False(double.IsNaN(rms));
641+
Assert.False(double.IsInfinity(rms));
642+
}
643+
578644
private static IEnumerable<Point3f> Create3DChessboardCorners(Size boardSize, float squareSize)
579645
{
580646
for (var y = 0; y < boardSize.Height; y++)

test/OpenCvSharp.Tests/shape/HistogramCostExtractorTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ public void Norm_DefaultCostRoundTrip()
6363
public void Norm_BuildCostMatrix()
6464
{
6565
using var ext = NormHistogramCostExtractor.Create();
66-
using var hist1 = Mat.FromArray(new float[] { 0.5f, 0.3f, 0.2f });
67-
using var hist2 = Mat.FromArray(new float[] { 0.4f, 0.4f, 0.2f });
66+
using var hist1 = Mat.FromArray([0.5f, 0.3f, 0.2f]);
67+
using var hist2 = Mat.FromArray([0.4f, 0.4f, 0.2f]);
6868
using var costMat = new Mat();
6969

7070
ext.BuildCostMatrix(hist1, hist2, costMat);
@@ -237,4 +237,4 @@ public void SCDE_SetTransformAlgorithm_Affine()
237237

238238
extractor.SetTransformAlgorithm(affine);
239239
}
240-
}
240+
}

0 commit comments

Comments
 (0)