CUDA入門 > OpenCVとCUDA > 1ピクセルずつコピー

1ピクセルずつコピー


1ピクセルずつコピー
OpenCVを利用し、カーネル内で1ピクセルずつコピーする処理のサンプルです。
4chまで対応しています。
解像度も、ある程度は対応(カーネルに条件分岐入れると完全に対応は可能ですが・・・)

サンプルプログラム
#include <stdio.h> #include "cv.h" #include "cxcore.h" #include "highgui.h" #pragma comment(lib,"cv.lib") #pragma comment(lib,"cxcore.lib") #pragma comment(lib,"highgui.lib") #include <cutil.h> __global__ void bit1cpykernel(unsigned char *in, unsigned char *out, int width, int channels){ int x = blockDim.x * blockIdx.x + threadIdx.x; int y = blockDim.y * blockIdx.y + threadIdx.y; out[y * width * channels + x * channels + 0] = in[y * width * channels + x * channels + 0]; } __global__ void bit2cpykernel(unsigned char *in, unsigned char *out, int width, int channels){ int x = blockDim.x * blockIdx.x + threadIdx.x; int y = blockDim.y * blockIdx.y + threadIdx.y; out[y * width * channels + x * channels + 0] = in[y * width * channels + x * channels + 0]; out[y * width * channels + x * channels + 1] = in[y * width * channels + x * channels + 1]; } __global__ void bit3cpykernel(unsigned char *in, unsigned char *out, int width, int channels){ int x = blockDim.x * blockIdx.x + threadIdx.x; int y = blockDim.y * blockIdx.y + threadIdx.y; out[y * width * channels + x * channels + 0] = in[y * width * channels + x * channels + 0]; out[y * width * channels + x * channels + 1] = in[y * width * channels + x * channels + 1]; out[y * width * channels + x * channels + 2] = in[y * width * channels + x * channels + 2]; } __global__ void bit4cpykernel(unsigned char *in, unsigned char *out, int width, int channels){ int x = blockDim.x * blockIdx.x + threadIdx.x; int y = blockDim.y * blockIdx.y + threadIdx.y; out[y * width * channels + x * channels + 0] = in[y * width * channels + x * channels + 0]; out[y * width * channels + x * channels + 1] = in[y * width * channels + x * channels + 1]; out[y * width * channels + x * channels + 2] = in[y * width * channels + x * channels + 2]; out[y * width * channels + x * channels + 3] = in[y * width * channels + x * channels + 3]; } int main(int argc, char **argv){ CUT_DEVICE_INIT( argc, argv ); IplImage *imgin, *imgout; unsigned char *d_in, *d_out; int memsize; imgin = cvLoadImage("ファイルパス"); imgout = cvCreateImage(cvSize(imgin->width, imgin->height), imgin->depth, imgin->nChannels); printf("width = %d, height = %d, nChannels = %d\n", imgin->width, imgin->height, imgin->nChannels); memsize = imgin->width * imgin->height * imgin->nChannels; CUDA_SAFE_CALL(cudaMalloc((void**)&d_in, memsize)); CUDA_SAFE_CALL(cudaMalloc((void**)&d_out, memsize)); CUDA_SAFE_CALL(cudaMemcpy(d_in, imgin->imageData, memsize, cudaMemcpyHostToDevice)); dim3 threads(32,8); dim3 blocks(imgin->width / threads.x, imgin->height / threads.y); // 前の情報を一旦初期化(処理されなかったメモリは、前のデータが表示されるため) // デバッグ用。通常は必要なし cudaMemset(d_out, 0, memsize); CUDA_SAFE_CALL( cudaThreadSynchronize() ); unsigned int timer = 0; CUT_SAFE_CALL( cutCreateTimer( &timer)); CUT_SAFE_CALL( cutStartTimer( timer)); switch(imgin->nChannels){ case 1: bit1cpykernel<<< blocks, threads >>> (d_in, d_out, imgin->width, imgin->nChannels); break; case 2: bit2cpykernel<<< blocks, threads >>> (d_in, d_out, imgin->width, imgin->nChannels); break; case 3: bit3cpykernel<<< blocks, threads >>> (d_in, d_out, imgin->width, imgin->nChannels); break; case 4: bit4cpykernel<<< blocks, threads >>> (d_in, d_out, imgin->width, imgin->nChannels); break; } // 同期をとる。 CUDA_SAFE_CALL( cudaThreadSynchronize() ); CUT_SAFE_CALL( cutStopTimer( timer)); printf("処理時間: %f (ms)\n", cutGetTimerValue( timer)); CUT_SAFE_CALL( cutDeleteTimer( timer)); CUDA_SAFE_CALL(cudaMemcpy(imgout->imageData, d_out, memsize, cudaMemcpyDeviceToHost)); cvNamedWindow("in", 1); cvNamedWindow("out", 1); cvShowImage("in", imgin); cvShowImage("out", imgout); // キーを何か押したら終了 cvWaitKey(-1); cvDestroyWindow("in"); cvDestroyWindow("out"); cvReleaseImage(&imgin); cvReleaseImage(&imgout); cudaFree(d_in); cudaFree(d_out); return 0; }