OpenCV-复数矩阵点乘ComplexMatrixDotMultiplication

发布于:2024-04-25 ⋅ 阅读:(15) ⋅ 点赞:(0)

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

需求说明

       一般用到FFT,就涉及到复数的计算,为了便于调用,我自行封装了一个简单的复数矩阵点乘函数。复数乘法公式:

(a+bi)(c+di)=(ac-bd)+(ad+bc)i

       下面展示代码。

功能函数

// 复数矩阵点乘
cv::Mat ComplexMatrixDotMultiplication(const cv::Mat& A, const cv::Mat& B)
{
	// 确保A和B都是双通道的矩阵
	CV_Assert(A.channels() == 2 && B.channels() == 2);

	// 提取A和B的实部和虚部
	std::vector<cv::Mat> A_channels, B_channels;
	cv::split(A, A_channels);
	cv::split(B, B_channels);
	cv::Mat A_real = A_channels[0];
	cv::Mat A_imag = A_channels[1];
	cv::Mat B_real = B_channels[0];
	cv::Mat B_imag = B_channels[1];

	// 计算相乘
	cv::Mat C_real = A_real.mul(B_real) - A_imag.mul(B_imag);
	cv::Mat C_imag = A_real.mul(B_imag) + A_imag.mul(B_real);

	// 合并结果
	std::vector<cv::Mat> C_channels{ C_real, C_imag };
	cv::Mat C;
	cv::merge(C_channels, C);

	return C;
}

C++&Matlab测试代码

#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

// 复数矩阵点乘
cv::Mat ComplexMatrixDotMultiplication(const cv::Mat& A, const cv::Mat& B)
{
	// 确保A和B都是双通道的矩阵
	CV_Assert(A.channels() == 2 && B.channels() == 2);

	// 提取A和B的实部和虚部
	std::vector<cv::Mat> A_channels, B_channels;
	cv::split(A, A_channels);
	cv::split(B, B_channels);
	cv::Mat A_real = A_channels[0];
	cv::Mat A_imag = A_channels[1];
	cv::Mat B_real = B_channels[0];
	cv::Mat B_imag = B_channels[1];

	// 计算相乘
	cv::Mat C_real = A_real.mul(B_real) - A_imag.mul(B_imag);
	cv::Mat C_imag = A_real.mul(B_imag) + A_imag.mul(B_real);

	// 合并结果
	std::vector<cv::Mat> C_channels{ C_real, C_imag };
	cv::Mat C;
	cv::merge(C_channels, C);

	return C;
}

int main()
{
	// 定义实际数据的双通道矩阵 A 和 B
	cv::Mat A = (cv::Mat_<std::complex<float>>)cv::Mat::zeros(4, 4, CV_32FC2);
	cv::Mat B = (cv::Mat_<std::complex<float>>)cv::Mat::zeros(4, 4, CV_32FC2);

	// 自定义 A 和 B 的数据
	for (int i = 0; i < A.rows; ++i) {
		for (int j = 0; j < A.cols; ++j) {
			A.at<std::complex<float>>(i, j) = std::complex<float>(i + 1, j + 1);
			B.at<std::complex<float>>(i, j) = std::complex<float>(i + 2, j + 2);
		}
	}

	// 调用复数矩阵乘法函数
	cv::Mat C = GlobalFunc::complexMatrixMultiplication(A, B);

	// 打印结果
	std::cout << "Result Matrix C:\n" << C << std::endl;

	return 0;
}
% 定义 A 和 B 的大小
rows = 4;
cols = 4;

% 创建实际数据的双通道矩阵 A 和 B,初始值为零
A = zeros(rows, cols) + 1i * zeros(rows, cols);
B = zeros(rows, cols) + 1i * zeros(rows, cols);

% 自定义 A 和 B 的数据
for i = 1:rows
    for j = 1:cols
        A(i, j) = complex(i, j);
        B(i, j) = complex(i + 1, j + 1);
    end
end

% 复数矩阵点乘
C = A .* B;

% 显示结果
disp('Result Matrix C:');
disp(C);

测试效果

       如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!