c# - C# 中 OnnxRuntime 张量的高效位图

标签 c# image tensor onnxruntime microsoft.ml

我正在使用 Microsoft OnnxRuntime 来检测和分类图像中的对象,我想将其应用于实时视频。为此,我必须将每一帧转换为 OnnxRuntime 张量。现在我已经实现了一个大约需要 300 毫秒的方法:

public Tensor<float> ConvertImageToFloatTensor(Bitmap image)
    {
        // Create the Tensor with the appropiate dimensions  for the NN
        Tensor<float> data = new DenseTensor<float>(new[] { 1, image.Width, image.Height, 3 });

        // Iterate over the bitmap width and height and copy each pixel
        for (int x = 0; x < image.Width; x++)
        {
            for (int y = 0; y < image.Height; y++)
            {
                Color color = image.GetPixel(x, y);

                data[0, y, x, 0] = color.R / (float)255.0;
                data[0, y, x, 1] = color.G / (float)255.0;
                data[0, y, x, 2] = color.B / (float)255.0;
            }
        }

        return data;
    }

我需要这段代码尽可能快地运行,因为我将检测器的输出边界框表示为视频顶部的一层。有谁知道进行这种转换的更快方法?

最佳答案

根据 davidtbernal ( Fast work with Bitmaps in C# ) 和 FelipeDurar ( Grayscale image from binary data ) 的答案,您应该能够使用 LockBits 和一些“不安全”代码更快地访问像素

public Tensor<float> ConvertImageToFloatTensorUnsafe(Bitmap image)
{
    // Create the Tensor with the appropiate dimensions  for the NN
    Tensor<float> data = new DenseTensor<float>(new[] { 1, image.Width, image.Height, 3 });    
    
    BitmapData bmd = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat);
    int PixelSize = 3;

    unsafe
    {
        for (int y = 0; y < bmd.Height; y++)
        {
            // row is a pointer to a full row of data with each of its colors
            byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);
            for (int x = 0; x < bmd.Width; x++)
            {           
                // note the order of colors is BGR
                data[0, y, x, 0] = row[x*PixelSize + 2] / (float)255.0;
                data[0, y, x, 1] = row[x*PixelSize + 1] / (float)255.0;
                data[0, y, x, 2] = row[x*PixelSize + 0] / (float)255.0;
            }
        }

        image.UnlockBits(bmd);
    }
    return data;
}
我已经比较了这段代码,平均运行 1000 多次,与原始代码相比,性能提高了大约 3 倍,但结果可能会有所不同。
另请注意,我每个像素使用了 3 个 channel ,因为您的原始答案仅使用这些值,如果您使用 32bpp 位图,则可以将 PixelSize 更改为 4,最后一个 channel 应为 alpha channel (行 [x*PixelSize + 3])

关于c# - C# 中 OnnxRuntime 张量的高效位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62470779/

相关文章:

python - Pytorch 跨不同数组的行进行点积

c# - .NET 4.0 进程中的 clr.dll!LogHelp_TerminateOnAssert

c# - 空的序列化 XML 文件

C# DispatcherHelper.CheckBeginInvokeOnUI 不会在 UnitTest 上运行

image - docker中的图层和图像有什么区别?

html - 如何在鼠标悬停(悬停)时更改图像 <img>

ruby - 如何区分没有颜色的像素和黑色像素?

C#、WPF、MVVM 和 INotifyPropertyChanged

python - 带有 requires_grad 参数的 torch.Tensor()

python - PyTorch 张量的加权平均值