OpenCV C++学习笔记(2): Mat数据结构
opencv用了一种Mat的矩阵来存储图像数据, Mat看起来很神秘, 尤其是在处理图片局部的时候, 很神秘, 我一直想把两个摄像头拍摄的画面合并到一张图上显示, 查了很多, 才大概弄明白一点.
Mat
图像数据都是存储在矩阵里的, 或者说是二维数组, OpenCV中封装在Mat里.
Mat里可以装一张图, 也可以装视频中的一帧.
初始化一个Mat:
Mat two_cap=Mat::zeros(Size(frame_width*2,frame_height), CV_8UC3);
- 语法和matlab里的zeros初始化差不多, 虽然还有其他的初始化方式, 但一开始就赋上初始值, 把0都填上还是好习惯,
- 用
Size(宽, 高)
来定义比较容易按图片来理解, 否则row和col每次搞得我很晕, 横竖经常分不清楚. -
CV_8UC3
是最常用的0-255整数, 三种颜色.
ROI
感兴趣区域, 最简单的是矩形区域:
Rect r1 = Rect(0,0,frame_width,frame_height);
Rect r2 = Rect(frame_width, 0, frame_width, frame_height);
定义了感兴趣区以后, 就可以直接调用这一块位置, 有点类似于数组的切片.
这时候, Mat作为左值也可以, 作为右值也可以.
比如可以
two_cap(r1)=0;
也可以
Mat frame=two_cap(r1)
但是!
Mat在复制的时候是浅复制,
mat_target(r1)=mat_source;
mat_target里面并没有好好被mat_source中的数据替换. 要达成目的, 应该使用copyTo,
mat_source.copyTo(mat_target(r1))
demo
以下是照着各种demo简单写的一个双摄像头显示, 本来是想写个简单的video see through, usb摄像头的延时居然达到了200ms, copyTo的速度不影响, 可能是OpenCV里套了太多GUI的锅, 也可能是硬件的问题.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// OpenCV includes
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
using namespace cv;
int main( int argc, const char** argv )
{
int frame_width=640;
int frame_height=480;
VideoCapture capA(1), capB(2);
if (capA.isOpened() == false || capB.isOpened() == false)
{
cout << "Cannot open the video cameras" << endl;
cin.get(); //wait for any key press
return -1;
}
capA.set(CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
capB.set(CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
capA.set(CAP_PROP_FPS, 30);
capA.set(CAP_PROP_FRAME_WIDTH,frame_width);
capA.set(CAP_PROP_FRAME_HEIGHT,frame_height);
capB.set(CAP_PROP_FPS, 30);
capB.set(CAP_PROP_FRAME_WIDTH,frame_width);
capB.set(CAP_PROP_FRAME_HEIGHT,frame_height);
Mat two_cap=Mat::zeros(Size(frame_width*2,frame_height), CV_8UC3);
Rect r1 = Rect(0,0,frame_width,frame_height);
Rect r2 = Rect(frame_width, 0, frame_width, frame_height);
string window_name="double webcam";
namedWindow(window_name);
Mat frameA;
Mat frameB;
while (true)
{
// read frame from webcam
bool bASuccess = capA.read(frameA);
bool bBSuccess = capB.read(frameB);
//Breaking the while loop if the frames cannot be captured
if (bASuccess == false || bBSuccess == false )
{
cout << "Video cameras are disconnected" << endl;
cin.get(); //Wait for any key press
break;
}
//show the frame in the created window
frameA.copyTo(two_cap(r1));
frameB.copyTo(two_cap(r2));
imshow(window_name, two_cap);
if (waitKey(1) == 27)
{
cout << "Esc key is pressed by user. Stop the video" << endl;
break;
}
}
capA.release();
capB.release();
return 0;
}