2017-02-04 4 views
8

私はC#ラッパーとしてCudafyを使用しています ビットマップのカラー情報InputBitmap0.GetPixel(x, y)を取得し、出力用に新しいビットマップを作成する必要があります。GPUのビットマップGetPixel()、SetPixel()

私はGPUで以下の作業を行う必要があります。要するにCPU

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

IN

がoutputbitmapビットマップの各画素点での入力ビットマップの各画素点、とsetPixel()は()getPixelメソッドする方法GPU。

+0

この質問は書かれた通り広すぎると私はそのように閉じるように投票しました – talonmies

+0

@talonmies投稿者が簡単に理解できるように詳細にしようとしました!それを閉じるのではなく、解決の可能な方法を学ぶことができますか? –

+0

あなたはここで深刻な質問をしていません。 *あなたは何を知っていますか? CUDAにはネイティブのC#バインディングがなく、使用しているフレームワークについても言及していません。あなたはビットマップデータ形式を理解していますか?カーネルを実際に作成しようとしましたか?あなたが持っている場合、問題は何ですか?これが広すぎる理由です。あなたはあなたの応答のために[SO]の質問 – talonmies

答えて

5

OutputBitmap.SetPixel(object_point_x、object_point_y、InputBitmap0.GetPixel(x、y)は)

それは時間がかかりましたが、最終的には、私は、私のケースを割りました。

我々は、2つのBitmapを有する:入力InputBitmap0

ための出力OutputBitmap用と別の部品にこのタスクを分割します:

  1. は、その後のためOutputBitmap.SetPixel()
  2. 座標yxためInputBitmap0.GetPixel()を行います異なる座標object_point_x, object_point_y

Cudafyはまたは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. 

我々はrgbValues配列にInputBitmap0の内容をコピーしています。今我々はGetPixel()の仕事をする必要がある(R、G、B、Aの値を得る)。

GPUでSetPixel()を実行しているため、上記の作業(make array)をOutputBitmapに対して実行する必要がありますが、後でその配列をビットマップにコピーして戻します。

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); 

今GPUに input_ragba_coloroutput_ragbaを送信します。第一タスク ( InputBitmap0.GetPixel())を解くれ input_ragba_color[(y * stride0) + (x * 4) + 1]:今すぐ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、元の値を取ってい

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); 

dev_output_rgba_colorは、input_ragba_color の値をとっています。例:

我々は今、GPUが私たちのOutputBitmapのための配列(dev_output_rgba_color)を埋めたことを知っている私たちの第二のタスク(OutputBitmap.SetPixel()

を解決している

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

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には更新された値が含まれています。

1

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; 

}