如何使用cuda tex2D访问像素的每个通道

时间:2013-04-25 10:35:30

标签: opencv cuda textures

我正在学习cuda纹理记忆。现在,我得到了一个opencv Iplimage,我得到了它的imagedata。然后我将纹理绑定到这个uchar数组,如下所示:

Iplimage *image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
unsigned char* imageDataArray = (unsigned char*)image->imagedata;

texture<unsigned char,2,cudaReadModeElementType> tex;
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(8, 8, 8, 0, 
                                                          cudaChannelFormatKindUnsigned); 
cudaArray *cuArray = NULL;
CudaSafeCall(cudaMallocArray(&cuArray,&channelDesc,width,height));

cudaMemcpy2DToArray(cuArray,0,0,imageDataArray,image->widthstep,
    width * sizeof(unsigned char), height, cudaMemcpyHostToDevice);
cudaBindTextureToArray(texC1_cf,cuArray_currentFrame, channelDesc);

现在我抓住我的内核,我想访问每个像素,该图像的每个通道。这是我感到困惑的地方。

我使用此代码获取像素坐标(X,Y):

int X = (blockIdx.x*blockDim.x+threadIdx.x);
int Y = (blockIdx.y*blockDim.y+threadIdx.y);

如何访问此(X,Y)的每个频道?以下代码返回的内容是什么?

tex2D(tex, X, Y);

除此之外,你能告诉我纹理内存如何使用纹理来访问数组,以及这种转换是如何形成的?

enter image description here

1 个答案:

答案 0 :(得分:3)

要将3通道OpenCV图像绑定到cudaArray纹理,您必须创建宽度等于image->width * image->nChannels的cudaArray,因为通道是由OpenCV交错存储的。

cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<unsigned char>();

cudaArray *cuArray = NULL;
CudaSafeCall(cudaMallocArray(&cuArray,&channelDesc,width * image->nChannels,height));

cudaMemcpy2DToArray(cuArray,0,0,imageDataArray,image->widthstep, width * image->nChannels * sizeof(unsigned char), height, cudaMemcpyHostToDevice);

cudaBindTextureToArray(texC1_cf,cuArray_currentFrame, channelDesc);

现在,要在内核中单独访问每个通道,您只需将x索引与通道数相乘,并添加所需通道的偏移量,如下所示:

unsigned char blue = tex2D(tex, (3 * X) , Y);
unsigned char green = tex2D(tex, (3 * X) + 1, Y);
unsigned char red = tex2D(tex, (3 * X) + 2, Y);

第一个是蓝色,因为OpenCV存储具有通道序列BGR的图像。

至于您尝试使用texture<uchar3,..>访问tex2D时出现的错误; CUDA仅支持创建1,2和4元素矢量类型的2D纹理。不幸的是,不支持ON3,这对于绑定RGB图像非常有用,是一个非常理想的功能。