主要是依靠 copyTo()
方法实现图像的传递。
copyTo
- 内存分配:当源图像和目标图像
size
和type
一致时,不会分配新内存;否则先申请新内存空间再拷贝 - 目标图像:可以将数据复制到指定的目标图像中,目标图像可以是已经存在的图像或者新图像。
- MASK:通过MASK可以指定ROI
clone
- 内存分配:分配新的内存,创建一个和原始图像完全相同的图像,是深拷贝(完全创建一整套新的Mat对象,包括矩阵头和数据空间)
- 目标图像:新创建的目标图像。即使源图像被释放或者修改,目标图像不受影响
- MASK:不可指定MASK,会复制整个图像
直接'='赋值(重载)
- 内存分配:仅是创建了源图像的头部分,源图像和目标图像共享数据区,是浅拷贝(创建了新的矩阵头,内存仍然指向原来的数据空间)
- 目标图像:创建一个新的图像头,与源图像共享数据。
- MASK:不可指定MASK,会复制整个图像
'()'复制(拷贝构造函数),如 cv::Mat dstImage(srcImage);
同上
代码
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <thread>
#define WIDTH 640
#define HEIGHT 480
cv::Mat res(HEIGHT * 2, WIDTH * 2, CV_8UC3, cv::Scalar(0,0,0));
void cameraThread(int camID,cv::Rect roi){
cv::VideoCapture cap(camID);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, HEIGHT);
cap.set(cv::CAP_PROP_FRAME_WIDTH, WIDTH);
cv::Mat frame;
if(!cap.isOpened()){
std::cerr << "Camera " << camID << "is not opened" << std::endl;
}
while (true){
cap >> frame;
if (frame.empty()) {
std::cerr << "Camera " << camID << "can't read frame" << std::endl;
break;
}
if(roi.x + roi.width > res.cols || roi.y + roi.height > res.rows){
std::cerr << "ROI out of range" << std::endl;
break;
}
frame.copyTo(res(roi));
// cv::imshow(std::to_string(camID),frame);
// cv::waitKey(30);
}
}
void showRes(cv::Mat resFrame){
while(true){
cv::imshow("4in1",resFrame);
if(cv::waitKey(10) == 'q'){
break;
}
}
}
int main() {
cv::Rect roi0(0,0,WIDTH,HEIGHT);
cv::Rect roi1(WIDTH,0,WIDTH,HEIGHT);
cv::Rect roi2(0,HEIGHT,WIDTH,HEIGHT);
cv::Rect roi3(WIDTH,HEIGHT,WIDTH,HEIGHT);
std::thread cap0(cameraThread,0,roi0);
std::thread cap1(cameraThread,2,roi1);
std::thread result(showRes,res);
cap0.join();
cap1.join();
result.join();
return 0;
}