My opencv Study Notes (24): detailed discussion of the data structure in opencv

Source: Internet
Author: User

Recently, I am writing my own algorithms, which are actually an improvement for some traditional algorithms. For more information about traditional algorithms, see opecv source code. While reading the source code, I gradually realized the power of opencv, not because it implements various algorithms, but because it designs basic data structures, others can easily use these data structures to implement their own algorithms. The help manual provides detailed descriptions of these data structures. Today I will serve the children who are not good at English and give a brief introduction to them.

First, we will introduce the two-dimensional point to point _, which is a template class. We can directly access data members X and Y. It not only sets +,-, = ,! = These four basic operations also define vertex multiplication, cross multiplication, and other operations. This class also provides the inside function to determine whether a vertex is in a rectangle. In addition, some other type conversion functions are defined, such as converting to a cvpoint of version 1.x.
For ease of use, opencv also defines common types:
Typedef point _ <int> point2i;
Typedef point2i point;
Typedef point _ <float> point2f;
Typedef point _ <double> point2d;

Similarly, point3_is a three-dimensional point (x, y, z. Its common types are:
Typedef point3 _ <int> point3i;
Typedef point3 _ <float> point3f;
Typedef point3 _ <double> point3d;

After the introduction, we can introduce the size. It is also a template class.
Typedef size _ <int> size2i;
Typedef size2i size;
Typedef size _ <float> size2f
The member variables that can be accessed by size are height and width. The area function is also defined to calculate the area. Other operations are basically type conversion functions.

Next we will introduce the rect _ template class. It is defined by the upper left corner and the length and width. In opecv, it is generally defined as left-open and right-closed intervals. Interestingly, this class also provides a rect + point function to offset the rectangle and a rect + size function, which remains unchanged in the upper left corner, resize the rectangle. Other operations include the intersection and Union of & and |, which are two rectangles.

In addition to the basic rectangle, opecv also provides a rotatedrect that can be rotated. It is determined by the center, length, and rotation angle. You can access these three members, or use the points function to return its four vertices and use boundingrect to find its external rectangle (non-rotating). The following is an example:

int main(void){Mat bg(200,200,CV_8UC3,Scalar(0));imshow("",bg);RotatedRect rRect(Point2f(100,100),Size(100,100),40); Point2f vertices[4];rRect.points(vertices);for(int i = 0; i < 4;++i)line(bg,vertices[i],vertices[(i+1)%4],Scalar(0,255,0));Rect brect = rRect.boundingRect();rectangle(bg,brect,Scalar(255,0,0));imshow("",bg);waitKey();return 0;}

The matx class is introduced below, which is also a template class used to record small rectangles. These rectangles are fixed in size before Compilation:
Typedef matx <float, 1, 2> matx12f;
Typedef matx <double, 1, 2> matx12d;
...
Typedef matx <float, 1, 6> matx16f;
Typedef matx <double, 1, 6> matx16d;
Typedef matx <float, 2, 1> matx21f;
Typedef matx <double, 2, 1> matx30d;
...
Typedef matx <float, 6, 1> matx61f;
Typedef matx <double, 6, 1> matx61d;
Typedef matx <float, 2, 2> matx22f;
Typedef matx <double, 2, 2> matx22d;
...
Typedef matx <float, 6, 6> matx66f;
Typedef matx <double, 6, 6> matx66d;

If you want to use flexible rectangles, use mat.

The following describes the VEC class, which is actually a vector with few elements.
Typedef VEC <uchar, 2> vec2b;
Typedef VEC <uchar, 3> vec3b;
Typedef VEC <uchar, 4> vec4b;
Typedef VEC <short, 2> vec2s;
Typedef VEC <short, 3> vec3s;
Typedef VEC <short, 4> vec4s;
Typedef VEC <int, 2> vec2i;
Typedef VEC <int, 3> vec3i;
Typedef VEC <int, 4> vec4i;
Typedef VEC <float, 2> vec2f;
Typedef VEC <float, 3> vec3f;
Typedef VEC <float, 4> vec4f;
Typedef VEC <float, 6> vec6f;
Typedef VEC <double, 2> vec2d;
Typedef VEC <double, 3> vec3d;
Typedef VEC <double, 4> vec4d;
Typedef VEC <double, 6> vec6d;
It supports addition, subtraction, multiplication, equality, inequality, and norm calculation.

The scalar _ class is actually derived from VEC <TP, 4>, that is, it is a 4-tuple: typedef scalar _ <double> scalar;
It is usually used to transmit pixels.

The range class is used to specify consecutive subsequences. For example, a part of the matrix is relatively simple. Let's look at the definition directly:

class CV_EXPORTS Range{public:    Range();    Range(int _start, int _end);    Range(const CvSlice& slice);    int size() const;    bool empty() const;    static Range all();    operator CvSlice() const;    int start, end;};

After talking about these simple types, let's look at a very important type; mat. MAT is a very important data structure in opencv. When I first started using it, I used it as a data structure for storing images, And then I understood it slowly, it not only stores two-dimensional Matrices, but also stores high-dimensional matrices, which are very common in pattern recognition and machine learning. For this type of problem, we do not need to manually allocate the memory, just use them directly. This class has a lot of content, but the help manual of opencv helps us sort out the content.
The core data member's data storage method has been discussed in the previous blog "My opencv Study Notes (23): How the actual data in mat is saved, here we only make a supplement, that is, multi-dimensional situations:

Int main (void) {int SZ [] = {4, 5, 6}; mat img (3, SZ, cv_8u); // 3-dimensional array cout 

We create a three-dimensional array with the length of each dimension being 4, 5, and 6, respectively. This can be obtained through size. Because each first-dimensional vector contains five second-dimensional arrays, and each second-dimensional array contains six third-dimensional arrays, each step of the first dimension is added, it is equivalent to moving the entire address 5*6. so step [0] is equal to 30.
Next we will mainly look at the functions provided by mat.
The first is constructor. There are many optical constructor types. Here we will introduce several common methods:
1. Use (nrows, ncols, type) to initialize a 2-dimensional matrix
// Create a 7*7 2-channel floating point matrix, which is usually used to represent the complex matrix
Mat M (7, 7, cv_32fc2, scalar (1, 3 ));
// Change to the 15-channel uchar matrix of 100*60. The original data will be released.
M. Create (100,60, cv_8uc (15 ));
Create a high-dimensional matrix
// Create a 3-dimensional matrix of 100*100*100
Int SZ [] = {100,100,100 };
Mat bigcube (3, SZ, cv_8u, scalar: All (0 ));

The following are some simple operations on the whole row and the whole column.
// 5th rows X 3 + 3rd rows. Such operations are common in linear algebra.
M. Row (3) = M. Row (3) + M. Row (5) * 3;

// Copy the 7th columns to the 1st Columns
// M. COL (1) = M. COL (7); // This cannot be written.
Mat M1 = M. COL (1 );
M. COL (7). copyto (M1 );

Use a part of the source image to create a new image
// Create a 320*240 image
Mat IMG (SIZE (320,240), cv_8uc3 );
// Select the region of interest
Mat ROI (IMG, rect (10, 10, 100,100 ));
// Change the region to green and the original image will be modified.
ROI = scalar (0,255, 0 );

B is the [1, 3) column of A. Modifying B will affect.

int main(void){Mat A = Mat::eye(5,5,CV_8U);Mat B = A(Range::all(),Range(1,3));B.setTo(100);for(int i = 0; i < 5;++i){for(int j = 0; j < 5;++j){cout<<(int)A.at<uchar>(i,j)<<endl;}}return 0;}

If deep copy is required, use the clone method.

There are other methods for initializing mat:
For example, Matlab zeros (), ones (), eye ():
M + = mat: Eye (M. Rows, M. cols, cv_64f );

Mat M = (MAT _ <double> (3, 3) <1, 0, 0, 0, 1, 0, 0, 0, 1 );

If you are processing "external" data, adding data to the constructor will easily convert the external data into the mat structure:

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);}double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};Mat M = Mat(3, 3, CV_64F, m).inv();

Specifically, for interaction with the iplimage structure in opencv1.x:

IplImage* img = cvLoadImage("greatwave.jpg", 1);Mat mtx(img); // convert IplImage* -> MatCvMat oldmat = mtx; // convert Mat -> CvMat

After all, we should discuss the element access methods for construction and initialization. In my previous blog, I also mentioned my opencv Study Notes (II ): operations per pixel are no longer repeated here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.