2

我正在尝试在 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)。

提前感谢您的帮助。

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

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));

然而,这在一个循环中工作,这使得该过程非常慢。有什么办法一口气搞定吗?

4

2 回答 2

3

还有函数mulSpectrums,它可以让您对复杂矩阵进行元素乘法。因此,如果 K 是您的内核矩阵,而 I 是一些复杂的矩阵,即 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);
于 2014-07-16T11:19:18.887 回答
2

OpenCVstd::complex就像简单的一对数字一样对待(参见文档中的示例)。没有应用关于算术运算的特殊规则。你可以通过直接乘法来克服这个问题std::complex。所以基本上,这很简单:您要么选择自动复数算术(就像你现在所做的那样),要么选择自动矢量化(在矩阵上使用 OpenCV 函数时)。

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

于 2012-12-04T11:10:09.260 回答