OpenCV CUDA模块设备层-----逐通道的正弦运算函数sin()

发布于:2025-06-28 ⋅ 阅读:(8) ⋅ 点赞:(0)
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

OpenCV 的 CUDA 模块(cv::cudev) 中的一个设备端数学函数,用于在 CUDA 核函数中对 uchar4 类型(即 4 通道无符号字符类型)进行 逐通道的正弦运算,并将结果转换为 float4 类型输出。

将一个 uchar4 类型像素值(每个通道取值范围 [0, 255])逐通道转换为浮点数,并计算其正弦值(单位:弧度),返回 float4 类型结果。
这在图像处理、颜色空间变换或 GPU 数学计算中有一定用途,尤其是在需要对图像像素进行三角函数变换时。

函数原型

__device__ __forceinline__ float4 cv::cudev::sin 	( 	const uchar4 &  	a	) 	

参数

  • a const uchar4& 输入的 4 通道无符号字符向量(如 RGBA 图像中的一个像素)

返回值

  • 返回一个新的 float4 值;
  • 每个通道的值为 sin((float)a.x), sin((float)a.y), sin((float)a.z), sin((float)a.w);
  • 输入会先被转换为浮点数,再调用 CUDA 的 sinf(…) 函数计算正弦值。

代码


#include <opencv2/cudaimgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/cudev/util/vec_math.hpp>


using namespace cv;
using namespace cv::cudev;

// CUDA 核函数:将 uchar4 像素转换为 float4 并计算正弦值
template <typename SrcPtr, typename DstPtr>
__global__ void sinKernel(SrcPtr src, DstPtr dst, int width, int height) {
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;

    if (x < width && y < height) {
        // 获取输入像素
        uchar4 val = src(y, x);

        // 将每个通道转换为浮点数,并除以 255,映射到 [0,1]
        float4 normalized = make_float4(
            static_cast<float>(val.x) / 255.0f,
            static_cast<float>(val.y) / 255.0f,
            static_cast<float>(val.z) / 255.0f,
            static_cast<float>(val.w) / 255.0f
        );

        // 计算正弦值(弧度制)
        float4 sinVal = make_float4(
            sinf(normalized.x * 2.0f * (float)CV_PI),  // 映射到 [0, 2π]
            sinf(normalized.y * 2.0f * (float)CV_PI),
            sinf(normalized.z * 2.0f * (float)CV_PI),
            sinf(normalized.w * 2.0f * (float)CV_PI)
        );

        // 写入输出图像
        dst(y, x) = sinVal;
    }
}

int main() {
    // 加载图像(RGBA 或 RGB)
    Mat h_img = imread("/media/dingxin/data/study/OpenCV/sources/images/img0.jpg", IMREAD_UNCHANGED);
    if (h_img.empty()) {
        std::cerr << "Failed to load image!" << std::endl;
        return -1;
    }

    // 转换为 4 通道 RGBA 格式
    Mat h_rgba;
    if (h_img.channels() == 3) {
        cv::cvtColor(h_img, h_rgba, COLOR_BGR2BGRA);
    } else if (h_img.channels() == 1) {
        cv::cvtColor(h_img, h_rgba, COLOR_GRAY2BGRA);
    } else {
        h_rgba = h_img.clone();
    }

    // 上传到 GPU
    cuda::GpuMat d_rgba, d_result;
    d_rgba.upload(h_rgba);
    d_result.create(d_rgba.size(), CV_32FC4);  // float4 对应 CV_32FC4

    // 构造 PtrStepSz 访问器
    auto ptr = PtrStepSz<uchar4>(d_rgba);
    auto dptr = PtrStepSz<float4>(d_result);

    // 设置核函数参数
    dim3 block(16, 16);
    dim3 grid((d_rgba.cols + block.x - 1) / block.x,
              (d_rgba.rows + block.y - 1) / block.y);

    // 调用核函数
    sinKernel<<<grid, block>>>(ptr, dptr, d_rgba.cols, d_rgba.rows);
    cudaDeviceSynchronize();

    // 下载结果
    Mat h_result;
    d_result.download(h_result);

    // 归一化到 [0, 1] 用于显示
    Mat display;
    normalize(h_result, display, 0, 1, NORM_MINMAX, CV_32FC4);

    // 显示图像
    imshow("Sin Image", display);
    imwrite("output_sin_image.png", display * 255);  // 保存为 PNG
    waitKey(0);

    return 0;
}

运行结果

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到