最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C/C++中OpenCV 矩陣運算的實現

 更新時間:2025年05月31日 09:09:42   作者:whoarethenext  
本文主要介紹了C/C++中OpenCV 矩陣運算的實現,包括基本算術運算(標量與矩陣)、矩陣乘法、轉置、逆矩陣、行列式、跡、范數等操作,感興趣的可以了解一下

OpenCV 是一個強大的開源計算機視覺和機器學習庫,它提供了豐富的矩陣運算功能,這對于圖像處理和計算機視覺算法至關重要。本文將詳細介紹如何使用 C/C++ 和 OpenCV 進行常見的矩陣運算。

矩陣的創(chuàng)建與初始化

在進行矩陣運算之前,我們首先需要知道如何創(chuàng)建和初始化矩陣。OpenCV 提供了 cv::Mat 類來處理矩陣。

創(chuàng)建矩陣

有多種方法可以創(chuàng)建 cv::Mat 對象:

使用構造函數:可以指定行數、列數、數據類型以及可選的初始值。

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

int main() {
    // 創(chuàng)建一個 3x3 的浮點型矩陣,所有元素初始化為 0
    cv::Mat matrix1 = cv::Mat::zeros(3, 3, CV_32F);
    std::cout << "Matrix1:\n" << matrix1 << std::endl;

    // 創(chuàng)建一個 2x4 的整型矩陣,所有元素初始化為 1
    cv::Mat matrix2 = cv::Mat::ones(2, 4, CV_8UC1); // 8位無符號單通道
    std::cout << "Matrix2:\n" << matrix2 << std::endl;

    // 創(chuàng)建一個具有特定尺寸和類型的矩陣,不初始化
    cv::Mat matrix3(4, 2, CV_64FC3); // 64位浮點型三通道

    // 使用 Scalar 初始化
    cv::Mat matrix4 = cv::Mat(3, 3, CV_32F, cv::Scalar(5.0));
    std::cout << "Matrix4:\n" << matrix4 << std::endl;

    // 通過 C/C++ 數組創(chuàng)建
    double data[] = {1, 2, 3, 4, 5, 6};
    cv::Mat matrix5 = cv::Mat(2, 3, CV_64F, data);
    std::cout << "Matrix5:\n" << matrix5 << std::endl;

    return 0;
}

cv::Mat::create() 方法:如果矩陣已經存在,此方法會重新分配內存(如果需要)。

cv::Mat matrix;
matrix.create(4, 4, CV_32F);

cv::Mat::eye() 方法:創(chuàng)建單位矩陣。

cv::Mat identityMatrix = cv::Mat::eye(3, 3, CV_64F);
std::cout << "Identity Matrix:\n" << identityMatrix << std::endl;

訪問矩陣元素

可以使用 at() 方法或者直接通過指針訪問矩陣元素。at() 方法更安全,因為它會進行邊界檢查。

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

int main() {
    cv::Mat matrix = (cv::Mat_<double>(3,3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
    std::cout << "Original Matrix:\n" << matrix << std::endl;

    // 使用 at() 方法訪問和修改元素
    double& elem = matrix.at<double>(0, 0); // 獲取 (0,0) 處的元素引用
    elem = 100.0;
    std::cout << "Modified Matrix (at()):\n" << matrix << std::endl;

    // 直接通過指針訪問 (效率更高,但不安全)
    // 注意:需要確保數據類型匹配
    double* p = matrix.ptr<double>(1); // 獲取第二行的指針
    p[1] = 200.0; // 修改第二行第二列的元素 (1,1)
    std::cout << "Modified Matrix (ptr):\n" << matrix << std::endl;

    return 0;
}

基本的算術運算 ?????

OpenCV 支持對矩陣進行各種基本的算術運算。這些運算可以是矩陣與標量之間的運算,也可以是矩陣與矩陣之間的運算。

矩陣與標量運算

可以直接使用標準的算術運算符:

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,2) << 1, 2, 3, 4);
    double scalar = 5.0;
    cv::Mat result;

    // 加法
    result = matrixA + scalar;
    std::cout << "MatrixA + Scalar:\n" << result << std::endl;

    // 減法
    result = matrixA - scalar;
    std::cout << "MatrixA - Scalar:\n" << result << std::endl;
    result = scalar - matrixA;
    std::cout << "Scalar - MatrixA:\n" << result << std::endl;

    // 乘法
    result = matrixA * scalar;
    std::cout << "MatrixA * Scalar:\n" << result << std::endl;

    // 除法
    result = matrixA / scalar;
    std::cout << "MatrixA / Scalar:\n" << result << std::endl;

    return 0;
}

矩陣與矩陣運算 (逐元素)

對于加法、減法和逐元素的乘法、除法,可以使用重載的運算符或 OpenCV 提供的函數。

  • 加法 (+ 或 cv::add())
  • 減法 (- 或 cv::subtract())
  • 逐元素乘法 (cv::multiply())
  • 逐元素除法 (cv::divide())
#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,2) << 1, 2, 3, 4);
    cv::Mat matrixB = (cv::Mat_<double>(2,2) << 5, 6, 7, 8);
    cv::Mat result;

    // 加法
    result = matrixA + matrixB;
    // 或者 cv::add(matrixA, matrixB, result);
    std::cout << "MatrixA + MatrixB:\n" << result << std::endl;

    // 減法
    result = matrixA - matrixB;
    // 或者 cv::subtract(matrixA, matrixB, result);
    std::cout << "MatrixA - MatrixB:\n" << result << std::endl;

    // 逐元素乘法
    cv::multiply(matrixA, matrixB, result);
    // 注意: matrixA * matrixB 是矩陣乘法,而不是逐元素乘法
    std::cout << "Element-wise multiplication (A .* B):\n" << result << std::endl;

    // 逐元素除法
    cv::divide(matrixA, matrixB, result);
    std::cout << "Element-wise division (A ./ B):\n" << result << std::endl;

    return 0;
}

矩陣乘法 (標準線性代數乘法)

使用 * 運算符可以執(zhí)行標準的矩陣乘法 (m x n 矩陣乘以 n x p 矩陣得到 m x p 矩陣)?;蛘呤褂?nbsp;cv::gemm() 函數 (通用矩陣乘法)。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,3) << 1, 2, 3, 4, 5, 6);
    cv::Mat matrixB = (cv::Mat_<double>(3,2) << 7, 8, 9, 10, 11, 12);
    cv::Mat result;

    // 矩陣乘法
    result = matrixA * matrixB;
    std::cout << "MatrixA * MatrixB (Matrix Multiplication):\n" << result << std::endl;

    // 使用 cv::gemm()
    // gemm(src1, src2, alpha, src3, beta, dst, flags)
    // dst = alpha*src1*src2 + beta*src3
    cv::Mat matrixC = cv::Mat::zeros(2, 2, CV_64F);
    cv::gemm(matrixA, matrixB, 1.0, cv::Mat(), 0.0, result, 0); // result = 1.0 * matrixA * matrixB
    std::cout << "MatrixA * MatrixB (using gemm):\n" << result << std::endl;


    return 0;
}

注意: 參與矩陣乘法的兩個矩陣的維度必須兼容 (第一個矩陣的列數等于第二個矩陣的行數)。

其他重要的矩陣運算 ??

OpenCV 還提供了許多其他有用的矩陣運算函數。

轉置 (cv::transpose() 或 Mat::t())

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,3) << 1, 2, 3, 4, 5, 6);
    cv::Mat transposedMatrix;

    cv::transpose(matrixA, transposedMatrix);
    // 或者 transposedMatrix = matrixA.t();
    std::cout << "Original MatrixA:\n" << matrixA << std::endl;
    std::cout << "Transposed MatrixA:\n" << transposedMatrix << std::endl;

    return 0;
}

逆矩陣 (cv::invert() 或 Mat::inv())

只有方陣且非奇異矩陣(行列式不為零)才有逆矩陣。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,2) << 4, 7, 2, 6);
    cv::Mat inverseMatrix;

    // method 可以是 DECOMP_LU, DECOMP_SVD, DECOMP_CHOLESKY (對于對稱正定矩陣)
    double det = cv::determinant(matrixA);
    if (det != 0) {
        cv::invert(matrixA, inverseMatrix, cv::DECOMP_LU);
        // 或者 inverseMatrix = matrixA.inv(cv::DECOMP_LU);
        std::cout << "Original MatrixA:\n" << matrixA << std::endl;
        std::cout << "Inverse MatrixA:\n" << inverseMatrix << std::endl;

        // 驗證 A * A_inv = I
        std::cout << "A * A_inv:\n" << matrixA * inverseMatrix << std::endl;
    } else {
        std::cout << "MatrixA is singular, cannot compute inverse." << std::endl;
    }

    return 0;
}

行列式 (cv::determinant())

計算方陣的行列式。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(3,3) << 1, 2, 3, 0, 1, 4, 5, 6, 0);
    double det = cv::determinant(matrixA);
    std::cout << "MatrixA:\n" << matrixA << std::endl;
    std::cout << "Determinant of MatrixA: " << det << std::endl;

    return 0;
}

跡 (cv::trace())

計算方陣的跡(主對角線元素之和)。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(3,3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
    cv::Scalar traceValue = cv::trace(matrixA);
    std::cout << "MatrixA:\n" << matrixA << std::endl;
    std::cout << "Trace of MatrixA: " << traceValue[0] << std::endl; // trace返回一個Scalar

    return 0;
}

范數 (cv::norm())

計算矩陣的范數(例如 L1 范數、L2 范數、無窮范數)。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(1,3) << 3, -4, 0); // 也可以是多維矩陣

    double normL1 = cv::norm(matrixA, cv::NORM_L1);
    double normL2 = cv::norm(matrixA, cv::NORM_L2);
    double normInf = cv::norm(matrixA, cv::NORM_INF);

    std::cout << "MatrixA: " << matrixA << std::endl;
    std::cout << "L1 Norm: " << normL1 << std::endl;   // |3| + |-4| + |0| = 7
    std::cout << "L2 Norm: " << normL2 << std::endl;   // sqrt(3^2 + (-4)^2 + 0^2) = 5
    std::cout << "Infinity Norm: " << normInf << std::endl; // max(|3|, |-4|, |0|) = 4

    cv::Mat matrixB = (cv::Mat_<double>(2,2) << 1, 2, 3, 4);
    double frobeniusNorm = cv::norm(matrixB, cv::NORM_L2); // 對于矩陣,NORM_L2 是 Frobenius 范數
    std::cout << "MatrixB:\n" << matrixB << std::endl;
    std::cout << "Frobenius Norm of MatrixB: " << frobeniusNorm << std::endl;


    return 0;
}

矩陣操作 ???

改變形狀 (Mat::reshape())

在不改變數據的情況下改變矩陣的維度。

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

int main() {
    cv::Mat matrixA = (cv::Mat_<double>(2,3) << 1, 2, 3, 4, 5, 6);
    std::cout << "Original MatrixA (2x3):\n" << matrixA << std::endl;

    // 改變?yōu)橐粋€通道,3行 (列數自動計算)
    cv::Mat reshaped1 = matrixA.reshape(1, 3);
    std::cout << "Reshaped to 3 rows (1 channel):\n" << reshaped1 << std::endl;
    std::cout << "Reshaped1 channels: " << reshaped1.channels() << ", rows: " << reshaped1.rows << ", cols: " << reshaped1.cols << std::endl;


    // 改變?yōu)?3 通道,2 行 (假設原始數據可以這樣組織)
    // 注意:reshape(cn, rows) cn是新的通道數
    // 原始矩陣是單通道,6個元素。如果reshape(3, 2),則變成2行1列,3通道。
    // (1,2,3) 像素1
    // (4,5,6) 像素2
    cv::Mat matrixB = cv::Mat::arange(1, 7).reshape(1, 2); // 2行3列,單通道
    matrixB = matrixB.reshape(3, 2); // 2行1列,3通道
    std::cout << "Original MatrixB (2x3, 1 channel then reshaped to 2x1, 3 channels):\n" << matrixB << std::endl;
    std::cout << "MatrixB value at (0,0) Ch0: " << matrixB.at<cv::Vec3b>(0,0)[0] << std::endl; // 假設是 CV_8UC3
                                                                                              // arange 默認是 CV_32S
    cv::Mat matrixC = (cv::Mat_<int>(1,6) << 1,2,3,4,5,6);
    std::cout << "Original MatrixC (1x6, 1 channel):\n" << matrixC << std::endl;
    cv::Mat reshapedC = matrixC.reshape(3, 2); // 2行1列,3通道
    std::cout << "ReshapedC (2x1, 3 channels):\n" << reshapedC << std::endl;
    // 訪問 reshapedC.at<cv::Vec3i>(0,0)[0] 等

    return 0;
}

注意reshape() 不會復制數據。新的矩陣頭指向原始數據。

合并與拼接 (cv::hconcat(), cv::vconcat())

  • cv::hconcat(): 水平拼接矩陣 (列數增加)
  • cv::vconcat(): 垂直拼接矩陣 (行數增加)
#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    cv::Mat matrixA = cv::Mat::ones(2, 2, CV_64F);
    cv::Mat matrixB = cv::Mat::zeros(2, 2, CV_64F);
    cv::Mat matrixC = cv::Mat::eye(2, 2, CV_64F) * 2;

    cv::Mat horizontalConcat;
    cv::hconcat(matrixA, matrixB, horizontalConcat); // 可以傳遞多個矩陣
    cv::hconcat(horizontalConcat, matrixC, horizontalConcat);
    std::cout << "Horizontal Concatenation:\n" << horizontalConcat << std::endl;

    cv::Mat matrixD = cv::Mat::ones(2, 2, CV_64F) * 3;
    cv::Mat matrixE = cv::Mat::ones(2, 2, CV_64F) * 4;
    cv::Mat verticalConcat;
    std::vector<cv::Mat> matrices_to_stack = {matrixD, matrixE};
    cv::vconcat(matrices_to_stack, verticalConcat); // 可以傳遞一個Mat的vector
    // 或者 cv::vconcat(matrixD, matrixE, verticalConcat);

    std::cout << "Vertical Concatenation:\n" << verticalConcat << std::endl;

    return 0;
}

總結 ??

OpenCV 提供了非常全面且易于使用的矩陣運算功能。通過 cv::Mat 類及其相關函數,可以高效地執(zhí)行從基本算術運算到復雜線性代數運算的各種操作。熟練掌握這些運算是進行圖像處理和計算機視覺算法開發(fā)的基礎。記得查閱 OpenCV 官方文檔以獲取更詳細的信息和更多高級功能。

到此這篇關于C/C++中OpenCV 矩陣運算的實現的文章就介紹到這了,更多相關OpenCV 矩陣運算內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • OpenCV實現拼接圖像的簡單方法

    OpenCV實現拼接圖像的簡單方法

    這篇文章主要為大家詳細介紹了OpenCV實現拼接圖像的簡單方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 利用mmap實現文件拷貝功能

    利用mmap實現文件拷貝功能

    這篇文章主要為大家詳細介紹了利用mmap實現文件拷貝功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • VC實現批量刪除指定文件的方法

    VC實現批量刪除指定文件的方法

    這篇文章主要介紹了VC實現批量刪除指定文件的方法,是一個比較普遍且實用的功能,需要的朋友可以參考下
    2014-07-07
  • VSCode+Qt+CMake詳細教程

    VSCode+Qt+CMake詳細教程

    本文詳解如何在VSCode中搭建Qt與CMake開發(fā)環(huán)境,涵蓋安裝步驟、配置Qt路徑、編寫CMakeLists.txt及項目構建運行流程,強調擴展工具鏈的使用,助力實現高效跨平臺Qt C++開發(fā),本文給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2025-08-08
  • C++11 std::function和std::bind 的使用示例詳解

    C++11 std::function和std::bind 的使用示例詳解

    C++11中的std::function和std::bind是函數對象的重要組成部分,它們可以用于將函數和參數綁定在一起,形成一個可調用的對象,這篇文章主要介紹了C++11 std::function和std::bind 的使用示例詳解,需要的朋友可以參考下
    2023-03-03
  • windows系統下C++調用matlab程序的方法詳解

    windows系統下C++調用matlab程序的方法詳解

    這篇文章主要給大家介紹了關于在windows系統下C++調用matlab程序的方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用C++具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。
    2017-08-08
  • FFmpeg實現音頻漸響效果參數值詳解

    FFmpeg實現音頻漸響效果參數值詳解

    這篇文章主要為大家介紹了FFmpeg實現音頻漸響效果參數值詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Qt實現將qsqlite數據庫中的數據導出為Excel表格

    Qt實現將qsqlite數據庫中的數據導出為Excel表格

    這篇文章主要為大家詳細介紹了如何通過Qt實現將qsqlite數據庫中的數據導出為Excel表格,文中的示例代碼簡潔易懂,有需要的小伙伴可以了解一下
    2024-12-12
  • c語言打開文件函數使用方法

    c語言打開文件函數使用方法

    這篇文章主要介紹了c語言打開文件函數使用方法,需要的朋友可以參考下
    2014-02-02
  • Qt Designer的簡單使用方法

    Qt Designer的簡單使用方法

    用 C++ 代碼編寫圖形界面的問題就是不直觀,因此 Qt 項目開發(fā)了專門的可視化圖形界面編輯器,本文就詳細的介紹一下
    2021-08-08

最新評論

阳东县| 南丰县| 墨江| 固安县| 华容县| 新宁县| 广宗县| 江西省| 罗源县| 内黄县| 闵行区| 沾化县| 罗源县| 六枝特区| 类乌齐县| 鲁甸县| 漯河市| 建湖县| 阜康市| 五指山市| 松滋市| 腾冲县| 博爱县| 闽清县| 社旗县| 荆门市| 广水市| 琼结县| 聊城市| 西安市| 信丰县| 和静县| 浑源县| 邹平县| 柳河县| 泉州市| 四会市| 宾川县| 金秀| 高清| 吉林市|