@@ -7,6 +7,8 @@ namespace OpenCvSharp.Tests.Aruco;
77// ReSharper disable once InconsistentNaming
88public class ArucoTest : TestBase
99{
10+ // ==================== DetectorParameters ====================
11+
1012 [ Fact ]
1113 public void CreateDetectorParameters ( )
1214 {
@@ -47,6 +49,28 @@ public void CreateDetectorParameters()
4749 Assert . Equal ( 0 , param . MinMarkerLengthRatioOriginalImg ) ;
4850 }
4951
52+ // ==================== RefineParameters ====================
53+
54+ [ Fact ]
55+ public void CreateRefineParametersDefaults ( )
56+ {
57+ var param = new RefineParameters ( ) ;
58+ Assert . Equal ( 10f , param . MinRepDistance , 1e-3f ) ;
59+ Assert . Equal ( 3f , param . ErrorCorrectionRate , 1e-3f ) ;
60+ Assert . True ( param . CheckAllOrders ) ;
61+ }
62+
63+ [ Fact ]
64+ public void CreateRefineParametersCustom ( )
65+ {
66+ var param = new RefineParameters ( 5f , 2f , false ) ;
67+ Assert . Equal ( 5f , param . MinRepDistance , 1e-3f ) ;
68+ Assert . Equal ( 2f , param . ErrorCorrectionRate , 1e-3f ) ;
69+ Assert . False ( param . CheckAllOrders ) ;
70+ }
71+
72+ // ==================== Dictionary ====================
73+
5074 [ Fact ]
5175 public void GetPredefinedDictionary ( )
5276 {
@@ -86,16 +110,6 @@ public void ReadDictionaryFromFile()
86110 dict . Dispose ( ) ;
87111 }
88112
89- [ Fact ]
90- public void DetectMarkers ( )
91- {
92- using var image = LoadImage ( "markers_6x6_250.png" , ImreadModes . Grayscale ) ;
93- using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict6X6_250 ) ;
94- using var detector = new ArucoDetector ( dict ) ;
95-
96- detector . DetectMarkers ( image , out _ , out _ , out _ ) ;
97- }
98-
99113 [ Fact ]
100114 public void DictionaryProperties ( )
101115 {
@@ -111,6 +125,69 @@ public void DictionaryProperties()
111125 Assert . Equal ( 50 , dict . MaxCorrectionBits ) ;
112126 }
113127
128+ // ==================== ArucoDetector ====================
129+
130+ [ Fact ]
131+ public void ArucoDetector_CreateDefault ( )
132+ {
133+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict6X6_250 ) ;
134+ using var detector = new ArucoDetector ( dict ) ;
135+ Assert . NotNull ( detector ) ;
136+ }
137+
138+ [ Fact ]
139+ public void ArucoDetector_CreateWithCustomParams ( )
140+ {
141+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict6X6_250 ) ;
142+ var dp = new DetectorParameters { CornerRefinementMethod = CornerRefineMethod . Subpix } ;
143+ var rp = new RefineParameters ( 5f , 2f , false ) ;
144+ using var detector = new ArucoDetector ( dict , dp , rp ) ;
145+ Assert . NotNull ( detector ) ;
146+ }
147+
148+ [ Fact ]
149+ public void ArucoDetector_DetectMarkers ( )
150+ {
151+ using var image = LoadImage ( "markers_6x6_250.png" , ImreadModes . Grayscale ) ;
152+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict6X6_250 ) ;
153+ using var detector = new ArucoDetector ( dict ) ;
154+
155+ detector . DetectMarkers ( image , out var corners , out var ids , out var rejectedImgPoints ) ;
156+
157+ Assert . NotNull ( corners ) ;
158+ Assert . NotNull ( ids ) ;
159+ Assert . NotNull ( rejectedImgPoints ) ;
160+ Assert . True ( ids . Length > 0 , "Expected at least one marker to be detected" ) ;
161+ Assert . Equal ( ids . Length , corners . Length ) ;
162+ foreach ( var markerCorners in corners )
163+ Assert . Equal ( 4 , markerCorners . Length ) ;
164+ }
165+
166+ [ Fact ]
167+ public void ArucoDetector_DetectMarkersWithCustomParams ( )
168+ {
169+ using var image = LoadImage ( "markers_6x6_250.png" , ImreadModes . Grayscale ) ;
170+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict6X6_250 ) ;
171+ var dp = new DetectorParameters { CornerRefinementMethod = CornerRefineMethod . Subpix } ;
172+ using var detector = new ArucoDetector ( dict , dp , new RefineParameters ( ) ) ;
173+
174+ detector . DetectMarkers ( image , out var corners , out var ids , out _ ) ;
175+
176+ Assert . True ( ids . Length > 0 ) ;
177+ Assert . Equal ( ids . Length , corners . Length ) ;
178+ }
179+
180+ [ Fact ]
181+ public void ArucoDetector_Dispose ( )
182+ {
183+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
184+ var detector = new ArucoDetector ( dict ) ;
185+ detector . Dispose ( ) ;
186+ Assert . True ( detector . IsDisposed ) ;
187+ }
188+
189+ // ==================== DrawDetected* ====================
190+
114191 [ Fact ]
115192 public void DrawDetectedMarker ( )
116193 {
@@ -121,14 +198,173 @@ public void DrawDetectedMarker()
121198 detector . DetectMarkers ( image , out var corners , out var ids , out var rejectedImgPoints ) ;
122199
123200 CvAruco . DrawDetectedMarkers ( outputImage , corners , ids , new Scalar ( 255 , 0 , 0 ) ) ;
201+ // ids=null path
124202 CvAruco . DrawDetectedMarkers ( outputImage , rejectedImgPoints , null , new Scalar ( 0 , 0 , 255 ) ) ;
125203
126204 if ( Debugger . IsAttached )
127205 {
128- // If you want to save markers image, you must change the following values.
129206 const string path = "C:\\ detected_markers_6x6_250.png" ;
130207 Cv2 . ImWrite ( path , outputImage ) ;
131208 Process . Start ( path ) ;
132209 }
133210 }
211+
212+ // ==================== CharucoBoard ====================
213+
214+ [ Fact ]
215+ public void CharucoBoard_Create ( )
216+ {
217+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
218+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
219+ Assert . NotNull ( board ) ;
220+ }
221+
222+ [ Fact ]
223+ public void CharucoBoard_Properties ( )
224+ {
225+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
226+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
227+
228+ Assert . Equal ( new Size ( 5 , 7 ) , board . ChessboardSize ) ;
229+ Assert . Equal ( 0.04f , board . SquareLength , 1e-5f ) ;
230+ Assert . Equal ( 0.02f , board . MarkerLength , 1e-5f ) ;
231+ }
232+
233+ [ Fact ]
234+ public void CharucoBoard_LegacyPattern ( )
235+ {
236+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
237+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
238+
239+ Assert . False ( board . LegacyPattern ) ;
240+ board . LegacyPattern = true ;
241+ Assert . True ( board . LegacyPattern ) ;
242+ board . LegacyPattern = false ;
243+ Assert . False ( board . LegacyPattern ) ;
244+ }
245+
246+ [ Fact ]
247+ public void CharucoBoard_GenerateImage ( )
248+ {
249+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
250+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
251+ using var img = new Mat ( ) ;
252+
253+ board . GenerateImage ( new Size ( 500 , 700 ) , img ) ;
254+
255+ Assert . False ( img . Empty ( ) ) ;
256+ Assert . Equal ( 700 , img . Rows ) ;
257+ Assert . Equal ( 500 , img . Cols ) ;
258+ }
259+
260+ [ Fact ]
261+ public void CharucoBoard_CheckCharucoCornersCollinear_Collinear ( )
262+ {
263+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
264+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
265+
266+ // IDs on the same row are collinear
267+ var collinearIds = new [ ] { 0 , 1 , 2 , 3 } ;
268+ using var idsMat = Mat . FromArray ( collinearIds ) ;
269+ Assert . True ( board . CheckCharucoCornersCollinear ( idsMat ) ) ;
270+ }
271+
272+ [ Fact ]
273+ public void CharucoBoard_Dispose ( )
274+ {
275+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
276+ var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
277+ board . Dispose ( ) ;
278+ Assert . True ( board . IsDisposed ) ;
279+ }
280+
281+ // ==================== CharucoDetector ====================
282+
283+ [ Fact ]
284+ public void CharucoDetector_Create ( )
285+ {
286+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
287+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
288+ using var detector = new CharucoDetector ( board ) ;
289+ Assert . NotNull ( detector ) ;
290+ }
291+
292+ [ Fact ]
293+ public void CharucoDetector_CreateWithAllParams ( )
294+ {
295+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
296+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
297+ var dp = new DetectorParameters ( ) ;
298+ var rp = new RefineParameters ( ) ;
299+ using var detector = new CharucoDetector ( board , null , null , 2 , false , true , dp , rp ) ;
300+ Assert . NotNull ( detector ) ;
301+ }
302+
303+ [ Fact ]
304+ public void CharucoDetector_DetectBoard ( )
305+ {
306+ // Generate a synthetic charuco board image and detect from it
307+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
308+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
309+ using var boardImage = new Mat ( ) ;
310+ board . GenerateImage ( new Size ( 600 , 800 ) , boardImage , 10 , 1 ) ;
311+
312+ using var detector = new CharucoDetector ( board ) ;
313+ detector . DetectBoard ( boardImage , out var charucoCorners , out var charucoIds ,
314+ out var markerCorners , out var markerIds ) ;
315+
316+ Assert . NotNull ( charucoCorners ) ;
317+ Assert . NotNull ( charucoIds ) ;
318+ Assert . NotNull ( markerCorners ) ;
319+ Assert . NotNull ( markerIds ) ;
320+ Assert . True ( charucoIds . Length > 0 , "Expected at least one charuco corner detected" ) ;
321+ Assert . Equal ( charucoCorners . Length , charucoIds . Length ) ;
322+ Assert . Equal ( markerCorners . Length , markerIds . Length ) ;
323+ }
324+
325+ [ Fact ]
326+ public void CharucoDetector_DetectBoard_EmptyImage ( )
327+ {
328+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
329+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
330+ using var emptyImage = Mat . Zeros ( 300 , 300 , MatType . CV_8UC1 ) ;
331+
332+ using var detector = new CharucoDetector ( board ) ;
333+ detector . DetectBoard ( emptyImage , out var charucoCorners , out var charucoIds ,
334+ out var markerCorners , out var markerIds ) ;
335+
336+ // No markers or corners should be detected in a blank image
337+ Assert . Equal ( 0 , charucoIds . Length ) ;
338+ Assert . Equal ( 0 , markerIds . Length ) ;
339+ }
340+
341+ [ Fact ]
342+ public void CharucoDetector_Dispose ( )
343+ {
344+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
345+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
346+ var detector = new CharucoDetector ( board ) ;
347+ detector . Dispose ( ) ;
348+ Assert . True ( detector . IsDisposed ) ;
349+ }
350+
351+ // ==================== DrawDetectedCornersCharuco / DrawDetectedDiamonds ====================
352+
353+ [ Fact ]
354+ public void DrawDetectedCornersCharuco ( )
355+ {
356+ using var dict = CvAruco . GetPredefinedDictionary ( PredefinedDictionaryType . Dict4X4_50 ) ;
357+ using var board = new CharucoBoard ( 5 , 7 , 0.04f , 0.02f , dict ) ;
358+ using var boardImage = new Mat ( ) ;
359+ board . GenerateImage ( new Size ( 600 , 800 ) , boardImage , 10 , 1 ) ;
360+ using var outputImage = boardImage . CvtColor ( ColorConversionCodes . GRAY2RGB ) ;
361+
362+ using var detector = new CharucoDetector ( board ) ;
363+ detector . DetectBoard ( boardImage , out var charucoCorners , out var charucoIds , out _ , out _ ) ;
364+
365+ // With ids
366+ CvAruco . DrawDetectedCornersCharuco ( outputImage , charucoCorners , charucoIds , new Scalar ( 0 , 255 , 0 ) ) ;
367+ // Without ids (null path)
368+ CvAruco . DrawDetectedCornersCharuco ( outputImage , charucoCorners , null ) ;
369+ }
134370}
0 commit comments