Cuda проблема при преобразовании изображения в оттенки серого
У меня проблема со следующим кодом. Следующий код берет входное изображение и должно сохранить его в градациях серого. К сожалению, кажется, что он выполняет ожидаемое поведение, но обрабатывает только часть изображения, а не целое. Кажется, что проблема возникает в cudamemcpy от устройства к хосту.
Я полагаю, что, вероятно, у меня возникли проблемы, когда я выделяю память в Cuda.
__global__ void rgb2grayCudaKernel(unsigned char *inputImage, unsigned char *grayImage, const int width, const int height)
{
int ty = (blockIdx.x * blockDim.x) + threadIdx.x;
//int tx = (blockIdx.x * blockDim.x) + threadIdx.x;
int tx = (blockIdx.y * blockDim.y) + threadIdx.y;
if( (ty < height && tx<width) )
{
float grayPix = 0.0f;
float r = static_cast< float >(inputImage[(ty * width) + tx]);
float g = static_cast< float >(inputImage[(width * height) + (ty * width) + tx]);
float b = static_cast< float >(inputImage[(2 * width * height) + (ty * width) + tx]);
grayPix = (0.3f * r) + (0.59f * g) + (0.11f * b);
grayImage[(ty * width) + tx] = static_cast< unsigned char >(grayPix);
}
}
//***************************************rgb2gray function, call of kernel in here *************************************
void rgb2grayCuda(unsigned char *inputImage, unsigned char *grayImage, const int width, const int height)
{
unsigned char *inputImage_c, *grayImage_c;
const int sizee= (width*height);
// **********memory allocation for pointers and cuda******************
cudaMalloc((void **) &inputImage_c, sizee);
checkCudaError("im not alloc!");
cudaMalloc((void **) &grayImage_c, sizee);
checkCudaError("gray not alloc !");
//***********copy to device*************************
cudaMemcpy(inputImage_c, inputImage, sizee*sizeof(unsigned char), cudaMemcpyHostToDevice);
checkCudaError("im not send !");
cudaMemcpy(grayImage_c, grayImage, sizee*sizeof(unsigned char), cudaMemcpyHostToDevice);
checkCudaError("gray not send !");
dim3 thrb(32,32);
dim3 numb (ceil(width*height/1024));
//**************Execute Kernel (Timer in here)**************************
NSTimer kernelTime = NSTimer("kernelTime", false, false);
kernelTime.start();
rgb2grayCudaKernel<<<numb,1024>>> (inputImage_c, grayImage_c, width, height);
checkCudaError("kernel!");
kernelTime.stop();
//**************copy back to host*************************
printf("/c");
cudaMemcpy(grayImage, grayImage_c, sizee*sizeof(unsigned char), cudaMemcpyDeviceToHost);
checkCudaError("Receiving data from CPU failed!");
//*********************free memory***************************
cudaFree(inputImage_c);
cudaFree(grayImage_c);
//**********************print time****************
cout << fixed << setprecision(6);
cout << "rgb2gray (cpu): \t\t" << kernelTime.getElapsed() << " seconds." << endl;
}
1 ответ
const int sizee= (width*height);
должно быть:
const int sizee= (width*height*3);
для данных RGB (1 байт на канал).
Я верю в растровые изображения, цвета должны чередоваться как в:
rgb of pixel1, rgb of pixel 2 ... rgb of pixel width*height
Поэтому ваше ядро должно быть:
__global__ void rgb2grayCudaKernel(unsigned char *inputImage, unsigned char *grayImage, const int width, const int height)
{
int tx = (blockIdx.y * blockDim.y) + threadIdx.y;
int ty = (blockIdx.x * blockDim.x) + threadIdx.x;
if( (ty < height && tx<width) )
{
unsigned int pixel = ty*width+tx;
float grayPix = 0.0f;
float r = static_cast< float >(inputImage[pixel*3]);
float g = static_cast< float >(inputImage[pixel*3+1]);
float b = static_cast< float >(inputImage[pixel*3+2]);
grayPix = (0.3f * r) + (0.59f * g) + (0.11f * b);
grayImage[pixel] = static_cast< unsigned char >(grayPix);
}
}
Также из того, что я видел, светимость рассчитывается как 0,21 R + 0,72 G + 0,07 B.