当前位置: 首页 > news >正文

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算,比用cpp的vector或vector进行矩阵运算要快吗?

使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int>std::vector<double> 更快。这主要有以下几个原因:

  1. 优化的底层实现:Eigen 和 OpenCV 都是为高效的矩阵运算而设计的库,内部实现了许多优化,例如使用 SIMD(单指令多数据)指令、并行计算等。这些优化可以显著提高计算速度。

  2. 内存布局:Eigen 和 OpenCV 在内存布局上进行了优化,通常使用连续的内存块来存储矩阵数据,这样可以提高缓存命中率,从而加快访问速度。

  3. 专用的算法:这些库提供了许多专用的算法和函数,能够高效地执行常见的矩阵运算(如乘法、求逆、特征值分解等),而使用 std::vector 进行这些操作时,通常需要手动实现算法,效率较低。

  4. 类型安全和表达能力:Eigen 提供了强类型的矩阵和向量类,能够在编译时进行更多的检查,减少运行时错误,同时也使得代码更易于阅读和维护。

因此,如果你的应用涉及大量的矩阵运算,建议使用 Eigen 或 OpenCV 这样的专用库,而不是直接使用 std::vector

构造

link1

索引

访问Mat的通道数

#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 创建一个3通道的彩色图像(例如,BGR格式)cv::Mat colorImage = cv::Mat::zeros(100, 100, CV_8UC3);// 创建一个单通道的灰度图像cv::Mat grayImage = cv::Mat::zeros(100, 100, CV_8UC1);// 获取通道数int colorChannels = colorImage.channels();int grayChannels = grayImage.channels();// 输出通道数std::cout << "彩色图像的通道数: " << colorChannels << std::endl; // 应该输出3std::cout << "灰度图像的通道数: " << grayChannels << std::endl;   // 应该输出1return 0;
}

定义4维Mat

#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 定义4维矩阵,大小为2x3x4x5,数据类型为CV_32F(32位浮点数)cv::Mat mat4D(2, new int[4]{3, 4, 5}, CV_32F);// 填充矩阵for (int i = 0; i < 2; ++i) {for (int j = 0; j < 3; ++j) {for (int k = 0; k < 4; ++k) {for (int l = 0; l < 5; ++l) {mat4D.at<float>(i, j, k, l) = static_cast<float>(i * 1000 + j * 100 + k * 10 + l);}}}}// 输出矩阵的形状和内容std::cout << "4维矩阵的大小: " << mat4D.size << std::endl;std::cout << "4维矩阵的内容:" << std::endl;for (int i = 0; i < 2; ++i) {for (int j = 0; j < 3; ++j) {for (int k = 0; k < 4; ++k) {for (int l = 0; l < 5; ++l) {std::cout << mat4D.at<float>(i, j, k, l) << " ";}std::cout << std::endl;}std::cout << std::endl;}}// 释放动态分配的内存delete[] mat4D.size;return 0;
}

取某一行

#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 创建一个 3x3 的矩阵cv::Mat mat = (cv::Mat_<float>(3, 3) << 1, 2, 3,4, 5, 6,7, 8, 9);// 获取第 3 行(索引为 2)的所有元素cv::Mat thirdRow = mat.row(2); // 行索引从 0 开始// 输出结果std::cout << "第三行的元素是:" << std::endl;std::cout << thirdRow << std::endl;return 0;
}

提取块

#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 创建一个 5x5 的矩阵cv::Mat mat = (cv::Mat_<float>(5, 5) << 1, 2, 3, 4, 5,6, 7, 8, 9, 10,11, 12, 13, 14, 15,16, 17, 18, 19, 20,21, 22, 23, 24, 25);// 定义要提取的块的起始位置和大小int startRow = 1; // 起始行索引int startCol = 1; // 起始列索引int blockRows = 3; // 块的行数int blockCols = 3; // 块的列数// 提取块cv::Mat block = mat(cv::Range(startRow, startRow + blockRows), cv::Range(startCol, startCol + blockCols));// 输出结果std::cout << "提取的块是:" << std::endl;std::cout << block << std::endl;return 0;
}

访问某行某列的元素

在C++中,使用OpenCV库的cv::Mat类来表示图像或矩阵。要访问cv::Mat中的特定行和列的元素,可以使用at(row, col)方法,其中type是元素的数据类型。

#include <iostream>
#include <opencv2/opencv.hpp>int main() {// 创建一个3x3的矩阵,类型为CV_8UC1(单通道8位无符号整数)cv::Mat mat = (cv::Mat_<uchar>(3, 3) << 1, 2, 3,4, 5, 6,7, 8, 9);// 输出整个矩阵std::cout << "矩阵内容:\n" << mat << std::endl;// 访问特定行和列的元素int row = 1; // 第二行(索引从0开始)int col = 2; // 第三列(索引从0开始)// 使用at方法访问元素uchar value = mat.at<uchar>(row, col);std::cout << "元素在 (" << row << ", " << col << ") 的值: " << (int)value << std::endl;// 修改特定行和列的元素mat.at<uchar>(row, col) = 10;std::cout << "修改后的矩阵内容:\n" << mat << std::endl;return 0;
}

示例输出:

矩阵内容:
[1, 2, 3;
4, 5, 6;
7, 8, 9]
元素在 (1, 2) 的值: 6
修改后的矩阵内容:
[1, 2, 3;
4, 5, 10;
7, 8, 9]

运算

矩阵乘法和Hamornoid积

#include <iostream>
#include <opencv2/opencv.hpp>int main() {// 创建两个相同维度的矩阵cv::Mat mat1 = (cv::Mat_<float>(2, 2) << 1, 2,3, 4);cv::Mat mat2 = (cv::Mat_<float>(2, 2) << 5, 6,7, 8);// 输出原始矩阵std::cout << "矩阵1:\n" << mat1 << std::endl;std::cout << "矩阵2:\n" << mat2 << std::endl;// 方法1:使用 cv::multiplycv::Mat result1;cv::multiply(mat1, mat2, result1);std::cout << "矩阵乘法 (使用 cv::multiply):\n" << result1 << std::endl;// 方法2:使用 cv::mulcv::Mat result2 = mat1.mul(mat2); // 也可以使用 result2 = mat1 * mat2;std::cout << "矩阵乘法 (使用运算符 *):\n" << result2 << std::endl;// 方法3:使用运算符 *cv::Mat result3 = mat1*mat2; // 也可以使用 result2 = mat1 * mat2;std::cout << "逐元素相乘结果 (使用运算符 *):\n" << result3 << std::endl;return 0;
}

类型一致

  • opencv::Mat之间的加减乘除必须保证类型相同
  • 比如cv::divide()运算
cv::divide(new_cen, cen_index[cen_id].size(), new_cen);
  • opencv::Mat的类型有如下几种:
    在这里插入图片描述* 可在初始化时指定
	Mat new_cen=Mat::zeros(1,128,CV_32FC1);

opencv::Mat是继承Eigen的实现吗?

cv::Mat并不是继承自Eigen库的实现。OpenCV和Eigen是两个独立的库,它们各自有自己的数据结构和实现方式。

OpenCV的cv::Mat

  • cv::Mat是OpenCV中用于表示图像和矩阵的主要数据结构。它提供了多种功能,包括图像处理、矩阵运算、图像读取和写入等。
  • cv::Mat支持多维数组,能够处理不同的数据类型(如8位无符号整数、浮点数等),并且可以表示单通道和多通道图像(如RGB图像)。
  • OpenCV的设计目标是高效处理图像和视频数据,特别是在计算机视觉和图像处理领域。

Eigen库:

  • Eigen是一个用于线性代数的C++模板库,提供了矩阵和向量的高效操作。它专注于数学运算,特别是线性代数、几何变换和数值计算。
  • Eigen的设计目标是提供高性能的数学运算,同时保持易用性和灵活性。

结论:

虽然OpenCV和Eigen都涉及矩阵和线性代数的概念,但它们是独立的库,cv::Mat并不继承自Eigen的实现。实际上,OpenCV和Eigen可以一起使用,开发者可以在OpenCV中处理图像数据,然后使用Eigen进行更复杂的数学运算,或者反之亦然。两者之间的结合可以利用各自的优势。


http://www.mrgr.cn/news/82255.html

相关文章:

  • 改投论文时如何重构
  • AfuseKt1.4.4 | 刮削视频播放器,支持阿里云盘和自动海报墙
  • 【pytorch练习】使用pytorch神经网络架构拟合余弦曲线
  • PHP框架+gatewayworker实现在线1对1聊天--gatewayworker说明(2)
  • 无线AP安装注意事项
  • Spring Security(maven项目) 3.0.2.3版本
  • 解析 SQL 中的 NULL 与比较操作:NULL 值与任何值的比较会返回 UNKNOWN
  • 期末速成C++【知识点汇总完】
  • Flutter:打包apk,详细图文介绍(一)
  • 【系统分析师】- 案例 -数据库特训
  • Redis(一)基本特点和常用全局命令
  • 免费开源跨平台SSH工具 WindTerm:媲美 xshell 的最佳平替(含详细使用教程)
  • Wend看源码-Java-Collections 工具集学习
  • blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质
  • 数据挖掘——决策树分类
  • ChatBI来啦!NBAI 正式上线 NL2SQL 功能
  • Linux postgresql-15部署文档
  • Flink operator实现自动扩缩容
  • AWVS安装使用教程
  • SpringCloud源码-openFeign
  • 关于无线AP信道调整的优化(锐捷)
  • Linux的源码在Windows下解压时提示文件名字相同(重名)的原因及解决办法
  • Promise实现原理解析,及实现方法。
  • rouyi(前后端分离版本)配置
  • msposd 开源代码之树莓派3B+ Bookworm部署
  • 笔上云世界微服务版