OpenCV algorithm (1)--Basic image container mat

Source: Internet
Author: User
Tags constructor data structures image processing library scalar
Purpose

There are many ways to get digital images from the real world, such as digital cameras, scanners, CT, or magnetic resonance imaging. Either way, we (humans) see the image, and when the digital device "sees" it, it is recording the value of each point in the image.

For example, in the image above, you see only a matrix in the marked mirror area, which contains the intensity values of all the pixels. How to obtain and store these pixel values is determined by our needs, and ultimately all images in the computer world can be simplified to a numerical moment and matrix information. As a computer vision library, the main purpose of OpenCV is to obtain more advanced information by processing and manipulating this information. So, OpenCV how to store and manipulate images is the first thing you need to learn. Mat

When it first appeared in 2001, OpenCV was built on the C language interface. In order to store images in memory, a C language structure named Iplimage was used, and today this still appears in most of the older tutorials and teaching materials. But this approach must accept all the deficiencies of the C language, the largest of which is manual memory management, based on the user's responsibility for opening up and destroying the memory. While it's not a problem to manually manage memory for a small program, once the code starts getting bigger and larger, you need to get more and more entangled in the problem rather than focusing on your development goals.

Fortunately, C + + appears, and brings up the concept of class, which gives the user another option: Automatic memory management (not strictly speaking). This is good news, if C + + is fully compatible with C, this change will not lead to compatibility issues. To this end, OpenCV introduced a new C + + interface in version 2.0, using automatic memory management to give a new way to solve the problem. With this approach, you don't have to tangle with managing memory, and your code will be concise (much less written). However, the only disadvantage of the C + + interface is that many embedded development systems support only C language. So, it's not necessary to use the old method when the target is not the development platform (unless you're a trouble-free masochistic farmer).

The first thing you need to know about Mat is that you don't have to manually (1) open up space for it (2) to release the space immediately when you don't need it. But it's still possible to do it manually: most OPENCV functions will still manually open up space for the output data. When passing an existing Mat object, the well-established matrix space is reused. In other words, we use the exact size of the memory each time to complete the task.

Basically, Mat is a class consisting of two data parts: a matrix header (containing information such as matrix size, storage method, storage address, etc.) and a pointer to a matrix that stores all the pixel values (depending on the different matrices of the selected storage method). The size of the matrix head is a constant value, but the size of the matrix itself varies according to the image and is usually a number of orders of magnitude larger than the size of the matrix head. Therefore, when you pass an image in a program and create a copy, the large overhead is caused by the matrix, not the information header. OpenCV is an image processing library that includes a large number of image processing functions, and in order to solve the problem it is common to use multiple functions in the library, so passing images in a function is commonplace. And don't forget that we're talking about a computationally significant image processing algorithm, so we shouldn't copy large images unless we have to, because it slows down the program.

To solve this problem, OpenCV uses a reference counting mechanism. The idea is to have each Mat object have its own information header, but share the same matrix. This is accomplished by pointing the matrix pointer to the same address. The copy constructor copies only the information header and matrix pointers , not the matrix.


Mat A, C;                                 Create only the Information header section
A = Imread (argv[1], cv_load_image_color);//here for the Matrix Open memory

Mat B (A);                                 Use copy constructor

C = A;                                    Assignment operators
All the mat objects in the above code end up pointing to the same and only one data matrix. Although their information headers are different, changes made by any one object can affect other objects as well. In fact, different objects are just different ways to access the same data. Here's a great feature to mention: You can create information headers that reference only part of the data. For example, to create an area of interest (ROI), you only need to create an information header that contains the boundary information:

Mat D (A, Rect (10, 10, 100, 100)); Use matrix
Mat E = A (Range:all (), Range (1,3));//Use the boundary of a row or column

Now you might ask, if the matrix belongs to more than one Mat object, who will be responsible for cleanup when it is no longer needed. The simple answer is: The last object to use it. Implemented by a reference counting mechanism. Whenever someone copies the information header of a Mat object, it increases the number of references to the matrix, whereas when a header is released, the count is reduced by one; When the count is zero, the matrix is cleared. But at some point you still want to copy the matrix itself (not just information headers and matrix pointers), you can use the function clone () or CopyTo ().

Mat F = A.clone ();
Mat G;
A.copyto (G);

Changing F or G now does not affect the matrix that the Mat information header points to. To summarize, what you need to remember is that
The memory allocation for the output image in the OPENCV function is automatic (if not specifically specified). There is no need to consider memory deallocation when using OpenCV's C + + interface. Assignment operators and copy Constructors (ctor) copy only information headers. Use the function clone () or CopyTo () to copy the matrix of a pair of images. Storage Methods

This describes how to store pixel values. You need to specify a color space and data type. Color space refers to a given color, how the color element is combined to encode it. The simplest color space is a grayscale space, dealing only with black and white, and combining them can produce varying degrees of gray.

There are more kinds of color space for color, but either way, the color is divided into three or four base elements, and all colors can be produced by combining the base elements. The RGB color space is one of the most commonly used color spaces, thanks to the way it also forms the color inside the human eye. Its base color is red, green, and blue, and sometimes the fourth element, Alpha (a), is added to indicate transparent colors.

There are a lot of color systems, each has its own advantages: RGB is the most common, this is because the human eye with similar working mechanism, it is also shown by the device. HSV and HLS break down colors into shades, saturation, and lightness/lightness. This is a more natural way of describing colors, such as the ability to discard the last element to make the algorithm insensitive to the lighting conditions of the input image. YCRCB is widely used in JPEG image formats. The CIE l*a*b* is a color space that is evenly sensed, and it is suitable for measuring distances between two colors.

Each constituent element has its own definition field, depending on its data type. How to store an element determines the precision that we can control on its defined domain. The smallest data type is char, which takes one byte or 8 bits, which can be signed (between 0 and 255) or unsigned (-127 to +127). Although using three char elements can already represent 16 million possible colors (using RGB color space), using float (4-byte, 32-bit) or double (8-byte, 64-bit) can give finer color resolution. However, it is also necessary to remember that increasing the size of an element also increases the amount of memory space that the image occupies. to create a Mat object explicitly

Tutorial read, modify, save the image has been explained how to use the function imwrite () to write a matrix to the image file. But in order to debug, the more convenient way is to look at the actual value. You can do this by using the Mat operator <<, but keep in mind that this is only valid for two-dimensional matrices. Mat is not only a great image container class, it is also a common matrix class, so it can be used to create and manipulate multidimensional matrices. There are several ways to create a mat object:

Mat () constructor

    Mat M (2,2, CV_8UC3, Scalar (0,0,255)); 
    cout << "m =" << Endl << "" << M << endl << Endl;   


For a two-dimensional multichannel image, first define its size, number of rows and number of columns.

Then, you specify the data type of the storage element and the number of channels for each matrix point. For this reason, there are many definitions based on the following rules

    Mat M (2,2, CV_8UC3, Scalar (0,0,255)); 
    cout << "m =" << Endl << "" << M << endl << Endl;   


For example, CV_8UC3 represents the use of a 8-bit unsigned char type, each pixel consisting of three elements three channels. The number of pre-defined channels can be as many as four. Scalar is a short type of vector. Specifies that the matrix can be initialized with the specified custom value. Of course, if you need more channel numbers, you can use uppercase macros and put the number of channels in parentheses, as shown below

Class in c\c++ by constructor function

int sz[3] = {2,2,2}; 
 Mat L (3,sz, Cv_8uc (1), Scalar::all (0));

The above example shows how to create a matrix over two dimensions: Specify the dimension, and then pass a pointer to an array that contains the dimensions of each dimension;

Create an information header for an existing iplimage pointer:

iplimage* img = cvloadimage ("Greatwave.png", 1);
Mat MTX (IMG); Convert iplimage*-Mat

Create () Function: Functions

    M.create (bis, CV_8UC (2));
    cout << "m =" << Endl << ""  << M << endl << Endl;


This creation method cannot set an initial value for the matrix, it simply re-opens the memory for the matrix data when resizing.

mode of initialization in MATLAB: Zeros (), ones (),: Eyes (). Specify the dimensions and data types using the following methods:

Mat E = Mat::eye (4, 4, cv_64f);    
    cout << "e =" << Endl << "" << E << endl << Endl;
    
    Mat O = Mat::ones (2, 2, cv_32f);    
    cout << "o =" << endl << "" << O << endl << Endl;

    Mat Z = Mat::zeros (3,3, CV_8UC1);
    cout << "z =" << endl << "" << Z << endl << Endl;

For small matrices You can use a comma-separated initialization function:

Mat C = (mat_<double> (3,3) << 0,-1, 0,-1, 5,-1, 0,-1, 0); 
    cout << "c =" << Endl << "" << C << endl << Endl;

Use Clone () or CopyTo () to create a new information header for an existing Mat object.

Mat Rowclone = C.row (1). Clone ();
cout << "Rowclone =" << endl << "<< rowclone << endl << Endl;
Format Print

Note

Calling function Randu () to fill a matrix with random numbers requires specifying the upper and lower bounds of the random number:

Mat R = Mat (3, 2, CV_8UC3);
Randu (R, Scalar::all (0), Scalar::all (255));


In addition to the default format shown in the example above, OPENCV also supports the following output habits

Default mode

cout << "R (Default) =" << Endl <<        R           << endl << Endl;

Python

cout << "R (python)  =" << endl << format (R, "Python") << Endl << Endl;

Comma-separated values (CSV)

cout << "R (CSV)     =" << endl << format (R, "CSV"   ) << Endl << Endl;

Numpy

cout << "R (numpy)   =" << endl << format (R, "NumPy") << Endl << Endl;

C language

cout << "R (c)       =" << endl << format (R, "C"     ) << Endl << Endl;
print other common items

OPENCV supports the use of operators << to print other commonly used OPENCV data structures.

2-dimensional point

POINT2F P (5, 1);
    cout << "point (2D) =" << P << endl << Endl;

3-dimensional point

point3f p3f (2, 6, 7);
    cout << "point (3D) =" << p3f << endl << Endl;

Std::vector based on the Cv::mat

Vector<float> v;
    V.push_back ((float) cv_pi);   V.push_back (2);    V.push_back (3.01f);
    
    cout << "Vector of floats via Mat =" << Mat (v) << Endl << Endl;

Std::vector Point

Vector<point2f> vpoints ();
    for (size_t E = 0; E < Vpoints.size (); ++e)
        Vpoints[e] = point2f ((float) (E * 5), (float) (e% 7));

    cout << "A vector of 2D Points =" << vpoints << endl << Endl;

Most of the examples here are in a short console application that you can download here or find in the C + + sample section.



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.