图像储存容器Mat[OpenCV 笔记11]
IplImage 与 Mat
IplImage是OpenCV1中的图像存储结构体,基于C接口创建。在退出之前必须release,否则就会造成内存泄露。在一些只能使用C语言的嵌入式系统中,不得不使用。
IplImage* img = cvLoadImage("imagename.jpg",);
Mat类内存分配是自动完成的,不必手动开辟空间(非必须),不必在不需要时释放空间。
Mat类的构成
Mat由矩阵头和一个指向存储图像矩阵的指针组成。为应该尽量避免图像的复制,加快程序运行速度,Mat的拷贝构造函数只复制信息头和矩阵指针,不复制矩阵。因此通过任何一个对象所做的改变也会影响其他对象。如果想要创建一个感兴趣的区域(Region of Interest (ROI))只需要创建包含边界信息的信息头:
Mat ROI1(matrix, Rect(x,y,width,height)); // use rectangle to set the boundary
Mat ROI2 = matrix(Range:all(), Range(,)); // use rows and cols
Mat通过对象计数机制来实现最后一个使用它的对象自动负责清理存储空间。如果想要复制矩阵本身,可以使用:
Mat duplicate1 = matrix.clone();
Mat duplicate2;
matrix.copyTo(duplicate2);
改变duplicate1和duplicate2不会影响matrix指向的矩阵。
构造函数
Mat()
Mat(int rows, int cols, int type, const Scalar & s)
- rows:矩阵行数
- cols:矩阵列数
- type:规定存储元素的数据类型和每个矩阵点的通道数
- CV_[the number of bits per item: 8/16/32/64] [Signed, Unsigned, or Float: S/U/F] C [The channel number: 1/2/3/4]
- CV_8UC3:三通道8位的unsigned char型
- s:可以省去,Scalar是short型的向量,用来初始化矩阵
Mat(Size size, int type, const Scalar & s)
- size: 二位矩阵尺寸,Size(cols, rows),注意维数尺寸跟前面的构造函数是相反的
- type和s:同上
Mat(int ndims, const int* sizes, type, const Scalar & s)
- ndims: 第二个参数,size矩阵,的维数
- sizes: 整型矩阵,规定Mat的尺寸
- type和s:同上
Mat (const Mat &m)
Mat (const Mat &m, const Range &rowRange, const Range &colRange=Range::all())
Mat (const Mat &m, const Rect &roi)
Mat (const Mat &m, const Range *ranges)
- m: 赋值矩阵,它的部分或者全部值将以指针传递给构造出的矩阵,注意数据不会被拷贝给新矩阵
- 其他参数:规定赋值部分的范围
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=)
- data:指向用户数据的指针,构造的矩阵将指向这些用户数据,没有进行数据拷贝
- step:矩阵更新到下一行需要跨过的字节数,如果矩阵每行的尾部包含无用的填充数据,需要把这部分计算进去,自动计算时设为cols*elemSize()
- 其他参数:设置矩阵的大小和类型
Mat::Mat(const IplImage* img, bool copyData=false)
- img: IplImage类型的图,利用它来创建信息头
Mat (const std::vector< _Tp > &vec, bool copyData=false)
- vec:STL vector,矩阵行数等于vec的元素数,矩阵的数据类型与vec相同,因此vec必须为单一类型的数据结构。默认情况下,不会进行数据拷贝,这种情况下在矩阵被释放之前,不能再向vec内加入新数据(这样会造成存储空间重新分配,之前的指针可能会失效)或进行其他可能改变vec内存空间的操作。
其他构造函数可以参见OpenCV Documentation:
其他初始化方法
void create (int rows, int cols, int type)
void create (Size size, int type)
void create (int ndims, const int *sizes, int type)
分配新内存,但不能为矩阵设置初值。大部分需要分配空间的OpenCV函数都会从内部调用这个函数,所以在调用他们之前不用手动分配内存空间
- 如果现在矩阵的形状数据类型与目标相同,直接返回。否则释放原来的内存空间。
- 初始化新矩阵头
- 分配total()*elemSize()字节内存
- 设置新的对象计数值,并设为1
static MatExpr eye (int rows, int cols, int type)
static MatExpr eye (Size size, int type)
static MatExpr ones (int rows, int cols, int type)
static MatExpr ones (Size size, int type)
static MatExpr ones (int ndims, const int *sz, int type)
static MatExpr zeros (int rows, int cols, int type)
static MatExpr zeros (Size size, int type)
static MatExpr zeros (int ndims, const int *sz, int type)
Matlab形式的初始化方式。MatExpr是Matrix expression representation,可以进行各种矩阵运算操作。用法如下,
Mat E = Mat::eye(,,CV_64F);
Mat O = Mat::ones(,,CV_32F)*0.1;
逗号分隔式初始化
Mat C = (Mat_<double>(,) << ,-,, -,,-, ,-,);
Mat clone () const
void copyTo (OutputArray m) const
void copyTo (OutputArray m, InputArray mask) const
拷贝矩阵,回先调用create函数分配内存空间,
- mask:非零数据代表了需要拷贝的数据,如果传递了这个参数那么分配完内存空间后,矩阵先被初始化为0,mask是CV_8U类型可以包含一个或多个通道
格式化输出方法
5种输出风格:OpenCV默认,Python,逗号分隔,Numpy, C语言风格。事例程序和运行结果如下:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
// main
int main( int argc, char** argv )
{
cv::Mat r = cv::Mat(,,CV_8UC3);
cv::randu(r, cv::Scalar::all(), cv::Scalar::all()); // [1] OpenCV default style
std::cout << "r (OpenCV default style) = \n" << r << ";" << std::endl << std::endl; // [2] Python style
// OpenCV2
// std::cout << "r (Python style) = " << format(r,"python") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (Python style) = \n" << format(r,cv::Formatter::FMT_PYTHON) << ";" << std::endl << std::endl; // [3] Comma separated values (CSV)
// OpenCV2
// std::cout << "r (CSV style) = " << format(r,"csv") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (CSV style) = \n" << format(r,cv::Formatter::FMT_CSV) << ";" << std::endl << std::endl; // [4] Numpy style
// OpenCV2
// std::cout << "r (Numpy style) = " << format(r,"numpy") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (Numpy style) = \n" << format(r,cv::Formatter::FMT_NUMPY) << ";" << std::endl << std::endl; // [3] C style
// OpenCV2
// std::cout << "r (C style) = " << format(r,"C") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (C style) = \n" << format(r,cv::Formatter::FMT_C) << ";" << std::endl << std::endl; return ;
}
r (OpenCV default style) =
[ , , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ]; r (Python style) =
[[[ , , ], [, , ], [, , ]],
[[, , ], [, , ], [, , ]],
[[, , ], [ , , ], [, , ]],
[[, , ], [, , ], [ , , ]],
[[ , , ], [, , ], [, , ]],
[[ , , ], [, , ], [, , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]]]; r (CSV style) =
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
; r (Numpy style) =
array([[[ , , ], [, , ], [, , ]],
[[, , ], [, , ], [, , ]],
[[, , ], [ , , ], [, , ]],
[[, , ], [, , ], [ , , ]],
[[ , , ], [, , ], [, , ]],
[[ , , ], [, , ], [, , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]]], dtype='uint8'); r (C style) =
{ , , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , };
图像储存容器Mat[OpenCV 笔记11]的更多相关文章
- 图像载入 imread()[OpenCV 笔记4]
Mat imread( ); filename 载入的图像名: flags 指定加载图像的颜色类型,默认载入三通道彩色图像, 如果取枚举类型 (OpenCV3中暂时失效),则定义如下 enum{ CV ...
- 图像显示 imshow()[OpenCV 笔记5]
void imshow(const string& winname InputArray mat); winname 窗口表识名称 mat 需要显示的图像.InputArray类型,声明如下 ...
- 访问图像中的像素[OpenCV 笔记16]
再更一发好久没更过的OpenCV,不过其实写到这个部分对计算机视觉算法有所了解的应该可以做到用什么查什么了,所以后面可能会更的慢一点吧,既然开了新坑,还是机器学习更有研究价值吧... 图像在内存中的存 ...
- 实例:图像载入、显示、混合与输出[OpenCV 笔记8]
是的是的,忍着尿意努力更新,就是为了更到wuli男神的部分,当然要把男神放在前面镇楼,欢迎下载配图,具体操作见code wuliEddie.jpg logo.png results.jpg LoadS ...
- 查找并绘制轮廓[OpenCV 笔记XX]
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
- OpenCV基本架构[OpenCV 笔记0]
最近正在系统学习OpenCV,将不定期发布笔记,主要按照毛星云的<OpenCV3编程入门>的顺序学习,会参考官方教程和文档.学习工具是Xcode+CMake,会对书中一部分内容更正,并加入 ...
- 颜色空间转换 cvtColor()[OpenCV 笔记13]
void cvtColor(InputArray src, OutputArray dst, ) src: 输入图像 dst: 输出图像 code: 颜色空间转换标识符 OpenCV2的CV_前缀宏命 ...
- 鼠标操作[OpenCV 笔记10]
) winname 窗口名字 onMouse 指定窗口每次鼠标事件发生的时候,被调用的函数指针.函数的原型应为void Foo(int event, int x, int y, int flags, ...
- 输出图像到文件 imwrite()[OpenCV 笔记7]
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector& ...
随机推荐
- FireFox浏览器的下载和安装、借助RamDisk让你的FireFox飞起来
想说的是,为什么我要写此博文,算是纪念我对FireFox浏览器的一个入门.最近,开始接触了它,看到了很多IT牛人极力推荐使用 “ FireFox浏览器 ”作为开发. 深得大牛指导! 下载 安装 这是, ...
- 无法识别的属性“targetFramework”。请注意属性名称区分大小写。错误分析以及解决方案
我的配置文件中是这样写的,<compilation debug="true" targetFramework="4.0"> 发布在iis上出现了 “ ...
- 校友信息管理系统&SNS互动平台之用户需求及概要设计
前言.提纲及说明: 请移步:<校友信息管理&SNS互动平台之前言.目录及说明>(博客园地址:http://www.cnblogs.com/s6cn/p/3516876.html) ...
- Linux下OpenSSL 安装
安装环境: 操作系统:CentOs6.3 OpenSSL Version:openssl-1.0.0e.tar.gz 目前版本最新的SSL地址为http://www.openssl.org/sour ...
- SmartForms 小技巧
1.添加空行,保证每一页有固定的打印的表格行数 上图,每页最多打印13行,数据只有11行,自动添加两个空行补齐 代码如下“ "定义变量: data: l_blank type i. &quo ...
- 运行时动态修改webconfig
网站运行时,如果直接手动修改webconfig.xml,会造成线程池重启,对于PV大的网站来说风险是很大的,并且如果有多台服务器,逐台修改也会造成数据不一致. .NET 2.0后可以通过代码修改web ...
- iOS开发多线程篇---atomic nonatomic区别
摘要 atomic和nonatomic区别用来决定编译器生成的getter和setter是否为原子操 作.atomic提供多线程安全,是描述该变量是否支持多线程的同步访问,如果选择了atomic 那么 ...
- HBase中的备份和故障恢复方法
本文将对Apache HBase可用的数据备份机制和大量数据的故障恢复/容灾机制做简要介绍. 随着HBase在重要的商业系统中应用的大量添加,很多企业须要通过对它们的HBase集群建立健壮的备份和故障 ...
- mysql优化之连接优化
Posted by Money Talks on 2012/02/23 | 第一篇 序章第二篇 连接优化第三篇 索引优化第四篇 查询优化第五篇 到实战中去 连接优化 连接优化主要指客户端连接数据库以及 ...
- java中最简单的方式新起一个线程
启动一个线程在一个方法中启动一个线程,有两种方法第一种是让类实现Runable接口,这样的话编译器就会提示你实现里面的未实现的方法(就是run方法)第二种是,现在方法中new一个线程,然后直接调用他的 ...