OpenCV CUDA模块设备层----- 反双曲正弦(inverse hyperbolic sine)运算函数asinh

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

算法描述

该函数接收一个 uchar1 类型的像素值(范围 [0, 255]),将其归一化到 [0, 1] 范围后映射到 [0, 1] 或 [-1, 1](根据实现),然后计算其 反双曲正弦值(asinh),并返回一个 float1 类型的结果。

函数原型

cpp 复制代码
__device__ __forceinline__ float1 cv::cudev::asinh 	( 	const uchar1 &  	a	) 	

参数

  • uchar1 CUDA 内建向量类型,等价于单通道无符号字符(即 unsigned char,取值范围 [0, 255])

示例代码

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/cudaimgproc.hpp>         // cuda::GpuMat
#include <opencv2/cudev/functional/functional.hpp>    // cv::cudev::asinh

#include <iostream>

using namespace cv;
using namespace cudev;

// CUDA 核函数定义
__global__ void asinhKernel(const uchar* srcData, float* dstData,
                            int width, int height, size_t srcStep, size_t dstStep)
{
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;

    if (x < width && y < height)
    {
        // 手动计算偏移量
        const uchar* rowSrc = reinterpret_cast<const uchar*>(reinterpret_cast<uintptr_t>(srcData) + y * srcStep);
        float* rowDst = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(dstData) + y * dstStep);

        uchar1 pixel;
        pixel.x = rowSrc[x];  // 获取输入像素值

        float1 result = cv::cudev::asinh(pixel);  // 调用设备端 asinh 函数
        rowDst[x] = result.x; // 存储输出结果
    }
}

int main(int argc, char* argv[])
{
    std::string imagePath = "/media/dingxin/data/study/OpenCV/sources/images/Lenna.png";

    // 1. 加载图像(灰度图)
    Mat h_src = imread(imagePath, IMREAD_GRAYSCALE);
    if (h_src.empty())
    {
        std::cerr << "Failed to load image: " << imagePath << std::endl;
        return -1;
    }

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

    // 创建输出图像(float 类型)
    d_dst.create(h_src.size(), CV_32FC1);

    // 3. 配置 CUDA 核函数参数
    dim3 block(16, 16);
    dim3 grid((h_src.cols + block.x - 1) / block.x,
              (h_src.rows + block.y - 1) / block.y);

    // 4. 启动核函数
    asinhKernel<<<grid, block>>>(
        d_src.ptr<uchar>(), d_dst.ptr<float>(),
        h_src.cols, h_src.rows,
        d_src.step, d_dst.step
    );

    cudaDeviceSynchronize();  // 确保核函数执行完成

    // 5. 下载结果并归一化显示
    Mat h_result;
    d_dst.download(h_result);

    // 归一化到 [0, 255] 显示
    Mat h_display;
    normalize(h_result, h_display, 0, 255, NORM_MINMAX, CV_8UC1);

    // 显示结果
    imshow("Original Image", h_src);
    imshow("Asinh Transformed", h_display);
    std::cout << "Press any key to exit..." << std::endl;
    waitKey(0);

    return 0;
}

运行结果