Skip to content

Commit 26b961f

Browse files
authored
Merge pull request #901 from shimat/fix_ffmpeg
Fix .props & enhance Aruco
2 parents 435eb38 + 673c8b2 commit 26b961f

File tree

11 files changed

+413
-34
lines changed

11 files changed

+413
-34
lines changed

nuget/OpenCvSharp4.runtime.win.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Link>dll\x86\OpenCvSharpExtern.dll</Link>
88
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
99
</Content>
10-
<Content Include="$(NativeDlls)\win-x86\native\opencv_videoio_ffmpeg420.dll">
10+
<Content Include="$(NativeDlls)\win-x86\native\opencv_videoio_ffmpeg430.dll">
1111
<Link>dll\x86\opencv_videoio_ffmpeg430.dll</Link>
1212
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1313
</Content>
@@ -17,7 +17,7 @@
1717
<Link>dll\x64\OpenCvSharpExtern.dll</Link>
1818
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1919
</Content>
20-
<Content Include="$(NativeDlls)\win-x64\native\opencv_videoio_ffmpeg420_64.dll">
20+
<Content Include="$(NativeDlls)\win-x64\native\opencv_videoio_ffmpeg430_64.dll">
2121
<Link>dll\x64\opencv_videoio_ffmpeg430_64.dll</Link>
2222
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2323
</Content>

src/OpenCvSharp/Modules/aruco/CvAruco.cs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,45 @@ public static void DrawMarker(Dictionary dictionary, int id, int sidePixels, Out
187187
GC.KeepAlive(mat);
188188
}
189189

190+
/// <summary>
191+
/// Draw coordinate system axis from pose estimation.
192+
/// </summary>
193+
/// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param>
194+
/// <param name="cameraMatrix">input 3x3 floating-point camera matrix</param>
195+
/// <param name="distCoeffs">vector of distortion coefficients (k1,k2,p1,p2[,k3[,k4,k5,k6],[s1,s2,s3,s4]]) of 4, 5, 8 or 12 elements</param>
196+
/// <param name="rvec">rotation vector of the coordinate system that will be drawn.</param>
197+
/// <param name="tvec">translation vector of the coordinate system that will be drawn.</param>
198+
/// <param name="length">length of the painted axis in the same unit than tvec (usually in meters)</param>
199+
public static void DrawAxis(InputOutputArray image, InputArray cameraMatrix, InputArray distCoeffs, InputArray rvec, InputArray tvec, float length)
200+
{
201+
if (image == null)
202+
throw new ArgumentNullException(nameof(image));
203+
if (cameraMatrix == null)
204+
throw new ArgumentNullException(nameof(cameraMatrix));
205+
if (distCoeffs == null)
206+
throw new ArgumentNullException(nameof(distCoeffs));
207+
if (rvec == null)
208+
throw new ArgumentNullException(nameof(rvec));
209+
if (tvec == null)
210+
throw new ArgumentNullException(nameof(tvec));
211+
212+
image.ThrowIfDisposed();
213+
cameraMatrix.ThrowIfDisposed();
214+
distCoeffs.ThrowIfDisposed();
215+
rvec.ThrowIfDisposed();
216+
tvec.ThrowIfDisposed();
217+
218+
NativeMethods.HandleException(
219+
NativeMethods.aruco_drawAxis(image.CvPtr, cameraMatrix.CvPtr, distCoeffs.CvPtr,
220+
rvec.CvPtr, tvec.CvPtr, length));
221+
222+
GC.KeepAlive(image);
223+
GC.KeepAlive(cameraMatrix);
224+
GC.KeepAlive(distCoeffs);
225+
GC.KeepAlive(rvec);
226+
GC.KeepAlive(tvec);
227+
}
228+
190229
/// <summary>
191230
/// Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME
192231
/// </summary>
@@ -198,5 +237,108 @@ public static Dictionary GetPredefinedDictionary(PredefinedDictionaryName name)
198237
NativeMethods.aruco_getPredefinedDictionary((int) name, out IntPtr p));
199238
return new Dictionary(p);
200239
}
240+
241+
/// <summary>
242+
/// Detect ChArUco Diamond markers.
243+
/// </summary>
244+
/// <param name="image">input image necessary for corner subpixel.</param>
245+
/// <param name="markerCorners">list of detected marker corners from detectMarkers function.</param>
246+
/// <param name="markerIds">list of marker ids in markerCorners.</param>
247+
/// <param name="squareMarkerLengthRate">rate between square and marker length: squareMarkerLengthRate = squareLength/markerLength. The real units are not necessary.</param>
248+
/// <param name="diamondCorners">output list of detected diamond corners (4 corners per diamond). The order is the same than in marker corners: top left, top right, bottom right and bottom left. Similar format than the corners returned by detectMarkers (e.g std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt;).</param>
249+
/// <param name="diamondIds">ids of the diamonds in diamondCorners. The id of each diamond is in fact of type Vec4i, so each diamond has 4 ids, which are the ids of the aruco markers composing the diamond.</param>
250+
/// <param name="cameraMatrix">Optional camera calibration matrix.</param>
251+
/// <param name="distCoeffs">Optional camera distortion coefficients.</param>
252+
public static void DetectCharucoDiamond(InputArray image, Point2f[][] markerCorners, IEnumerable<int> markerIds,
253+
float squareMarkerLengthRate, out Point2f[][] diamondCorners, out Vec4i[] diamondIds,
254+
InputArray? cameraMatrix = null, InputArray? distCoeffs = null)
255+
{
256+
if (image == null)
257+
throw new ArgumentNullException(nameof(image));
258+
if (markerCorners == null)
259+
throw new ArgumentNullException(nameof(markerCorners));
260+
if (markerIds == null)
261+
throw new ArgumentNullException(nameof(markerIds));
262+
263+
if (cameraMatrix == null && distCoeffs != null)
264+
throw new ArgumentNullException(nameof(cameraMatrix));
265+
if (cameraMatrix != null && distCoeffs == null)
266+
throw new ArgumentNullException(nameof(distCoeffs));
267+
268+
image.ThrowIfDisposed();
269+
270+
cameraMatrix?.ThrowIfDisposed();
271+
distCoeffs?.ThrowIfDisposed();
272+
273+
using var markerCornersAddress = new ArrayAddress2<Point2f>(markerCorners);
274+
using var markerIdsVec = new VectorOfInt32(markerIds);
275+
276+
using var diamondCornersVec = new VectorOfVectorPoint2f();
277+
using var diamondIdsVec = new VectorOfVec4i();
278+
279+
NativeMethods.HandleException(
280+
NativeMethods.aruco_detectCharucoDiamond(
281+
image.CvPtr, markerCornersAddress.GetPointer(), markerCornersAddress.GetDim1Length(), markerCornersAddress.GetDim2Lengths(),
282+
markerIdsVec.CvPtr, squareMarkerLengthRate,
283+
diamondCornersVec.CvPtr, diamondIdsVec.CvPtr,
284+
cameraMatrix?.CvPtr ?? IntPtr.Zero, distCoeffs?.CvPtr ?? IntPtr.Zero));
285+
286+
diamondCorners = diamondCornersVec.ToArray();
287+
diamondIds = diamondIdsVec.ToArray();
288+
289+
GC.KeepAlive(image);
290+
if (cameraMatrix != null)
291+
GC.KeepAlive(cameraMatrix);
292+
if (distCoeffs != null)
293+
GC.KeepAlive(distCoeffs);
294+
}
295+
296+
/// <summary>
297+
/// Draw a set of detected ChArUco Diamond markers.
298+
/// </summary>
299+
/// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param>
300+
/// <param name="diamondCorners">positions of diamond corners in the same format returned by detectCharucoDiamond(). (e.g std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt;). For N detected markers, the dimensions of this array should be Nx4. The order of the corners should be clockwise.</param>
301+
/// <param name="diamondIds">vector of identifiers for diamonds in diamondCorners, in the same format returned by detectCharucoDiamond() (e.g. std::vector&lt;Vec4i&gt;). Optional, if not provided, ids are not painted.</param>
302+
public static void DrawDetectedDiamonds(InputArray image, Point2f[][] diamondCorners, IEnumerable<Vec4i>? diamondIds = null)
303+
{
304+
DrawDetectedDiamonds(image, diamondCorners, diamondIds, new Scalar(0, 0, 255));
305+
}
306+
307+
/// <summary>
308+
/// Draw a set of detected ChArUco Diamond markers.
309+
/// </summary>
310+
/// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param>
311+
/// <param name="diamondCorners">positions of diamond corners in the same format returned by detectCharucoDiamond(). (e.g std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt;). For N detected markers, the dimensions of this array should be Nx4. The order of the corners should be clockwise.</param>
312+
/// <param name="diamondIds">vector of identifiers for diamonds in diamondCorners, in the same format returned by detectCharucoDiamond() (e.g. std::vector&lt;Vec4i&gt;). Optional, if not provided, ids are not painted.</param>
313+
/// <param name="borderColor">color of marker borders. Rest of colors (text color and first corner color) are calculated based on this one.</param>
314+
public static void DrawDetectedDiamonds(InputArray image,
315+
Point2f[][] diamondCorners, IEnumerable<Vec4i>? diamondIds, Scalar borderColor)
316+
{
317+
if (image == null)
318+
throw new ArgumentNullException(nameof(image));
319+
if (diamondCorners == null)
320+
throw new ArgumentNullException(nameof(diamondCorners));
321+
322+
using var cornersAddress = new ArrayAddress2<Point2f>(diamondCorners);
323+
324+
if (diamondIds == null)
325+
{
326+
NativeMethods.HandleException(
327+
NativeMethods.aruco_drawDetectedDiamonds(image.CvPtr,
328+
cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(),
329+
IntPtr.Zero, borderColor));
330+
}
331+
else
332+
{
333+
using var ids = new VectorOfVec4i(diamondIds);
334+
335+
NativeMethods.HandleException(
336+
NativeMethods.aruco_drawDetectedDiamonds(image.CvPtr,
337+
cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(),
338+
ids.CvPtr, borderColor));
339+
}
340+
341+
GC.KeepAlive(image);
342+
}
201343
}
202344
}

src/OpenCvSharp/Modules/aruco/DetectorParameters.cs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Runtime.InteropServices;
1+
using System;
2+
using System.Runtime.InteropServices;
23

34
namespace OpenCvSharp.Aruco
45
{
@@ -213,6 +214,91 @@ public double ErrorCorrectionRate
213214
set => Native.errorCorrectionRate = value;
214215
}
215216

217+
/// <summary>
218+
/// Detection of quads can be done on a lower-resolution image, improving speed at a cost of pose accuracy and a slight decrease in detection rate.
219+
/// Decoding the binary payload is still done at full resolution.
220+
/// </summary>
221+
public float AprilTagQuadDecimate
222+
{
223+
get => Native.aprilTagQuadDecimate;
224+
set => Native.aprilTagQuadDecimate = value;
225+
}
226+
227+
/// <summary>
228+
/// What Gaussian blur should be applied to the segmented image (used for quad detection?) Parameter is the standard deviation in pixels.
229+
/// Very noisy images benefit from non-zero values (e.g. 0.8).
230+
/// </summary>
231+
public float AprilTagQuadSigma
232+
{
233+
get => Native.aprilTagQuadSigma;
234+
set => Native.aprilTagQuadSigma = value;
235+
}
236+
237+
/// <summary>
238+
/// reject quads containing too few pixels.
239+
/// </summary>
240+
public int AprilTagMinClusterPixels
241+
{
242+
get => Native.aprilTagMinClusterPixels;
243+
set => Native.aprilTagMinClusterPixels = value;
244+
}
245+
246+
/// <summary>
247+
/// how many corner candidates to consider when segmenting a group of pixels into a quad.
248+
/// </summary>
249+
public int AprilTagMaxNmaxima
250+
{
251+
get => Native.aprilTagMaxNmaxima;
252+
set => Native.aprilTagMaxNmaxima = value;
253+
}
254+
255+
/// <summary>
256+
/// Reject quads where pairs of edges have angles that are close to straight or close to 180 degrees. Zero means that no quads are rejected. (In radians).
257+
/// </summary>
258+
public float AprilTagCriticalRad
259+
{
260+
get => Native.aprilTagCriticalRad;
261+
set => Native.aprilTagCriticalRad = value;
262+
}
263+
264+
/// <summary>
265+
/// When fitting lines to the contours, what is the maximum mean squared error allowed?
266+
/// This is useful in rejecting contours that are far from being quad shaped; rejecting these quads "early" saves expensive decoding processing.
267+
/// </summary>
268+
public float AprilTagMaxLineFitMse
269+
{
270+
get => Native.aprilTagMaxLineFitMse;
271+
set => Native.aprilTagMaxLineFitMse = value;
272+
}
273+
274+
/// <summary>
275+
/// should the thresholded image be deglitched? Only useful for very noisy images
276+
/// </summary>
277+
public bool AprilTagDeglitch
278+
{
279+
get => Convert.ToBoolean(Native.aprilTagDeglitch);
280+
set => Native.aprilTagDeglitch = Convert.ToInt32(value);
281+
}
282+
283+
/// <summary>
284+
/// When we build our model of black &amp; white pixels, we add an extra check that the white model must be (overall) brighter than the black model.
285+
/// How much brighter? (in pixel values, [0,255]).
286+
/// </summary>
287+
public int AprilTagMinWhiteBlackDiff
288+
{
289+
get => Native.aprilTagMinWhiteBlackDiff;
290+
set => Native.aprilTagMinWhiteBlackDiff = value;
291+
}
292+
293+
/// <summary>
294+
/// to check if there is a white marker. In order to generate a "white" marker just invert a normal marker by using a tilde, ~markerImage. (default false)
295+
/// </summary>
296+
public bool DetectInvertedMarker
297+
{
298+
get => Convert.ToBoolean(Native.detectInvertedMarker);
299+
set => Native.detectInvertedMarker = Convert.ToInt32(value);
300+
}
301+
216302
#pragma warning disable CA1051
217303
#pragma warning disable 1591
218304
[StructLayout(LayoutKind.Sequential)]
@@ -238,6 +324,15 @@ public struct NativeStruct
238324
public double maxErroneousBitsInBorderRate;
239325
public double minOtsuStdDev;
240326
public double errorCorrectionRate;
327+
public float aprilTagQuadDecimate;
328+
public float aprilTagQuadSigma;
329+
public int aprilTagMinClusterPixels;
330+
public int aprilTagMaxNmaxima;
331+
public float aprilTagCriticalRad;
332+
public float aprilTagMaxLineFitMse;
333+
public int aprilTagDeglitch;
334+
public int aprilTagMinWhiteBlackDiff;
335+
public int detectInvertedMarker;
241336
}
242337
#pragma warning restore CA1051
243338
#pragma warning restore 1591

src/OpenCvSharp/Modules/aruco/Enum/CornerRefineMethod.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@
66
public enum CornerRefineMethod
77
{
88
/// <summary>
9-
/// default corners
9+
/// Tag and corners detection based on the ArUco approach.
1010
/// </summary>
1111
None,
1212

1313
/// <summary>
14-
/// refine the corners using subpix
14+
/// ArUco approach and refine the corners locations using corner subpixel accuracy.
1515
/// </summary>
1616
Subpix,
1717

1818
/// <summary>
19-
/// refine the corners using the contour-points
19+
/// ArUco approach and refine the corners locations using the contour-points line fitting.
2020
/// </summary>
21-
Contour
21+
Contour,
22+
23+
/// <summary>
24+
/// Tag and corners detection based on the AprilTag 2 approach
25+
/// </summary>
26+
AprilTag
2227
}
2328
}

src/OpenCvSharp/Modules/aruco/Enum/PredefinedDictionaryName.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public enum PredefinedDictionaryName
2323
Dict7X7_100,
2424
Dict7X7_250,
2525
Dict7X7_1000,
26-
DictArucoOriginal
26+
DictArucoOriginal,
27+
DictAprilTag_16h5,
28+
DictAprilTag_25h9,
29+
DictAprilTag_36h10,
30+
DictAprilTag_36h11
2731
}
2832
}

src/OpenCvSharp/PInvoke/NativeMethods/NativeMethods_aruco.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,26 @@ public static extern ExceptionStatus aruco_estimatePoseSingleMarkers(
3737
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornersLength1,
3838
int[] cornersLengths2, float markerLength,
3939
IntPtr cameraMatrix, IntPtr distCoeffs, IntPtr rvecs, IntPtr tvecs, IntPtr objPoints);
40-
40+
41+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
42+
public static extern ExceptionStatus aruco_drawAxis(
43+
IntPtr image, IntPtr cameraMatrix, IntPtr distCoeffs, IntPtr rvec, IntPtr tvec, float length);
44+
4145
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
4246
public static extern ExceptionStatus aruco_getPredefinedDictionary(int name, out IntPtr returnValue);
4347

48+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
49+
public static extern ExceptionStatus aruco_detectCharucoDiamond(
50+
IntPtr image, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] markerCorners, int markerCornersSize1, int[] markerCornersSize2,
51+
IntPtr markerIds, float squareMarkerLengthRate,
52+
IntPtr diamondCorners, IntPtr diamondIds, IntPtr cameraMatrix, IntPtr distCoeffs);
53+
54+
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
55+
public static extern ExceptionStatus aruco_drawDetectedDiamonds(
56+
IntPtr image,
57+
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] corners, int cornerSize1, int[] contoursSize2,
58+
IntPtr ids, Scalar borderColor);
59+
4460
#region Dictionary
4561

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

0 commit comments

Comments
 (0)