Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 85 additions & 31 deletions src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_aruco.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using OpenCvSharp.Aruco;

#pragma warning disable 1591
Expand All @@ -9,67 +9,121 @@ namespace OpenCvSharp.Internal;

static partial class NativeMethods
{
[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_detectMarkers(
IntPtr image, IntPtr dictionary, IntPtr corners, IntPtr ids, ref DetectorParameters detectParameters, IntPtr outrejectedImgPoints);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_drawDetectedMarkers(
IntPtr image,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
IntPtr image,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
[MarshalAs(UnmanagedType.LPArray)] int[] ids, int idxLength, Scalar borderColor);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_drawDetectedMarkers(
IntPtr image, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2, IntPtr ids, int idxLength, Scalar borderColor);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_estimatePoseSingleMarkers(
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornersLength1,
int[] cornersLengths2, float markerLength,
IntPtr cameraMatrix, IntPtr distCoeffs, IntPtr rvecs, IntPtr tvecs, IntPtr objPoints);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_getPredefinedDictionary(int name, out IntPtr returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_readDictionary(string dictionaryFile, out IntPtr returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_detectCharucoDiamond(
IntPtr image, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] markerCorners, int markerCornersSize1, int[] markerCornersSize2,
IntPtr markerIds, float squareMarkerLengthRate,
IntPtr diamondCorners, IntPtr diamondIds, IntPtr cameraMatrix, IntPtr distCoeffs);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_drawDetectedDiamonds(
IntPtr image,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
IntPtr ids, Scalar borderColor);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_detectCharucoBoard(
public static extern ExceptionStatus aruco_drawDetectedCornersCharuco(
IntPtr image,
int squaresX, int squaresY, float squareLength, float markerLength, int arucoDictId,
IntPtr charucoCorners, IntPtr charucoIds, IntPtr markerCorners, IntPtr markerIds);
IntPtr corners, IntPtr ids, Scalar cornerColor);

#region ArucoDetector

[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);
public static extern ExceptionStatus aruco_ArucoDetector_create(
IntPtr dictionary, ref DetectorParameters detectorParams, ref RefineParameters refineParams, out IntPtr returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_drawDetectedCornersCharuco(
IntPtr image,
IntPtr corners, IntPtr ids, Scalar cornerColor);
public static extern ExceptionStatus aruco_ArucoDetector_delete(IntPtr ptr);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_ArucoDetector_detectMarkers(
IntPtr detector, IntPtr image, IntPtr corners, IntPtr ids, IntPtr rejectedImgPoints);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_ArucoDetector_refineDetectedMarkers(
IntPtr detector, IntPtr image, IntPtr board,
IntPtr detectedCorners, IntPtr detectedIds, IntPtr rejectedCorners,
IntPtr cameraMatrix, IntPtr distCoeffs, IntPtr recoveredIdxs);

#endregion

#region CharucoBoard

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_create(
int squaresX, int squaresY, float squareLength, float markerLength, IntPtr dictionary, out IntPtr returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_delete(IntPtr ptr);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_getChessboardSize(IntPtr ptr, out Size returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_getSquareLength(IntPtr ptr, out float returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_getMarkerLength(IntPtr ptr, out float returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_setLegacyPattern(IntPtr ptr, int value);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_getLegacyPattern(IntPtr ptr, out int returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_generateImage(
IntPtr ptr, Size outSize, IntPtr img, int marginSize, int borderBits);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoBoard_checkCharucoCornersCollinear(
IntPtr ptr, IntPtr charucoIds, out int returnValue);

#endregion

#region CharucoDetector

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoDetector_create(
IntPtr board, IntPtr cameraMatrix, IntPtr distCoeffs,
int minMarkers,
[MarshalAs(UnmanagedType.U1)] bool tryRefineMarkers,
[MarshalAs(UnmanagedType.U1)] bool checkMarkers,
ref DetectorParameters detectorParams, ref RefineParameters refineParams,
out IntPtr returnValue);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoDetector_delete(IntPtr ptr);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoDetector_detectBoard(
IntPtr detector, IntPtr image,
IntPtr charucoCorners, IntPtr charucoIds,
IntPtr markerCorners, IntPtr markerIds);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_CharucoDetector_detectDiamonds(
IntPtr detector, IntPtr image,
IntPtr diamondCorners, IntPtr diamondIds,
IntPtr markerCorners, IntPtr markerIds);

#endregion

#region Dictionary

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_Dictionary_delete(IntPtr ptr);

[DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus aruco_Dictionary_setMarkerSize(IntPtr obj, int value);

Expand Down
63 changes: 63 additions & 0 deletions src/OpenCvSharp/Modules/aruco/ArucoDetector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using OpenCvSharp.Internal;
using OpenCvSharp.Internal.Vectors;

namespace OpenCvSharp.Aruco;

/// <summary>
/// The main functionality of ArucoDetector class is detection of markers in an image with detectMarkers() method.
/// </summary>
public class ArucoDetector : CvObject
{
/// <summary>
/// Creates ArucoDetector with default parameters.
/// </summary>
public ArucoDetector(Dictionary dictionary)
: this(dictionary, new DetectorParameters(), new RefineParameters())
{
}

/// <summary>
/// Creates ArucoDetector.
/// </summary>
public ArucoDetector(Dictionary dictionary, DetectorParameters detectorParams, RefineParameters refineParams)
{
if (dictionary is null)
throw new ArgumentNullException(nameof(dictionary));
dictionary.ThrowIfDisposed();

NativeMethods.HandleException(
NativeMethods.aruco_ArucoDetector_create(dictionary.CvPtr, ref detectorParams, ref refineParams, out var ptr));
SetSafeHandle(new OpenCvPtrSafeHandle(ptr, true,
static h => NativeMethods.HandleException(NativeMethods.aruco_ArucoDetector_delete(h))));
GC.KeepAlive(dictionary);
}

/// <summary>
/// Basic marker detection.
/// </summary>
public void DetectMarkers(
InputArray image,
out Point2f[][] corners,
out int[] ids,
out Point2f[][] rejectedImgPoints)
{
if (image is null)
throw new ArgumentNullException(nameof(image));
ThrowIfDisposed();

using var cornersVec = new VectorOfVectorPoint2f();
using var idsVec = new VectorOfInt32();
using var rejectedVec = new VectorOfVectorPoint2f();

NativeMethods.HandleException(
NativeMethods.aruco_ArucoDetector_detectMarkers(
CvPtr, image.CvPtr, cornersVec.CvPtr, idsVec.CvPtr, rejectedVec.CvPtr));

corners = cornersVec.ToArray();
ids = idsVec.ToArray();
rejectedImgPoints = rejectedVec.ToArray();

GC.KeepAlive(this);
GC.KeepAlive(image);
}
}
136 changes: 136 additions & 0 deletions src/OpenCvSharp/Modules/aruco/CharucoBoard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using OpenCvSharp.Internal;

namespace OpenCvSharp.Aruco;

/// <summary>
/// ChArUco board — a planar chessboard where the markers are placed inside the white squares.
/// </summary>
public class CharucoBoard : CvObject
{
/// <summary>
/// Creates a CharucoBoard.
/// </summary>
/// <param name="squaresX">number of chessboard squares in x direction</param>
/// <param name="squaresY">number of chessboard squares in y direction</param>
/// <param name="squareLength">chessboard square side length (normally in meters)</param>
/// <param name="markerLength">marker side length (same unit as squareLength)</param>
/// <param name="dictionary">dictionary of markers</param>
public CharucoBoard(int squaresX, int squaresY, float squareLength, float markerLength, Dictionary dictionary)
{
if (dictionary is null)
throw new ArgumentNullException(nameof(dictionary));
dictionary.ThrowIfDisposed();

NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_create(squaresX, squaresY, squareLength, markerLength, dictionary.CvPtr, out var ptr));
SetSafeHandle(new OpenCvPtrSafeHandle(ptr, true,
static h => NativeMethods.HandleException(NativeMethods.aruco_CharucoBoard_delete(h))));
GC.KeepAlive(dictionary);
}

internal CharucoBoard(IntPtr ptr)
{
SetSafeHandle(new OpenCvPtrSafeHandle(ptr, true,
static h => NativeMethods.HandleException(NativeMethods.aruco_CharucoBoard_delete(h))));
}

/// <summary>
/// Gets the number of chessboard squares in x and y directions.
/// </summary>
public Size ChessboardSize
{
get
{
ThrowIfDisposed();
NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_getChessboardSize(CvPtr, out var size));
GC.KeepAlive(this);
return size;
}
}

/// <summary>
/// Gets the chessboard square side length.
/// </summary>
public float SquareLength
{
get
{
ThrowIfDisposed();
NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_getSquareLength(CvPtr, out var val));
GC.KeepAlive(this);
return val;
}
}

/// <summary>
/// Gets the marker side length.
/// </summary>
public float MarkerLength
{
get
{
ThrowIfDisposed();
NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_getMarkerLength(CvPtr, out var val));
GC.KeepAlive(this);
return val;
}
}

/// <summary>
/// Gets or sets the legacy pattern mode for compatibility with patterns created before OpenCV 4.6.
/// </summary>
public bool LegacyPattern
{
get
{
ThrowIfDisposed();
NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_getLegacyPattern(CvPtr, out var val));
GC.KeepAlive(this);
return val != 0;
}
set
{
ThrowIfDisposed();
NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_setLegacyPattern(CvPtr, value ? 1 : 0));
GC.KeepAlive(this);
}
}

/// <summary>
/// Generate the board image.
/// </summary>
public void GenerateImage(Size outSize, OutputArray img, int marginSize = 0, int borderBits = 1)
{
if (img is null)
throw new ArgumentNullException(nameof(img));
img.ThrowIfNotReady();
ThrowIfDisposed();

NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_generateImage(CvPtr, outSize, img.CvPtr, marginSize, borderBits));
img.Fix();
GC.KeepAlive(this);
}

/// <summary>
/// Check whether the ChArUco markers are collinear.
/// </summary>
public bool CheckCharucoCornersCollinear(InputArray charucoIds)
{
if (charucoIds is null)
throw new ArgumentNullException(nameof(charucoIds));
charucoIds.ThrowIfDisposed();
ThrowIfDisposed();

NativeMethods.HandleException(
NativeMethods.aruco_CharucoBoard_checkCharucoCornersCollinear(CvPtr, charucoIds.CvPtr, out var ret));
GC.KeepAlive(this);
GC.KeepAlive(charucoIds);
return ret != 0;
}
}
Loading
Loading