首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#中位图到OnnxRuntime张量的高效实现

C#中位图到OnnxRuntime张量的高效实现
EN

Stack Overflow用户
提问于 2020-06-19 20:54:38
回答 1查看 929关注 0票数 3

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

代码语言:javascript
复制
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;
    }

我需要这段代码尽可能快地运行,因为我将检测器的输出边界框表示为视频顶部的一个层。有没有人知道做这个conversión的更快的方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-27 15:27:12

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

代码语言:javascript
复制
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个通道,因为您的原始答案仅使用这些值,如果您使用32bpp位图,则可以将PixelSize更改为4,最后一个通道应为alpha通道(rowx*PixelSize + 3)

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62470779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档