OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析
opencv mat 用法
opencv mat 用法OpenCV是一个广泛使用的计算机视觉库,它提供了许多功能和工具,用于图像处理、视频处理、特征提取等任务。
在OpenCV中,Mat 是一个非常重要的数据结构,用于存储和操作图像数据。
在本篇文章中,我们将介绍Mat的基本用法,包括创建、读取、写入和操作图像数据。
一、Mat的创建在使用Mat之前,需要先创建它。
OpenCV提供了多种方法来创建Mat对象,可以根据需要选择合适的方法。
常用的创建Mat的方法包括:1.使用zeros()或ones()函数创建指定尺寸的零矩阵或全矩阵。
2.使用imread()函数从文件中加载图像,并将其存储为Mat对象。
3.使用随机数生成器创建具有一定分布的图像数据。
下面是一个简单的示例代码,演示如何使用imread()函数创建Mat对象:```pythonimportcv2#读取图像并创建Mat对象img=cv2.imread('image.jpg')#显示图像cv2.imshow('Image',img)cv2.waitKey(0)```二、Mat的读取和写入使用imread()函数可以从文件中加载图像数据并将其存储为Mat 对象。
同样地,使用imwrite()函数可以将Mat对象中的数据写入文件。
下面是一个简单的示例代码,演示如何使用imwrite()函数将Mat 对象中的数据写入文件:```pythonimportcv2importnumpyasnp#创建一个随机图像数据data=np.random.randint(0,256,(500,500,3),dtype=np.uint8) #创建Mat对象并设置数据mat=cv2.Mat(500,500,CV_8UC3,data)#显示Mat对象的内容cv2.imshow('Mat',mat)cv2.waitKey(0)#将Mat对象写入文件cv2.imwrite('output.jpg',mat)```三、Mat的数据类型和尺寸Mat对象可以存储不同类型的数据,包括单通道和多通道数据。
open cv中的Mat详解
通常比矩阵头的尺寸大数个数量级。因此,当在程序中传递图像并创建拷贝时,大的开销 是由矩阵造成的,而不是信息头。OpenCV 是一个图像处理库,囊括了大量的图像处理函数, 为了解决问题通常要使用库中的多个函数,因此在函数中传递图像是家常便饭。同时不要忘 了我们正在讨论的是计算量很大的图像处理算法,因此,除非万不得已,我们不应该拷 贝 大 的图像,因为这会降低程序速度。 二、Mat 的基本操作
如果想建立互不影响的 Mat,是真正的复制操作,需要使用函数 clone()或者 copyTo()。
说到数据的存储,这一直就是一个值得关注的问题,Mat_<uchar>对应的是 CV_8U, Mat_<uchar>对应的是 CV_8U,Mat_<char>对应的是 CV_8S,Mat_<int>对应的是 CV_32S, Mat_<float>对应的是 CV_32F,Mat_<double>对应的是 CV_64F,对应的数据深度如下:
需要注意的是,copy 这样的操作只是 copy 了矩阵的 matrix header 和那个指针,而不是矩 阵的本身,也就意味着两个矩阵的数据指针指向的是同一个地址,需要开发者格外注意。比 如上面这段程序,A、B、C 指向的是同一块数据,他们的 header 不同,但对于 A 的操作 同样也影响着 B、C 的结果。刚刚提高了内存自动释放的问题,那么当我不再使用 A 的时 候就把内存释放了,那时候再操作 B 和 C 岂不是很危险。不用担心,OpenCV 的大神为我 们已经考虑了这个问题,是在最后一个 Mat 不再使用的时候才会释放内存,咱们就放心用 就行了。
在 2001 年刚刚出现的时候,OpenCV 基于 C 语言接口而建。为了在内存(memory) 中存放图像,当时采用名为 IplImage 的 C 语言结构体,时至今日这仍出现在大多数的旧 版教程和教学材料。但这种方法必须接受 C 语言所有的不足,这其中最大的不足要数手动内 存管理,其依据是用户要为开辟和销毁内存负责。虽然对于小型的程序来说手动管理内 一、Mat 简介
opencv中Mat格式的数据访问.at
opencv中Mat格式的数据访问.atopencv3中图形存储基本为Mat格式,如果我们想获取像素点的灰度值或者RGB值,可以通过image.at<uchar>(i,j)的⽅式轻松获取。
Mat类中的at⽅法对于获取图像矩阵某点的RGB值或者改变某点的值很⽅便,对于单通道的图像,则可以使⽤:image.at<uchar>(i, j)其中有⼀个要注意的地⽅是i对应的是点的y坐标,j对应的是点的x坐标,⽽不是我们习惯的(x,y)来获取或改变该点的值,⽽RGB通道的则可以使⽤:image.at<Vec3b>(i, j)[0]image.at<Vec3b>(i, j)[1]image.at<Vec3b>(i, j)[2]来分别获取B、G、R三个通道的对应的值。
下边的代码实现对图像加椒盐噪声:// created by ning zhang 2018/4/25// The function of this program is to add noise to the image#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;void salt_noise( Mat image, int time );int main ( int argc, char** argv ){Mat image = imread("../lena.jpg",0); //input the gray imageif ( image.empty() ){cout << "Load image error" << endl;return -1;}salt_noise(image, 3000);namedWindow("image", 1);imshow("image", image);waitKey();return 0;}void salt_noise ( Mat image, int time ){for (int k = 0; k < time; k++ ) //time is the number of noise you add{int i = rand() % image.rows;int j = rand() % image.cols;if (image.channels() == 1) //single channel{image.at<uchar>(i,j) = rand() % 255;}else if (image.channels() == 3) //RGB channel{image.at<Vec3b>(i, j)[0] = rand() % 255;image.at<Vec3b>(i, j)[1] = rand() % 255;image.at<Vec3b>(i, j)[2] = rand() % 255;}}}效果图如下所⽰,可以为图⽚增加噪点还有⽐较省时的⽅法使⽤Mat的模板⼦类Mat_<T>,,对于单通道的具体使⽤:Mat_<uchar> img = image;img(i, j) = rand() % 255;对于RGB通道的使⽤:Mat_<Vec3b> img = image;img(i, j)[0] = rand() % 255;img(i, j)[1] = rand() % 255;mg(i, j)[2] = rand() % 255;还可以⽤指针的⽅法遍历每⼀像素:(耗时较⼩)void colorReduce(Mat image, int div = 64){int nrow = image.rows;int ncol = image.cols*image.channels();for (int i = 0; i < nrow; i++){uchar* data = image.ptr<uchar>(i);//get the address of row i;for (int j = 0; j < ncol; j++){data[i] = (data[i] / div)*div ;}}}我们要尤其注意OpenCV坐标系与row&col的关系 (Mat::at(x,y)和Mat::at(Point(x, y))的区别)直接给出对应关系吧row == heigh == Point.ycol == width == Point.xMat::at(Point(x, y)) == Mat::at(y,x)因为还有点的坐标,所以建议在访问时都⽤Mat::at(Point(x, y))这种形式吧,免去了点坐标和⾏列的转换详细说明:1. 坐标体系中的零点坐标为图⽚的左上⾓,X轴为图像矩形的上⾯那条⽔平线;Y轴为图像矩形左边的那条垂直线。
opencvmat类存取方法(元素访问
Opencv----Mat类∙cv::Mat∙depth/dims/channels/step/data/elemSizeMat矩阵中数据元素的地址计算公式:addr(M i0,i1,…i m-1) = M.data + M.step[0] * i0 + M.step[1] * i1+ … + M.step[m-1] * i m-1。
其中m = M.dims 是指M的维度i.data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存(uchar*data).ii.row: 行;col:列;rows:行数;cols:列数。
iii.dims :Mat所代表的矩阵的维度,如3 * 4 的矩阵为2 维,3 * 4 * 5 的为3维. iv.channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说3 * 4 矩阵中一共12 个元素,如果每个元素有三个值,那么就说这个矩阵是3 通道的,即channels = 3。
常见的是一张彩色图片有红、绿、蓝三个通道。
但是opencv用imread(opencv读图的函数)读进来的图像,三通道存放顺序为B、G、R。
v.depth:深度,即每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个0 –6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };可见0和1都代表8位,2和3都代表16位,4和5代表32位,6代表64位;vi.step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意step1(step / elemSize1),M.step[m-1] 总是等于elemSize,M.step1(i)返回的是第i 维的步长,因此M.step1(m-1)总是等于channels,m是M的维度;这里是解释步长step[k]的,步长也可以看作是与第k维的存储单位,在2维的矩阵中,因为存储是按照行的顺序存储的,整个矩阵存储为一个平面,所以第k=0维的步长也就是单位肯定就是一行所占的字节数;如果是3维的话,第0维是按照面为单位来存储的,第1维是按照行为单位来存储的,第2维是按照元素类型为单位存储的,每个元素类型是基本类型(即uchar,float,short等等)与通道数的乘积...;也就是基本数据类型与通道数组成元素,多个元素组成了行,多行组成了面,多个面组成了3维体,多个3维体组成4维超体。
open cv中的Mat详解
分类: OpenCV2011-12-28 10:33 26348 人阅读 评论(16) 收藏 举报 数据结构 matrixheadernumbers 存储 matlab
我记得开始接触 OpenCV 就是因为一个算法里面需要 2 维动态数组,那时候看 core 这部分 也算是走马观花吧,随着使用的增多,对 Mat 这个结构越来越喜爱,也觉得有必要温故而 知新,于是这次再看看 Mat。
在 2001 年刚刚出现的时候,OpenCV 基于 C 语言接口而建。为了在内存(memory) 中存放图像,当时采用名为 IplImage 的 C 语言结构体,时至今日这仍出现在大多数的旧 版教程和教学材料。但这种方法必须接受 C 语言所有的不足,这其中最大的不足要数手动内 存管理,其依据是用户要为开辟和销毁内存负责。虽然对于小型的程序来说手动管理内 一、Mat 简介
亲,有木有很简单!!!
还有一种快速初始化数据的办法,如下:
[cpp] view plaincopy
1.double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; 2.Mat M = Mat(3, 3, CV_64F, m).inv();
也可以把原来的 IplImage 格式的图片直接用 Mat(IplImage)的方式转成 Mat 结构,也可 以像 Matlab 一样调用 zeros()、ones()、eye()这样的函数进行初始化。
幸运的是,C++出现了,并且带来类的概念,这给用户带来另外一个选择:自动的内存 管理(不严谨地说)。这是一个好消息,如果 C++完全兼容 C 的话,这个变化不会带来兼容 性问题。为此,OpenCV 在 2.0 版本中引入了一个新的 C++接口,利用自动内存管理给出了解 决问题的新方法。使用这个方法,你不需要纠结在管理内存上,而且你的代码会变得简洁(少 写多得)。但 C++接口唯一的不足是当前许多嵌入式开发系统只支持 C 语言。所以,当目标 不是这种开发平台时,没有必要使用 旧 方法(除非你是自找麻烦的受虐狂码农)。
OpenCV中对Mat的遍历访问与赋值
OpenCV中对Mat的遍历访问与赋值⼀、访问对于Mat的访问有两种⽅式第⼀种,利⽤Mat::at进⾏访问//读取3通道彩⾊图像Mat img = imread("图⽚地址");int px;//读取图像中第⼀⾏第⼀列,Blue通道数据int px = img.at<Vec3b>(0, 0)[0];第⼆种,利⽤Mat的成员ptr指针进⾏访问//读取3通道彩⾊图像Mat img = imread("图⽚地址");//将Mat中的第⼀⾏地址赋予pxVecuchar* pxVec=img.ptr<uchar>(0);//遍历访问Mat中各个像素值int i, j;int px;for (i = 0; i < img.rows; i++){pxvec = img.ptr<uchar>(i);//三通道数据都在第⼀⾏依次排列,按照BGR顺序//依次赋值为1for (j = 0; j < img.cols*img.channels(); j++){px=pxvec[j];//do anything}}⼆、赋值不能⽤Mat::at进⾏赋值,只能⽤ptr对Mat中的像素点进⾏赋值⼀个完整的例⼦如下:#include "stdafx.h"#include <opencv2\core\core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>#include <vector>int main(){//对Mat进⾏遍历赋值//初始化Mat数据结构,256*256,三通道8位(256⾊)图像Mat myimg(256,256,CV_8UC3);//取像素数据⾸地址uchar* pxvec = myimg.ptr<uchar>(0);int i, j;for (i = 0; i < myimg.rows; i++){pxvec = myimg.ptr<uchar>(i);//三通道数据都在第⼀⾏依次排列,按照BGR顺序//依次赋值为1for (j = 0; j < myimg.cols*myimg.channels(); j++){pxvec[j] = 1;}}//展⽰图像imshow("abc", myimg); waitKey(10000);}结果如下:。
opencv中Mat使用,很好,顶!
opencv中Mat使用,很好,顶!(一)Mat矩阵中数据指针Mat.data是uchar类型指针,CV_8U 系列可以通过计算指针位置快速地定位矩阵中的任意元素。
二维单通道元素可以用Mat::at(i, j)访问,i是行序号,j是列序号。
但对于多通道的非unsigned char类型矩阵来说,以上方法都不好(注:后来知道可以通过类型转换,用指针访问data数据,见后文)。
可以用Mat::ptr()来获得指向某行元素的指针,在通过行数与通道数计算相应点的指针。
参照OpenCV的Mat::at()函数,写了一个访问二维Mat矩阵的两个简单的小函数,没有边界检查。
1#include <opencv2/core/core.hpp>23template<typename ItemType>4ItemType* getMatPointPtr(cv::Mat & src, int i , int j , int c = 0)5{6ItemType* curRow = src.ptr<ItemType>(i); 7return curRow + j * src.channels() + c; 8}9template<typename ItemType>10ItemType getMatPoint(cv::Mat & src, int i , int j , int c = 0)11{12ItemType* curRow = src.ptr<ItemType>(i);13return *(curRow + j * src.channels() + c);14}OpenCV中的Mat::at()代码有严格的边界检测,Mat::ptr()也有边界检测,但代码中没有检测j是否越界。
以上为推荐使用的情况,下边的不推荐使用。
可以通过转换指针类型,访问非uchar类型的Mat元素。
OPENCV的MAT类详解
类 Mat导言OpenCV c + + n 维稠密数组类类 CV_EXPORTS Mat{public:/ / … …很多的方法....../*!包括几位字段:-神奇的签名-连续性标志-深度(Note:应该是位深)-通道数*/int flags;(Note :目前还不知道flags做什么用的)//!数组的维数,> = 2int dims ;//!行和列的数量或 (-1,-1) 此时数组已超过 2 维int rows,cols;//!指向数据的指针uchar *data ;//!指针的引用计数器;/ / 阵列指向用户分配的数据时,当指针为 NULLint * refcount ;/ / 其他成员...};Mat类表示一个 n 维的密集数值单通道或多通道数组。
它可以用于存储实数或复数值的向量和矩阵、灰度或彩色图像、体素、向量场、点云、张量、直方图(尽管较高维的直方图存储在SparseMat可能更好)。
M 数组的数据布局是由阵列 M.step[]定义的,使元素的地址(i0,。
i M.dims-1),其中 0<= i k< M.size [k],可以计算为:addr( Mi0;:::;i M.dims-1) = M.data+ M.step[ 0]*i0+ M.step[ 1] *i1+ .…+M.step[ M:dims- 1] i M:dims- 12维的数组的情况下根据上述公式被减至:addr( M i,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j请注意,M.step[i] > =M.step[i+1] (事实上,M.step[i] > =M.step[i+1]*M.size[i+1])。
这意味着2维矩阵是按行存储的,3 维矩阵是由平面存储,以此类推。
M.step[M.dims-1] 是最小的而且总是等于元素大小M.elemSize()。
Mat数据类型与访问
Mat数据类型与访问Mat数据类型与访问1.opencv数据类型与常⽤类型对应关系 想要准确的访问Mat中元素值,了解opencv中数据类型很重要,他决定了Mat中每个元素所占内存的⼤⼩。
opencv中各种类型定义:#define CV_8U 0 //对应uchar#define CV_8S 1 //对应char#define CV_16U 2 //对应ushort#define CV_16S 3 //对应short#define CV_32S 4 //对应int#define CV_32F 5 //对应float#define CV_64F 6 //对应double#define CV_USRTYPE1 7...#define CV_8UC1 CV_MAKETYPE(CV_8U,1) //0#define CV_8UC2 CV_MAKETYPE(CV_8U,2) //8#define CV_8UC3 CV_MAKETYPE(CV_8U,3) //16#define CV_8UC4 CV_MAKETYPE(CV_8U,4) //32#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))#define CV_8SC1 CV_MAKETYPE(CV_8S,1) //1#define CV_8SC2 CV_MAKETYPE(CV_8S,2) //9#define CV_8SC3 CV_MAKETYPE(CV_8S,3) //17#define CV_8SC4 CV_MAKETYPE(CV_8S,4) //33#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))...#define CV_64FC1 CV_MAKETYPE(CV_64F,1) //6#define CV_64FC2 CV_MAKETYPE(CV_64F,2) //14#define CV_64FC3 CV_MAKETYPE(CV_64F,3) //22#define CV_64FC4 CV_MAKETYPE(CV_64F,4) //38#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))注:CV_MAKETYPE(depth,cn)=(cn-1)*8+depth //定义类型,类型不冲突补充:opencv中数据类型的变化 注意opencv中各个函数所适⽤的Mat矩阵数据类型。
opencv mat类运算
opencv mat类运算OpenCVMat类是一个非常重要的数据结构,可以表示图像、矩阵和向量等,在计算机视觉和图形学领域广泛应用。
本文将介绍Mat类的基本操作,包括创建、访问、赋值、运算等。
1. 创建Mat对象首先,我们可以通过以下两种方式创建一个Mat对象:(1)使用构造函数:Mat(int rows, int cols, int type);(2)使用静态方法:Mat::zeros(int rows, int cols, int type);其中,rows和cols表示矩阵的行数和列数,type表示数据类型和通道数,常用的有CV_8UC1、CV_8UC3、CV_32FC1等。
2. 访问Mat元素访问Mat对象的元素可以使用at()方法或者指针操作符[],例如:Mat img = imread('image.jpg', CV_LOAD_IMAGE_GRAYSCALE); uchar pixel = img.at<uchar>(i, j);或者:uchar* data = img.ptr<uchar>(i);uchar pixel = data[j];3. 赋值操作Mat对象之间可以进行赋值操作,例如:Mat img = imread('image.jpg', CV_LOAD_IMAGE_GRAYSCALE);Mat img2 = img.clone();4. 运算操作Mat对象之间可以进行加、减、乘、除等运算,例如:Mat img1 = imread('image1.jpg', CV_LOAD_IMAGE_GRAYSCALE); Mat img2 = imread('image2.jpg', CV_LOAD_IMAGE_GRAYSCALE); Mat img_add = img1 + img2;Mat img_sub = img1 - img2;Mat img_mul = img1.mul(img2);Mat img_div = img1 / img2;除此之外,还可以进行矩阵转置、矩阵相乘、矩阵求逆、矩阵求特征值等高级运算。
opencv mat类运算
opencv mat类运算OpenCVMat类是OpenCV中最基本的数据类型之一。
它代表一个多维数组,可以用于存储图像、矩阵、点云等数据。
在实际应用中,我们经常需要对Mat对象进行各种运算,本文将介绍一些常用的Mat 类运算。
1. Mat对象的创建和初始化在使用Mat对象之前,我们需要创建它并对其进行初始化。
创建Mat对象的方法如下:Mat image;//创建一个空的Mat对象Mat image(rows,cols,type);//创建指定大小和类型的Mat对象其中,rows表示矩阵的行数,cols表示矩阵的列数,type表示矩阵的数据类型,常用的类型有CV_8UC1(8位无符号单通道)、CV_8UC3(8位无符号三通道)、CV_32FC1(32位浮点单通道)等。
Mat对象的初始化可以通过赋值、拷贝、从文件读取等方式进行。
2. Mat对象的运算Mat对象支持各种数学运算,包括加、减、乘、除、逻辑运算等。
下面以加法运算为例,介绍Mat对象的运算。
Mat a(rows,cols,CV_8UC1,Scalar(1));//创建一个大小为rows*cols,类型为CV_8UC1,值为1的Mat对象Mat b(rows,cols,CV_8UC1,Scalar(2));//创建一个大小为rows*cols,类型为CV_8UC1,值为2的Mat对象Mat result = a + b;//将a和b相加,结果保存在result中在进行运算时,需要注意Mat对象的大小和数据类型必须相同,否则会导致运算失败。
此外,Mat对象的运算速度较慢,应尽量避免在循环中使用。
3. Mat对象的转换Mat对象可以进行类型转换和通道分离,以便在不同的应用场景中使用。
下面以类型转换为例,介绍Mat对象的转换。
Mat a(rows,cols,CV_8UC1,Scalar(1));//创建一个大小为rows*cols,类型为CV_8UC1,值为1的Mat对象Mat b;//创建一个空的Mat对象a.convertTo(b, CV_32FC1);//将a转换为CV_32FC1类型,结果保存在b中在进行类型转换时,需要注意目标类型应该能够容纳源类型的值,否则会丢失精度。
五种Mat元素的访问方法
五种Mat元素的访问方法方法1、使用Mat的成员函数at<>()Mat的成员函数at()是一个模板函数,我们这里用的是二维矩阵,所以我们使用的at()函数的声明如代码段3所示(取自OpenCV的源文件)。
[cpp]view plaincopy1.template<typename _Tp> _Tp& at(int i0, int i1);代码段3 .at()函数的声明代码段4是本文第二部分描述的算法的实现,矩阵元素使用at<>()函数来索引。
[cpp]view plaincopy1.Vec3b pix;2.for (int r = 0; r < im.rows; r++)3.{4.for (int c = 0; c < im.cols; c++)5. {6. pix = im.at<Vec3b>(r,c);7. pix = pix*scale;8. om.at<Vec3b>(r,c) = pix;9. }10.}代码段4. 使用at<>()函数访问矩阵元素注意:使用at函数时,应该知道矩阵元素的类型和通道数,根据矩阵元素类型和通道数来确定at函数传递的类型,代码段4中使用的是Vec3b这个元素类型,他是一个包含3个unsigned char类型向量。
之所以采用这个类型来接受at的返回值,是因为,我们的矩阵im是3通道,类型为unsigned char类型的。
方法2、使用Mat的成员函数ptr<>()此函数也是模板函数,我们将会用到的ptr函数声明如代码段5所示。
此函数返回指定的数据行的首地址。
[cpp]view plaincopy1.template<typename _Tp> _Tp* ptr(int i0=0);代码段5. ptr成员函数的声明使用ptr<>()成员函数完成本文第二部分所述算法的代码如代码段6所示。
OpenCV学习之CvMat的用法详解及实例
OpenCV学习之CvMat的用法详解及实例目录1.初始化矩阵: (2)2.IplImage 到cvMat的转换 (2)3.cvArr(IplImage或者cvMat)转化为cvMat (2)4.图像直接操作 (3)5.cvMat的直接操作 (3)6.间接访问cvMat (5)7.修改矩阵的形状——cvReshape的操作 (6)8.计算色彩距离 (8)CvMat是OpenCV比较基础的函数。
初学者应该掌握并熟练应用。
但是我认为计算机专业学习的方法是,不断的总结并且提炼,同时还要做大量的实践,如编码,才能记忆深刻,体会深刻,从而引导自己想更高层次迈进。
1.初始化矩阵:方式一、逐点赋值式:CvMat* mat = cvCreateMat( 2, 2, CV_64FC1 );cvZero( mat );cvmSet( mat, 0, 0, 1 );cvmSet( mat, 0, 1, 2 );cvmSet( mat, 1, 0, 3 );cvmSet( mat, 2, 2, 4 );cvReleaseMat( &mat );方式二、连接现有数组式:double a[] = { 1, 2, 3, 4,5, 6, 7, 8,9, 10, 11, 12 };CvMat mat = cvMat( 3, 4, CV_64FC1, a ); // 64FC1 for double// 不需要cvReleaseMat,因为数据内存分配是由double定义的数组进行的。
2.IplImage 到cvMat的转换方式一、cvGetMat方式:CvMat mathdr, *mat = cvGetMat( img, &mathdr );方式二、cvConvert方式:CvMat *mat = cvCreateMat( img->height, img->width, CV_64FC3 ); cvConvert( img, mat );// #define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 ) 3.cvArr(IplImage或者cvMat)转化为cvMat方式一、cvGetMat方式:int coi = 0;cvMat *mat = (CvMat*)arr;if( !CV_IS_MAT(mat) ){mat = cvGetMat( mat, &matstub, &coi );if (coi != 0) reutn; // CV_ERROR_FROM_CODE(CV_BadCOI);}写成函数为:// This is just an example of function// to support both IplImage and cvMat as an inputCVAPI( void ) cvIamArr( const CvArr* arr ){CV_FUNCNAME( "cvIamArr" );__BEGIN__;CV_ASSERT( mat == NULL );CvMat matstub, *mat = (CvMat*)arr;int coi = 0;if( !CV_IS_MAT(mat) ){CV_CALL( mat = cvGetMat( mat, &matstub, &coi ) );if (coi != 0) CV_ERROR_FROM_CODE(CV_BadCOI);}// Process as cvMat__END__;}4.图像直接操作方式一:直接数组操作 int col, row, z;uchar b, g, r;for( y = 0; row < img->height; y++ ){for ( col = 0; col < img->width; col++ ){b = img->imageData[img->widthStep * row + col * 3]g = img->imageData[img->widthStep * row + col * 3 + 1];r = img->imageData[img->widthStep * row + col * 3 + 2];}}方式二:宏操作:int row, col;uchar b, g, r;for( row = 0; row < img->height; row++ ){for ( col = 0; col < img->width; col++ ){b = CV_IMAGE_ELEM( img, uchar, row, col * 3 );g = CV_IMAGE_ELEM( img, uchar, row, col * 3 + 1 );r = CV_IMAGE_ELEM( img, uchar, row, col * 3 + 2 );}}注:CV_IMAGE_ELEM( img, uchar, row, col * img->nChannels + ch ) 5.cvMat的直接操作数组的直接操作比较郁闷,这是由于其决定于数组的数据类型。
python opencv的mat结构及其应用场景
python opencv的mat结构及其应用场景
在Python的OpenCV库中,Mat是一个核心类,用于表示图像和矩阵。
Mat对象可以看作是一个多维数组,能够保存实数或复数的向量、矩阵、灰度或彩色图像、立体元素、点云、张量以及直方图。
Mat对象可以分为两个部分:矩阵头和指向像素数据的矩阵指针。
矩阵头包括数字图像的矩阵尺寸、存储方法、存储地址和引用次数等,矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。
Mat对象的应用场景包括但不限于以下几个方面:
1.图像处理和计算机视觉任务:这是Mat对象最常用的场景之一。
通过使用Mat对象,可以对图像进行各种
操作,如读取、显示、保存、裁剪、旋转、缩放、滤波、边缘检测、特征提取等。
2.机器学习和深度学习任务:Mat对象可以用于存储和处理数据,包括训练和测试数据集。
通过使用OpenCV
库中的各种算法和函数,可以对Mat对象进行预处理、特征提取和模型训练等操作。
3.图像分析和图像识别任务:通过使用Mat对象,可以对图像进行分析和识别,如人脸检测、目标跟踪、手
势识别等。
4.图像生成和渲染:使用Mat对象可以生成和处理图像,如制作动画、生成艺术效果等。
总之,Mat对象是OpenCV库中的核心类之一,其应用场景非常广泛,可用于图像处理、计算机视觉、机器学习、深度学习等领域。
opencv mat的元素个数
opencv mat的元素个数OpenCV是一个开源的计算机视觉库,广泛应用于图像处理和计算机视觉领域。
其中最基本的数据结构就是Mat,它是一个多维数组,用于存储图像或其他类型的矩阵数据。
本文将围绕着Mat的元素个数展开,深入探讨其背后的原理和应用。
一、Mat的基本原理Mat是OpenCV中最基本的数据结构之一,它的本质是一个矩阵,用于存储像素值或其他类型的数据。
Mat的元素个数可以通过rows和cols属性来获取,即行数乘以列数。
例如,一个3x3的Mat,其元素个数为9。
二、Mat的应用场景1. 图像处理在图像处理中,Mat是最常用的数据结构之一。
图像可以看作是一个二维矩阵,每个元素代表一个像素点的数值。
通过Mat,可以方便地对图像进行操作,如裁剪、缩放、旋转等。
2. 视频处理类似于图像处理,视频处理也需要使用Mat来存储每一帧图像的像素值。
通过Mat,可以对视频进行处理,如提取关键帧、合成视频等。
3. 计算机视觉在计算机视觉领域,Mat也是不可或缺的。
例如,通过Mat可以将摄像头捕捉到的图像转换为可用于计算机视觉算法的矩阵形式,如人脸识别、目标检测等。
三、Mat的内存管理Mat的内存管理是OpenCV中的重要概念。
Mat的内存由OpenCV自动管理,这意味着我们无需手动申请和释放内存。
当Mat不再使用时,内存会被自动释放,这为我们提供了方便和安全性。
四、Mat的数据类型Mat支持多种数据类型,如CV_8U、CV_32F等。
不同的数据类型可以适应不同的应用场景,例如CV_8U可以表示8位无符号整数,CV_32F可以表示32位浮点数。
通过指定不同的数据类型,可以更加高效地存储和处理数据。
五、Mat的操作Mat提供了丰富的操作方法,可以实现图像处理和计算机视觉算法等。
常见的操作包括像素访问、矩阵运算、图像滤波等。
通过这些操作,可以实现各种各样的功能。
六、Mat的性能优化由于Mat的元素个数可能非常庞大,因此对Mat的性能进行优化是非常重要的。
opencv mat 运算符 操作 详解
在 OpenCV 中,cv::Mat类型是表示矩阵(图像)的核心数据结构。
它支持各种矩阵运算和操作,可以进行像素级别的图像处理和计算。
以下是一些常见的cv::Mat运算符和操作的详解:
创建cv::Mat对象:
1.创建空白矩阵:
2.通过数据创建矩阵:
3.复制矩阵:
基本运算:
1.矩阵加法:
2.矩阵减法:
3.矩阵乘法:
4.标量乘法:
逐元素运算:
1.逐元素加法:
2.逐元素减法:
3.逐元素乘法:
4.逐元素除法:
转置和翻转:
1.矩阵转置:
2.水平翻转:
3.垂直翻转:
其他操作:
1.矩阵元素访问:
2.改变矩阵大小:
3.提取子矩阵:
4.通道拆分与合并:
这些是一些常见的cv::Mat运算符和操作的示例。
OpenCV 提供了丰富的功能,允许进行更复杂的图像处理和计算。
具体的操作和运算可以根据具体需求进行查阅OpenCV 文档。
pencv中mat的数学运算和基本操作
pencv中mat的数学运算和基本操作在OpenCV中,Mat是一个多维数组,被广泛用于图像处理和计算机视觉领域。
Mat类提供了各种数学运算和基本操作,用于处理图像的像素值、形状和数据类型等。
1.创建和初始化Mat对象:Mat可以通过多种方法进行创建和初始化。
常见的方法包括:-使用默认构造函数创建一个空的Mat对象:Mat()-使用指定的行数、列数和数据类型创建一个Mat对象:Mat(int rows, int cols, int type)-复制一个已有的Mat对象:Mat(Mat m)-从数组、向量或指针初始化Mat对象:Mat(int rows, int cols, int type, void* data)2.访问和修改元素:可以使用at()方法或操作符()来访问和修改Mat对象的元素。
at()方法具有边界检查,而操作符()没有。
例如:-获取指定位置的像素值:int value = mat.at<int>(row, col);-修改指定位置的像素值:mat.at<int>(row, col) = newValue;3.像素值的常见运算:Mat对象可以进行各种常见的数学运算,包括像素值的加法、减法、乘法和除法。
这些运算可以对整个图像进行,也可以对指定区域进行。
例如:-对整个图像进行像素值加法:mat1 = mat1 + mat2;-对指定区域进行像素值减法:mat1(Rect(x, y, width, height)) -= Scalar(b, g, r);4.形状和尺寸操作:Mat对象提供了各种方法来获取和修改图像的形状和尺寸。
常见的方法包括:-获取图像的行数和列数:int rows = mat.rows; int cols = mat.cols;-获取图像的尺寸:Size size = mat.size();-修改图像的尺寸:mat.resize(height, width);-转置图像:mat = mat.t();5.通道操作:对于多通道的图像,Mat对象还提供了通道的操作方法。
OpenCV学习笔记(2):Mat矩阵的初始化和元素访问
OpenCV学习笔记(2):Mat矩阵的初始化和元素访问在研究Mat矩阵的初始化的时候,发现其不能像Matx轻量级矩阵那样,直接利⽤数组来进⾏初始化,⽽是利⽤⼀个内部的变量类型:Scalar来进⾏初始化的。
参考⼿册中的构造函数如下所⽰:(1) Mat::Mat()(2) Mat::Mat(int rows, int cols, int type)(3) Mat::Mat(Size size, int type)(4) Mat::Mat(int rows, int cols, int type, const Scalar& s)(5) Mat::Mat(Size size, int type, const Scalar& s)(6) Mat::Mat(const Mat& m)(7) Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)(8) Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)(9) Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)(10) Mat::Mat(const Mat& m, const Rect& roi)(11) Mat::Mat(const CvMat* m, bool copyData=false)(12) Mat::Mat(const IplImage* img, bool copyData=false)(13) template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)(14) template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)(15) template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)(16) Mat::Mat(const MatExpr& expr)(17) Mat::Mat(int ndims, const int* sizes, int type)(18) Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s)(19) Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)(20) Mat::Mat(const Mat& m, const Range* ranges)似乎这样的矩阵让我们⽤起来感觉很不顺⼿,不过接着往下读参考⼿册,你会发现这样⼀个例⼦:Mat H(100, 100, CV_64F);for(int i = 0; i < H.rows; i++)for(int j = 0; j < H.cols; j++)H.at<double>(i,j)=1./(i+j+1);通过这个例⼦,我们尝试来给Mat类型初始化。
opencv mat类元素赋值
标题:OpenCV中Mat类元素赋值的操作一、介绍OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理功能,Mat类是OpenCV中使用最广泛的类之一,它可以用来存储图像数据,进行图像处理和运算。
在使用OpenCV时,对于Mat类的元素赋值操作是非常常见的,本文将介绍OpenCV中Mat类元素赋值的相关操作和技巧。
二、Mat类简介1. Mat类是OpenCV中用于存储图像数据的类,它是一个多维数组,可以存储图像的像素值。
2. Mat类可以存储单通道灰度图像、三通道彩色图像,以及其他类型的图像数据。
三、Mat元素赋值的基本操作1. 使用at方法对Mat元素进行赋值Mat img = imread("image.jpg");img.at<Vec3b>(i, j)[0] = 255; //对(i, j)位置的蓝色通道赋值为2552. 使用指针操作对Mat元素进行赋值Mat img = imread("image.jpg");Vec3b* pixel = img.ptr<Vec3b>(i); //获取第i行的像素指针pixel[j][0] = 255; //对第i行第j列的像素的蓝色通道赋值为255四、Mat元素赋值的高级操作1. 使用循环对Mat元素进行批量赋值Mat img(100, 100, CV_8UC3);for (int i = 0; i < img.rows; i++) {for (int j = 0; j < img.cols; j++) {img.at<Vec3b>(i, j) = Vec3b(0, 0, 255); //给整个图像赋值为蓝色}}2. 使用setTo方法对Mat元素进行批量赋值Mat img(100, 100, CV_8UC3);img.setTo(Vec3b(0, 0, 255)); //给整个图像赋值为蓝色五、Mat元素赋值的注意事项1. 确保元素位置的合法性在对Mat元素进行赋值时,需要确保元素的位置合法,避免越界访问导致内存访问错误。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析欢迎转载,尊重原创,所以转载请注明出处:/bendanban/article/details/30527785本文讲述了OpenCV中几种访问矩阵元素的方法,在指定平台上给出性能比较,分析每种矩阵元素访问方法的代码复杂度,易用性。
一、预备设置本文假设你已经正确配置了OpenCV的环境,为方便大家实验,在文中也给出了编译源程序的Makefile,其内容如代码段1所示。
采用如代码段2所示的计时函数,这段代码你可以在我之前的博文中找到,abtic() 可以返回微秒(10^-6秒)级,而且兼容Windows和Linux系统。
本文使用彩色图像做实验,所以矩阵是2维的3通道的。
[plain]view plaincopy = g++2.CPPFLAGS = -O3 `pkg-config --cflags opencv`3.CPPLIB = `pkg-config --libs opencv`4.5.OBJS = test.o6.7.main.exe : $(OBJS)8. $(CC) $(CPPFLAGS) $^ -o $@ $(CPPLIB)9.10.test.o: test.cpp11. $(CC) -c $(CPPFLAGS) $^ -o $@12.13.clean:14. rm -rf *.out main.exe *.o15.16.run:17. ./main.exe文件的内容[cpp]view plaincopy1.#if defined(_WIN32) && defined(_MSC_VER)2.#include <windows.h>3.double abtic() {4.__int64 freq;5.__int64 clock;6. QueryPerformanceFrequency( (LARGE_INTEGER *)&freq );7. QueryPerformanceCounter( (LARGE_INTEGER *)&clock );8.return (double)clock/freq*1000*1000;9.}10.#else11.#include <time.h>12.#include <sys/time.h>13.double abtic() {14.double result = 0.0;15.struct timeval tv;16. gettimeofday( &tv, NULL );17. result = _sec*1000*1000 + _usec;18.return result;19.}20.#endif /* _WIN32 */abtic()的定义二、测试算法文中用于测试的算法:将矩阵中每个元素乘以一个标量,写入一个新的矩阵,每个通道操作独立。
如果用im(r,c,k)表示矩阵im的第r行、第c列、第k个通道的值的话,算法为:om(r,c,k) = im(r,c,k)*scale;其中scale是一个大于0、小于1的浮点数。
三、五种Mat元素的访问方法方法1、使用Mat的成员函数at<>()Mat的成员函数at()是一个模板函数,我们这里用的是二维矩阵,所以我们使用的at()函数的声明如代码段3所示(取自OpenCV的源文件)。
[cpp]view plaincopy1.template<typename _Tp> _Tp& at(int i0, int i1);代码段3 .at()函数的声明[cpp]view plaincopy1.Vec3b pix;2.for (int r = 0; r < im.rows; r++)3.{4.for (int c = 0; c < im.cols; c++)5. {6. pix = im.at<Vec3b>(r,c);7. pix = pix*scale;8. om.at<Vec3b>(r,c) = pix;9. }10.}注意:使用at函数时,应该知道矩阵元素的类型和通道数,根据矩阵元素类型和通道数来确定at函数传递的类型,代码段4中使用的是Vec3b这个元素类型,他是一个包含3个unsigned char类型向量。
之所以采用这个类型来接受at的返回值,是因为,我们的矩阵im是3通道,类型为unsigned char类型的。
方法2、使用Mat的成员函数ptr<>()此函数也是模板函数,我们将会用到的ptr函数声明如代码段5所示。
此函数返回指定的数据行的首地址。
[cpp]view plaincopy1.template<typename _Tp> _Tp* ptr(int i0=0);[cpp]view plaincopy1.Vec3b *ppix_im(NULL);2.Vec3b *ppix_om(NULL);3.for (int r = 0; r < im.rows; r++)4.{5. ppix_im = im.ptr<Vec3b>(r);6. ppix_om = om.ptr<Vec3b>(r);7.for (int c = 0; c < im.cols; c++)8. {9. ppix_om[c] = ppix_im[c]*scale;10. }11.}方法3、使用迭代器这里使用的迭代器是OpenCV自己定义的。
使用迭代器完成第二部分所述算法的代码如代码段7所示。
[cpp]view plaincopy1.MatIterator_<Vec3b> it_im, itEnd_im;2.MatIterator_<Vec3b> it_om;3.it_im = im.begin<Vec3b>();4.itEnd_im = im.end<Vec3b>();5.it_om = om.begin<Vec3b>();6.for (; it_im != itEnd_im; it_im++, it_om++)7.{8. *it_om = (*it_im)*scale;9.}方法4、使用Mat_简化索引Mat_这个类的元素访问比较容易一点,把原Mat类的对象可以直接赋值给Mat_对象,当然赋值操作并不会开辟新的数据空间,这点大家放心。
也就是说使用Mat_时,不会在内存拷贝上花时间。
使用这种方法完成第二部分所述算法的代码如代码段8所示。
[cpp]view plaincopy1.Mat_<Vec3b> im_, om_;2.im_ = im;3.om_ = om;4.for (int r = 0; r < im.rows; r++)5.{6.for (int c = 0; c < im.cols; c++)7. {8. om_(r,c) = im_(r,c) * scale;9. }10.}方法5、使用OpenCV原有的实现我们的算法实际上OpenCV中已经有实现。
就是×运算符重载,代码如代码段9所示。
[cpp]view plaincopy1.om = im*scale;四、实验测试1、测试代码[cpp]view plaincopy1./*************************************************************************2. > File Name: test.cpp3. > Author: aban4. > Mail: sawpara@5. > Created Time: 2014年06月13日星期五 18时47分19秒6. ************************************************************************/7.8.9.#include <iostream>10.#include <opencv2/opencv.hpp>ing namespace cv;ing namespace std;13.14.#if defined(_WIN32) && defined(_MSC_VER)15.#include <windows.h>16.double abtic() {17.__int64 freq;18.__int64 clock;19. QueryPerformanceFrequency( (LARGE_INTEGER *)&freq );20. QueryPerformanceCounter( (LARGE_INTEGER *)&clock );21.return (double)clock/freq*1000*1000;22.}23.#else24.#include <time.h>25.#include <sys/time.h>26.double abtic() {27.double result = 0.0;28.struct timeval tv;29. gettimeofday( &tv, NULL );30. result = _sec*1000*1000 + _usec;31.return result;32.}33.#endif /* _WIN32 */34.35.#define ISSHOW 036.37.int main(int argc, char** argv)38.{39.double tRecorder(0.0);40. Mat im = imread("./bigim.tif");41. Mat om;42. om.create(im.rows, im.cols, CV_8UC3);43.44.#if ISSHOW45. imshow("orignal Image", im);46. waitKey();47.#endif48.49.float scale = 150.0f/255.0f;50.51.// 1. using at()52. tRecorder = abtic();53. Vec3b pix;54.for (int r = 0; r < im.rows; r++)55. {56.for (int c = 0; c < im.cols; c++)57. {58. pix = im.at<Vec3b>(r,c);59. pix = pix*scale;60. om.at<Vec3b>(r,c) = pix;61. }62. }63. cout << (abtic() - tRecorder) << " using at<>()" << endl;64.#if ISSHOW65. imshow("Scaled Image: using at<>()", om);66. waitKey();67.#endif68.69.// 2. using ptr70. tRecorder = abtic();71. Vec3b *ppix_im(NULL);72. Vec3b *ppix_om(NULL);73.for (int r = 0; r < im.rows; r++)74. {75. ppix_im = im.ptr<Vec3b>(r);76. ppix_om = om.ptr<Vec3b>(r);77.for (int c = 0; c < im.cols; c++)78. {79. ppix_om[c] = ppix_im[c]*scale;80. }81. }82. cout << (abtic() - tRecorder) << " using ptr<>() " << endl;83.#if ISSHOW84. imshow("Scaled Image: using ptr<>()", om);85. waitKey();86.#endif87.88.// 3. using iterator89. tRecorder = abtic();90. MatIterator_<Vec3b> it_im, itEnd_im;91. MatIterator_<Vec3b> it_om;92. it_im = im.begin<Vec3b>();93. itEnd_im = im.end<Vec3b>();94. it_om = om.begin<Vec3b>();95.for (; it_im != itEnd_im; it_im++, it_om++)96. {97. *it_om = (*it_im)*scale;98. }99. cout << (abtic() - tRecorder) << " using iterator " << endl; 100.#if ISSHOW101. imshow("Scaled Image: using iterator", om);102. waitKey();103.#endif104.105.// 4. using Mat_106. tRecorder = abtic();107. Mat_<Vec3b> im_, om_;108. im_ = im;109. om_ = om;110.for (int r = 0; r < im.rows; r++)111. {112.for (int c = 0; c < im.cols; c++)113. {114. om_(r,c) = im_(r,c) * scale;115. }116. }117. cout << (abtic() - tRecorder) << " using Mat_ " << endl; 118.#if ISSHOW119. imshow("Scaled Image: using Mat_", om);120. waitKey();121.#endif122.123.// 5. using *124. tRecorder = abtic();125. om = im*scale;126. cout << (abtic() - tRecorder) << " using * " << endl; 127.#if ISSHOW128. imshow("Scaled Image: using *", om);129. waitKey();130.#endif131.132.return 0;133.}如果你想使用第一部分提到的Makefile,你需要将代码段10保存成test.cpp,或者保存成你希望的某个名字,但是同时应该修改Makfile中的所有“test.cpp”。