Mat详解-OpenCV

转自:http://blog.skyoung.org/2014/03/26/OpenCV(III)-How-to-use-Mat/

Mat类是OpenCV最基本的一个数据类型,它可以表示一个多维的多通道的数组。Mat常用来存储图像,包括单通道二维数组——灰度图,多通道二维数组——彩色图。当然也可以用来存储点云,直方图等等,对于高维的数组可以考虑存储在SparseMat中。对于一个Mat对象M,其数据布局是由M.step[]决定的,数据存放在M.data里面,假设M有d维,则数据的寻址方式为:

addr(Mi0,...,id1)=M.data+i0M.step[0]+...+id1M.step[d1]addr(Mi0,...,id−1)=M.data+i0∗M.step[0]+...+id−1∗M.step[d−1]

例如ImgImg是一个二维三通道矩阵,则,

addr(Imgi0,i1)=M.data+i0M.step[0]+i1M.step[1]addr(Imgi0,i1)=M.data+i0∗M.step[0]+i1∗M.step[1]

这里需要说明的是各个维度的步长满足如下关系:M.step[i] >= M.step[i+1]*M.size[i+1],也就是二维数组的数据的存放是一行一行的,三维数组数据存放是一面一面的。

下面给出OpenCV中Mat类的一个粗略定义如下:

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
26
27
class CV_EXPORTS Mat
{
public:// ... a lot of methods ....../*! includes several bit-fields:- the magic signature- continuity flag- depth- number of channels*/int flags;//! the array dimensionality, >= 2int dims;//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensionsint rows, cols;//! pointer to the datauchar* data;//! pointer to the reference counter;// when array points to user-allocated data, the pointer is NULLint* refcount;// other members...
};

构造Mat的方法

构造Mat的方式有很多种,下面把常用的方法一一列出:

  1. 使用构造函数Mat(nrows, ncols, type[, fillValue]),例如,

    1
    2
    
    // 构建3×2的4通道8位矩阵,每个元素初始值为(1,2,3,4)
    Mat M(3,2,CV_8UC4,Scalar(1,2,3,4));
    

  2. 使用M.create(nrows,ncols,type),例如,

    1
    2
    
    //构建100×100的10通道8位矩阵
    M.create(100,100,CV_8UC(10))
    

  3. 构建多维的矩阵,

    1
    2
    3
    
    //构建一个100×100×100的8位三维矩阵
    int sz[] = {100,100,100}
    Mat Cube(3, sz, CV_32F, Scalar::all(0))
    

  4. 使用复制构造函数或者赋值操作符

    1
    2
    
    Mat A(B);
    Mat C = B;
    

  5. 单独对矩阵的某一行某一列进行操作

    1
    2
    3
    4
    5
    6
    
    //第4行加上第6行的3倍赋值给第4行
    M.row(3) = M.row(3) + M.row(5)*3;// 把第8列拷贝到第2列,通过 M.col(1) = M.col(7)是不起作用的,应该:
    Mat M1 = M.col(1);
    M.col(7).copyTo(M1);
    

  6. 构建矩阵的ROI区域,单独操作ROI区域的值

    1
    2
    3
    
    Mat img(Size(320,240),CV_8UC3);
    Mat roi(img, Rect(10,10,100,100));
    roi = Scalar(0,255,0);
    

    确定矩阵在原矩阵中的相对位置,使用locateROI,

    1
    2
    3
    4
    5
    6
    
    Mat A = Mat::eye(10, 10, CV_32S);
    Mat B = A(Range::all(), Range(1, 3));
    Mat C = B(Range(5, 9), Range::all());
    Size size; Point ofs;
    //得出ofs为(1,5),size为(10,10),为什么是(10,10)?目前没搞清楚
    C.locateROI(size, ofs);
    

  7. 对于外部数据输入,进行初始化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    //外部输入一个一维数组
    void process_video_frame(const unsigned char* pixels, int width, int height, int step)
    {
        Mat img(height, width, CV_8UC3, pixels, step);
        GaussianBlur(img, img, Size(7,7), 1.5, 1.5);
    }//用二维数组初始化矩阵
    double m[2][3] = { {1, 2, 3}, {4, 5, 6} };
    Mat M = Mat(2, 3, CV_64F, m);
    

  8. IplImage,CvMat和Mat相互转换
    1
    2
    3
    4
    5
    
    IplImage* img = cvLoadImage("lena.jpg", 1);
    Mat mtx(img); // IplImage* -> Mat
    IplImage* img1 = mtx; //Mat -> IplImage*
    CvMat oldmat = mtx; // Mat -> CvMat
    Mat mtx1(oldmat);  //CvMat -> Mat
    
  9. 类似Matlab方式和<<赋值

    1
    2
    3
    4
    5
    6
    7
    
    //类似Matlab中的单位矩阵等
    M = Mat::ones(10, 10, CV_64F);
    M = Mat::eye(10, 10, CV_64F);
    M = Mat::zeros(10, 10, CV_64F);//使用`Mat_`和`<<`配合
    Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
    

获取Mat元素的方法

构造好矩阵后,剩下一个很重要的事情就是如何快速准确的获取矩阵Mat中的元素,下面列出几种常用的获取Mat中的元素方法:

  1. 使用M.at(i,j)

    1
    
    M.at<double>(i,j)
    

  2. 对于二维矩阵,可以采取逐行获取的方式:

    1
    2
    3
    4
    5
    6
    7
    
    double sum=0;
    for(int i = 0; i < M.rows; i++)
    {const double* Mi = M.ptr<double>(i);for(int j = 0; j < M.cols; j++)sum += std::max(Mi[j], 0.);
    }
    

    对于不在乎矩阵的形状,只是简单的遍历矩阵的元素的,可以采用更快速的方法,首先检查元素排列是否连续,如果是,可以看成一个一维数组访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    double sum=0;
    int cols = M.cols, rows = M.rows;
    if(M.isContinuous())
    {cols *= rows;rows = 1;
    }
    for(int i = 0; i < rows; i++)
    {const double* Mi = M.ptr<double>(i);for(int j = 0; j < cols; j++)sum += std::max(Mi[j], 0.);
    }
    

  3. 仿照STL中,使用迭代器访问:

    1
    2
    3
    4
    
    	double sum=0;MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>();for(; it != it_end; ++it)sum += std::max(*it, 0.);
    

这个矩阵的迭代器可以传给STL的算法,例如std::sort()

Mat提供的常用成员函数

  1. 赋值操作符’=’
    除了普通的矩阵赋值外,如果一个Scalar赋值给一个Mat,则表示把Mat的所有元素赋值为这个Scalar值。

  2. 矩阵的取行列及对角线操作
    A.row(i),A.col(j)这些操作返回矩阵A的第i行和第j列。A.rowRange(m,n)和A.colRange(m,n)分别取的是A的第m行到第n行(包括m行,不包括n行)和A的第m列到第n列(包括m列,不包括n列)。这里需要注意一个问题,对于

    1
    
    A.row(i) = A.row(j)
    

    这一操作,并不能把第j行复制到第i行,因为A.row()返回的只是矩阵的头,以上操作仅仅相当于两个指针的操作,所指内存其实是没有发生变化的。如果想把第j行复制到第i行,可以

    1
    
    A.row(j).copyTo(A(i))
    

    当右边的矩阵发生操作后,是可以赋值的,比如

    1
    2
    
    A.row(i) = A.row(j)*a
    A.row(i) = A.row(j) + Scalar(0,0,0);
    

    A.diag(i)取的是矩阵的对角线,这里i=0代表最中间的对角线,i=1是偏右上一行的对角线,i=-1是左下一行的对角线,例如:

    1
    2
    3
    
    Mat A = (Mat_<float>(3,3)<< 1,9,3,7,5,0,7,3,9);
    

    A.diag(0)取得是{1,5,9},A.diag(1)取得是{9,0},A.diag(-1)取得是{7,3}。

  3. 复制函数

    1
    2
    3
    
    A.clone()//返回A的拷贝。
    A.copyTo(B)//执行把A拷贝到B矩阵中。
    A.copyTo(B,mask)//进拷贝mask对应的部分
    

  4. 转换矩阵元素的数据类型

    1
    2
    
    A.converTo(B,tpye,scale)//把A的类型转换为type并且按照scale缩放A到B矩阵中
    assignTo(A,type)//更改A的元素数据类型
    

  5. 设定矩阵的值

    1
    
    A.setTo(s)//把A中所有的值赋值为s
    

  6. 更改矩阵的通道数和行数

    A.reshape()改变通道数,A.resize()改变行数。其中A.reshape()这个操作不改变roscolschannels的个数,仅仅相当于重构这些元素,例如:

    1
    2
    3
    
    vector<Point> vec;//vec是N个Point
    Mat pointMat = Mat(vec); //pointMat是一个三通道的N×1的矩阵
    pointMat.reshape(1)//pointMat变为一个单通道N×3的矩阵
    

    更改矩阵的行数如下

    1
    
    A.resize(sz) //A变为sz行
    

  7. locateROI和adjustROI

    这两个函数主要是对submatrix的操作,即通过A.row(),A(Range(i,j),Range::all())等操作获得的submatrix在原始矩阵中位置。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    Mat A = (Mat_<float>(3,3)<< 1,9,3,7,5,0,7,3,9);
    Mat B = A(Range(0,2),Range(1,3));//B变为 {9,3,//      5,0}
    Size sz;
    Point p1;
    B.locateROI(sz, p1);
    cout<<sz<<" "<<p1<<endl;  //sz是原矩阵的大小3×3,p1是B在A中位置(1,0)
    B.adjustROI(0,1,0,0); //四个参数分别是上下左右平移的像素数,这里是把B向下平移1行,//最后得出B为{9,3,//           5,0,//    	   3,9}
    cout<<B<<endl;
    

  8. Mat的各项属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    A.total() //元素的个数
    A.elemSize() //元素的大小,如果是8UC3的话,返回3*sizeof(uchar)
    A.elemSize1() //如果是8UC3的话,返回sizeof(uchar)
    A.type() //元素的数据类型
    A.depth()//元素的位数
    A.channels()//矩阵的通道数
    A.step1() //矩阵的每一行元素的个数,A.step/A.elemSize1
    A.size() //矩阵的尺寸
    //注意以下是成员变量不是成员函数
    A.step //矩阵的一行的字节数
    A.rows //矩阵的行数,即高
    A.cols //矩阵的列数,即宽
    

总结

Mat提供了关于矩阵的一些基本操作,这对图像的操作打下了坚实的基础,更多复杂的算法都是基于这些操作实现的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313249.shtml

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

相关文章

.Net Core 3.0 IdentityServer4 快速入门

一、简介IdentityServer4是用于ASP.NET Core的OpenID Connect和OAuth 2.0框架。将IdentityServer4部署到您的应用中具备如下特点&#xff1a;1&#xff09;、认证服务2&#xff09;、单点登陆3&#xff09;、API访问控制4&#xff09;、联合网关5&#xff09;、专注于定制6&…

.NET Core3.0创建Worker Services

.NET CORE 3.0新增了Worker Services的新项目模板&#xff0c;可以编写长时间运行的后台服务&#xff0c;并且能轻松的部署成windows服务或linux守护程序。如果安装的vs2019是中文版本&#xff0c;Worker Services变成了辅助角色服务。Worker Services 咱也不知道怎么翻译成了这…

初学随机森林

http://blog.csdn.net/holybin/article/details/25653597 基础知识 [关于决策树的基础知识参考&#xff1a;http://blog.csdn.NET/holybin/article/details/22914417] 在机器学习中&#xff0c;随机森林由许多的决策树组成&#xff0c;因为这些决策树的形成采用了随机的方法&a…

OpenCV Mat数据类型像素操作

转自&#xff1a;http://blog.csdn.net/skeeee/article/details/13297457 OpenCV图像像素操作及效率分析 在计算机视觉应用中&#xff0c;对于图像内容的读取分析是第一步&#xff0c;所以学习高效的处理图像是很有用的。一个图像有可能包含数以万计的像素&#xff0c;从根本上…

Bumblebee微服务网关之Url重写

为了提高Url访问的统一和友好性&#xff0c;一般访问的Url和服务定义的Url有所不同;为了解决这一问题Bumblebee提供Url重写功能;通过Url重写功能可以在转发前进行一个重写后再转发到后台服务。引用插件Bumblebee中使用Url重写需要引用两个插件&#xff0c;分别是Bumblebee.Conf…

依赖注入:一个Mini版的依赖注入框架

前面的章节中&#xff0c;我们从纯理论的角度对依赖注入进行了深入论述&#xff0c;我们接下来会对.NET Core依赖注入框架进行单独介绍。为了让读者朋友能够更好地理解.NET Core依赖注入框架的设计与实现&#xff0c;我们按照类似的原理创建了一个简易版本的依赖注入框架&#…

t-SNE初学

http://www.datakit.cn/blog/2015/08/06/t_SNE.html 本文主要参考wikipedia&#xff0c;介绍t-SNE算法&#xff0c;以及python下的一些实现可视化应用。 目录 1、概述2、原理 2.1基本原理2.2详细过程2.4理由 3、算法流程4、python试用 1、概述 最开始接触t-SNE是在kaggle的比…

.NET Core 3.0 新 JSON API - JsonSerializer

JsonSerializer 前面几节的内容可能稍微有点底层&#xff0c;我们大部分时候可能只需要对C#的类进行串行化或者将JSON数据反串行化成C#类&#xff0c;在.NET Core 3.0里面&#xff0c;我们可以使用JsonSerializer这个类来做这些事情。 例子 还是使用之前用到的json数据&#xf…

Caffe查看每一层学习出来的pattern

Filter visualization http://www.cnblogs.com/dupuleng/articles/4244877.html 这一节参考http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/filter_visualization.ipynb&#xff0c;主要介绍如何显示每一层的参数及输出&#xff0c;这一部分非常重要&am…

.NET Core 3.0 新 JSON API - Utf8JsonWriter

Utf8JsonWriter类 下面研究一下如何写入json文件。这里需要使用Utf8JsonWriter类。 直接看代码&#xff1a; 这个类需要传递的参数类型是Stream或者Buffer&#xff0c;也就是向Stream或Buffer里面写入数据。 那么就提供一个buffer&#xff1a; 下面单独写一个方法&#xff0c;来…

力扣15 三数之和(Java版本)

文章目录 题目解题思路代码 题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中…

python查看CNN训练模型参数

参照&#xff1a;http://blog.csdn.net/u011762313/article/details/49851795 #!/usr/bin/env python# 引入“咖啡” import caffeimport numpy as np# 使输出的参数完全显示 # 若没有这一句&#xff0c;因为参数太多&#xff0c;中间会以省略号“……”的形式代替 np.set_prin…

Bumblebee微服务网关之consul服务发现

网关需要维护相关负载的服务器&#xff0c;手动添加相对来说是一件比较麻烦的工作&#xff1b;为了解决这一问题组件扩展了一个基于consul服务发现插件&#xff0c;通过配置这个插件和启用后网关会自动从consul服务中获取服务并添加到网关对应的路由负载规则中。引用插件Bumble…

Github带来的不止是开源,还有折叠的认知

几乎每个程序员都知道github&#xff0c;但是知道目前上面有多少repositories的估计没几个。Z哥今天去看了下&#xff0c;最新的数量显示是1.39亿个。▲截图来自于github.com而这个数字在2008年那会只是3.3万个。这个增长速度可谓真的是“爆炸式增长”。与此同时&#xff0c;大…

最优间隔分类器-SVM

http://blog.csdn.net/Andrewseu/article/details/46991541 本讲大纲&#xff1a; 1.最优间隔分类器(optimal margin classifier) 2.原始/对偶优化问题&#xff08;KKT&#xff09;&#xff08;primal/dual optimization problem&#xff09; 3.SVM对偶(SVM dual) 4.核方法(…

自动给 Asp.Net Core Api 增加 ApiVersionNeutral

自动给 Asp.Net Core Api 增加 ApiVersionNeutralIntro新增加一个 Controller 的时候&#xff0c;经常忘记在 Controller 上增加 ApiVersion &#xff0c;结果就导致前端使用指定的 ApiVersion 访问的时候就会失败&#xff0c;不支持的 Api 版本。错误信息如下&#xff1a;{ &q…

K-means与高斯混合模型

K-means http://blog.pluskid.org/?p17 Clustering 中文翻译作“聚类”&#xff0c;简单地说就是把相似的东西分到一组&#xff0c;同 Classification (分类)不同&#xff0c;对于一个 classifier &#xff0c;通常需要你告诉它“这个东西被分为某某类”这样一些例子&#xf…

轻量级ORM《sqlcommon》第一个版本发布了

一、sqlcommon的特色1. 轻量级&#xff0c;整个包只有123kb。2. 性能好&#xff0c;自测。。。3. API和功能简单、代码简短、可维护性好基本都能看懂。这个点我认为很重要&#xff0c;你不用为了实现一个需求而四处查资料&#xff0c;这意味着这个包你可以自行维护修改&#xf…

从基于直方图的Graph-Cut到Grab-Cut

http://blog.csdn.net/zouxy09/article/details/8534954 区别&#xff1a; &#xff08;1&#xff09;Graph Cut的目标和背景的模型是灰度直方图&#xff0c;Grab Cut取代为RGB三通道的混合高斯模型GMM&#xff1b; &#xff08;2&#xff09;Graph Cut的能量最小化&#xf…

1024程序员节活动继续:购书优惠劵,折后再折,赶紧来抢啊

1024程序员节当当网计算机图书每满100减50&#xff01;满200减100&#xff01;满300-150&#xff01;机械工业出版社华章公司联合当当网特意为【DotNET技术圈】用户申请了一批可与满减叠加使用的“满200减30”的图书优惠码&#xff0c;优惠码使用后相当于&#xff1a;400减230 …