- 操作系统: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;
}