【OpenCV】Mat 相关

本文介绍了OpenCV中Mat类的常用构造函数、遍历二维图像的方法、获取Header信息的技巧,包括判断Mat是否为空、获取数据类型和深度,以及矩阵操作如加减法、乘法、转置和求逆等。同时,还讨论了Mat与其他数据结构如IplImage、CvMat的转换。
摘要由CSDN通过智能技术生成

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 returns CV_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 的矩阵操作

Here

  • 矩阵加减法
  • 矩阵乘法
    • 矩阵乘法 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 是多通道图像或多维矩阵,则函数分别计算不同通道的均值与标准差
  • 矩阵全局极值及位置
  • 其他矩阵运算函数列表

Mat 与 IplImage, CvMat 等其他数据结构的相互转化

here


Ref

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值