An indexing error using the Mat.Row function?
Hi - a repro below of an issue that causes an "attempt to read or write protected memory" access violation. It has all the hallmarks of a "one-off" bug, crashing when iRow is 200 and iCol is 363. The test image is a 364 pixels wide JPG, available here and the data row claims it is Mat with 364 entries.
using OpenCvSharp;
namespace CvSharpTest
{
internal class Program
{
static int Main(string[] args)
{
string inputFilePath = @"D:\MikeP\Images\ATest\ColoursGrid_364x556.jpg";
Mat pixels = Cv2.ImRead(inputFilePath, ImreadModes.Color);
if (pixels == null)
{
Console.WriteLine($"!!! Couldn't open {inputFilePath}");
return 1;
}
int nRows = pixels.Rows;
int nCols = pixels.Cols;
for (int iRow = 0; iRow < nRows; iRow++)
{
var dataRow = pixels.Row(iRow);
for (int iCol = 0; iCol < nCols; iCol++)
{
OpenCvSharp.Vec3b vec3B = dataRow.At<OpenCvSharp.Vec3b>(iCol);
byte r = vec3B.Item2;
byte g = vec3B.Item1;
byte b = vec3B.Item0;
}
dataRow.Dispose();
}
pixels.Dispose();
return 0;
}
}
}
Hi @MikePelton,
Thanks for the detailed repro — I came across a very similar issue while experimenting with OpenCvSharp and did a bit of digging into how Mat.Row() behaves internally.
It looks like the crash may be due to the assumption that Row(i) returns a submatrix where the row data is tightly packed (i.e., step == cols * elemSize()), but in practice, OpenCV often aligns each row with padding for performance reasons (SIMD, memory alignment, etc.).
In the image you're using (364 pixels wide, 3 channels), the actual memory layout likely includes padding at the end of each row, so indexing into that row with At<Vec3b>(iCol) can lead to an out-of-bounds access near the last column. That seems to line up exactly with the crash you're seeing at iCol == 363.
As a workaround, using the full matrix indexing avoids this problem entirely:
for (int iRow = 0; iRow < pixels.Rows; iRow++)
{
for (int iCol = 0; iCol < pixels.Cols; iCol++)
{
Vec3b vec3b = pixels.At<Vec3b>(iRow, iCol);
byte r = vec3b.Item2;
byte g = vec3b.Item1;
byte b = vec3b.Item0;
}
}
From what I can tell, pixels.At(i, j) internally accounts for the full step and padding, while Row(i) gives a submatrix where At(j) assumes no extra padding — which breaks when the row is not tightly packed.
Just thought I'd share in case it's helpful to others who might hit this — I really enjoy working with OpenCvSharp and appreciate all the work on the project.