OpenCV Mat

From C to C++

转:http://www.aishack.in/2010/07/opencvs-c-interface/

Since version 2.0 OpenCV introduced, in its new C++ API, the type cv::Mat, or simply Mat, to replace both C types CvMat and IplImage. Though both C structures are still supported, I’ll highly recommend that you shift to C++. Why?

Here’s why. Mat uniforms the concepts of matrix and image. In fact, they’re the same thing in the end! Mat also adds some nice features such as the reference counter, that can be a great help. It takes off the burden of micromanaging memory yourself.

Other than this, you get some clean looking code too. Code that just makes sense.

 

Introducing Mat

Before being able to use the C++ interface, you must “include” the OpenCV namespace. This is done by writing the following statement after the all #include statements:

using namespace cv;

If you don’t write this, you’ll have to use cv:: to get access to things in this namespace, like cv::Mat.

The new Mat type supports matrix algebra in a “Matlab” style, for instance:

Mat A=Mat(3,4,CV_32FC1);
Mat B=Mat(4,3,CV_32FC1);
...
//code for initialization of A and B
...
Mat C = 2*A*B;

Here C will be a Mat object representing a matrix of size 3×3, whose elements have been multiplied by the scalar (number) 2. This way of writing matrix algebra operations is much simpler and intuitive than using call to functions such as cvGEMM(…). And so it is inverting matrices using their method inv() or transposing them by using t().

Mat C = C.inv(); //Now C is its own inverse matrix
Mat D = A.t(); //D is the transposed matrix of A

This brief introduction should be enough to understand why it is convenient to learn the new C++ interface.

Internal structure

The Mat is the same as the old IplImage and CvMat structures. The “origin” is the top-left corner. Row and column numbers start from zero.

A C++ MatrixThe counter variable i varies from 0 to m-1. Similarly, the counter variable j varies from 0 to n-1.

Matrix declaration

A matrix can be built in various formats. Defining this format is necessary (unlike other languages like Matlab or Python). The matrix can have one, two, three or four channels.

The most simple way to create a matrix is:

Mat m = Mat(rows, cols, type);

The parameters are simple. rows and cols are the number of rows and columns in the matrix. type is the format of the matrix.

If you’re creating an image, a more intuitive method of creating a Mat is:

Mat m = Mat(Size(width,height), type);

And if you want to duplicate the size of another image, you can use:

Mat n = Mat(m.size(), type);

type defines the number of bytes allocated for each element in the matrix. Check 2D matrices with CvMat in OpenCV for constants you can use here. Yes, constants remain the same for the C and C++ interface.

Accessing elements

Accessing each pixel or element in a single channel Mat is trivial. You use the at method to access the value at a particular position (i, j).

Mat a= Mat(4,3, CV_32FC1);
float elem_a= a.at<float>(i,j); //access element aij, with i from 0 to rows-1 and j from 0 to cols-1

Instead of specifying the position with i and j, you can use a Point object:

Point p=Point(x,y);
float elem_a= a.at<float>(p); //Warning: y ranges from 0 to rows-1 and x from 0 to cols-1

If you’re dealing with a multi-channel Mat, things are a little more complex. But still easier than the CV_MAT_ELEM or CV_IMAGE_ELEM macros. You must use the ptr method to obtain a pointer to a particular row. Then you use the [] to access a particular pixel in a particular channel:

type elem = matrix.ptr<type>(i)[N<sub>c</sub>*j+c]

Here’s what everything means:

  • type: The datatype (float, int, uchar, etc)
  • i: The row you’re interested in
  • Nc: The number of channels
  • j: The column you’re interested in
  • c: The channel you’re interested in (varies from 0 to 3)

This could be done for single channel image too, but offset will be always 0 and Nc always 1.

Reshaping

Reshaping is playing around with the number of channels and the number of rows. Say we have a Nx1 matrix with Nc channels and we need to convert it into a NxNc matrix with 1 channel only. A simple reshape will help you accomplish this.

Mat a= Mat(4,1, CV_32FC3); //a is 4x1, 3 channels
Mat b=a.reshape(1); //b is 4x3, 1 channel

Where would this be useful? Suppose you have a list of Point objects… something like this:

vector<Point3f> v; //suppose it is already full

Suppose the list is already full with such points:

[(x0, y0, z0)]
[(x1, y1, z1)]
[(x2, y2, z2)]
[(x3, y3, z3)]
[(..., ..., ...)]

You can “import” this list a matrix like this:

Mat m1=Mat(v, true); //boolean value true is necessary in order to copy data from v to m1

If the boolean was not explicitly set to true, the matrix would only point to the list. It wouldn’t be a true copy (i.e., duplication of data in memory).

So m1 has some rows (equal to v.size() ), exactly one column and three channels. You can reshape this matrix into a matrix with v.size() rows, 3 columns and one channel.

The reshape operation

Now, you can use use this reshaped matrix in algebraic equations (see above). This is often necessary when dealing with homogeneous coordinates.

Some equivalents

Here’s a list of C code and its equivalent in C++. It should help you port your code from C to C++

  • CvSize -> Size
  • CvVideoCapture -> VideoCapture
  • IplImage, CvMat -> Mat
  • cvQueryFrame -> >> (operator)
  • cvShowImage -> imshow
  • cvLoadImage -> imread

You might want to check the previous post, Calibration and undistortions with the C++ interface. It takes you through a working example. And if you’ve got any more equivalents that might be helpful?Leave a comment and let me know!

Summary

Now you know a bit about how to get started with the C++ interface. It might take a little getting used to. But in the end, you’ll be in possession of a powerful API :P

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV中的Mat是一个多维数组,用于存储图像或其他类型的数据。它是OpenCV中最基本的数据结构之一。 Mat类提供了许多方法来操作和访问图像数据。你可以使用Mat对象加载、保存、修改和显示图像。它还提供了一些基本的数学运算,如加法、减法和乘法,以及一些高级图像处理功能,如滤波和边缘检测。 在使用Mat类之前,你需要包含OpenCV的头文件并链接对应的库。然后,你可以使用Mat对象来创建、读取和处理图像数据。例如,你可以使用Mat对象加载一张图像: ```cpp #include <opencv2/opencv.hpp> int main() { cv::Mat image = cv::imread("image.jpg", cv::IMREAD_COLOR); if (image.empty()) { std::cout << "Failed to load the image." << std::endl; return -1; } cv::imshow("Image", image); cv::waitKey(0); return 0; } ``` 这段代码将加载名为"image.jpg"的图像,并显示在一个窗口中。你可以使用Mat对象的其他方法来操作图像数据,如修改像素值、裁剪图像区域、调整图像大小等。 除了用于存储图像数据,Mat类还可以用于存储其他类型的多维数组。你可以使用构造函数或create()方法来创建指定类型和大小的Mat对象。例如,创建一个3x3的浮点型矩阵: ```cpp cv::Mat mat(3, 3, CV_32F); ``` 这样就创建了一个3x3的浮点型矩阵,可以用来存储和处理数值数据。 总之,OpenCVMat类是一个非常强大和灵活的数据结构,用于处理图像和其他类型的多维数据。它提供了许多方法和功能,让你能够方便地进行图像处理和计算机视觉任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值