Backto OpenCV Index
文章目录
在 OpenCV 2.x 中, Mat 是最核心的数据结构,
n-dimensional dense array class
. Mat 分为两个部分, 一个是 header, 定义了Mat 的维度, 存储的数据类型等, 另一个是 body, 是实实在在的存储数据的地方. Mat 中的数据是 row-by-row 存储的, 和大多数编程语言的习惯一样, 但是和 Matlab 中 col-by-col 的存储方式正好相反.
常用构造函数
基本的构造函数格式是, Mat(nrows, ncols, type[, fillValue])
, 为了方便不同的场景, Mat 定义了超多的构造函数, 其中最常用的是下面几个
/// consturct directly
// make a 7x7 complex matrix filled with 1+3i.
Mat M(7,7,CV_32FC2,Scalar(1,3));
/// use the creat
// and now turn M to a 100x60 15-channel 8-bit matrix.
// The old content will be deallocated
M.create(100,60,CV_8UC(15));
/// Pass dimensions by array
// create a 100x100x100 8-bit array
int sz[] = {100, 100, 100};
Mat bigCube(3, sz, CV_8U, Scalar::all(0));
/// Use copy(), clone(), roi
// add the 5-th row, multiplied by 3 to the 3rd row
M.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 work
Mat M1 = M.col(1);
M.col(7).copyTo(M1);
// create a new 320x240 image
Mat img(Size(320,240),CV_8UC3);
// select a ROI
Mat 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 modified
roi = Scalar(0,255,0);
/// Create Mat with C-style image pointer
// from const uchar*
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);
}
// from IplImage
Ptr<IplImage> iplimg(cvLoadImage(imagename.c_str()));
if(!iplimg)
{
fprintf(stderr, "Can not load image %s\n", imagename.c_str());
return -1;
}
// cv::Mat replaces the CvMat and IplImage, but it's easy to convert
// between the old and the new data structures (by default, only the header
// is converted, while the data is shared)
Mat img = cv::cvarrToMat(iplimg);
/// Quickly initialize small matrices
// using Array
double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
Mat M = Mat(3, 3, CV_64F, m).inv();
// using a comma-separated initializer:
// create a 3x3 double-precision identity matrix
Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
遍历二维图像 Mat
在 OpenCV 中,Mat 数据是按 行存储的,所以的读写 Mat 格子数据的下标顺序是先y 后 x,这和 OpenCV 中点的坐标 Point(x,y) 是相反的。
element-wise operation
// single dot Mij
M.at<double>(i,j) += 1.f;
// process row-by-row
// 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<double>(i);
for(int j = 0; j < M.cols; j++)
sum += std::max(Mi[j], 0.);
}
// iterator the whole image, if the image is continuous, reduce the loop-cost
// compute the sum of positive matrix elements, optimized variant
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.);
}
STL-style iterators(smart enough to skip gaps between successive rows
and can be passed to any STL algo, including std::sort())
// compute sum of positive matrix elements, iterator-based variant
double sum=0;
MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>();
for(; it != it_end; ++it)
sum += std::max(*it, 0.);
// copy color bgr pixel
src_img.at<cv::Vec3b>(i, j)[0] = dst_img.at<cv::Vec3b>(m, n)[0];
src_img.at<cv::Vec3b>(i, j)[1] = dst_img.at<cv::Vec3b>(m, n)[1];
src_img.at<cv::Vec3b>(i, j)[2] = dst_img.at<cv::Vec3b>(m, n)[2];
Mat 的 Header 信息获取
判断 Mat 是否为空(图像读取失败等)
bool cv::Mat::empty ( ) const
Returns true if the array has no elements.(if Mat::total() is 0 or if Mat::data is NULL.)
返回 Mat 的数据类型 (CV_8UC3 等)
-
int cv::Mat::type() const
Returns the type of a matrix element.The method returns a matrix element type. This is an identifier compatible with the CvMat type system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
返回 Mat 的数据类型深度 (CV_8U 等)
int cv::Mat::depth() const
Returns the depth of a matrix element.
The method returns the identifier of the matrix element depth (the type of each individual channel). For example, for a 16-bit signed element array, the method returnsCV_16S
注意和上面type()
的区别,type()
返回的是 Mat 中基本元素的数据类型, 而这里depth()
返回的则是单个通道中数据类型所占的 bits 数. 详见, opencv type() 和 depth()
返回 Mat 的元素个数 (图像中的像素数 等)
size_t cv::Mat::total () const
Returns the total number of array elements.(a number of pixels if the array represents an image).
Mat 的矩阵操作
- 矩阵加减法
- 矩阵乘法
- 矩阵乘法
C = A * B
, A , B, C 均为矩阵 - 矩阵点乘
d = A.dot(B)
, A,B 为同size矩阵,展开为向量,进行点乘操作,返回double 值 d。若 Mat 是多通道的,则结果是各通道的点积和。 - 矩阵对应元素相乘
C = A.mul(B)
, A,B,C为同size矩阵, A , B 对应元素相乘为C中的值。注意C中的精度若不够,可能溢出,溢出的值为当前精度下的最大值。
- 矩阵乘法
- 矩阵转置
M.t()
- 矩阵求逆
M.inv()
- 矩阵非零元素个数
int n = countNonZero(M)
- 矩阵均值与标准差
meanStdDev(M,Mean,Stddev)
若 M 是多通道图像或多维矩阵,则函数分别计算不同通道的均值与标准差 - 矩阵全局极值及位置
- 其他矩阵运算函数列表