C++使用OpenCV计算2通道复数Mat的共轭/两个复数Mat的直积/两个复数Mat的对应位相除

时间:2021-12-17 22:41:12

2通道复数Mat的共轭

代码如下

cv::Mat conj4mat(cv::Mat src) {
        if (src.channels() != 2) {
            std::cout << "func CONJ4MAT : channels parameters error!" << std::endl;
            return Mat();
        }
        int cols = src.cols;// 表示x轴
        int rows = src.rows;// 表示y轴
        cv::Mat result = cv::Mat::zeros(cv::Size(cols, rows), CV_32FC2);
        /*核心思想: 将图像按照每一行的顺序,进行展开,成为一个长的向量。 例如一个Size(640,480)的图像,展开后,向量的长度为 640*480 */
        std::vector<cv::Mat> channels;//用于存放实部和虚部,channels[0]存放的是实部,channels[1]存放的是虚部
        std::complex<double>* conj4mat = new std::complex<double>[cols * rows]; //用于存放展开后的复数向量
        std::complex<double> temp;
        cv::split(src, channels);
        int k = 0;//用于存放数据到复数数组里的索引,其最大值应该为 rows * cols
        double real = 0, imag = 0;

        //前向计算过程
        for (size_t i = 0; i < cols; i++) {
            for (size_t j = 0; j < rows; j++) {
                real = channels[0].at<float>(j, i);
                imag = channels[1].at<float>(j, i);
                temp = std::complex<double>(real, imag);

                conj4mat[k] = temp;
                k++;
            }
        }
        k = 0;
        std::complex<double> middle;
        //反向释放数据到Mat
        for (size_t i = 0; i < cols; i++) {
            for (size_t j = 0; j < rows; j++) {
                middle = std::conj(conj4mat[k]);
                real = middle.real();
                imag = middle.imag();
                channels[0].at<float>(j, i) = real;
                channels[1].at<float>(j, i) = imag;

                k++;
            }
        }

        // 将求得的结果合并为一个Mat
        merge(channels, result);
        return result;
    }

两个复数Mat的直积

cv::Mat cmplxMul(cv::Mat m1, cv::Mat m2) {
    //assert(m1.rows != m2.rows,"相乘矩阵的维度不一致");
    //assert(m1.cols != m2.cols,"相乘矩阵的维度不一致");

    int rows = m1.rows;//矩阵的行数以及列数
    int cols = m1.cols;

    cv::Mat result = cv::Mat::zeros(rows, cols,CV_32FC2);

    //用于存放实部[0]以及虚部[1]
    vector<Mat> channels_m1;
    vector<Mat> channels_m2;
    vector<Mat> channels_result;

    split(m1, channels_m1);
    split(m2, channels_m2);
    split(result, channels_result);

    //用于将矩阵形式的复数转换乘向量
    vector<std::complex<float>> complex_result;


    std::complex<float> m1_c;
    std::complex<float> m2_c;

    //分解m1以及m2中的复数
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            m1_c = std::complex<float>(
                channels_m1[0].at<float>(i, j),
                channels_m1[1].at<float>(i, j));
            m2_c = std::complex<float>(
                channels_m2[0].at<float>(i, j),
                channels_m2[1].at<float>(i, j));
            complex_result.push_back(m1_c * m2_c);
        }
    }

    int k = 0;
    //反向释放数据到Mat
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            channels_result[0].at<float>(i, j) = complex_result[k].real();
            channels_result[1].at<float>(i, j) = complex_result[k].imag();
            k++;
        }
    }

    merge(channels_result, result);

    return result;
}

两个复数Mat的对应位相除

cv::Mat cmplxDivision(cv::Mat m1, cv::Mat m2) {
    //assert(m1.rows != m2.rows,"相乘矩阵的维度不一致");
    //assert(m1.cols != m2.cols,"相乘矩阵的维度不一致");

    int rows = m1.rows;//矩阵的行数以及列数
    int cols = m1.cols;

    cv::Mat result = cv::Mat::zeros(rows, cols, CV_32FC2);

    //用于存放实部[0]以及虚部[1]
    vector<Mat> channels_m1;
    vector<Mat> channels_m2;
    vector<Mat> channels_result;

    split(m1, channels_m1);
    split(m2, channels_m2);
    split(result, channels_result);

    //用于将矩阵形式的复数转换乘向量
    vector<std::complex<float>> complex_result;

    std::complex<float> m1_c;
    std::complex<float> m2_c;

    //分解m1以及m2中的复数
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            m1_c = std::complex<float>(
                channels_m1[0].at<float>(i, j),
                channels_m1[1].at<float>(i, j));
            m2_c = std::complex<float>(
                channels_m2[0].at<float>(i, j),
                channels_m2[1].at<float>(i, j));
            complex_result.push_back(m1_c / m2_c);
        }
    }
    int k = 0;
    //反向释放数据到Mat
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            channels_result[0].at<float>(i, j) = complex_result[k].real();
            channels_result[1].at<float>(i, j) = complex_result[k].imag();
            k++;
        }
    }
    merge(channels_result, result);
    return result;
}