【问题标题】:Is there a way to resize an image using GPU?有没有办法使用 GPU 调整图像大小?
【发布时间】:2012-10-19 07:21:14
【问题描述】:

有没有办法使用可通过 .NET 应用程序消耗的 GPU(显卡)来调整图像大小?

我正在寻找一种非常高效的方法来调整图像大小,并且听说 GPU 可以比 CPU 快得多(使用 C# 的 GDI+)。是否有已知的实现或示例代码使用 GPU 来调整我可以在 .NET 中使用的图像大小?

【问题讨论】:

  • Anything 比 GDI+ 快。也许这会有所帮助:opencv.org 可以在 .net 中使用 DLLImport 导入。
  • 这是否使用 GPU 和更优化的 CPU 代码?
  • 根据文档,它使用 GPU,但仅来自 Nvidia (CUDA)。否则CPU。 opencv.willowgarage.com/wiki/OpenCV_GPU
  • 如果你愿意牺牲质量,WIC 大约是fast as it gets。到目前为止,我所见过的基于 GPU 的服务器端处理的所有尝试都未能像基于 CPU 的那样扩展

标签: c# .net gpu imaging


【解决方案1】:

是的,可以使用 GPU 来调整图像大小。这可以使用 DirectX Surfaces 来完成(例如在 C# 中使用 SlimDx)。您应该创建一个表面并将图像移动到该表面,然后您可以仅使用 GPU 将此表面拉伸到所需大小的另一个目标表面,最后从目标表面取回调整大小的图像。在这些情况下,表面的像素格式可能不同,GPU 会自动处理它。但是这里有些事情会影响此操作的性能。在 GPU 和 CPU 之间移动数据是一个耗时的过程。您可以根据自己的情况应用一些技术来提高性能,并避免 CPU 和 GPU 内存之间的额外数据传输。

【讨论】:

    【解决方案2】:

    我使用 WPF 编写了一个快速峰值来检查性能,但我不能肯定地说它使用的是 GPU。

    不过,请参见下文。这会将图像缩放到其原始大小的 33.5(或其他)倍。

    public void Resize()
    {
        double scaleFactor = 33.5;
    
        var originalFileStream = System.IO.File.OpenRead(@"D:\SkyDrive\Pictures\Random\Misc\DoIt.jpg");
    
        var originalBitmapDecoder = JpegBitmapDecoder.Create(originalFileStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
    
        BitmapFrame originalBitmapFrame = originalBitmapDecoder.Frames.First();
    
        var originalPixelFormat = originalBitmapFrame.Format;
    
        TransformedBitmap transformedBitmap =
            new TransformedBitmap(originalBitmapFrame, new System.Windows.Media.ScaleTransform()
            {
                ScaleX = scaleFactor,
                ScaleY = scaleFactor
            });
    
        int stride = ((transformedBitmap.PixelWidth * transformedBitmap.Format.BitsPerPixel) + 7) / 8;
        int pixelCount = (stride * (transformedBitmap.PixelHeight - 1)) + stride;
    
        byte[] buffer = new byte[pixelCount];
    
        transformedBitmap.CopyPixels(buffer, stride, 0);
    
        WriteableBitmap transformedWriteableBitmap = new WriteableBitmap(transformedBitmap.PixelWidth, transformedBitmap.PixelHeight, transformedBitmap.DpiX, transformedBitmap.DpiY, transformedBitmap.Format, transformedBitmap.Palette);
    
        transformedWriteableBitmap.WritePixels(new Int32Rect(0, 0, transformedBitmap.PixelWidth, transformedBitmap.PixelHeight), buffer, stride, 0);
    
        BitmapFrame transformedFrame = BitmapFrame.Create(transformedWriteableBitmap);
    
        var jpegEncoder = new JpegBitmapEncoder();
        jpegEncoder.Frames.Add(transformedFrame);
    
        using (var outputFileStream = System.IO.File.OpenWrite(@"C:\DATA\Scrap\WPF.jpg"))
        {
            jpegEncoder.Save(outputFileStream);
        }
    }
    

    我正在测试的图像是 495 x 360。它在几秒钟内将其大小调整为超过 16k x 12k,包括保存。

    在单核运行中,它以大约每秒 165 次的速度将大小调整为 1.5 倍。在 i7 和 GPU 上似乎什么都不做,20% 的 CPU 我希望多线程时获得 5 倍以上。

    性能分析显示了通往wpfgfx_v0400.dll 的热门路径,它是本机 WPF 图形库,接近 DirectX(在 Google 中查找“milcore”)。

    所以它可能会加速,我不知道。

    卢克

    【讨论】:

      【解决方案3】:

      您是否考虑过使用 XNA 调整图像大小? Here you can find out 如何使用 XNA 将图像作为 png/jpeg 保存到 MemoryStream 并在以后将其重用为 Bitmap 对象:

      编辑:我将在此处发布一个示例(取自上面的链接),说明如何使用 XNA。

      public static Image Texture2Image(Texture2D texture)
      {
          Image img;
          using (MemoryStream MS = new MemoryStream())
          {
              texture.SaveAsPng(MS, texture.Width, texture.Height);
              //Go To the  beginning of the stream.
              MS.Seek(0, SeekOrigin.Begin);
              //Create the image based on the stream.
              img = Bitmap.FromStream(MS);
          }
          return img;
       }
      

      我今天还发现你可以使用 OpenCV 来使用 GPU/多核 CPU。例如,您可以选择使用 .NET 包装器,例如 Emgu,并使用其 Image 类来处理您的图片并返回 .NET Bitmap 类:

      public static Bitmap ResizeBitmap(Bitmap sourceBM, int width, int height)
      {
          // Initialize Emgu Image object
          Image<Bgr, Byte> img = new Image<Bgr, Byte>(sourceBM); 
      
          // Resize using liniear interpolation
          img.Resize(width, height, INTER.CV_INTER_LINEAR);
      
          // Return .NET Bitmap object
          return img.ToBitmap();
      }
      

      【讨论】:

      • 如果您可以发布一个工作示例,以避免链接失效,这将是有帮助的。
      猜你喜欢
      • 1970-01-01
      • 2021-01-30
      • 2021-12-31
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      相关资源
      最近更新 更多