File tree Expand file tree Collapse file tree
src/OpenCvSharp/Modules/core/Mat
test/OpenCvSharp.Tests/core Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -4283,6 +4283,19 @@ public unsafe Span<T> RowSpan<T>(int row) where T : unmanaged
42834283 /// <typeparam name="T">Element type. Must match the matrix element type (e.g. <see cref="Vec3b"/> for CV_8UC3).</typeparam>
42844284 /// <returns>A <see cref="MatRowAccessor{T}"/> over this matrix.</returns>
42854285 /// <exception cref="InvalidOperationException">Thrown when the matrix is not 2-dimensional.</exception>
4286+ /// <remarks>
4287+ /// <b>Parallel usage:</b> Because <see cref="MatRowAccessor{T}"/> is a <c>ref struct</c> it cannot be
4288+ /// captured by a lambda closure. Call this method inside each <c>Parallel.For</c> iteration to obtain
4289+ /// a per-thread local accessor:
4290+ /// <code>
4291+ /// Parallel.For(0, mat.Rows, y =>
4292+ /// {
4293+ /// Span<float> row = mat.AsRows<float>()[y];
4294+ /// for (int x = 0; x < row.Length; x++)
4295+ /// row[x] = ComputeValue(y, x);
4296+ /// });
4297+ /// </code>
4298+ /// </remarks>
42864299 public unsafe MatRowAccessor < T > AsRows < T > ( ) where T : unmanaged
42874300 {
42884301 ThrowIfDisposed ( ) ;
Original file line number Diff line number Diff line change 2525/// This is a <c>ref struct</c> and therefore cannot be stored in fields, boxed, or used as a
2626/// generic type argument.
2727/// </para>
28+ /// <para>
29+ /// <b>Parallel usage:</b> <see cref="MatRowAccessor{T}"/> is safe to use concurrently from multiple threads
30+ /// as long as each thread writes to a distinct set of rows. Because <see cref="MatRowAccessor{T}"/> is a
31+ /// <c>ref struct</c> it cannot be captured by a lambda closure; instead, call <see cref="Mat.AsRows{T}"/>
32+ /// inside each iteration to obtain a per-thread local accessor:
33+ /// <code>
34+ /// Parallel.For(0, mat.Rows, y =>
35+ /// {
36+ /// Span<float> row = mat.AsRows<float>()[y];
37+ /// for (int x = 0; x < row.Length; x++)
38+ /// row[x] = ComputeValue(y, x);
39+ /// });
40+ /// </code>
41+ /// </para>
2842/// </remarks>
2943public readonly ref struct MatRowAccessor < T > where T : unmanaged
3044{
Original file line number Diff line number Diff line change @@ -1289,4 +1289,41 @@ public void SubmatOfMultiDimensionalMat()
12891289 }
12901290 }
12911291 }
1292+
1293+ // Regression test for https://github.com/shimat/opencvsharp/issues/1889
1294+ [ Fact ]
1295+ public void AsRowsParallelFor ( )
1296+ {
1297+ const int rows = 500 ;
1298+ const int cols = 1_000 ;
1299+
1300+ using var matX = new Mat ( rows , cols , MatType . CV_32FC1 ) ;
1301+ using var matY = new Mat ( rows , cols , MatType . CV_32FC1 ) ;
1302+ matX . SetTo ( Scalar . All ( 0f ) ) ;
1303+ matY . SetTo ( Scalar . All ( 0f ) ) ;
1304+
1305+ Parallel . For ( 0 , rows , y =>
1306+ {
1307+ var rowX = matX . AsRows < float > ( ) [ y ] ;
1308+ var rowY = matY . AsRows < float > ( ) [ y ] ;
1309+ for ( var x = 0 ; x < cols ; x ++ )
1310+ {
1311+ rowX [ x ] = 11f ;
1312+ rowY [ x ] = 12f ;
1313+ }
1314+ } ) ;
1315+
1316+ var resultX = matX . AsRows < float > ( ) ;
1317+ var resultY = matY . AsRows < float > ( ) ;
1318+ for ( var y = 0 ; y < rows ; y ++ )
1319+ {
1320+ var rowX = resultX [ y ] ;
1321+ var rowY = resultY [ y ] ;
1322+ for ( var x = 0 ; x < cols ; x ++ )
1323+ {
1324+ Assert . Equal ( 11f , rowX [ x ] ) ;
1325+ Assert . Equal ( 12f , rowY [ x ] ) ;
1326+ }
1327+ }
1328+ }
12921329}
You can’t perform that action at this time.
0 commit comments