OpenCV CUDA模块设备层-----双曲正弦函数sinh()
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
OpenCV的CUDA 模块(cv::cudev)中的一个设备端数学函数,用于在 GPU 上对 uchar3 类型的像素值(如RGB图像中的一个像素)逐通道计算双曲正弦函数(hyperbolic sine),并将结果转换为float3类型返回。
函数原型
__device__ __forceinline__ float3 cv::cudev::sinh ( const uchar3 & a )
参数
- a const uchar3& 输入的 3 通道无符号字符向量(如 RGB 图像中的一个像素)。
返回值
- 返回一个新的 float3 值;
- 每个通道的值为 sinh((float)a.x), sinh((float)a.y), sinh((float)a.z);
- 使用的是 CUDA 内建函数 sinhf(…) 来计算双曲正弦。
代码
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/cudev/util/vec_math.hpp>using namespace cv;
using namespace cv::cudev;// CUDA 核函数:对 uchar3 像素计算 sinh,并确保输出在 [0,1]
template <typename SrcPtr, typename DstPtr>
__global__ void sinhKernel(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) {// 获取原始像素值uchar3 val = src(y, x);// Step 1: 将 uchar3 归一化到 [0,1]float scale = 1.0f / 255.0f;float fx = val.x * scale;float fy = val.y * scale;float fz = val.z * scale;// Step 2: 构造一个 "fake" uchar3 输入,表示 [0,1] 区间uchar3 fake_input;fake_input.x = static_cast<unsigned char>(fx * 255.0f);fake_input.y = static_cast<unsigned char>(fy * 255.0f);fake_input.z = static_cast<unsigned char>(fz * 255.0f);// Step 3: 调用 OpenCV 提供的 sinh 函数(唯一一次调用)float3 sinhVal = sinh(fake_input); // ←←← 这里才是你想要的 cv::cudev::sinh(...)// Step 4: 将 sinh 输出压缩到 [0,1]const float inv_sinh1 = 1.0f / sinhf(1.0f); // sinh([0,1]) ∈ [0, ~1.175]sinhVal.x *= inv_sinh1;sinhVal.y *= inv_sinh1;sinhVal.z *= inv_sinh1;// Step 5: 写入输出图像dst(y, x) = sinhVal;}
}int main() {// 加载图像Mat h_img = imread("/media/dingxin/data/study/OpenCV/sources/images/img0.jpg", IMREAD_COLOR);if (h_img.empty()) {std::cerr << "Failed to load image!" << std::endl;return -1;}// 上传到 GPUcuda::GpuMat d_img, d_result;d_img.upload(h_img);d_result.create(d_img.size(), CV_32FC3); // float3 对应 CV_32FC3// 构造 PtrStepSz 访问器auto ptr = PtrStepSz<uchar3>(d_img);auto dptr = PtrStepSz<float3>(d_result);// 设置核函数参数dim3 block(16, 16);dim3 grid((d_img.cols + block.x - 1) / block.x,(d_img.rows + block.y - 1) / block.y);// 启动核函数sinhKernel<<<grid, block>>>(ptr, dptr, d_img.cols, d_img.rows);cudaDeviceSynchronize();// 下载并显示结果Mat h_result;d_result.download(h_result);imshow("Sinh Image", h_result); // 已经是 [0,1] 浮点图像imwrite("output_sinh_image.png", h_result * 255); // 保存为 PNGwaitKey(0);return 0;
}