diff --git a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs
index 37f2c8d15..6cc036ba5 100644
--- a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs
+++ b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs
@@ -48,6 +48,24 @@ public static extern ExceptionStatus aruco_drawDetectedDiamonds(
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
IntPtr ids, Scalar borderColor);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern ExceptionStatus aruco_detectCharucoBoard(
+ IntPtr image,
+ int squaresX, int squaresY, float squareLength, float markerLength, int arucoDictId,
+ IntPtr charucoCorners, IntPtr charucoIds, IntPtr markerCorners, IntPtr markerIds);
+
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern ExceptionStatus aruco_interpolateCornersCharuco(
+ IntPtr image,
+ int squaresX, int squaresY, float squareLength, float markerLength, int arucoDictId,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] markerCorners, int markerCornersSize1, int[] markerCornersSize2, IntPtr markerIds,
+ IntPtr charucoCorners, IntPtr charucoIds);
+
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern ExceptionStatus aruco_drawDetectedCornersCharuco(
+ IntPtr image,
+ IntPtr corners, IntPtr ids, Scalar cornerColor);
+
#region Dictionary
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
diff --git a/src/OpenCvSharp/Modules/aruco/CvAruco.cs b/src/OpenCvSharp/Modules/aruco/CvAruco.cs
index 7cfa6460b..750ec4808 100644
--- a/src/OpenCvSharp/Modules/aruco/CvAruco.cs
+++ b/src/OpenCvSharp/Modules/aruco/CvAruco.cs
@@ -296,4 +296,137 @@ public static void DrawDetectedDiamonds(InputArray image,
GC.KeepAlive(image);
}
+
+ ///
+ /// Detect ChArUco Board.
+ ///
+ /// input image necessary for corner refinement.
+ /// number of chessboard squares in x directions.
+ /// number of chessboard squares in y directions.
+ /// chessboard square side length (normally in meters).
+ /// marker side length (same unit than squareLength).
+ /// dictionary of markers indicating the type of markers.
+ /// output list of detected charuco corners.
+ /// ids of the charucos in charucoCorners.
+ /// output list of detected marker corners.
+ /// ids of the corners in markerCorners.
+ public static void DetectCharucoBoard(InputArray image, int squaresX, int squaresY, float squareLength, float markerLength,
+ PredefinedDictionaryName arucoDictId,
+ out Point2f[] charucoCorners, out int[] charucoIds,
+ out Point2f[][] markerCorners, out int[] markerIds)
+ {
+ if (image is null)
+ throw new ArgumentNullException(nameof(image));
+
+ image.ThrowIfDisposed();
+
+ using var charucoCornersVec = new VectorOfPoint2f();
+ using var charucoIdsVec = new VectorOfInt32();
+ using var markerCornersVec = new VectorOfVectorPoint2f();
+ using var markerIdsVec = new VectorOfInt32();
+
+ NativeMethods.HandleException(
+ NativeMethods.aruco_detectCharucoBoard(
+ image.CvPtr,
+ squaresX, squaresY, squareLength, markerLength, (int)arucoDictId,
+ charucoCornersVec.CvPtr, charucoIdsVec.CvPtr,
+ markerCornersVec.CvPtr, markerIdsVec.CvPtr
+ ));
+
+ charucoCorners = charucoCornersVec.ToArray();
+ charucoIds = charucoIdsVec.ToArray();
+ markerCorners = markerCornersVec.ToArray();
+ markerIds = markerIdsVec.ToArray();
+
+ GC.KeepAlive(image);
+ }
+
+ /// input image necessary for corner refinement.
+ /// number of chessboard squares in x directions.
+ /// number of chessboard squares in y directions.
+ /// chessboard square side length (normally in meters).
+ /// marker side length (same unit than squareLength).
+ /// dictionary of markers indicating the type of markers.
+ /// list of detected marker corners.
+ /// ids of the corners in markerCorners.
+ /// output list of detected charuco corners.
+ /// ids of the charucos in charucoCorners.
+ public static void InterpolateCornersCharuco(InputArray image,
+ int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName arucoDictId,
+ Point2f[][] markerCorners, IEnumerable markerIds,
+ out Point2f[] charucoCorners, out int[] charucoIds)
+ {
+ if (image is null)
+ throw new ArgumentNullException(nameof(image));
+ if (markerCorners is null)
+ throw new ArgumentNullException(nameof(markerCorners));
+ if (markerIds is null)
+ throw new ArgumentNullException(nameof(markerIds));
+
+ image.ThrowIfDisposed();
+
+ using var markerCornersAddress = new ArrayAddress2(markerCorners);
+ using var markerIdsVec = new VectorOfInt32(markerIds);
+ using var charucoCornersVec = new VectorOfPoint2f();
+ using var charucoIdsVec = new VectorOfInt32();
+
+ NativeMethods.HandleException(
+ NativeMethods.aruco_interpolateCornersCharuco(
+ image.CvPtr,
+ squaresX, squaresY, squareLength, markerLength, (int)arucoDictId,
+ markerCornersAddress.GetPointer(), markerCornersAddress.GetDim1Length(), markerCornersAddress.GetDim2Lengths(), markerIdsVec.CvPtr,
+ charucoCornersVec.CvPtr, charucoIdsVec.CvPtr)
+ );
+
+ charucoCorners = charucoCornersVec.ToArray();
+ charucoIds = charucoIdsVec.ToArray();
+
+ GC.KeepAlive(image);
+ }
+
+ ///
+ /// Draw a set of detected ChArUco Diamond markers.
+ ///
+ /// input/output image. It must have 1 or 3 channels. The number of channels is not altered.
+ /// vector of detected charuco corners.
+ /// list of identifiers for each corner in charucoCorners.
+ public static void DrawDetectedCornersCharuco(InputArray image, Point2f[] charucoCorners, IEnumerable? charucoIds = null)
+ {
+ DrawDetectedCornersCharuco(image, charucoCorners, charucoIds, new Scalar(0, 0, 255));
+ }
+
+ ///
+ /// Draw a set of detected ChArUco Diamond markers.
+ ///
+ /// input/output image. It must have 1 or 3 channels. The number of channels is not altered.
+ /// vector of detected charuco corners.
+ /// list of identifiers for each corner in charucoCorners.
+ /// color of the square surrounding each corner.
+ public static void DrawDetectedCornersCharuco(InputArray image,
+ Point2f[] charucoCorners, IEnumerable? charucoIds, Scalar cornerColor)
+ {
+ if (image is null)
+ throw new ArgumentNullException(nameof(image));
+ if (charucoCorners is null)
+ throw new ArgumentNullException(nameof(charucoCorners));
+
+ using var charucoCornersVec = new VectorOfPoint2f(charucoCorners);
+
+ if (charucoIds is null)
+ {
+ NativeMethods.HandleException(
+ NativeMethods.aruco_drawDetectedCornersCharuco(image.CvPtr,
+ charucoCornersVec.CvPtr, IntPtr.Zero, cornerColor));
+ }
+ else
+ {
+ using var ids = new VectorOfInt32(charucoIds);
+
+ NativeMethods.HandleException(
+ NativeMethods.aruco_drawDetectedCornersCharuco(image.CvPtr,
+ charucoCornersVec.CvPtr, ids.CvPtr, cornerColor));
+ }
+
+ GC.KeepAlive(image);
+ }
}
diff --git a/src/OpenCvSharpExtern/aruco.h b/src/OpenCvSharpExtern/aruco.h
index 2660116cb..61aaf0e7a 100644
--- a/src/OpenCvSharpExtern/aruco.h
+++ b/src/OpenCvSharpExtern/aruco.h
@@ -301,3 +301,74 @@ CVAPI(ExceptionStatus) aruco_drawDetectedDiamonds(
cv::aruco::drawDetectedDiamonds(*image, cornerVec, idArray, cpp(borderColor));
END_WRAP
}
+
+CVAPI(ExceptionStatus) aruco_detectCharucoBoard(
+ cv::_InputArray* image,
+ int squaresX,
+ int squaresY,
+ float squareLength,
+ float markerLength,
+ int arucoDictId,
+ std::vector* charucoCorners,
+ std::vector* charucoIds,
+ std::vector< std::vector >* markerCorners,
+ std::vector* markerIds
+ )
+{
+ BEGIN_WRAP
+ cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(arucoDictId);
+ cv::aruco::CharucoBoard charucoBoard(cv::Size(squaresX, squaresY), squareLength, markerLength, dictionary);
+ cv::aruco::CharucoDetector detector(charucoBoard);
+ cv::Mat charucoCorners_mat, charucoIds_mat;
+ //detector.detectBoard(*image, *charucoCorners, *charucoIds, *markerCorners, *markerIds);
+ detector.detectBoard(*image, charucoCorners_mat, charucoIds_mat, *markerCorners, *markerIds);
+ for (int i = 0; i < charucoCorners_mat.rows; ++i)
+ {
+ charucoCorners->push_back(charucoCorners_mat.at(i, 0));
+ charucoIds->push_back(charucoIds_mat.at(i, 0));
+ }
+ END_WRAP
+}
+
+CVAPI(ExceptionStatus) aruco_interpolateCornersCharuco(
+ cv::_InputArray* image,
+ int squaresX,
+ int squaresY,
+ float squareLength,
+ float markerLength,
+ int arucoDictId,
+ cv::Point2f** markerCorners,
+ int markerCornersSize1,
+ int* markerCornersSize2,
+ std::vector* markerIds,
+ std::vector* charucoCorners,
+ std::vector* charucoIds
+ )
+{
+ BEGIN_WRAP
+ std::vector< std::vector > markerCornerVec(markerCornersSize1);
+ for (int i = 0; i < markerCornersSize1; i++)
+ markerCornerVec[i] = std::vector(markerCorners[i], markerCorners[i] + markerCornersSize2[i]);
+
+ cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(arucoDictId);
+ cv::Ptr ptr_charucoBoard = new cv::aruco::CharucoBoard(cv::Size(squaresX, squaresY), squareLength, markerLength, dictionary);
+ cv::Mat charucoCorners_mat, charucoIds_mat;
+ cv::aruco::interpolateCornersCharuco(markerCornerVec, *markerIds, *image, ptr_charucoBoard, charucoCorners_mat, charucoIds_mat);
+ for (int i = 0; i < charucoCorners_mat.rows; ++i)
+ {
+ charucoCorners->push_back(charucoCorners_mat.at(i, 0));
+ charucoIds->push_back(charucoIds_mat.at(i, 0));
+ }
+ END_WRAP
+}
+
+CVAPI(ExceptionStatus) aruco_drawDetectedCornersCharuco(
+ cv::_InputOutputArray* image,
+ std::vector* corners,
+ std::vector* ids,
+ MyCvScalar cornerColor)
+{
+ BEGIN_WRAP
+ cv::aruco::drawDetectedCornersCharuco(*image, *corners, *ids, cpp(cornerColor));
+ END_WRAP
+}