- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
mulAndScaleSpectrums()是OpenCV CUDA模块中用于在频域(复数频谱)中执行逐元素乘法并缩放 的函数。
这个函数主要用于在 傅里叶变换后的频域空间中进行滤波、卷积、图像配准等操作。它实现了以下运算:
d s t = s c a l e ⋅ s r c 1 ⋅ ( c o n j B ? c o n j ( s r c 2 ) : s r c 2 ) dst=scale⋅src1⋅(conjB ? conj(src2) : src2) dst=scale⋅src1⋅(conjB?conj(src2):src2)
其中:
- src1 和 src2 是两个复数格式的频谱(CV_32FC2)
- conjB 控制是否对 src2 进行共轭
- scale 是一个可选的缩放因子
- flags 可控制额外的操作(如零填充、频谱重排)
函数原型
cpp
void cv::cuda::mulAndScaleSpectrums
(
InputArray src1,
InputArray src2,
OutputArray dst,
int flags,
float scale,
bool conjB = false,
Stream& stream = Stream::Null()
)
参数
参数说明
参数名 | 类型 | 是否必需 | 默认值 | 描述 |
---|---|---|---|---|
src1 |
InputArray |
是 | 无 | 第一个输入频谱(复数形式,CV_32FC2 ) |
src2 |
InputArray |
是 | 无 | 第二个输入频谱(复数形式,CV_32FC2 ) |
dst |
OutputArray |
是 | 无 | 输出结果,也是复数形式(CV_32FC2 ) |
flags |
int |
是 | 无 | 标志位,通常与 dft() 中一致(如 cv::DFT_ROWS , cv::DFT_COMPLEX_OUTPUT ) |
scale |
float |
是 | 无 | 缩放因子(常用于归一化) |
conjB |
bool |
否 | false |
是否对 src2 取共轭(用于相关计算或匹配) |
stream |
Stream& |
否 | Stream::Null() |
CUDA 流对象,用于异步执行 |
代码示例
cpp
#include <iostream>
#include <opencv2/cudaarithm.hpp>
#include <opencv2/opencv.hpp>
int main()
{
// 创建测试图像(单通道浮点型)
cv::Mat h_imgA = cv::Mat::zeros(512, 512, CV_32F);
cv::rectangle(h_imgA, cv::Rect(100, 100, 100, 100), cv::Scalar(255), -1);
cv::Mat h_imgB = h_imgA.clone();
cv::warpAffine(h_imgB, h_imgB, cv::getRotationMatrix2D(cv::Point2f(256, 256), 10, 1), h_imgB.size());
// 上传到 GPU
cv::cuda::GpuMat d_imgA, d_imgB;
d_imgA.upload(h_imgA);
d_imgB.upload(h_imgB);
// 扩展图像至最优 DFT 尺寸(提高计算效率)
cv::cuda::GpuMat d_imgA_padded, d_imgB_padded;
cv::cuda::copyMakeBorder(d_imgA, d_imgA_padded, 0, 0, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all(0));
cv::cuda::copyMakeBorder(d_imgB, d_imgB_padded, 0, 0, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all(0));
// 执行 DFT(输出复数,2通道)
cv::cuda::GpuMat d_fftA, d_fftB;
cv::cuda::dft(d_imgA_padded, d_fftA, d_imgA_padded.size(), 0);
cv::cuda::dft(d_imgB_padded, d_fftB, d_imgB_padded.size(), 0);
// 频域乘法 + 共轭(互相关)
cv::cuda::GpuMat d_corr;
cv::cuda::mulSpectrums(d_fftA, d_fftB, d_corr, cv::DFT_ROWS, true); // 使用共轭
// 逆变换得到空间域互相关图(复数)
cv::cuda::GpuMat d_icorr;
cv::cuda::dft(d_corr, d_icorr, d_corr.size(), cv::DFT_INVERSE | cv::DFT_SCALE);
// 提取实部(互相关结果是实数)
std::vector<cv::cuda::GpuMat> planes;
cv::cuda::split(d_icorr, planes); // 分离复数结果的实部和虚部
cv::cuda::GpuMat d_icorr_real = planes[0]; // 提取实部
// 下载并归一化
cv::Mat h_icorr;
d_icorr_real.download(h_icorr);
cv::normalize(h_icorr, h_icorr, 0, 1, cv::NORM_MINMAX);
// 找到峰值位置(匹配点)
cv::Point max_loc;
cv::minMaxLoc(h_icorr, nullptr, nullptr, nullptr, &max_loc);
std::cout << "Peak at: " << max_loc << std::endl;
// 可视化(绘制峰值)
cv::Mat h_icorr_display;
h_icorr.convertTo(h_icorr_display, CV_8UC1, 255.0);
cv::cvtColor(h_icorr_display, h_icorr_display, cv::COLOR_GRAY2BGR);
cv::circle(h_icorr_display, max_loc, 5, cv::Scalar(0, 0, 255), 2);
cv::imshow("Cross Correlation", h_icorr_display);
cv::waitKey(0);
return 0;
}
运行结果
bash
Peak at: [8, 492]
