Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mat.AsSpan() doesn't get correct length #1698

Closed
truebigsand opened this issue Aug 24, 2024 · 1 comment
Closed

Mat.AsSpan() doesn't get correct length #1698

truebigsand opened this issue Aug 24, 2024 · 1 comment

Comments

@truebigsand
Copy link
Contributor

Summary of your issue

I'm currently working on converting Mat to Microsoft.ML.OnnxRuntime.Tensors.Tensor<T>. To be efficient, I used mat.AsSpan() to manually access the data in a CV_8UC3 image. However, it always comes OutOfRange. Referring to the source code below:

/// <summary>
/// Creates a new span over the Mat.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public unsafe Span<T> AsSpan<T>() where T : unmanaged
=> IsContinuous() ? new Span<T>(DataPointer, (int)Total()) : [];

Maybe it should consider the size of T and gets the length like

public unsafe Span<T> AsSpan<T>() where T : unmanaged  
     => IsContinuous() ? new Span<T>(DataPointer, (int)Total() * ElemSize() / sizeof(T)) : []; 

Environment

  • .NET 8.0.302
  • OpenCvSharp4 version 4.10.0.20240616

What did you do when you faced the problem?

Accessing from mat.DataPointer directly just works.

Example code:

Output:

What did you intend to be?

@GuaiGuaiOnMyComputer
Copy link

GuaiGuaiOnMyComputer commented Sep 12, 2024

Having the same issue. Here's a minimal reproducible example using 3-channel Mats. The length of the returned Span is only Width x Height instead of 3 x Width x Height.

    static void ReproduceIndexOutOfRange()
    {
        // Read a jpeg image of format 3-channel 10x20 pixels
        Mat testImage8u = new(10, 20, MatType.CV_8UC3);
        Span<byte> testImageData = testImage8u.AsSpan<byte>();

        for (int i = 0; i < testImage8u.Channels() * testImage8u.Rows * testImage8u.Cols; i++)
            testImageData[i] = 255; // IndexOutOfRangeException at i = 200

        Cv2.ImShow("testImage8u", testImage8u);
        Cv2.WaitKey(0);
    }

But it's not like the span points to a single channel of the image. If I set the bound of the loop to testImage8u.Rows * testImage8u.Cols instead of three times of that to avoid IndexOutOfRangeException like so:

    static void ReproduceIndexOutOfRange()
    {
        // Read a jpeg image of format 3-channel 10x20 pixels
        Mat testImage8u = new(10, 20, MatType.CV_8UC3);
        Span<byte> testImageData = testImage8u.AsSpan<byte>();

        for (int i = 0; i < testImage8u.Rows * testImage8u.Cols; i++)
            testImageData[i] = 255; 

        Cv2.ImShow("testImage8u", testImage8u);
        Cv2.WaitKey(0);
    }

The resulting image looks like this
testImage8u_screenshot_12 09 2024

OpenCvSharp version: 4.9.0.20240103
Os: Linux
.NET version: 8.0.108

@shimat shimat closed this as completed in 3a8eefc Oct 24, 2024
shimat added a commit that referenced this issue Oct 24, 2024
Fix: #1698 fix length of Mat.AsSpan()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants