博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OPENCV(2) —— Basic Structures(二)
阅读量:4918 次
发布时间:2019-06-11

本文共 6638 字,大约阅读时间需要 22 分钟。

Mat

OpenCV C++ n-dimensional dense array class

The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a SparseMat ).

 

The data layout of the array M is defined by the array M.step[], so that the address of element (i_0,...,i_{M.dims-1}), where 0\leq i_k<M.size[k], is computed as:

addr(M_{i_0,...,i_{M.dims-1}}) = M.data + M.step[0]*i_0 + M.step[1]*i_1 + ... + M.step[M.dims-1]*i_{M.dims-1}

In case of a 2-dimensional array, the above formula is reduced to:

addr(M_{i,j}) = M.data + M.step[0]*i + M.step[1]*j

 

Note that M.step[i] >= M.step[i+1] (in fact, M.step[i] >= M.step[i+1]*M.size[i+1] ). This means that 2-dimensional matrices are stored row-by-row, 3-dimensional matrices are stored plane-by-plane, and so on. M.step[M.dims-1] is minimal and always equal to the element size M.elemSize() .

 

There are many different ways to create a Mat object.

Use the create(nrows, ncols, type) method or the similar Mat(nrows, ncols, type[, fillValue]) constructor.

// make a 7x7 complex matrix filled with 1+3j.Mat M(7,7,CV_32FC2,Scalar(1,3));// and now turn M to a 100x60 15-channel 8-bit matrix.// The old content will be deallocatedM.create(100,60,CV_8UC(15));

As noted in the introduction to this chapter, create() allocates only a new array when the shape or type of the current array are different from the specified ones.

Create a multi-dimensional array:

// create a 100x100x100 8-bit arrayint sz[] = {
100, 100, 100};Mat bigCube(3, sz, CV_8U, Scalar::all(0));

It passes the number of dimensions =1 to the Mat constructor but the created array will be 2-dimensional with the number of columns set to 1. So, Mat::dims is always >= 2 (can also be 0 when the array is empty).

Construct a header for a part of another array. It can be a single row, single column, several rows, several columns, rectangular region in the array (called a minor in algebra) or a diagonal. Such operations are also O(1) because the new header references the same data. You can actually modify a part of the array using this feature, for example:

// add the 5-th row, multiplied by 3 to the 3rd rowM.row(3) = M.row(3) + M.row(5)*3;// now copy the 7-th column to the 1-st column// M.col(1) = M.col(7); // this will not workMat M1 = M.col(1);M.col(7).copyTo(M1);// create a new 320x240 imageMat img(Size(320,240),CV_8UC3);// select a ROIMat roi(img, Rect(10,10,100,100));// fill the ROI with (0,255,0) (which is green in RGB space);// the original 320x240 image will be modifiedroi = Scalar(0,255,0);

Due to the additional datastart and dataend members, it is possible to compute a relative sub-array position in the main container array using locateROI():

Mat A = Mat::eye(10, 10, CV_32S);// extracts A columns, 1 (inclusive) to 3 (exclusive).Mat B = A(Range::all(), Range(1, 3));// extracts B rows, 5 (inclusive) to 9 (exclusive).// that is, C ~ A(Range(5, 9), Range(1, 3))Mat C = B(Range(5, 9), Range::all());Size size; Point ofs;C.locateROI(size, ofs);// size will be (width=10,height=10) and the ofs will be (x=1, y=5)

 

Make a header for user-allocated data. It can be useful to do the following:

Process “foreign” data using OpenCV (for example, when you implement a DirectShow* filter or a processing module for gstreamer, and so on). For example:

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);}

Quickly initialize small matrices and/or get a super-fast element access.

double m[3][3] = {
{a, b, c}, {d, e, f}, {g, h, i}};Mat M = Mat(3, 3, CV_64F, m).inv();

 

Partial yet very common cases of this user-allocated data case are conversions from CvMat and IplImage to Mat. For this purpose, there are special constructors taking pointers to CvMat or IplImage and the optional flag indicating whether to copy the data or not.

Backward conversion from Mat to CvMat or IplImage is provided via cast operators Mat::operator CvMat()const and Mat::operator IplImage(). The operators do NOT copy the data.

IplImage* img = cvLoadImage("greatwave.jpg", 1);Mat mtx(img); // convert IplImage* -> MatCvMat oldmat = mtx; // convert Mat -> CvMatCV_Assert(oldmat.cols == img->width && oldmat.rows == img->height &&    oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep);

 

Use MATLAB-style array initializers, zeros(), ones(), eye(), for example:

// create a double-precision identity martix and add it to M.M += Mat::eye(M.rows, M.cols, CV_64F);

 

 

Use a comma-separated initializer:

// create a 3x3 double-precision identity matrixMat M = (Mat_
(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);

 

// compute sum of positive matrix elements// (assuming that M isa double-precision matrix)double sum=0;for(int i = 0; i < M.rows; i++){    const double* Mi = M.ptr
(i); for(int j = 0; j < M.cols; j++) sum += std::max(Mi[j], 0.);}

 

// compute the sum of positive matrix elements, optimized variantdouble 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
(i); for(int j = 0; j < cols; j++) sum += std::max(Mi[j], 0.);}

 

// compute sum of positive matrix elements, iterator-based variantdouble sum=0;MatConstIterator_
it = M.begin
(), it_end = M.end
();for(; it != it_end; ++it) sum += std::max(*it, 0.);

 

Mat::row

Creates a matrix header for the specified matrix row.

The method makes a new header for the specified matrix row and returns it. This is an O(1) operation, regardless of the matrix size. The underlying data of the new matrix is shared with the original matrix.

Mat::rowRange

Creates a matrix header for the specified row span.

The method makes a new header for the specified row span of the matrix. Similarly to and , this is an O(1) operation.

Mat::copyTo

Copies the matrix to another one.

The method copies the matrix data to another matrix. Before copying the data, the method invokes

m.create(this->size(), this->type());

so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the function does not handle the case of a partial overlap between the source and the destination matrices.

When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, the newly allocated matrix is initialized with all zeros before copying the data.

 

 

Mat 类的熟悉程度决定着对OpenCV的操纵能力,必须花时间掌握好~~

转载于:https://www.cnblogs.com/sprint1989/p/4058556.html

你可能感兴趣的文章
文本处理方法概述
查看>>
homework3
查看>>
剑指前端(前端入门笔记系列)——Math对象
查看>>
spark学习之IDEA配置spark并wordcount提交集群
查看>>
flask seesion组件
查看>>
gprof—使用记录之自以为是优化
查看>>
Table被web编程弃用的原因
查看>>
Spring之<context:property-placeholder location="classpath:... "/>标签路径问题
查看>>
Windows API 之 FineFirstFile、FindNextFile
查看>>
C# 中两个DataTable join 连接
查看>>
杭电ACM 2046 阿牛的EOF牛肉串
查看>>
iOS的TCP/IP协议族剖析&&Socket
查看>>
C#中的NULL的初步理解
查看>>
cssText批量修改样式
查看>>
基于jQuery的俄罗斯方块
查看>>
爬取知乎热榜标题和连接 (python,requests,xpath)
查看>>
python多线程和多进程(二)
查看>>
Core Audio 在Vista/Win7上实现
查看>>
BZOJ 4318 OSU! 概率+递推
查看>>
以操作系统的角度述说线程与进程
查看>>