Skip to content

Commit f848c80

Browse files
authored
Merge pull request #1769 from okahiro1125/feature/add_charucoboard
Add DetectCharucoBoard and related functions
2 parents 7e98425 + 5108520 commit f848c80

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ public static extern ExceptionStatus aruco_drawDetectedDiamonds(
4848
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
4949
IntPtr ids, Scalar borderColor);
5050

51+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
52+
public static extern ExceptionStatus aruco_detectCharucoBoard(
53+
IntPtr image,
54+
int squaresX, int squaresY, float squareLength, float markerLength, int arucoDictId,
55+
IntPtr charucoCorners, IntPtr charucoIds, IntPtr markerCorners, IntPtr markerIds);
56+
57+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
58+
public static extern ExceptionStatus aruco_interpolateCornersCharuco(
59+
IntPtr image,
60+
int squaresX, int squaresY, float squareLength, float markerLength, int arucoDictId,
61+
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] markerCorners, int markerCornersSize1, int[] markerCornersSize2, IntPtr markerIds,
62+
IntPtr charucoCorners, IntPtr charucoIds);
63+
64+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
65+
public static extern ExceptionStatus aruco_drawDetectedCornersCharuco(
66+
IntPtr image,
67+
IntPtr corners, IntPtr ids, Scalar cornerColor);
68+
5169
#region Dictionary
5270

5371
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]

src/OpenCvSharp/Modules/aruco/CvAruco.cs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,137 @@ public static void DrawDetectedDiamonds(InputArray image,
296296

297297
GC.KeepAlive(image);
298298
}
299+
300+
/// <summary>
301+
/// Detect ChArUco Board.
302+
/// </summary>
303+
/// <param name="image">input image necessary for corner refinement.</param>
304+
/// <param name="squaresX">number of chessboard squares in x directions.</param>
305+
/// <param name="squaresY">number of chessboard squares in y directions.</param>
306+
/// <param name="squareLength">chessboard square side length (normally in meters).</param>
307+
/// <param name="markerLength">marker side length (same unit than squareLength).</param>
308+
/// <param name="arucoDictId">dictionary of markers indicating the type of markers.</param>
309+
/// <param name="charucoCorners">output list of detected charuco corners.</param>
310+
/// <param name="charucoIds">ids of the charucos in charucoCorners.</param>
311+
/// <param name="markerCorners">output list of detected marker corners.</param>
312+
/// <param name="markerIds">ids of the corners in markerCorners.</param>
313+
public static void DetectCharucoBoard(InputArray image, int squaresX, int squaresY, float squareLength, float markerLength,
314+
PredefinedDictionaryName arucoDictId,
315+
out Point2f[] charucoCorners, out int[] charucoIds,
316+
out Point2f[][] markerCorners, out int[] markerIds)
317+
{
318+
if (image is null)
319+
throw new ArgumentNullException(nameof(image));
320+
321+
image.ThrowIfDisposed();
322+
323+
using var charucoCornersVec = new VectorOfPoint2f();
324+
using var charucoIdsVec = new VectorOfInt32();
325+
using var markerCornersVec = new VectorOfVectorPoint2f();
326+
using var markerIdsVec = new VectorOfInt32();
327+
328+
NativeMethods.HandleException(
329+
NativeMethods.aruco_detectCharucoBoard(
330+
image.CvPtr,
331+
squaresX, squaresY, squareLength, markerLength, (int)arucoDictId,
332+
charucoCornersVec.CvPtr, charucoIdsVec.CvPtr,
333+
markerCornersVec.CvPtr, markerIdsVec.CvPtr
334+
));
335+
336+
charucoCorners = charucoCornersVec.ToArray();
337+
charucoIds = charucoIdsVec.ToArray();
338+
markerCorners = markerCornersVec.ToArray();
339+
markerIds = markerIdsVec.ToArray();
340+
341+
GC.KeepAlive(image);
342+
}
343+
344+
/// <param name="image">input image necessary for corner refinement.</param>
345+
/// <param name="squaresX">number of chessboard squares in x directions.</param>
346+
/// <param name="squaresY">number of chessboard squares in y directions.</param>
347+
/// <param name="squareLength">chessboard square side length (normally in meters).</param>
348+
/// <param name="markerLength">marker side length (same unit than squareLength).</param>
349+
/// <param name="arucoDictId">dictionary of markers indicating the type of markers.</param>
350+
/// <param name="markerCorners">list of detected marker corners.</param>
351+
/// <param name="markerIds">ids of the corners in markerCorners.</param>
352+
/// <param name="charucoCorners">output list of detected charuco corners.</param>
353+
/// <param name="charucoIds">ids of the charucos in charucoCorners.</param>
354+
public static void InterpolateCornersCharuco(InputArray image,
355+
int squaresX, int squaresY, float squareLength, float markerLength, PredefinedDictionaryName arucoDictId,
356+
Point2f[][] markerCorners, IEnumerable<int> markerIds,
357+
out Point2f[] charucoCorners, out int[] charucoIds)
358+
{
359+
if (image is null)
360+
throw new ArgumentNullException(nameof(image));
361+
if (markerCorners is null)
362+
throw new ArgumentNullException(nameof(markerCorners));
363+
if (markerIds is null)
364+
throw new ArgumentNullException(nameof(markerIds));
365+
366+
image.ThrowIfDisposed();
367+
368+
using var markerCornersAddress = new ArrayAddress2<Point2f>(markerCorners);
369+
using var markerIdsVec = new VectorOfInt32(markerIds);
370+
using var charucoCornersVec = new VectorOfPoint2f();
371+
using var charucoIdsVec = new VectorOfInt32();
372+
373+
NativeMethods.HandleException(
374+
NativeMethods.aruco_interpolateCornersCharuco(
375+
image.CvPtr,
376+
squaresX, squaresY, squareLength, markerLength, (int)arucoDictId,
377+
markerCornersAddress.GetPointer(), markerCornersAddress.GetDim1Length(), markerCornersAddress.GetDim2Lengths(), markerIdsVec.CvPtr,
378+
charucoCornersVec.CvPtr, charucoIdsVec.CvPtr)
379+
);
380+
381+
charucoCorners = charucoCornersVec.ToArray();
382+
charucoIds = charucoIdsVec.ToArray();
383+
384+
GC.KeepAlive(image);
385+
}
386+
387+
/// <summary>
388+
/// Draw a set of detected ChArUco Diamond markers.
389+
/// </summary>
390+
/// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param>
391+
/// <param name="charucoCorners">vector of detected charuco corners.</param>
392+
/// <param name="charucoIds">list of identifiers for each corner in charucoCorners.</param>
393+
public static void DrawDetectedCornersCharuco(InputArray image, Point2f[] charucoCorners, IEnumerable<int>? charucoIds = null)
394+
{
395+
DrawDetectedCornersCharuco(image, charucoCorners, charucoIds, new Scalar(0, 0, 255));
396+
}
397+
398+
/// <summary>
399+
/// Draw a set of detected ChArUco Diamond markers.
400+
/// </summary>
401+
/// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param>
402+
/// <param name="charucoCorners">vector of detected charuco corners.</param>
403+
/// <param name="charucoIds">list of identifiers for each corner in charucoCorners.</param>
404+
/// <param name="cornerColor">color of the square surrounding each corner.</param>
405+
public static void DrawDetectedCornersCharuco(InputArray image,
406+
Point2f[] charucoCorners, IEnumerable<int>? charucoIds, Scalar cornerColor)
407+
{
408+
if (image is null)
409+
throw new ArgumentNullException(nameof(image));
410+
if (charucoCorners is null)
411+
throw new ArgumentNullException(nameof(charucoCorners));
412+
413+
using var charucoCornersVec = new VectorOfPoint2f(charucoCorners);
414+
415+
if (charucoIds is null)
416+
{
417+
NativeMethods.HandleException(
418+
NativeMethods.aruco_drawDetectedCornersCharuco(image.CvPtr,
419+
charucoCornersVec.CvPtr, IntPtr.Zero, cornerColor));
420+
}
421+
else
422+
{
423+
using var ids = new VectorOfInt32(charucoIds);
424+
425+
NativeMethods.HandleException(
426+
NativeMethods.aruco_drawDetectedCornersCharuco(image.CvPtr,
427+
charucoCornersVec.CvPtr, ids.CvPtr, cornerColor));
428+
}
429+
430+
GC.KeepAlive(image);
431+
}
299432
}

src/OpenCvSharpExtern/aruco.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,74 @@ CVAPI(ExceptionStatus) aruco_drawDetectedDiamonds(
301301
cv::aruco::drawDetectedDiamonds(*image, cornerVec, idArray, cpp(borderColor));
302302
END_WRAP
303303
}
304+
305+
CVAPI(ExceptionStatus) aruco_detectCharucoBoard(
306+
cv::_InputArray* image,
307+
int squaresX,
308+
int squaresY,
309+
float squareLength,
310+
float markerLength,
311+
int arucoDictId,
312+
std::vector<cv::Point2f>* charucoCorners,
313+
std::vector<int>* charucoIds,
314+
std::vector< std::vector<cv::Point2f> >* markerCorners,
315+
std::vector<int>* markerIds
316+
)
317+
{
318+
BEGIN_WRAP
319+
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(arucoDictId);
320+
cv::aruco::CharucoBoard charucoBoard(cv::Size(squaresX, squaresY), squareLength, markerLength, dictionary);
321+
cv::aruco::CharucoDetector detector(charucoBoard);
322+
cv::Mat charucoCorners_mat, charucoIds_mat;
323+
//detector.detectBoard(*image, *charucoCorners, *charucoIds, *markerCorners, *markerIds);
324+
detector.detectBoard(*image, charucoCorners_mat, charucoIds_mat, *markerCorners, *markerIds);
325+
for (int i = 0; i < charucoCorners_mat.rows; ++i)
326+
{
327+
charucoCorners->push_back(charucoCorners_mat.at<cv::Point2f>(i, 0));
328+
charucoIds->push_back(charucoIds_mat.at<int>(i, 0));
329+
}
330+
END_WRAP
331+
}
332+
333+
CVAPI(ExceptionStatus) aruco_interpolateCornersCharuco(
334+
cv::_InputArray* image,
335+
int squaresX,
336+
int squaresY,
337+
float squareLength,
338+
float markerLength,
339+
int arucoDictId,
340+
cv::Point2f** markerCorners,
341+
int markerCornersSize1,
342+
int* markerCornersSize2,
343+
std::vector<int>* markerIds,
344+
std::vector<cv::Point2f>* charucoCorners,
345+
std::vector<int>* charucoIds
346+
)
347+
{
348+
BEGIN_WRAP
349+
std::vector< std::vector<cv::Point2f> > markerCornerVec(markerCornersSize1);
350+
for (int i = 0; i < markerCornersSize1; i++)
351+
markerCornerVec[i] = std::vector<cv::Point2f>(markerCorners[i], markerCorners[i] + markerCornersSize2[i]);
352+
353+
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(arucoDictId);
354+
cv::Ptr<cv::aruco::CharucoBoard> ptr_charucoBoard = new cv::aruco::CharucoBoard(cv::Size(squaresX, squaresY), squareLength, markerLength, dictionary);
355+
cv::Mat charucoCorners_mat, charucoIds_mat;
356+
cv::aruco::interpolateCornersCharuco(markerCornerVec, *markerIds, *image, ptr_charucoBoard, charucoCorners_mat, charucoIds_mat);
357+
for (int i = 0; i < charucoCorners_mat.rows; ++i)
358+
{
359+
charucoCorners->push_back(charucoCorners_mat.at<cv::Point2f>(i, 0));
360+
charucoIds->push_back(charucoIds_mat.at<int>(i, 0));
361+
}
362+
END_WRAP
363+
}
364+
365+
CVAPI(ExceptionStatus) aruco_drawDetectedCornersCharuco(
366+
cv::_InputOutputArray* image,
367+
std::vector<cv::Point2f>* corners,
368+
std::vector<int>* ids,
369+
MyCvScalar cornerColor)
370+
{
371+
BEGIN_WRAP
372+
cv::aruco::drawDetectedCornersCharuco(*image, *corners, *ids, cpp(cornerColor));
373+
END_WRAP
374+
}

0 commit comments

Comments
 (0)