Растровое изображение 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
давайте разделим эту задачу на части:
- do
InputBitmap0.GetPixel()
наx
,y
координации - затем ,
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;
}