- 操作系統:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 編程語言:C++11
算法描述
OpenCV 的CUDA并行計算模塊(cv::cudev)中的一個設備端內聯函數,用于在CUDA核函數中對兩個uchar2類型像素值進行逐通道最小值比較。
對兩個 uchar2 類型變量(即 2 通道無符號字符類型)進行逐通道比較,返回每個通道中的最小值。
它常用于 GPU 加速的圖像融合、像素比較、背景建模等場景。
函數原型
__device__ __forceinline__ uchar2 cv::cudev::min ( const uchar2 & a,const uchar2 & b )
參數
- a const uchar2& 第一個輸入像素值(x, y 兩個通道)
- b const uchar2& 第二個輸入像素值
返回值
- 返回一個新的 uchar2 值;
- 每個通道的值為 a.x 和 b.x 的最小值,a.y 和 b.y 的最小值。
代碼
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/cudev/util/vec_math.hpp>using namespace cv;
using namespace cv::cudev;// CUDA 核函數:取兩個 uchar2 像素的最小值
template <typename Ptr1, typename Ptr2, typename DstPtr>
__global__ void minKernel(Ptr1 src1, Ptr2 src2, 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) {// 獲取兩個圖像的像素值uchar2 val1 = src1(y, x);uchar2 val2 = src2(y, x);// 取最小值并寫入輸出圖像dst(y, x) = min(val1, val2);}
}int main() {// 加載兩張圖像(假設尺寸相同),轉換為 2 通道格式(比如合并兩個灰度圖為 uchar2)Mat h_img1 = imread("/media/dingxin/data/study/OpenCV/sources/images/img0.jpg", IMREAD_GRAYSCALE);Mat h_img2 = imread("/media/dingxin/data/study/OpenCV/sources/images/img1.jpg", IMREAD_GRAYSCALE);if (h_img1.empty() || h_img2.empty()) {std::cerr << "Failed to load images!" << std::endl;return -1;}// 轉換為 2 通道圖像(uchar2)Mat h_2ch[] = {h_img1, h_img2};Mat h_combined;merge(h_2ch, 2, h_combined); // 合并為 CV_8UC2// 上傳到 GPUcuda::GpuMat d_combined, d_result;d_combined.upload(h_combined);d_result.create(d_combined.size(), d_combined.type());// 構造訪問器auto ptr = PtrStepSz<uchar2>(d_combined);auto dptr = PtrStepSz<uchar2>(d_result);// 設置核函數參數dim3 block(16, 16);dim3 grid((d_combined.cols + block.x - 1) / block.x,(d_combined.rows + block.y - 1) / block.y);// 調用核函數minKernel<<<grid, block>>>(ptr, ptr, dptr, d_combined.cols, d_combined.rows);cudaDeviceSynchronize();// 分離通道并顯示結果Mat h_result;d_result.download(h_result);std::vector<Mat> channels;split(h_result, channels);imshow("Min Channel 1", channels[0]);imshow("Min Channel 2", channels[1]);waitKey(0);return 0;
}