OpenCV CUDA模块设备层-----用于CUDA 使用纹理内存的一个类模板TextureOff()

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

cv::cudev::TextureOff<T, P> 是 OpenCV 的 CUDA 模块(opencv_cudev) 中用于在 GPU 上使用纹理内存的一个类模板,它主要用于将图像数据绑定到 CUDA 纹理对象,并支持偏移量访问。

定义:

template <typename T, typename Ptr>
class TextureOff : public Texture<T>
  • T:纹理中元素的类型(如 uchar, float)
  • Ptr:指向图像数据的指针类型(如 GlobPtrSz)

这个类封装了从图像数据创建 CUDA 约束纹理对象的过程,并支持带有 ROI(Region of Interest)偏移量的访问。

主要功能

  • 自动将图像数据上传到 CUDA Array
  • 创建并管理 cudaTextureObject_t
  • 支持带偏移量的纹理访问(offsetX(), offsetY())
  • 可以像普通纹理一样在核函数中使用

相关类和结构体

类/结构体作用
cv::cudev::Texture纹理基类
cv::cudev::TextureOff<T, P>支持偏移的纹理类
cv::cudev::GlobPtrSz封装 GpuMat 数据的指针包装器
cudaTextureObject_tCUDA 原生纹理对象句柄
cudaResourceDesc描述纹理资源来源(如 array)
cudaTextureDesc描述纹理采样方式(filter mode, address mode 等)

代码示例

注意:是cu文件

#include <opencv2/opencv.hpp>
#include <opencv2/cudaimgproc.hpp>

#include <iostream>

using namespace cv;
using namespace cuda;

// CUDA 错误检查宏
#define CUDA_CHECK(call) \
    do { \
        cudaError_t err = call; \
        if (err != cudaSuccess) { \
            std::cerr << "CUDA error at " << __FILE__ << ":" << __LINE__ << ": " \
                      << cudaGetErrorString(err) << std::endl; \
            exit(EXIT_FAILURE); \
        } \
    } while (0)

// 核函数:使用纹理对象进行图像缩放
__global__ void resizeKernel(
    uchar* dst, int dst_cols, int dst_rows, size_t dst_step,
    float scale, cudaTextureObject_t texObj, int dx, int dy) {

    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;

    if (x < dst_cols && y < dst_rows) {
        float src_x = (x / scale) + dx;
        float src_y = (y / scale) + dy;

        // 使用纹理对象采样
        uchar val = tex2D<uchar>(texObj, src_x + 0.5f, src_y + 0.5f);
        dst[y * dst_step + x] = val;
    }
}

void resizeWithTextureOff(cuda::GpuMat& d_src, cuda::GpuMat& d_dst, float scale) {
    int width = d_src.cols;
    int height = d_src.rows;

    // 创建 CUDA Array 并拷贝数据
    cudaChannelFormatDesc channel_desc = cudaCreateChannelDesc<uchar>();
    cudaArray* cu_array = nullptr;
    CUDA_CHECK(cudaMallocArray(&cu_array, &channel_desc, width, height));

    CUDA_CHECK(cudaMemcpy2DToArray(
        cu_array, 0, 0,
        d_src.data, d_src.step,
        width, height,
        cudaMemcpyDeviceToDevice));

    // 配置纹理资源描述符
    cudaResourceDesc res_desc = {};
    memset(&res_desc, 0, sizeof(res_desc));
    res_desc.resType = cudaResourceTypeArray;
    res_desc.res.array.array = cu_array;

    // 配置纹理描述符
    cudaTextureDesc tex_desc = {};
    memset(&tex_desc, 0, sizeof(tex_desc));
    tex_desc.addressMode[0] = cudaAddressModeClamp;
    tex_desc.addressMode[1] = cudaAddressModeClamp;
    tex_desc.filterMode = cudaFilterModePoint;
    tex_desc.readMode = cudaReadModeElementType;
    tex_desc.normalizedCoords = 0;

    // 创建纹理对象
    cudaTextureObject_t texObj = 0;
    CUDA_CHECK(cudaCreateTextureObject(&texObj, &res_desc, &tex_desc, NULL));

    // 启动核函数
    dim3 block(16, 16);
    dim3 grid((d_dst.cols + block.x - 1) / block.x,
              (d_dst.rows + block.y - 1) / block.y);

    resizeKernel<<<grid, block>>>(
        d_dst.data, d_dst.cols, d_dst.rows, d_dst.step,
        scale, texObj, 0, 0);

    CUDA_CHECK(cudaDeviceSynchronize());

    // 清理资源
    CUDA_CHECK(cudaDestroyTextureObject(texObj));
    CUDA_CHECK(cudaFreeArray(cu_array));
}

int main() {
    // 加载图像(灰度图)
    cv::Mat h_src = cv::imread("/media/dingxin/data/study/OpenCV/sources/images/Lenna.png", cv::IMREAD_GRAYSCALE);
    if (h_src.empty()) {
        std::cerr << "Failed to load image!" << std::endl;
        return -1;
    }

    // 上传到 GPU
    cv::cuda::GpuMat d_src, d_dst;
    d_src.upload(h_src);

    // 设置目标尺寸(放大两倍)
    float scale = 2.0f;
    d_dst.create(cvRound(h_src.rows * scale), cvRound(h_src.cols * scale), h_src.type());

    // 调用基于 Texture 的缩放函数
    resizeWithTextureOff(d_src, d_dst, scale);

    // 下载结果
    cv::Mat h_dst;
    d_dst.download(h_dst);

    // 归一化显示
    cv::Mat h_dst_normalized;
    cv::normalize(h_dst, h_dst_normalized, 0, 255, cv::NORM_MINMAX, CV_8UC1);

    // 显示图像
    cv::imshow("Original", h_src);
    cv::imshow("Resized (Texture)", h_dst_normalized);
    cv::waitKey(0);

    return 0;
}

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

村北头的码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值