- 操作系統:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 編程語言:C++11
算法描述
在 OpenCV 的 CUDA 模塊中,與范數(Norm)相關的函數主要用于計算矩陣的范數或者兩個矩陣之間的差值范數。
主要函數
1.計算單個 GPU 矩陣的范數:norm
原型
double cv::cuda::norm
(InputArray src1, // 輸入 GPU 矩陣int normType = NORM_L2, // 范數類型,默認為L2范數InputArray mask = noArray() // 可選掩碼,用于選擇性地應用范數計算到src1的部分區域
);
參數
- InputArray src1: 需要計算范數的輸入 GPU 矩陣。
- int normType: 指定使用的范數類型。常見的有:
- NORM_INF: 無窮范數,等于絕對值最大的元素。
- NORM_L1: L1范數,所有元素絕對值之和。
- NORM_L2: L2范數,平方和的平方根。
- InputArray mask: 可選參數,如果提供,則只對mask中非零元素對應的src1部分進行計算。
2.計算兩個 GPU 矩陣之間的差值范數norm
原型
double cv::cuda::norm
(InputArray src1, // 第一個輸入 GPU 矩陣InputArray src2, // 第二個輸入 GPU 矩陣,尺寸/類型相同int normType = NORM_L2 // 范數類型,默認為L2范數
);
參數
- InputArray src2: 第二個輸入 GPU 矩陣,要求與src1具有相同的尺寸和通道數。
- 其余參數同上。
3.異步計算單個 GPU 矩陣的范數calcNorm
原型
void cv::cuda::calcNorm
(InputArray src, // 輸入 GPU 矩陣OutputArray dst, // 輸出結果,標量int normType, // 范數類型InputArray mask = noArray(), // 可選掩碼Stream& stream = Stream::Null() // 可選 CUDA 流
);
參數
- OutputArray dst: 輸出結果,通常是一個 GpuMat 或者 Scalar,表示計算出的范數值。
- Stream& stream: 可選參數,指定執行此操作的CUDA流,默認為 Stream::Null() 表示使用默認流。
4.異步計算兩個 GPU 矩陣之間的差值范數calcNormDiff
原型
void cv::cuda::calcNormDiff
(InputArray src1, // 第一個輸入 GPU 矩陣InputArray src2, // 第二個輸入 GPU 矩陣,尺寸/類型相同OutputArray dst, // 輸出結果,標量int normType = NORM_L2, // 范數類型,默認為L2范數Stream& stream = Stream::Null() // 可選 CUDA 流
);
參數
- InputArray src2: 第二個輸入 GPU 矩陣,要求與src1具有相同的尺寸和通道數。
- 其余參數同上。
代碼示例
#include <opencv2/opencv.hpp>
#include <opencv2/cudaarithm.hpp>
#include <iostream>int main() {// 創建兩個 float 類型的 3x3 測試矩陣cv::Mat h_mat1 = (cv::Mat_<float>(3, 3) <<1.0f, -2.0f, 3.0f,-4.0f, 5.0f, -6.0f,7.0f, -8.0f, 9.0f);cv::Mat h_mat2 = cv::Mat::zeros(h_mat1.size(), h_mat1.type());// 創建一個 mask 矩陣(只允許中心區域參與計算)cv::Mat h_mask = cv::Mat::zeros(h_mat1.size(), CV_8UC1);cv::rectangle(h_mask, cv::Rect(1, 1, 1, 1), cv::Scalar(255), cv::FILLED); // 中心像素// 將數據轉換為 CV_8UC1 類型cv::Mat h_mat1_8u, h_mat2_8u;h_mat1.convertTo(h_mat1_8u, CV_8UC1);h_mat2.convertTo(h_mat2_8u, CV_8UC1);// 上傳到 GPUcv::cuda::GpuMat d_mat1, d_mat2, d_mask;d_mat1.upload(h_mat1_8u);d_mat2.upload(h_mat2_8u);d_mask.upload(h_mask);// 存儲異步結果的 GpuMatcv::cuda::GpuMat d_norm_result;// 創建 CUDA 流cv::cuda::Stream stream;// 1?? 同步:單矩陣 L2 范數(帶 mask)double l2_norm = cv::cuda::norm(d_mat1, cv::NORM_L2, d_mask);std::cout << "Sync L2 Norm of mat1 (with mask): " << l2_norm << std::endl;// 2?? 同步:兩矩陣之間的 L2 差值范數double diff_norm = cv::cuda::norm(d_mat1, d_mat2, cv::NORM_L2);std::cout << "Sync L2 Diff Norm between mat1 and mat2: " << diff_norm << std::endl;// 3?? 異步:單矩陣 L1 范數cv::cuda::calcNorm(d_mat1, d_norm_result, cv::NORM_L1, cv::noArray(), stream);stream.waitForCompletion();cv::Mat host_norm;d_norm_result.download(host_norm);double async_l1_norm = host_norm.at<double>(0, 0);std::cout << "Async L1 Norm of mat1: " << async_l1_norm << std::endl;// 4?? ? 異步:兩個矩陣之間的 L2 差值范數(必須調用 calcNormDiff)cv::cuda::calcNormDiff(d_mat1, d_mat2, d_norm_result, cv::NORM_L2, stream);stream.waitForCompletion();d_norm_result.download(host_norm);double async_diff_norm = host_norm.at<double>(0, 0);std::cout << "Async L2 Diff Norm between mat1 and mat2: " << async_diff_norm << std::endl;return 0;
}
運行結果
Sync L2 Norm of mat1 (with mask): 5
Sync L2 Diff Norm between mat1 and mat2: 12.8452
Async L1 Norm of mat1: 25
Async L2 Diff Norm between mat1 and mat2: 12.8452