简体   繁体   English

使用 CUDA 和纹理进行图像减法

[英]Image subtraction with CUDA and textures

My goal is to use C++ with CUDA to subtract a dark frame from a raw image.我的目标是使用 C++ 和 CUDA 从原始图像中减去暗帧。 I want to use textures for acceleration.我想使用纹理进行加速。 The input of the images is cv::Mat with the type CV_8UC4 (I use the pointer to the data of the cv::Mat).图像的输入是类型为 CV_8UC4 的 cv::Mat(我使用指向 cv::Mat 数据的指针)。 This is the kernel I came up with, but I have no idea how to eventually subtract the textures from each other:这是我想出的内核,但我不知道如何最终从彼此减去纹理:

__global__ void DarkFrameSubtractionKernel(unsigned char* outputImage, size_t pitchOutputImage,
cudaTextureObject_t inputImage, cudaTextureObject_t darkImage, int width, int height)
{
    const int x = blockIdx.x * blockDim.x + threadIdx.x;
    const int y = blockDim.y * blockIdx.y + threadIdx.y;

    const float tx = (x + 0.5f);
    const float ty = (y + 0.5f);

    if (x >= width || y >= height) return;

    uchar4 inputImageTemp = tex2D<uchar4>(inputImage, tx, ty);
    uchar4 darkImageTemp = tex2D<uchar4>(darkImage, tx, ty);

    outputImage[y * pitchOutputImage + x] = inputImageTemp - darkImageTemp; // this line will throw an error
}

This is the function that calls the kernel (you can see that I create the textures from unsigned char):这是调用内核的函数(你可以看到我从无符号字符创建了纹理):

void subtractDarkImage(unsigned char* inputImage, size_t pitchInputImage, unsigned char* outputImage,
size_t pitchOutputImage, unsigned char* darkImage, size_t pitchDarkImage, int width, int height, 
cudaStream_t stream)
{
    cudaResourceDesc resDesc = {};
    resDesc.resType = cudaResourceTypePitch2D;
    resDesc.res.pitch2D.width = width;
    resDesc.res.pitch2D.height = height;
    resDesc.res.pitch2D.devPtr = inputImage;
    resDesc.res.pitch2D.pitchInBytes = pitchInputImage;
    resDesc.res.pitch2D.desc = cudaCreateChannelDesc(8, 8, 8, 8, cudaChannelFormatKindUnsigned);

    cudaTextureDesc texDesc = {};
    texDesc.readMode = cudaReadModeElementType;
    texDesc.addressMode[0] = cudaAddressModeBorder;
    texDesc.addressMode[1] = cudaAddressModeBorder;

    cudaTextureObject_t imageInputTex, imageDarkTex;
    CUDA_CHECK(cudaCreateTextureObject(&imageInputTex, &resDesc, &texDesc, 0));

    resDesc.res.pitch2D.devPtr = darkImage;
    resDesc.res.pitch2D.pitchInBytes = pitchDarkImage;
    CUDA_CHECK(cudaCreateTextureObject(&imageDarkTex, &resDesc, &texDesc, 0));

    dim3 block(32, 8);
    dim3 grid = paddedGrid(block.x, block.y, width, height);

    DarkImageSubtractionKernel << <grid, block, 0, stream >> > (reinterpret_cast<uchar4*>(outputImage), pitchOutputImage / sizeof(uchar4),
    imageInputTex, imageDarkTex, width, height);


    CUDA_CHECK(cudaDestroyTextureObject(imageInputTex));
    CUDA_CHECK(cudaDestroyTextureObject(imageDarkTex));
}

The code does not compile as I can not subtract a uchar4 from another one (in the kernel).代码无法编译,因为我无法从另一个(在内核中)减去 uchar4。 Is there an easy way of subtraction here?这里有简单的减法方​​法吗?

Help is very much appreciated.非常感谢帮助。

Is there an easy way of subtraction here?这里有简单的减法方​​法吗?

There are no arithmetic operators defined for CUDA built-in vector types.没有为 CUDA 内置向量类型定义算术运算符。 If you replace如果你更换

outputImage[y * pitchOutputImage + x] = inputImageTemp - darkImageTemp;

with

uchar4 val;
val.x = inputImageTemp.x - darkImageTemp.x;
val.y = inputImageTemp.y - darkImageTemp.y;
val.z = inputImageTemp.z - darkImageTemp.z;
val.w = inputImageTemp.w - darkImageTemp.w;
outputImage[y * pitchOutputImage + x] = val;

things will work.事情会奏效的。 If this offends you, I suggest writing a small library of helper functions to hide the mess.如果这冒犯了您,我建议编写一个小型的辅助函数库来隐藏混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM