我正在学习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);
除此之外,你能告诉我纹理内存如何使用纹理来访问数组,以及这种转换是如何形成的?
答案 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图像非常有用,是一个非常理想的功能。