【问题标题】:C# Bitmap GetPixel(), SetPixel() in GPUGPU 中的 C# 位图 GetPixel()、SetPixel()
【发布时间】:2017-02-04 07:21:31
【问题描述】:

我使用 Cudafy 作为 c# 包装器 我需要获取位图的颜色信息InputBitmap0.GetPixel(x, y) 并制作一个新的位图用于输出。

我需要在 GPU 中完成以下工作。

输入 CPU

OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y));

简而言之:

如何在GPU中对输入Bitmap的每个像素点进行GetPixel(),对输出Bitmap的每个像素点进行SetPixel()。

【问题讨论】:

  • 这个问题写得太宽泛了,我已经投票结束了
  • @talonmies 我试图详细说明,以便贡献者可以轻松理解!除了关闭它,我还能学习一种可能的解决方法吗?
  • 你没有在这里提出一个严肃的问题。 究竟你知道什么? CUDA 没有本地 C# 绑定,你甚至没有说你正在使用什么框架。你了解位图数据格式吗?您是否尝试过实际编写内核?如果你有什么问题?这就是为什么这太宽泛了。您发布了愿望清单,而不是Stack Overflow 问题
  • @talonmies 感谢您的回复!我缩小了我的问题!你现在能帮忙吗?
  • 我相信 CUDAfy.NET 主要针对非图形相关的密集数字操作,而您正在查看图形操作,由 CUDA 的 NPP developer.nvidia.com/npp 提供服务(CUDAfy 似乎不支持.NET)

标签: c# image bitmap gpgpu cudafy.net


【解决方案1】:

OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y))

花了一些时间,但我终于破案了。

我们有两个Bitmap:一个用于输出OutputBitmap,另一个用于输入InputBitmap0

让我们把这个任务分成几部分:

  1. xInputBitmap0.GetPixel(),y坐标
  2. 然后,OutputBitmap.SetPixel() 用于不同的坐标object_point_x, object_point_y

Cudafy 不支持 BitmapColor 类型的数据。所以我将位图转换为byte 类型。

BitmapData InputBitmapData0 = InputBitmap0.LockBits(new Rectangle(0, 0, InputBitmap0.Width, InputBitmap0.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

IntPtr ptr0 = InputBitmapData0.Scan0;//pointer for color

int stride0 = InputBitmapData0.Stride;

byte[]  input_ragba_color = new byte[InputBitmapData0.Stride * InputBitmap0.Height];

Marshal.Copy(ptr0, input_ragba_color, 0, bytes0);// Copy the RGB values of color value into the array.

我们已将InputBitmap0 的内容复制到rgbValues 数组中。现在我们需要做GetPixel()的工作(获取R、G、B、A的值)。

我们还需要为OutputBitmap 执行上述工作(制作数组),因为我们将在 GPU 中执行SetPixel(),但稍后我们会将数组复制回位图。

BitmapData OutputBitmapData = OutputBitmap.LockBits(new Rectangle(0, 0, OutputBitmap.Width, OutputBitmap.Height), ImageLockMode.WriteOnly, OutputBitmap.PixelFormat);
IntPtr ptr_output = OutputBitmapData.Scan0;

byte[] output_ragba = new byte[OutputBitmapData.Stride * OutputBitmap.Height]; 

它的 GPU 计算时间。让我们初始化 gpu。

CudafyModule km = new CudafyTranslator.Cudafy();
GPGPU gpu = new CudafyHost.getDevice(CudafyModes.Target, CudafyModes.DeviceId);
gpu.LoadModule(km);

现在将input_ragba_coloroutput_ragba 发送到gpu,因为我们可以迭代数组并进行任何计算。

byte[] dev_output_rgba_color = gpu.Allocate<byte>(output_ragba.Length);
byte[] dev_input_ragba_color = gpu.CopyToDevice(input_ragba_color);
gpu.Launch(N, 1).update_bitmap(x, y, object_point_x, object_point_y,int stride0, int OutputBitmapData.Stride,dev_input_ragba_color,dev_output_rgba_color);

现在在 GPU(内核)中

[Cudafy]
public static void update_bitmap(GThread thread, int x,int y,int object_point_x,int  object_point_y,int stride0, int OutputBitmapData_Stride,byte [] dev_input_ragba_color,byte [] dev_output_rgba_color)
{
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4)] = input_ragba_color[(y * stride0) + (x * 4)];  
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 1] = input_ragba_color[(y * stride0) + (x * 4) + 1];
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 2] = input_ragba_color[(y * stride0) + (x * 4) + 2];
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 3] = input_ragba_color[(y * stride0) + (x * 4) + 3];

}

我正在获取每个 R、G、B、A 的值,例如:input_ragba_color[(y * stride0) + (x * 4) + 1] 正在解决第一个任务 (InputBitmap0.GetPixel())

dev_output_rgba_color 采用input_ragba_color 的值 示例:

dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4)] = input_ragba_color[(y * stride0) + (x * 4)]; 

这解决了我们的第二个任务 (OutputBitmap.SetPixel())

我们现在知道 gpu 已经为我们的 OutputBitmap 填充了一个数组 (dev_output_rgba_color)。

gpu.CopyFromDevice(dev_output_rgba_color, output_ragba);   //dev_output_rgba_color values will be assigned to output_ragba
gpu.FreeAll();

使用内存指针将结果复制回OutputBitmap,然后将其从内存中解锁。

Marshal.Copy(output_ragba, 0, ptr_output, output_bytes);// Copy the RGB values of color value into the array.
OutputBitmap.UnlockBits(OutputBitmapData);

现在OutputBitmap 包含更新后的值。

【讨论】:

    【解决方案2】:

    我认为您需要使用 byte[] 并将其分配到 GPU 上。 I've seen you asking around 这个答案正在进行中,我会在接下来的几天内继续更新它。

    CudafyModule km = new CudafyTranslator.Cudafy();
    GPGPU gpu = new CudafyHost.getDevice(CudafyModes.Target, CudafyModes.DeviceId);
    gpu.LoadModule(km);
    
    var image = new Bitmap(width, height);
    image = (Bitmap)Image.FromFile(@"C:\temp\a.bmp", true);
    byte[] imageBytes = new byte[width * height * 4];
    using(MemoryStream ms = new MemoryStream())
    {
        image.Save(ms, format);
        imageBytes = ms.ToArray();
    }
    byte[] device_imageBytes = _gpu.CopyToDevice(imageBytes);
    
    byte r = 0;
    byte g = 0;
    byte b = 0;
    
    byte device_r = _gpu.Allocate<byte>(r);
    byte device_g = _gpu.Allocate<byte>(g);
    byte device_b = _gpu.Allocate<byte>(b);
    
    //Call this in a loop
    gpu.Launch(N, 1).GetPixel(x, y, device_imageBytes, device_r, device_g, device_b);
    
    ...
    
    [Cudafy]
    public static void GetPixel(GThread thread, int x, int y, byte[] imageBytes, byte blue, byte green, byte red)
    {
        int offset = x * BPP + y * stride;
        blue = imageBytes[offset++];
        green = imageBytes[offset++];
        red = imageBytes[offset];
    
        double R = red;
        double G = green * 255;
        double B = blue * 255 * 255;
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      • 2016-09-02
      • 1970-01-01
      • 2014-09-02
      • 1970-01-01
      • 2012-03-27
      相关资源
      最近更新 更多