欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++中OpenCV 矩陣運算的實現(xiàn)

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

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

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

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

創(chuàng)建矩陣

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

使用構(gòu)造函數(shù):可以指定行數(shù)、列數(shù)、數(shù)據(jù)類型以及可選的初始值。

#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++ 數(shù)組創(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() 方法:如果矩陣已經(jīng)存在,此方法會重新分配內(nèi)存(如果需要)。

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;

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

    return 0;
}

基本的算術(shù)運算 ?????

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

矩陣與標(biāo)量運算

可以直接使用標(biāo)準的算術(shù)運算符:

#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 提供的函數(shù)。

  • 加法 (+ 或 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;
}

矩陣乘法 (標(biāo)準線性代數(shù)乘法)

使用 * 運算符可以執(zhí)行標(biāo)準的矩陣乘法 (m x n 矩陣乘以 n x p 矩陣得到 m x p 矩陣)。或者使用 cv::gemm() 函數(shù) (通用矩陣乘法)。

#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;
}

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

其他重要的矩陣運算 ??

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

轉(zhuǎn)置 (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;
}

范數(shù) (cv::norm())

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

#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 范數(shù)
    std::cout << "MatrixB:\n" << matrixB << std::endl;
    std::cout << "Frobenius Norm of MatrixB: " << frobeniusNorm << std::endl;


    return 0;
}

矩陣操作 ???

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

在不改變數(shù)據(jù)的情況下改變矩陣的維度。

#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行 (列數(shù)自動計算)
    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 行 (假設(shè)原始數(shù)據(jù)可以這樣組織)
    // 注意:reshape(cn, rows) cn是新的通道數(shù)
    // 原始矩陣是單通道,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; // 假設(shè)是 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() 不會復(fù)制數(shù)據(jù)。新的矩陣頭指向原始數(shù)據(jù)。

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

  • cv::hconcat(): 水平拼接矩陣 (列數(shù)增加)
  • cv::vconcat(): 垂直拼接矩陣 (行數(shù)增加)
#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;
}

總結(jié) ??

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

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

相關(guān)文章

  • C++實現(xiàn)神經(jīng)BP神經(jīng)網(wǎng)絡(luò)

    C++實現(xiàn)神經(jīng)BP神經(jīng)網(wǎng)絡(luò)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)神經(jīng)BP神經(jīng)網(wǎng)絡(luò),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語言數(shù)據(jù)結(jié)構(gòu) link 鏈表反轉(zhuǎn)的實現(xiàn)

    C語言數(shù)據(jù)結(jié)構(gòu) link 鏈表反轉(zhuǎn)的實現(xiàn)

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu) link 鏈表反轉(zhuǎn)的實現(xiàn)的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • C++實現(xiàn)簡單學(xué)生信息管理系統(tǒng)

    C++實現(xiàn)簡單學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語言進階練習(xí)二叉樹的遞歸遍歷

    C語言進階練習(xí)二叉樹的遞歸遍歷

    樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點)按分支關(guān)系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機構(gòu)都可用樹形象表示,本篇介紹二叉樹的遞歸與非遞歸遍歷的方法
    2022-06-06
  • C++ POSIX API超詳細分析

    C++ POSIX API超詳細分析

    這篇文章主要介紹了C++ POSIXAPI的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • QT6中QTextcodec頭文件找不到的解決方法

    QT6中QTextcodec頭文件找不到的解決方法

    本文主要介紹了QT6中QTextcodec頭文件找不到的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • C++使用boost::lexical_cast進行數(shù)值轉(zhuǎn)換

    C++使用boost::lexical_cast進行數(shù)值轉(zhuǎn)換

    這篇文章介紹了C++使用boost::lexical_cast進行數(shù)值轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C++類型轉(zhuǎn)換的深入總結(jié)

    C++類型轉(zhuǎn)換的深入總結(jié)

    這篇文章主要給大家介紹了關(guān)于C++類型轉(zhuǎn)換的深入總結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • C++實踐IP地址類項目參考

    C++實踐IP地址類項目參考

    今天小編就為大家分享一篇關(guān)于C++實踐IP地址類項目參考,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • C語言Iniparser庫實現(xiàn)ini文件讀寫

    C語言Iniparser庫實現(xiàn)ini文件讀寫

    iniparser是針對INI文件的解析器。ini文件則是一些系統(tǒng)或者軟件的配置文件。本文就來介紹一下如何利用Iniparser庫實現(xiàn)ini文件讀寫吧
    2023-03-03

最新評論