Растровое изображение C# GetPixel (), SetPixel () в GPU

Я использую Cudafy в качестве оболочки c# Мне нужно получить информацию о цвете InputBitmap0.GetPixel(x, y) растрового и сделать новое растровое изображение для вывода .

мне нужно выполнить следующую работу в GPU.

В CPU

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

короче:

Как получить Pixel() для каждой пиксельной точки входного растрового изображения, SetPixel () для каждой пиксельной точки растрового изображения outputbitmap в GPU.

2 ответов


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

потребовалось время, но, наконец, Я раскрыл свое дело.

у нас есть два Bitmap : один для вывода OutputBitmap и еще один для ввода InputBitmap0

давайте разделим эту задачу на части:

  1. do InputBitmap0.GetPixel() на x ,y координации
  2. затем , OutputBitmap.SetPixel() для другой координаты object_point_x, object_point_y

Cudafy не поддерживает Bitmap или Color тип данных. Поэтому я преобразовал растровые изображения в 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 тоже, потому что мы будем делать SetPixel() в GPU, но мы скопируем массив обратно в растровое изображение позже.

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_color и output_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, ex: input_ragba_color[(y * stride0) + (x * 4) + 1] который решает 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)]; 

который решает нашу 2-ю задачу (OutputBitmap.SetPixel())

теперь мы знаем, что gpu заселил массив(dev_output_rgba_color) для OutputBitmap.

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 содержит обновленные значения.


Я думаю, вам нужно будет использовать byte[] и выделите это на GPU. Я видел, как ты спрашивал и этот ответ находится в процессе работы, я буду продолжать обновлять его в течение следующих нескольких дней, как я получаю время.

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;

}