Opencv-C++ Notes (1): Opencv Data Structure

1. OPNECV elements

1.CvPoint

For ease of use, opencv defines commonly used types:

typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;

In the same way, there is Point3_, but it is a 3-dimensional point (x, y, z). Its common types are:

typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;

2. Template class

Size template class

The member variables that can be accessed are height and width. The area function is also defined to find the area. Other operations are basically type conversion functions.

typedef Size_<int> Size2i;
typedef Size2i Size;
typedef Size_<float> Size2f

Rect template class

. It is defined by top left point and length, width. In opecv, it is generally defined as a left-open and right-closed interval.

Interestingly, this class also provides a Rect+Point function, which is used to offset the rectangle, and a Rect Size function, which re-adjusts the size of the rectangle while keeping the upper left corner unchanged. Other operations include AND & and |, which is to find the intersection and union of two rectangles

RotatedRect template class

In addition to the basic rectangle, opecv also provides a rotating rectangle RotatedRect, which is determined by the center, variable length, and rotation angle. You can access these three members, or use the points function to return its 4 vertices, and use boundingRect to find its circumscribed rectangle (non-rotation). Here 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();
	}

2. MAT

Mat. Mat is a very important data structure in opencv. When I first started using it, I just regarded it as a data structure for storing images. Later, I gradually understood that it can not only store two-dimensional matrices, but also store high-dimensional Matrix, which is very commonly used in pattern recognition and machine learning. For this type of problem, we don't need to manually allocate memory ourselves, just use them directly. This class has a lot of content, but the opencv help manual helps us sort out the content very well.

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> Matx21d;
...
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 a flexible rectangle, use Mat

int main(void)
{
    
    
	int sz[]={
    
    4,5,6};
	Mat img(3,sz,CV_8U);//3维数组
	cout<<img.dims<<endl;
	cout<<img.size[0]<<endl;
	cout<<img.size[1]<<endl;
	cout<<img.size[2]<<endl;
 
	cout<<img.step[0]<<endl;
	cout<<img.step[1]<<endl;
	cout<<img.step[2]<<endl;
	//遍历每个元素
	for(int i = 0; i < 4;++i)
	{
    
    
		for(int j = 0; j < 5;++j)
		{
    
    
			for(int k = 0; k < 6;++k)
			{
    
    
				cout<<(int)*(B.data + B.step[0]*i + B.step[1]*j + B.step[2]*k)<<endl;
			}
		}
	}
	return 0;
}

Below we mainly look at the functions provided by Mat.
The first is the constructor. There are many kinds of light constructors. Here are a few commonly used methods:

1. Use (nrows, ncols, type) to initialize a 2-dimensional matrix

// 创建一个7*7的2通道浮点矩阵,通常这样的矩阵用来表示复矩阵
Mat M(7,7,CV_32FC2,Scalar(1,3));
//改变为100*60的15通道uchar矩阵,原先的数据将会被释放
M.create(100,60,CV_8UC(15));
创建高维矩阵
//创建100*100*100的3维矩阵
int sz[] = {
    
    100, 100, 100};
Mat bigCube(3, sz, CV_8U, Scalar::all(0));
下面是一些简单的对整行、整列的操作
// 第5行*3 + 第3行,这样的操作在线性代数中很常见
M.row(3) = M.row(3) + M.row(5)*3;

// 把第7列拷贝到第1列
// M.col(1) = M.col(7); // 不能这样写
Mat M1 = M.col(1);
M.col(7).copyTo(M1);
用源图像的一部分创建新图像
// 创建一个320*240的图像
Mat img(Size(320,240),CV_8UC3);
// 选择感兴趣区域
Mat roi(img, Rect(10,10,100,100));
// 将区域改为绿色,原图像也会发生修改
roi = Scalar(0,255,0);
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 a deep copy is required, use the clone method.

For initializing Mat, there are other methods: such as Matlab-style zeros(), ones(), eye(): M +=
Mat::eye(M.rows, M.cols, CV_64F);

Mat M = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);

If you are dealing with "foreign" data, then adding data to the constructor will be very convenient to convert the foreign data into a 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();
特别的,对于与opencv1.X中的IplImage结构的交互:
IplImage* img = cvLoadImage("greatwave.jpg", 1);
Mat mtx(img); // convert IplImage* -> Mat
CvMat oldmat = mtx; // convert Mat -> CvMat

Read in the picture image and associate the image with the result. An important feature of OpenCV is that you do not need to specify the length, width, pixel depth and other information of the image in advance, the library function will automatically complete it for you. Then filter the image image and display the result of the filtered result image (note: not the result of image).

For the image result, the program provides 3 ways to associate with the image image: the first is to use "=", the second is to use copyTo, and the third is to use clone. Run the code and you can find that: when using "=", filtering the image will cause the image of the result to change; and using clone or copyTo will not cause the change of the result.

what is the reason? Because when using "=", the new data is not copied, but the result is only pointed to the image. They point to the same data in memory. After the equal sign operation, the reference count of the image is +1. This is the so-called "shallow copy". And copyTo is to re-copy each element of the matrix to result. copyTo not only copies the matrix element values, but also copies some other information of the matrix. They are so-called "deep copies".

Three, Vec class

The following introduces the Vec class, which is actually a vector with fewer 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 operations such as addition, subtraction, multiplication, equality, inequality, and norm.
The Scalar_ class is actually derived from Vec<tp,4>, that is, it is a 4-tuple:
typedef Scalar_Scalar; He is usually used to transfer pixels.
The Range class is used to specify contiguous subsequences. For example, part of the matrix is ​​relatively simple, let's look directly at the definition:

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;
    };

Guess you like

Origin blog.csdn.net/jiyanghao19/article/details/130886714