最近使用C#處理PictureBox, Bitmap 與 C::Mat 物件, 做個重點記錄, 程式很長, 就不解釋了.
CudaKernel.cu
__global__ void copyKernel(byte *destArray, byte *srcArray, int channels) { int p = (blockIdx.x*blockDim.x + threadIdx.x)*channels; for (int c = 0; c < channels; c++) { destArray[p + c] = srcArray[p + c]/2; } }
………………………………
cudaError_t OpArray(byte* destArray, byte* srcArray, int width, int height, int channels) { trace("OpArray()");
if (width > 1024 || height > 1024) { trace("Image Size too Large"); return cudaSuccess; }
byte *dev_srcArray = 0; byte *dev_destArray = 0; cudaError_t cudaStatus; size_t pixelBytes = width * height * channels;
sprintf(tracebuf, "pixelBytes=%d", (int)pixelBytes); trace(tracebuf);
// Choose which GPU to run on, change this on a multi-GPU system. cudaStatus = cudaSetDevice(0); if (cudaStatus != cudaSuccess) { trace("cudaSetDevice failed! Do you have a CUDA-capable GPU installed?"); goto Error; }
// Allocate GPU buffers for three vectors (one input, one output)
trace("Allocate GPU buffers"); cudaStatus = cudaMalloc((void**)&dev_srcArray, pixelBytes); if (cudaStatus != cudaSuccess) { trace("cudaMalloc dev_src failed!"); goto Error; }
cudaStatus = cudaMalloc((void**)&dev_destArray, pixelBytes); if (cudaStatus != cudaSuccess) { trace("cudaMalloc dev_dest failed!"); goto Error; }
// Copy input vectors from host memory to GPU buffers. cudaStatus = cudaMemcpy(dev_srcArray, srcArray, pixelBytes, cudaMemcpyHostToDevice); if (cudaStatus != cudaSuccess) { trace("cudaMemcpy failed!"); goto Error; }
// Launch a kernel on the GPU with one thread for each element.
trace("start kernel"); copyKernel << <height, width >> > (dev_destArray, dev_srcArray, channels);
// Check for any errors launching the kernel cudaStatus = cudaGetLastError(); if (cudaStatus != cudaSuccess) { sprintf(tracebuf, "ipKernel launch failed: %s\n", cudaGetErrorString(cudaStatus)); trace(tracebuf); goto Error; }
// cudaDeviceSynchronize waits for the kernel to finish, and returns // any errors encountered during the launch. cudaStatus = cudaDeviceSynchronize(); if (cudaStatus != cudaSuccess) { sprintf(tracebuf, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus); trace(tracebuf); goto Error; }
// Copy output vector from GPU buffer to host memory.
trace("copy result"); cudaStatus = cudaMemcpy(destArray, dev_destArray, pixelBytes, cudaMemcpyDeviceToHost); if (cudaStatus != cudaSuccess) { trace("cudaMemcpy failed!"); goto Error; } // All done, reset the device cudaStatus = cudaDeviceReset(); if (cudaStatus != cudaSuccess) { trace("cudaDeviceReset failed!"); goto Error; }
Error: cudaFree(dev_srcArray); cudaFree(dev_destArray);
trace("end"); return cudaStatus; }
cudaError_t OpMat(Mat *destMat, Mat *srcMat) { trace("OpMat()");
if (srcMat->cols > 1024 || srcMat->rows > 1024) { trace("Image Size too Large"); return cudaSuccess; }
byte *dev_srcMat = 0; byte *dev_destMat = 0; size_t pixelBytes = srcMat->total() *srcMat->elemSize();
cudaError_t cudaStatus;
sprintf(tracebuf, "pixelBytes=%d", pixelBytes); trace(tracebuf);
// Choose which GPU to run on cudaStatus = cudaSetDevice(0); if (cudaStatus != cudaSuccess) { trace("cudaSetDevice failed!"); goto Error; }
// Allocate GPU buffers
cudaStatus = cudaMalloc((void**)&dev_srcMat, pixelBytes); if (cudaStatus != cudaSuccess) { trace("cudaMalloc failed!"); goto Error; } cudaStatus = cudaMalloc((void**)&dev_destMat, pixelBytes); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMalloc failed!"); goto Error; }
// Copy from host memory to GPU buffers. cudaStatus = cudaMemcpy(dev_srcMat, srcMat->data, pixelBytes, cudaMemcpyHostToDevice); if (cudaStatus != cudaSuccess) { trace("cudaMemcpy failed!"); goto Error; }
int channels = srcMat->channels(); copyKernel << <srcMat->rows, srcMat->cols >> > (dev_destMat, dev_srcMat, channels);
// Check for any errors launching the kernel cudaStatus = cudaGetLastError(); if (cudaStatus != cudaSuccess) { sprintf(tracebuf, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus)); trace(tracebuf); goto Error; }
// cudaDeviceSynchronize waits for the kernel to finish cudaStatus = cudaDeviceSynchronize(); if (cudaStatus != cudaSuccess) { sprintf(tracebuf, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus); trace(tracebuf); goto Error; }
// Copy output from GPU buffer to host memory. cudaStatus = cudaMemcpy(destMat->data, dev_destMat, pixelBytes, cudaMemcpyDeviceToHost); if (cudaStatus != cudaSuccess) { trace("cudaMemcpy failed!"); goto Error; }
// All done, reset the device cudaStatus = cudaDeviceReset(); if (cudaStatus != cudaSuccess) { trace("cudaDeviceReset failed!"); goto Error; } Error: cudaFree(dev_srcMat); cudaFree(dev_destMat);
trace("end"); return cudaStatus; }
|
CudaWrapper.cpp
extern "C" DLLEXPORT bool testArray(byte* destArray, byte* srcArray, int width, int height, int channels) { trace("testArray()"); cudaError_t cudaStatus = OpArray(destArray, srcArray, width,height, channels); return (cudaStatus == cudaSuccess); }
extern "C" DLLEXPORT bool testMat(Mat *destMat, Mat *srcMat) { trace("testMat()"); cudaError_t cudaStatus = OpMat(destMat, srcMat); return (cudaStatus == cudaSuccess); } |
MainForm.cs
[DllImport("RmtCoreCuda.dll", EntryPoint = "testArray", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] unsafe private static extern bool testArray(IntPtr dest, IntPtr src, int width, int height, int channels); [DllImport("RmtCoreCuda.dll", EntryPoint = "testMat", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern bool testMat(IntPtr destMat, IntPtr srcMat);
……………………………… private void testCudaMat() { //String filename = "D:\\LENA.JPG"; String filename = "D:\\MARBLES.BMP"; //String filename = "D:\\LENA.JPG"; Mat srcMat = CvInvoke.Imread(filename); //, Emgu.CV.CvEnum.ImreadModes.Grayscale); // Read the file and convert to grayscale
statusMessage.Text = ""; if (srcMat == null) { statusMessage.Text = "No Source Picture"; return; } if (srcMat.Width > 1024 || srcMat.Height > 1024) { statusMessage.Text = "Source Picture too large"; return; }
//Mat destMat = srcMat; // new Mat(srcMat.Size, srcMat.GetType(), srcMat.NumberOfChannels); Mat destMat = new Mat(srcMat.Size, DepthType.Cv8U, srcMat.NumberOfChannels); testMat(destMat, srcMat); CvInvoke.Imshow("destMat", destMat); }
private void testCudaArray() { statusMessage.Text = ""; if (picSource==null) { statusMessage.Text = "No Source Picture"; return; } if (picSource.Image.Width>1024 || picSource.Image.Height>1024) { statusMessage.Text = "Source Picture too large"; return; }
Bitmap srcImage = (Bitmap)picSource.Image; Rectangle size = new Rectangle(0, 0, srcImage.Width, srcImage.Height); Bitmap destImage = new Bitmap(srcImage.Width, srcImage.Height, srcImage.PixelFormat);
BitmapData srcData = srcImage.LockBits(size, ImageLockMode.ReadOnly, srcImage.PixelFormat); BitmapData destData = destImage.LockBits(size, ImageLockMode.ReadWrite, srcImage.PixelFormat);
int channels = 0; unsafe { IntPtr srcPtr = srcData.Scan0; IntPtr destPtr = destData.Scan0; switch (srcImage.PixelFormat) { case PixelFormat.Format8bppIndexed: channels = 1; break; case PixelFormat.Format16bppArgb1555: case PixelFormat.Format16bppGrayScale: case PixelFormat.Format16bppRgb555: case PixelFormat.Format16bppRgb565: channels = 2; break; case PixelFormat.Format24bppRgb: channels = 3; break; case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppPArgb: case PixelFormat.Format32bppRgb: channels = 4; break;
default: channels = 0; break; } testArray(destPtr, srcPtr, srcImage.Width, srcImage.Height, channels);
int byteLength = srcImage.Width * srcImage.Height * channels; byte[] srcByte = new byte[byteLength]; byte[] destByte = new byte[byteLength];
Marshal.Copy(srcPtr, srcByte, 0, byteLength); Marshal.Copy(destPtr, destByte, 0, byteLength); File.WriteAllBytes("d:\\srcData.bin", srcByte); File.WriteAllBytes("d:\\destData.bin",destByte); } //destImage.Palette = srcImage.Palette; srcImage.UnlockBits(srcData); destImage.UnlockBits(destData);
picSource.Image = srcImage;
if (channels == 3) { //set alpha=255 to show the image for (int w = 0; w < destImage.Width; w++) { for (int h = 0; h < destImage.Height; h++) { Color c = destImage.GetPixel(w, h); Color newC = Color.FromArgb(255, c); destImage.SetPixel(w, h, newC); } } } picOutput.Image = destImage; } |
留言列表