[note] OpenCV+FFmpeg+Qt implements the OpenCV core type Mat of the video editor

Posted by jennatar on Mon, 06 Dec 2021 04:01:47 +0100

1, Source code analysis and space creation release

1.1 inline features

1.2 characteristics

The inline keyword must be placed with the function body definition. It has no effect in combination with the declaration.

1.2.1 difference of call overhead

The implementation is so simple that its consumption is even less than that of standard function calls, and its call instructions are relatively simple. If we need a large number of call functions at this time, it is accompanied by a large amount of instruction overhead; In view of this waste, developers with the serious idea of "every inch of land and every inch of money" designed the inline function, also known as the inline function.

The most important function of inline function is introduced for the function body whose function call cost is greater than the function instruction cost! In the compilation stage, the calling overhead is ignored and the code is expanded directly at the function, and the inline function will no longer generate function symbols!

1.2.2 code body differences

(1) In the debug version, inline is useless. It can only be used in the release version!
(2) Not all inline functions will be processed as inline functions by the compiler, such as recursion; The code body is too large to expand, or the code body is an insatiable bottomless hole and cannot be expanded;

1.3 Mat creation

1.3.1 construction method creation

inline
Mat::Mat(int _rows, int _cols, int _type)

for example

Mat mat(3000,4000,CV_8UC3);

1.3.2 Mat.Create()

inline
void Mat::create(int _rows, int _cols, int _type)

for example

Mat mat;
mat.create(3000,4000,CV_8UC1);

1.4 Mat release

1.4.1 release or destruct

The reference count is 1 before it is actually released

2, Traversing and modifying continuous Mat image space

2.1 traversing and modifying continuous OpenCV Mat image space

int main(int argc, char* argv) {
	Mat image(3000, 4000, CV_8UC3);

	int es = image.elemSize();
	int size = image.rows * image.cols * es;
	for (int i = 0; i < size; i += es) {
		image.data[i] = 255;//B
		image.data[i + 1] = 0;//G
		image.data[i + 2] = 0;//R
	}
	namedWindow("img");
	imshow("img", image);
	waitKey(0);
	return 0;
}

2.1.1 RGB storage mode (continuous)

Note: the first row and the second row are not stored consecutively, that is, the end of the first row is not the beginning of the second row, but some bytes may be empty for memory alignment.

2.2 judge whether it is continuous (iscontinues)

2.2.1 judge whether the storage space is continuous

2.2.2 record through steps

2.3 use opencv interface to realize the runtime function to analyze the execution time

int PrintMs(const char *text = "") 
{
	static long long last = 0;
	long long cur  = getTickCount();
	if (last == 0) {
		last = cur;
	}

	long long ms = ((double)(cur - last) / getTickFrequency()) *1000;

	if (*text != 0) {
		printf("%s = %d ms\n", text,ms);
	}

	return 0;
}

Optimization disabling takes 39ms
Optimized to maximize speed for 22ms

Note: the debug version needs to be set to maximize the speed:
1. Project attribute c/c + ± > optimize - > maximize speed
2.c/c + ± > General - > debugging information - program database (/ Zi)
3.c/c + + code generation - > Basic runtime check - > Default

2.4 traversing discontinuous OpenCV Mat space

	for (int row = 0; row < image.rows; row++) {
		for (int col = 0; col < image.cols; col++) {
			(&image.data[row*image.step])[col*es] = 0;//B
			(&image.data[row*image.step])[col*es + 1] = 0;//G
			(&image.data[row*image.step])[col*es + 2] = 0;//R
		}
	}

2.5 ptr template function traverses Mat and tests its performance

Compared with traversal access, ptr access is closer to direct address access

	for (int row = 0; row < image.rows; row++) {
		for (int col = 0; col < image.cols; col++) {
			Vec3b* c = image.ptr<Vec3b>(row, col);			
			c->val[0] = 0; //B
			c->val[1] = 255; //G
			c->val[2] = 0; //R
		}
	}

2.6 at function traverses Mat and catches exceptions

	try{
	    //Here, rows*2 is specially tested for exceptions
		for (int row = 0; row < image.rows *2; row++) {
			for (int col = 0; col < image.cols; col++) {
				Vec3b &m = image.at<Vec3b>(row, col);
				m.val[0] = 0; //B
				m.val[1] = 255; //G
				m.val[2] = 0; //R
			}
		}
	}
	catch (cv::Exception &ex) {
		std::cout << ex.what() << std::endl;
	}

Note: the Release version will not throw exceptions, only Debug will throw exceptions
reason: Solve the problem that try catch cannot catch errors in RELEASE version

2.7 iterator traverses Mat and summarizes traversal methods

	auto it = image.begin<Vec3b>();
	auto it_end = image.end<Vec3b>();
	for (; it != it_end; it++)
	{
		(*it).val[0] = 0;//B
		(*it).val[1] = 0;//G
		(*it).val[2] = 255;//R
	}

2.7.1 features

1> You can ignore the row, size and type of mat

2.8 summary traversal method

1> Direct access to data via address
2> By Ptr
3> Through at
4> Through iterator

2.9 QT custom opengl Widget drawing Mat

The source code address will not be pasted later

Topics: OpenCV Qt