opencvsharp icon indicating copy to clipboard operation
opencvsharp copied to clipboard

An indexing error using the Mat.Row function?

Open MikePelton opened this issue 7 months ago • 1 comments

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;
        }
    }
}

MikePelton avatar Jul 02 '25 11:07 MikePelton

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.

mrwangshipei avatar Jul 25 '25 10:07 mrwangshipei