在OpenCV中实现复值矩阵方程

时间:2012-11-28 14:12:56

标签: c++ opencv matrix

我试图在OpenCV中实现复值矩阵方程。我在MATLAB中做了原型,工作正常。从等式(精确的MATLAB实现)开始:

kernel = exp(1i .* k .* Circ3D) .* z ./ (1i .* lambda .* Circ3D .* Circ3D)

其中

1i = complex number
k = constant (float)
Circ3D = real-valued matrix of known size
lambda = constant (float)
.* = element-wise multiplication
./ = element-wise division

结果是复值矩阵。我成功地生成了必要的Circ3D矩阵作为CV_32F,但复数i的乘法给我带来了麻烦。从OpenCV文档中我了解复杂矩阵只是一个双通道矩阵(CV_32FC2)。

真正的麻烦来自如何定义i。我尝试了几个选项,其中将i定义为

cv::Vec2d complex = cv::Vec2d(0,1);

然后乘以矩阵

kernel = complex * Circ3D

但这不起作用(虽然我没想到)。我怀疑我需要用std :: complex做一些事情,但我不知道是什么(http://docs.opencv.org/modules/core/doc/basic_structures.html)。

提前感谢您的帮助。

编辑:在写完这篇文章之后,我确实取得了一些进展,通过如下定义我:

std::complex<float> complex(0,1)

然后我可以按如下方式分配复杂值:

kernel.at<std::complex<float>>(i,j) = cv::exp(complex * k * Circ3D.at<float>(i,j)) * ...
z / (complex * lambda * pow(Circ3D.at<float>(i,j),2));

然而,这在循环中起作用,这使得程序非常慢。有没有办法一次性完成?

2 个答案:

答案 0 :(得分:1)

OpenCV将std::complex视为简单的数字对(参见example in the documentation)。没有应用算术运算的特殊规则。您可以通过直接乘以std::complex来克服此问题。所以基本上,这很简单:你要么选择自动复杂算术(正如你现在所做的那样),要么自动矢量化(当在矩阵上使用OpenCV函数时)。

我认为,在你的情况下,你应该自己携带所有复杂的算术。将复数值C{ai + b}的矩阵存储为两个矩阵A{a}B{b}。实现取幂by yourself。标量和乘法的乘法应该不是问题。

答案 1 :(得分:1)

还有函数mulSpectrums,它允许您对复杂矩阵进行元素乘法运算。因此,如果K是你的核矩阵并且我是一个复杂的矩阵,即CV_32FC2(浮动双通道),你可以执行以下操作来计算元素乘法,

// Make K a complex matrix
cv::Mat Ktmp[] = {cv::Mat_<float>(K), cv::Mat::zeros(K.size(), CV_32FC1)};
cv::Mat Kc;
cv::merge(Ktmp,2,Kc);
// Do matrix multiplication
cv::mulSpectrums(Kc,I,I,0);