矩阵运算提速——玩转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.mzph.cn/pingmian/66241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python文件操作相关(excel)

python文件操作相关&#xff08;excel&#xff09; 1. openpyxl 库openpyxl其他用法创建与删除操作单元格追加数据格式化单元格合并单元格插入图片公式打印设置保护工作表其他功能 2. pandas 库3. xlrd 和 xlwt 库4. xlsxwriter 库5. pyxlsb 库应用场景参考资料 在 Python 中&a…

C++ 基础概念: 未定义行为(Undefined Behavior)

文章目录 Intro如何正确认识 UB有多少未定义行为?对 UB 的误解 C 标准定义的几种行为1. 定义的行为 (defined behavior)2. 实现定义的行为 (implementation defined behavior)3. 未指定的行为 (unspecified behavior)4. 未定义行为 (undefined behavior)揭晓答案 C 中如何定义…

yolo小damo合集

效果如下&#xff1a;这个是图片检测 效果如下&#xff1a;这个是视频检测 效果如下&#xff1a;这个是摄像头检测 1 相关库 除了yolov11所用库之外&#xff0c;本文所用到的额外库为pyqt5&#xff0c;输入指令进行安装 pip install pyqt5 导入所需要的库 import sys fro…

【蓝桥杯研究生组】第14届Java试题答案整理

试题链接&#xff1a;链接 A题 满足条件的答案有&#xff1a;35813116 public class TianShu {public static void main(String[] args) {int ans 0;// 2000.1.1 - 2000000.1.1// 年份是月份的倍数&#xff0c;也是日的倍数for (int year2000; year<2000000; year) {for …

基于Java的超级玛丽游戏的设计与实现【源码+文档+部署讲解】

目 录 1、绪论 1.1背景以及现状 1.2 Java语言的特点 1.3 系统运行环境及开发软件&#xff1a; 1.4 可行性的分析 1.4.1 技术可行性 1.4.2 经济可行性 1.4.3 操作可行性 2、 需求分析 2.1 用户需求分析 2.2功能需求分析 2.3界面设计需求分析…

25考研王道数据机构课后习题-----顺序表链表部分

文章目录 1.顺序表题目2.链表相关题目3.我的个人总结 声明&#xff1a;以下内容来自于B站知名up主白话拆解数据结构&#xff0c;望获悉&#xff1b; 1.顺序表题目 下面的这个说的是&#xff1a;下面的哪一个是组成我们的顺序表的有限序列&#xff0c;这个应该是数据元素&#x…

LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 (4)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务&#xff0c;通过网络接口&#xff0c;提供 AI 模型功能的服务&#xff0c;允许通过发送 HTTP 请求&#xff0c;交互…

Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)

概念 事务定义 事务&#xff0c;就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行&#xff0c;我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行&#xff0c;我们称该事务被提交。…

学英语学压测:02jmeter组件-测试计划和线程组ramp-up参数的作用

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 Functional Testing功能测试[ˈfʌŋkʃənəl ˈtɛstɪŋ]Sample样…

多线程访问FFmpegFrameGrabber.start方法阻塞问题

一、背景 项目集成网络摄像头实现直播功能需要用到ffmpeg处理rtmp视频流进行web端播放 通过网上资源找到大神的springboot项目实现了rtmp视频流转为http请求进行视频中转功能&#xff0c;其底层利用javacv的FFmpegFrameGrabber进行拉流、推流&#xff0c;进而实现了视频中转。 …

医学图像分析工具01:FreeSurfer || Recon -all 全流程MRI皮质表面重建

FreeSurfer是什么 FreeSurfer 是一个功能强大的神经影像学分析软件包&#xff0c;广泛用于处理和可视化大脑的横断面和纵向研究数据。该软件由马萨诸塞州总医院的Martinos生物医学成像中心的计算神经影像实验室开发&#xff0c;旨在为神经科学研究人员提供一个高效、精确的数据…

在Microsoft Windows上安装MySQL

MySQL仅适用于Microsoft Windows 64位操作系统&#xff0c;在Microsoft Windows上安装MySQL有不同的方法&#xff1a;MSI、包含您解压缩的所有必要文件的标准二进制版本&#xff08;打包为压缩文件&#xff09;以及自己编译MySQL源文件。 注意&#xff1a;MySQL8.4服务器需要在…

探索最新的编程技术趋势:AI 编程助手和未来的编程方式

随着技术的飞速发展&#xff0c;编程技术领域在近年来经历了深刻的变革。从人工智能到低代码开发工具&#xff0c;新的技术趋势不断涌现&#xff0c;不仅大幅提高了开发效率&#xff0c;也重新定义了开发者的角色和工作方式。本篇博客将探讨几项当前最值得关注的编程技术&#…

k8s集群,CRI-Docker部署条件及方法

CRI-Docker部署条件及方法 文章目录 CRI-Docker部署条件及方法CRI-Docker使用条件安装 cri-docker 的步骤&#xff1a; CRI-Docker使用条件 在 Kubernetes 1.20 及以上版本&#xff0c;kubeadm 默认使用 containerd 作为容器运行时&#xff08;Container Runtime Interface, C…

OKHttp调用第三方接口,响应转string报错okhttp3.internal.http.RealResponseBody@4a3d0218

原因分析 通过OkHttp请求网络&#xff0c;结果请求下来的数据一直无法解析并且报错&#xff0c;因解析时String res response.body().toString() 将toString改为string即可&#xff01;

oceanbase集群访问异常问题处理

1.报错现象 2.问题排查 检查obproxy状态发现为不可用状态 重启obproxy 依次重启Obproxy集群 观察任务状态 重启完成 Obproxy状态正常 3.验证登录 登录成功

如何判断状态:停留还是移动。【计算加速度de方案】

跑步过程中 记录了一天时间的经纬度 时间&#xff0c;如何判断状态&#xff1a;停留还是移动。需要完整的解决方案。精准判断是停留还是移动 邓 要判断在跑步过程中是“停留”还是“移动”&#xff0c;需要根据GPS的经纬度数据以及时间来进行分析。你可以通过以下步骤实现准确…

ruckus R510升级到Unleashe后不能访问

ruckus R510 是IPQ4019&#xff0c;升级到Unleashe&#xff0c;它弹窗提示 但是这个IP没办法用&#xff0c;访问不了AP。 必应了一下&#xff0c;官方提示用advance ip scanner扫描。 扫描持续好久&#xff0c;发现IP竟然是从主路由获得。 9090的端口不用填&#xff0c;甚至不…

使用R语言绘制标准的中国地图和世界地图

在日常的学习和生活中&#xff0c;有时我们常常需要制作带有国界线的地图。这个时候绘制标准的国家地图就显得很重要。目前国家标准地图服务系统向全社会公布的标准中国地图数据&#xff0c;是最权威的地图数据。 今天介绍的R包“ggmapcn”&#xff0c;就是基于最新公布的地图…

影刀RPA高级操作实战(二):数据抓取与数据库写入

在数字化转型的浪潮中&#xff0c;影刀RPA凭借其强大的自动化能力&#xff0c;成为企业提升效率、降低成本的重要工具。掌握影刀RPA的高级操作&#xff0c;能够帮助我们应对更加复杂的业务场景&#xff0c;实现高效的数据处理与系统集成。本文将详细讲解影刀RPA在数据抓取与数据…