引言
由于opencv自身不带有复数计算功能,但我又经常需要进行复数运算,所以我只能自己写两个函数来进行复数的乘除法运算。
opencv中的复数表示
复数包含了实部和虚部,在opencv中是使用一个二通道的Mat对象来存放一个复数数组,两个通道分别存储复数的实部和虚部,图像傅里叶变换的结果就是一个使用二通道数组存放的复数数组。比如一个复数:
[
0
+
0
j
0
+
j
1
+
0
j
1
+
j
]
\begin{bmatrix} 0+0j&0+j\\ 1+0j&1+j \end{bmatrix}
[0+0j1+0j0+j1+j]
这个复数就可以存放在Mat对象里面,存放方法如下:
Mat complex(2, 2, CV_64FC2);//二通道数组
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
complex.at<double>(i, 2 * j) = i;
complex.at<double>(i, 2 * j + 1) = j;
}
}
复数乘法
两复数
a
+
b
j
a+bj
a+bj与
c
+
d
j
c+dj
c+dj相乘,公式如下:
(
a
+
b
j
)
(
c
+
d
j
)
=
a
c
−
b
d
+
(
b
c
+
a
d
)
j
(a+bj)(c+dj)=ac-bd+(bc+ad)j
(a+bj)(c+dj)=ac−bd+(bc+ad)j
现在两个复数数组要想进行复数乘法运算,可以先将两个复数进行通道分离,再通过复数乘法公式进行处理即可。代码如下:
Mat Mult(Mat input1, Mat input2)
{
if ((input1.channels() != 2) | (input2.channels() != 2)) {
std::cout << "输入数组应该为包含实部和虚部的二通道数组" << std::endl;
return Mat();
}
Mat src1 = input1.clone();
Mat src2 = input2.clone();
Mat F[2];//分别存放实部和虚部
split(src1, F);//a=F[0],b=F[1]
Mat G[2];
split(src2, G);//c=G[0],d=G[1];
Mat ac;
multiply(F[0], G[0], ac);//multiply实现矩阵的点乘
Mat bd;
multiply(F[1], G[1], bd);
Mat Real = ac - bd;//得到的结果的实部
Mat ad;
multiply(F[0], G[1], ad);
Mat bc;
multiply(F[1], G[0], bc);
Mat Im = ad + bc;
Mat value[2] = { Real,Im };
Mat result;
merge(value, 2, result);
return result;
}
复数除法
两复数
a
+
b
j
a+bj
a+bj与
c
+
d
j
c+dj
c+dj相除,公式如下:
(
a
+
b
j
)
/
(
c
+
d
j
)
=
[
a
c
+
b
d
+
(
b
c
−
a
d
)
j
]
/
(
c
2
+
d
2
)
(a+bj)/(c+dj)=[ac+bd+(bc-ad)j]/{(c^2+d^2)}
(a+bj)/(c+dj)=[ac+bd+(bc−ad)j]/(c2+d2)
现在两个复数数组要想进行复数除法运算,一样的先将两个复数进行通道分离,再通过复数除法公式进行处理即可。代码如下:
Mat Div(Mat input1, Mat input2)
{
if ((input1.channels() != 2) | (input2.channels() != 2)) {
std::cout << "输入数组应该为包含实部和虚部的二通道数组" << std::endl;
return Mat();
}
Mat src1 = input1.clone();
Mat src2 = input2.clone();
Mat F[2];//分别存放实部和虚部
split(src1, F);
Mat G[2];
split(src2, G);
Mat a = F[0];
Mat b = F[1];
Mat c = G[0];
Mat d = G[1];
Mat c2;
multiply(c, c, c2);
Mat d2;
multiply(d, d, d2);
Mat ac;
multiply(a, c, ac);
Mat bd;
multiply(b, d, bd);
Mat bc;
multiply(b, c, bc);
Mat ad;
multiply(a, d, ad);
Mat real;
divide(ac + bd, c2 + d2, real);
Mat im;
divide(bc - ad, c2 + d2, im);
Mat value[2] = { real,im };
Mat result;
merge(value, 2, result);
return result;
}