OpenCV-----Mat, Mat中插入一行可用push_back与vector类似

Mat是OpenCV中最为重要的属性。Mat的官方解释可以参看OpenCV的help文档。以下是Mat中一些重要的性质:

 

1.浅拷贝和深拷贝

OpenCV is an image processing library. It contains a large collection of image processing functions. To solve a computational challenge, most of the time you will end up using multiple functions of the library. Because of this, passing images to functions is a common practice. We should not forget that we are talking about image processing algorithms, which tend to be quite computationally heavy. The last thing we want to do is further decrease the speed of your program by making unnecessary copies of potentially large images.(大致意思为:OpenCV是一个图像处理的库。它包含了大量的图像处理函数。为了解决计算这一挑战,大多你会选择各种各样的函数而结束。正因为如此,将图片传递至函数是一个常见的步骤。我们应该注意到我们所讨论的是计算量将非常大的图像处理算子。最后一件事情是大图像没有必要的拷贝将会降低的程序的运行速率。)

To tackle this issue OpenCV uses a reference counting system. The idea is that each Mat object has its own header, however the matrix may be shared between two instance of them by having their matrix pointers point to the same address. Moreover, the copy operators will only copy the headers and the pointer to the large matrix, not the data itself.(大致译为:为了解决这一问题,OpenCV使用了“reference counting system”。每一个Mat对象都有自己的头,然而两个不同的头的Mat可能享用同一个矩阵内容。拷贝操作只是拷贝了头和指向数据矩阵的指针,自身数据内容没有被拷贝。)

 

1
2
3
4
5
6
Mat A, C;                                 // creates just the header parts
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we'll know the method used (allocate matrix)

Mat B(A);                                 // Use the copy constructor

C = A;                                    // Assignment operator

 

All the above objects, in the end, point to the same single data matrix. Their headers are different,however, and making a modification using any of them will affect all the other ones as well. (以上对于任意一个Mat的修改会影响其他所有的Mat,属于浅拷贝)In practice the different objects just provide different access method to the same underlying data. Nevertheless, their header parts are different. The real interesting part is that you can create headers which refer to only a subsection of the full data.(最为有趣的是你可以产生一个头指向一部分数据。) For example, to create a region of interest (ROI) in an image you just create a new header with the new boundaries:

1
2
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries

Now you may ask if the matrix itself may belong to multiple Mat objects who takes responsibility for cleaning it up when it’s no longer needed. The short answer is: the last object that used it. This is handled by using a reference counting mechanism. Whenever somebody copies a header of a Mat object, a counter is increased for the matrix. Whenever a header is cleaned this counter is decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy the matrix itself too, so OpenCV provides the clone() and copyTo() functions.

1
2
3
Mat F = A.clone();
Mat G;
A.copyTo(G);

Now modifying F or G will not affect the matrix pointed by the Mat header. What you need to remember from all this is that:

  • Output image allocation for OpenCV functions is automatic (unless specified otherwise).
  • You do not need to think about memory management with OpenCVs C++ interface.
  • The assignment operator and the copy constructor only copies the header.
  • The underlying matrix of an image may be copied using the clone() and copyTo() functions.

 

有一张经典的图解释浅拷贝和深拷贝如下:

浅拷贝与深拷贝运行时间:(一下例子中浅拷贝时间为0s,深拷贝为0.005s(取决于图片大小))

int main() 
{

	clock_t t1, t2, t3, t4;

	Mat srcImage = imread("C:/Users/SLJ/Desktop/pic7.bmp", 0);
    
	t1 = clock();
	Mat srcA(srcImage);
	t2 = clock();

	cout << "Mat srcA(srcImage)所花费的时间为: " << (double)(t2 - t1) / CLOCKS_PER_SEC << "s" <<endl;

	t3 = clock();
	Mat srcB = srcImage.clone();
	t4 = clock();

	cout << "Mat srcB = srcImage.clone()所花费的时间为: " << (double)(t4 - t3) / CLOCKS_PER_SEC << "s" <<endl;

	system("pause");


}


2.Mat支持每一行的插入,与vector容器类似,不需要实现知道rows的大小

     Mat支持每一行插入(Mat::push_back),这一点与vector类似,将一行Mat插入到另外 一个Mat我们只需要保证两者的cols是相同的。如Mat mean;表示Mat的一行,现需要重复多行将mean压缩至Mat descripTop(mean.cols,0)当中,我们不需要特意指出descripTop矩阵中的rows的大小,即不需要事先知道rows的大小:

     然后执行descripTop.push_back(mean);即可。

需要注意的是cols与rows都不需要初始化也可push_back

Mat m_mDescriptors_L;  // 行和列都不需要初始化
Mat curDes = m_mDescriptors.row(curIndex); // 提取的一行
m_mDescriptors_L.push_back(curDes);  // 将提取的一行压缩至m_mDescriptors_L中

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV-TBB 是 OpenCV 库的一个拓展,它使用了 Intel 的 TBB(Threading Building Blocks)库来实现多线程加速。相机标定是计算机视觉的一个重要问题,它的目的是确定相机的内部参数和外部参数,以便进行准确的三维重建和测量。在 OpenCV ,可以使用 calibrateCamera 函数来进行相机标定。使用 TBB 加速相机标定的方法如下: 1. 安装 TBB 库,可以从 Intel 的官网下载。 2. 在 OpenCV 使用 TBB 加速需要编译 OpenCV 库时开启 TBB 选项。 3. 在代码使用 TBB 的 parallel_for 函数来并行化计算。具体来说,可以将每一幅图片的标定任务分配给不同的线程进行计算,这样可以大大加快计算速度。 下面是一个简单的示例代码: ```cpp #include <opencv2/opencv.hpp> #include <opencv2/core/affine.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/calib3d.hpp> #include <tbb/tbb.h> using namespace std; using namespace cv; using namespace tbb; int main() { // 加载图片 vector<string> filenames; glob("*.jpg", filenames); vector<Mat> images; for (auto filename : filenames) { Mat image = imread(filename); images.push_back(image); } // 设置标定板参数 Size boardSize(6, 9); float squareSize = 1.0f; // 检测标定板角点 vector<vector<Point2f>> corners(images.size()); parallel_for(blocked_range<int>(0, images.size()), [&](const blocked_range<int>& range) { for (int i = range.begin(); i != range.end(); ++i) { Mat gray; cvtColor(images[i], gray, COLOR_BGR2GRAY); bool found = findChessboardCorners(gray, boardSize, corners[i]); if (found) { cornerSubPix(gray, corners[i], Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1)); } } }); // 设置标定板世界坐标系 vector<vector<Point3f>> objectPoints(1); for (int y = 0; y < boardSize.height; ++y) { for (int x = 0; x < boardSize.width; ++x) { objectPoints[0].push_back(Point3f(x * squareSize, y * squareSize, 0)); } } // 标定相机 Mat cameraMatrix, distCoeffs; vector<Mat> rvecs, tvecs; calibrateCamera(objectPoints, corners, images[0].size(), cameraMatrix, distCoeffs, rvecs, tvecs); return 0; } ``` 在这个代码,我们使用了 TBB 的 parallel_for 函数来并行化检测标定板角点的任务。由于每一幅图片的处理是相互独立的,因此可以将它们分配给不同的线程来计算。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值