OpenCV CUDA模块设备层-----用于在 CUDA 核函数中访问纹理数据的一个封装类TexturePtr()

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

算法描述

TexturePtr<T, R> 是 OpenCV 的 opencv_cudev 模块中用于在 CUDA 核函数中访问纹理数据的一个封装类。它主要用于将一个已创建好的 cudaTextureObject_t 封装为可以在核函数中使用的纹理指针对象。

  • T:纹理元素类型(如 uchar, float)
  • R:底层纹理指针类型(如 Texture2DLayeredPtr)

构造函数说明

构造函数定义:

cpp 复制代码
__host__ TexturePtr(const cudaTextureObject_t tex_)
参数 类型 描述
tex_ cudaTextureObject_t 已经创建好的 CUDA 纹理对象

此构造函数仅封装一个纹理对象,不带偏移量信息,适用于不需要 ROI 偏移的场景。

使用流程简述

步骤 内容
1. 创建 CUDA Array 使用 cudaMallocArray()cudaMemcpy2DToArray()
2. 配置资源描述符 cudaResourceDesc
3. 配置纹理描述符 cudaTextureDesc
4. 创建纹理对象 cudaCreateTextureObject()
5. 构造 TexturePtr TexturePtr<uchar>(texObj)
6. 传入核函数 使用模板泛型 template <typename TexPtr>
7. 采样数据 在核函数中使用 tex(y, x) 接口

代码示例

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudev/ptr2d/texture.hpp> // TexturePtr

using namespace cv;
using namespace cudev;

// 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)

// 核函数:使用 TexturePtr 进行图像缩放(最近邻插值)
template <typename TexPtr>
__global__ void resizeKernel(TexPtr tex, uchar* dst, int dst_cols, int dst_rows, size_t dst_step, float scale) {
    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;
        float src_y = y / scale;
        dst[y * dst_step + x] = tex(src_y, src_x); // 使用纹理采样
    }
}

void resizeWithTexturePtr(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));

    // 使用 TexturePtr 封装纹理对象
    TexturePtr<uchar> texPtr(texObj);

    // 启动核函数
    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>>>(texPtr, d_dst.data, d_dst.cols, d_dst.rows, d_dst.step, scale);

    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());

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

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

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

    return 0;
}

运行结果

相关推荐
heyheyhey_16 分钟前
大模型之深度学习PyTorch篇——导学、创建、运算
人工智能·pytorch·深度学习
大囚长31 分钟前
未来的随身AI IDC--AI手机
人工智能·智能手机
UQI-LIUWJ33 分钟前
论文略读:Large Language Models Assume People are More Rational than We Really are
人工智能·语言模型·自然语言处理
nancy_princess35 分钟前
4. 时间序列预测的自回归和自动方法
人工智能·数据挖掘·回归
机器之心37 分钟前
谢赛宁团队新基准让LLM集体自闭,DeepSeek R1、Gemini 2.5 Pro都是零分
人工智能·llm
LLM大模型1 小时前
LangGraph篇-LangGraph快速入门
人工智能·程序员·llm
MarkGosling1 小时前
【三维重建】VGGT:告别漫长等待,几秒解锁3D世界的CVPR黑马
深度学习·计算机视觉·图像识别
LLM大模型1 小时前
LangGraph篇-核心组件
人工智能·程序员·llm
struggle20251 小时前
DIPLOMAT开源程序是基于深度学习的身份保留标记对象多动物跟踪(测试版)
人工智能·python·深度学习
有Li1 小时前
SpinFlowSim:用于癌症组织学信息驱动的扩散MRI微血管映射的血流模拟框架|文献速递-深度学习医疗AI最新文献
论文阅读·人工智能·深度学习·计算机视觉·医学生